forked from barak/tarpoon
Add glide.yaml and vendor deps
This commit is contained in:
parent
db918f12ad
commit
5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions
7
vendor/gopkg.in/cheggaaa/pb.v1/.travis.yml
generated
vendored
Normal file
7
vendor/gopkg.in/cheggaaa/pb.v1/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.4.2
|
||||
sudo: false
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
12
vendor/gopkg.in/cheggaaa/pb.v1/LICENSE
generated
vendored
Normal file
12
vendor/gopkg.in/cheggaaa/pb.v1/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Copyright (c) 2012-2015, Sergey Cherepanov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
176
vendor/gopkg.in/cheggaaa/pb.v1/README.md
generated
vendored
Normal file
176
vendor/gopkg.in/cheggaaa/pb.v1/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
# Terminal progress bar for Go
|
||||
|
||||
Simple progress bar for console programs.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
go get gopkg.in/cheggaaa/pb.v1
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
count := 100000
|
||||
bar := pb.StartNew(count)
|
||||
for i := 0; i < count; i++ {
|
||||
bar.Increment()
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
bar.FinishPrint("The End!")
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Result will be like this:
|
||||
|
||||
```
|
||||
> go run test.go
|
||||
37158 / 100000 [================>_______________________________] 37.16% 1m11s
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
```Go
|
||||
// create bar
|
||||
bar := pb.New(count)
|
||||
|
||||
// refresh info every second (default 200ms)
|
||||
bar.SetRefreshRate(time.Second)
|
||||
|
||||
// show percents (by default already true)
|
||||
bar.ShowPercent = true
|
||||
|
||||
// show bar (by default already true)
|
||||
bar.ShowBar = true
|
||||
|
||||
// no counters
|
||||
bar.ShowCounters = false
|
||||
|
||||
// show "time left"
|
||||
bar.ShowTimeLeft = true
|
||||
|
||||
// show average speed
|
||||
bar.ShowSpeed = true
|
||||
|
||||
// sets the width of the progress bar
|
||||
bar.SetWidth(80)
|
||||
|
||||
// sets the width of the progress bar, but if terminal size smaller will be ignored
|
||||
bar.SetMaxWidth(80)
|
||||
|
||||
// convert output to readable format (like KB, MB)
|
||||
bar.SetUnits(pb.U_BYTES)
|
||||
|
||||
// and start
|
||||
bar.Start()
|
||||
```
|
||||
|
||||
## Progress bar for IO Operations
|
||||
|
||||
```go
|
||||
// create and start bar
|
||||
bar := pb.New(myDataLen).SetUnits(pb.U_BYTES)
|
||||
bar.Start()
|
||||
|
||||
// my io.Reader
|
||||
r := myReader
|
||||
|
||||
// my io.Writer
|
||||
w := myWriter
|
||||
|
||||
// create proxy reader
|
||||
reader := bar.NewProxyReader(r)
|
||||
|
||||
// and copy from pb reader
|
||||
io.Copy(w, reader)
|
||||
|
||||
```
|
||||
|
||||
```go
|
||||
// create and start bar
|
||||
bar := pb.New(myDataLen).SetUnits(pb.U_BYTES)
|
||||
bar.Start()
|
||||
|
||||
// my io.Reader
|
||||
r := myReader
|
||||
|
||||
// my io.Writer
|
||||
w := myWriter
|
||||
|
||||
// create multi writer
|
||||
writer := io.MultiWriter(w, bar)
|
||||
|
||||
// and copy
|
||||
io.Copy(writer, r)
|
||||
|
||||
bar.Finish()
|
||||
```
|
||||
|
||||
## Custom Progress Bar Look-and-feel
|
||||
|
||||
```go
|
||||
bar.Format("<.- >")
|
||||
```
|
||||
|
||||
## Multiple Progress Bars (experimental and unstable)
|
||||
|
||||
Do not print to terminal while pool is active.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// create bars
|
||||
first := pb.New(200).Prefix("First ")
|
||||
second := pb.New(200).Prefix("Second ")
|
||||
third := pb.New(200).Prefix("Third ")
|
||||
// start pool
|
||||
pool, err := pb.StartPool(first, second, third)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// update bars
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, bar := range []*pb.ProgressBar{first, second, third} {
|
||||
wg.Add(1)
|
||||
go func(cb *pb.ProgressBar) {
|
||||
for n := 0; n < 200; n++ {
|
||||
cb.Increment()
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))
|
||||
}
|
||||
cb.Finish()
|
||||
wg.Done()
|
||||
}(bar)
|
||||
}
|
||||
wg.Wait()
|
||||
// close pool
|
||||
pool.Stop()
|
||||
}
|
||||
```
|
||||
|
||||
The result will be as follows:
|
||||
|
||||
```
|
||||
$ go run example/multiple.go
|
||||
First 141 / 1000 [===============>---------------------------------------] 14.10 % 44s
|
||||
Second 139 / 1000 [==============>---------------------------------------] 13.90 % 44s
|
||||
Third 152 / 1000 [================>--------------------------------------] 15.20 % 40s
|
||||
```
|
||||
82
vendor/gopkg.in/cheggaaa/pb.v1/example_copy_test.go
generated
vendored
Normal file
82
vendor/gopkg.in/cheggaaa/pb.v1/example_copy_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package pb_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
)
|
||||
|
||||
func Example_copy() {
|
||||
// check args
|
||||
if len(os.Args) < 3 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
sourceName, destName := os.Args[1], os.Args[2]
|
||||
|
||||
// check source
|
||||
var source io.Reader
|
||||
var sourceSize int64
|
||||
if strings.HasPrefix(sourceName, "http://") {
|
||||
// open as url
|
||||
resp, err := http.Get(sourceName)
|
||||
if err != nil {
|
||||
fmt.Printf("Can't get %s: %v\n", sourceName, err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Printf("Server return non-200 status: %v\n", resp.Status)
|
||||
return
|
||||
}
|
||||
i, _ := strconv.Atoi(resp.Header.Get("Content-Length"))
|
||||
sourceSize = int64(i)
|
||||
source = resp.Body
|
||||
} else {
|
||||
// open as file
|
||||
s, err := os.Open(sourceName)
|
||||
if err != nil {
|
||||
fmt.Printf("Can't open %s: %v\n", sourceName, err)
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
// get source size
|
||||
sourceStat, err := s.Stat()
|
||||
if err != nil {
|
||||
fmt.Printf("Can't stat %s: %v\n", sourceName, err)
|
||||
return
|
||||
}
|
||||
sourceSize = sourceStat.Size()
|
||||
source = s
|
||||
}
|
||||
|
||||
// create dest
|
||||
dest, err := os.Create(destName)
|
||||
if err != nil {
|
||||
fmt.Printf("Can't create %s: %v\n", destName, err)
|
||||
return
|
||||
}
|
||||
defer dest.Close()
|
||||
|
||||
// create bar
|
||||
bar := pb.New(int(sourceSize)).SetUnits(pb.U_BYTES).SetRefreshRate(time.Millisecond * 10)
|
||||
bar.ShowSpeed = true
|
||||
bar.Start()
|
||||
|
||||
// create proxy reader
|
||||
reader := bar.NewProxyReader(source)
|
||||
|
||||
// and copy from reader
|
||||
io.Copy(dest, reader)
|
||||
bar.Finish()
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Println("copy [source file or url] [dest file]")
|
||||
}
|
||||
37
vendor/gopkg.in/cheggaaa/pb.v1/example_multiple_test.go
generated
vendored
Normal file
37
vendor/gopkg.in/cheggaaa/pb.v1/example_multiple_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package pb_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
)
|
||||
|
||||
func Example_multiple() {
|
||||
// create bars
|
||||
first := pb.New(200).Prefix("First ")
|
||||
second := pb.New(200).Prefix("Second ")
|
||||
third := pb.New(200).Prefix("Third ")
|
||||
// start pool
|
||||
pool, err := pb.StartPool(first, second, third)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// update bars
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, bar := range []*pb.ProgressBar{first, second, third} {
|
||||
wg.Add(1)
|
||||
go func(cb *pb.ProgressBar) {
|
||||
for n := 0; n < 200; n++ {
|
||||
cb.Increment()
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))
|
||||
}
|
||||
cb.Finish()
|
||||
wg.Done()
|
||||
}(bar)
|
||||
}
|
||||
wg.Wait()
|
||||
// close pool
|
||||
pool.Stop()
|
||||
}
|
||||
30
vendor/gopkg.in/cheggaaa/pb.v1/example_test.go
generated
vendored
Normal file
30
vendor/gopkg.in/cheggaaa/pb.v1/example_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package pb_test
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
count := 5000
|
||||
bar := pb.New(count)
|
||||
|
||||
// show percents (by default already true)
|
||||
bar.ShowPercent = true
|
||||
|
||||
// show bar (by default already true)
|
||||
bar.ShowBar = true
|
||||
|
||||
bar.ShowCounters = true
|
||||
|
||||
bar.ShowTimeLeft = true
|
||||
|
||||
// and start
|
||||
bar.Start()
|
||||
for i := 0; i < count; i++ {
|
||||
bar.Increment()
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
bar.FinishPrint("The End!")
|
||||
}
|
||||
87
vendor/gopkg.in/cheggaaa/pb.v1/format.go
generated
vendored
Normal file
87
vendor/gopkg.in/cheggaaa/pb.v1/format.go
generated
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Units int
|
||||
|
||||
const (
|
||||
// U_NO are default units, they represent a simple value and are not formatted at all.
|
||||
U_NO Units = iota
|
||||
// U_BYTES units are formatted in a human readable way (b, Bb, Mb, ...)
|
||||
U_BYTES
|
||||
// U_DURATION units are formatted in a human readable way (3h14m15s)
|
||||
U_DURATION
|
||||
)
|
||||
|
||||
func Format(i int64) *formatter {
|
||||
return &formatter{n: i}
|
||||
}
|
||||
|
||||
type formatter struct {
|
||||
n int64
|
||||
unit Units
|
||||
width int
|
||||
perSec bool
|
||||
}
|
||||
|
||||
func (f *formatter) Value(n int64) *formatter {
|
||||
f.n = n
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *formatter) To(unit Units) *formatter {
|
||||
f.unit = unit
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *formatter) Width(width int) *formatter {
|
||||
f.width = width
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *formatter) PerSec() *formatter {
|
||||
f.perSec = true
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *formatter) String() (out string) {
|
||||
switch f.unit {
|
||||
case U_BYTES:
|
||||
out = formatBytes(f.n)
|
||||
case U_DURATION:
|
||||
d := time.Duration(f.n)
|
||||
if d > time.Hour*24 {
|
||||
out = fmt.Sprintf("%dd", d/24/time.Hour)
|
||||
d -= (d / time.Hour / 24) * (time.Hour * 24)
|
||||
}
|
||||
out = fmt.Sprintf("%s%v", out, d)
|
||||
default:
|
||||
out = fmt.Sprintf(fmt.Sprintf("%%%dd", f.width), f.n)
|
||||
}
|
||||
if f.perSec {
|
||||
out += "/s"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B
|
||||
func formatBytes(i int64) (result string) {
|
||||
switch {
|
||||
case i > (1024 * 1024 * 1024 * 1024):
|
||||
result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024)
|
||||
case i > (1024 * 1024 * 1024):
|
||||
result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024)
|
||||
case i > (1024 * 1024):
|
||||
result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024)
|
||||
case i > 1024:
|
||||
result = fmt.Sprintf("%.02f KB", float64(i)/1024)
|
||||
default:
|
||||
result = fmt.Sprintf("%d B", i)
|
||||
}
|
||||
result = strings.Trim(result, " ")
|
||||
return
|
||||
}
|
||||
57
vendor/gopkg.in/cheggaaa/pb.v1/format_test.go
generated
vendored
Normal file
57
vendor/gopkg.in/cheggaaa/pb.v1/format_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package pb_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/cheggaaa/pb.v1"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_DefaultsToInteger(t *testing.T) {
|
||||
value := int64(1000)
|
||||
expected := strconv.Itoa(int(value))
|
||||
actual := pb.Format(value).String()
|
||||
|
||||
if actual != expected {
|
||||
t.Error(fmt.Sprintf("Expected {%s} was {%s}", expected, actual))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CanFormatAsInteger(t *testing.T) {
|
||||
value := int64(1000)
|
||||
expected := strconv.Itoa(int(value))
|
||||
actual := pb.Format(value).To(pb.U_NO).String()
|
||||
|
||||
if actual != expected {
|
||||
t.Error(fmt.Sprintf("Expected {%s} was {%s}", expected, actual))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CanFormatAsBytes(t *testing.T) {
|
||||
value := int64(1000)
|
||||
expected := "1000 B"
|
||||
actual := pb.Format(value).To(pb.U_BYTES).String()
|
||||
|
||||
if actual != expected {
|
||||
t.Error(fmt.Sprintf("Expected {%s} was {%s}", expected, actual))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CanFormatDuration(t *testing.T) {
|
||||
value := 10 * time.Minute
|
||||
expected := "10m0s"
|
||||
actual := pb.Format(int64(value)).To(pb.U_DURATION).String()
|
||||
if actual != expected {
|
||||
t.Error(fmt.Sprintf("Expected {%s} was {%s}", expected, actual))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_DefaultUnitsWidth(t *testing.T) {
|
||||
value := 10
|
||||
expected := " 10"
|
||||
actual := pb.Format(int64(value)).Width(7).String()
|
||||
if actual != expected {
|
||||
t.Error(fmt.Sprintf("Expected {%s} was {%s}", expected, actual))
|
||||
}
|
||||
}
|
||||
444
vendor/gopkg.in/cheggaaa/pb.v1/pb.go
generated
vendored
Normal file
444
vendor/gopkg.in/cheggaaa/pb.v1/pb.go
generated
vendored
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
// Simple console progress bars
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Current version
|
||||
const Version = "1.0.6"
|
||||
|
||||
const (
|
||||
// Default refresh rate - 200ms
|
||||
DEFAULT_REFRESH_RATE = time.Millisecond * 200
|
||||
FORMAT = "[=>-]"
|
||||
)
|
||||
|
||||
// DEPRECATED
|
||||
// variables for backward compatibility, from now do not work
|
||||
// use pb.Format and pb.SetRefreshRate
|
||||
var (
|
||||
DefaultRefreshRate = DEFAULT_REFRESH_RATE
|
||||
BarStart, BarEnd, Empty, Current, CurrentN string
|
||||
)
|
||||
|
||||
// Create new progress bar object
|
||||
func New(total int) *ProgressBar {
|
||||
return New64(int64(total))
|
||||
}
|
||||
|
||||
// Create new progress bar object using int64 as total
|
||||
func New64(total int64) *ProgressBar {
|
||||
pb := &ProgressBar{
|
||||
Total: total,
|
||||
RefreshRate: DEFAULT_REFRESH_RATE,
|
||||
ShowPercent: true,
|
||||
ShowCounters: true,
|
||||
ShowBar: true,
|
||||
ShowTimeLeft: true,
|
||||
ShowFinalTime: true,
|
||||
Units: U_NO,
|
||||
ManualUpdate: false,
|
||||
finish: make(chan struct{}),
|
||||
currentValue: -1,
|
||||
mu: new(sync.Mutex),
|
||||
}
|
||||
return pb.Format(FORMAT)
|
||||
}
|
||||
|
||||
// Create new object and start
|
||||
func StartNew(total int) *ProgressBar {
|
||||
return New(total).Start()
|
||||
}
|
||||
|
||||
// Callback for custom output
|
||||
// For example:
|
||||
// bar.Callback = func(s string) {
|
||||
// mySuperPrint(s)
|
||||
// }
|
||||
//
|
||||
type Callback func(out string)
|
||||
|
||||
type ProgressBar struct {
|
||||
current int64 // current must be first member of struct (https://code.google.com/p/go/issues/detail?id=5278)
|
||||
|
||||
Total int64
|
||||
RefreshRate time.Duration
|
||||
ShowPercent, ShowCounters bool
|
||||
ShowSpeed, ShowTimeLeft, ShowBar bool
|
||||
ShowFinalTime bool
|
||||
Output io.Writer
|
||||
Callback Callback
|
||||
NotPrint bool
|
||||
Units Units
|
||||
Width int
|
||||
ForceWidth bool
|
||||
ManualUpdate bool
|
||||
AutoStat bool
|
||||
|
||||
// Default width for the time box.
|
||||
UnitsWidth int
|
||||
TimeBoxWidth int
|
||||
|
||||
finishOnce sync.Once //Guards isFinish
|
||||
finish chan struct{}
|
||||
isFinish bool
|
||||
|
||||
startTime time.Time
|
||||
startValue int64
|
||||
currentValue int64
|
||||
|
||||
prefix, postfix string
|
||||
|
||||
mu *sync.Mutex
|
||||
lastPrint string
|
||||
|
||||
BarStart string
|
||||
BarEnd string
|
||||
Empty string
|
||||
Current string
|
||||
CurrentN string
|
||||
|
||||
AlwaysUpdate bool
|
||||
}
|
||||
|
||||
// Start print
|
||||
func (pb *ProgressBar) Start() *ProgressBar {
|
||||
pb.startTime = time.Now()
|
||||
pb.startValue = pb.current
|
||||
if pb.Total == 0 {
|
||||
pb.ShowTimeLeft = false
|
||||
pb.ShowPercent = false
|
||||
pb.AutoStat = false
|
||||
}
|
||||
if !pb.ManualUpdate {
|
||||
pb.Update() // Initial printing of the bar before running the bar refresher.
|
||||
go pb.refresher()
|
||||
}
|
||||
return pb
|
||||
}
|
||||
|
||||
// Increment current value
|
||||
func (pb *ProgressBar) Increment() int {
|
||||
return pb.Add(1)
|
||||
}
|
||||
|
||||
// Get current value
|
||||
func (pb *ProgressBar) Get() int64 {
|
||||
c := atomic.LoadInt64(&pb.current)
|
||||
return c
|
||||
}
|
||||
|
||||
// Set current value
|
||||
func (pb *ProgressBar) Set(current int) *ProgressBar {
|
||||
return pb.Set64(int64(current))
|
||||
}
|
||||
|
||||
// Set64 sets the current value as int64
|
||||
func (pb *ProgressBar) Set64(current int64) *ProgressBar {
|
||||
atomic.StoreInt64(&pb.current, current)
|
||||
return pb
|
||||
}
|
||||
|
||||
// Add to current value
|
||||
func (pb *ProgressBar) Add(add int) int {
|
||||
return int(pb.Add64(int64(add)))
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) Add64(add int64) int64 {
|
||||
return atomic.AddInt64(&pb.current, add)
|
||||
}
|
||||
|
||||
// Set prefix string
|
||||
func (pb *ProgressBar) Prefix(prefix string) *ProgressBar {
|
||||
pb.prefix = prefix
|
||||
return pb
|
||||
}
|
||||
|
||||
// Set postfix string
|
||||
func (pb *ProgressBar) Postfix(postfix string) *ProgressBar {
|
||||
pb.postfix = postfix
|
||||
return pb
|
||||
}
|
||||
|
||||
// Set custom format for bar
|
||||
// Example: bar.Format("[=>_]")
|
||||
// Example: bar.Format("[\x00=\x00>\x00-\x00]") // \x00 is the delimiter
|
||||
func (pb *ProgressBar) Format(format string) *ProgressBar {
|
||||
var formatEntries []string
|
||||
if len(format) == 5 {
|
||||
formatEntries = strings.Split(format, "")
|
||||
} else {
|
||||
formatEntries = strings.Split(format, "\x00")
|
||||
}
|
||||
if len(formatEntries) == 5 {
|
||||
pb.BarStart = formatEntries[0]
|
||||
pb.BarEnd = formatEntries[4]
|
||||
pb.Empty = formatEntries[3]
|
||||
pb.Current = formatEntries[1]
|
||||
pb.CurrentN = formatEntries[2]
|
||||
}
|
||||
return pb
|
||||
}
|
||||
|
||||
// Set bar refresh rate
|
||||
func (pb *ProgressBar) SetRefreshRate(rate time.Duration) *ProgressBar {
|
||||
pb.RefreshRate = rate
|
||||
return pb
|
||||
}
|
||||
|
||||
// Set units
|
||||
// bar.SetUnits(U_NO) - by default
|
||||
// bar.SetUnits(U_BYTES) - for Mb, Kb, etc
|
||||
func (pb *ProgressBar) SetUnits(units Units) *ProgressBar {
|
||||
pb.Units = units
|
||||
return pb
|
||||
}
|
||||
|
||||
// Set max width, if width is bigger than terminal width, will be ignored
|
||||
func (pb *ProgressBar) SetMaxWidth(width int) *ProgressBar {
|
||||
pb.Width = width
|
||||
pb.ForceWidth = false
|
||||
return pb
|
||||
}
|
||||
|
||||
// Set bar width
|
||||
func (pb *ProgressBar) SetWidth(width int) *ProgressBar {
|
||||
pb.Width = width
|
||||
pb.ForceWidth = true
|
||||
return pb
|
||||
}
|
||||
|
||||
// End print
|
||||
func (pb *ProgressBar) Finish() {
|
||||
//Protect multiple calls
|
||||
pb.finishOnce.Do(func() {
|
||||
close(pb.finish)
|
||||
pb.write(atomic.LoadInt64(&pb.current))
|
||||
switch {
|
||||
case pb.Output != nil:
|
||||
fmt.Fprintln(pb.Output)
|
||||
case !pb.NotPrint:
|
||||
fmt.Println()
|
||||
}
|
||||
pb.isFinish = true
|
||||
})
|
||||
}
|
||||
|
||||
// End print and write string 'str'
|
||||
func (pb *ProgressBar) FinishPrint(str string) {
|
||||
pb.Finish()
|
||||
if pb.Output != nil {
|
||||
fmt.Fprintln(pb.Output, str)
|
||||
} else {
|
||||
fmt.Println(str)
|
||||
}
|
||||
}
|
||||
|
||||
// implement io.Writer
|
||||
func (pb *ProgressBar) Write(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
pb.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// implement io.Reader
|
||||
func (pb *ProgressBar) Read(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
pb.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Create new proxy reader over bar
|
||||
// Takes io.Reader or io.ReadCloser
|
||||
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
|
||||
return &Reader{r, pb}
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) write(current int64) {
|
||||
width := pb.GetWidth()
|
||||
|
||||
var percentBox, countersBox, timeLeftBox, speedBox, barBox, end, out string
|
||||
|
||||
// percents
|
||||
if pb.ShowPercent {
|
||||
var percent float64
|
||||
if pb.Total > 0 {
|
||||
percent = float64(current) / (float64(pb.Total) / float64(100))
|
||||
} else {
|
||||
percent = float64(current) / float64(100)
|
||||
}
|
||||
percentBox = fmt.Sprintf(" %6.02f%%", percent)
|
||||
}
|
||||
|
||||
// counters
|
||||
if pb.ShowCounters {
|
||||
current := Format(current).To(pb.Units).Width(pb.UnitsWidth)
|
||||
if pb.Total > 0 {
|
||||
total := Format(pb.Total).To(pb.Units).Width(pb.UnitsWidth)
|
||||
countersBox = fmt.Sprintf(" %s / %s ", current, total)
|
||||
} else {
|
||||
countersBox = fmt.Sprintf(" %s / ? ", current)
|
||||
}
|
||||
}
|
||||
|
||||
// time left
|
||||
fromStart := time.Now().Sub(pb.startTime)
|
||||
currentFromStart := current - pb.startValue
|
||||
select {
|
||||
case <-pb.finish:
|
||||
if pb.ShowFinalTime {
|
||||
var left time.Duration
|
||||
left = (fromStart / time.Second) * time.Second
|
||||
timeLeftBox = fmt.Sprintf(" %s", left.String())
|
||||
}
|
||||
default:
|
||||
if pb.ShowTimeLeft && currentFromStart > 0 {
|
||||
perEntry := fromStart / time.Duration(currentFromStart)
|
||||
var left time.Duration
|
||||
if pb.Total > 0 {
|
||||
left = time.Duration(pb.Total-currentFromStart) * perEntry
|
||||
left = (left / time.Second) * time.Second
|
||||
} else {
|
||||
left = time.Duration(currentFromStart) * perEntry
|
||||
left = (left / time.Second) * time.Second
|
||||
}
|
||||
timeLeft := Format(int64(left)).To(U_DURATION).String()
|
||||
timeLeftBox = fmt.Sprintf(" %s", timeLeft)
|
||||
}
|
||||
}
|
||||
|
||||
if len(timeLeftBox) < pb.TimeBoxWidth {
|
||||
timeLeftBox = fmt.Sprintf("%s%s", strings.Repeat(" ", pb.TimeBoxWidth-len(timeLeftBox)), timeLeftBox)
|
||||
}
|
||||
|
||||
// speed
|
||||
if pb.ShowSpeed && currentFromStart > 0 {
|
||||
fromStart := time.Now().Sub(pb.startTime)
|
||||
speed := float64(currentFromStart) / (float64(fromStart) / float64(time.Second))
|
||||
speedBox = " " + Format(int64(speed)).To(pb.Units).Width(pb.UnitsWidth).PerSec().String()
|
||||
}
|
||||
|
||||
barWidth := escapeAwareRuneCountInString(countersBox + pb.BarStart + pb.BarEnd + percentBox + timeLeftBox + speedBox + pb.prefix + pb.postfix)
|
||||
// bar
|
||||
if pb.ShowBar {
|
||||
size := width - barWidth
|
||||
if size > 0 {
|
||||
if pb.Total > 0 {
|
||||
curCount := int(math.Ceil((float64(current) / float64(pb.Total)) * float64(size)))
|
||||
emptCount := size - curCount
|
||||
barBox = pb.BarStart
|
||||
if emptCount < 0 {
|
||||
emptCount = 0
|
||||
}
|
||||
if curCount > size {
|
||||
curCount = size
|
||||
}
|
||||
if emptCount <= 0 {
|
||||
barBox += strings.Repeat(pb.Current, curCount)
|
||||
} else if curCount > 0 {
|
||||
barBox += strings.Repeat(pb.Current, curCount-1) + pb.CurrentN
|
||||
}
|
||||
barBox += strings.Repeat(pb.Empty, emptCount) + pb.BarEnd
|
||||
} else {
|
||||
barBox = pb.BarStart
|
||||
pos := size - int(current)%int(size)
|
||||
if pos-1 > 0 {
|
||||
barBox += strings.Repeat(pb.Empty, pos-1)
|
||||
}
|
||||
barBox += pb.Current
|
||||
if size-pos-1 > 0 {
|
||||
barBox += strings.Repeat(pb.Empty, size-pos-1)
|
||||
}
|
||||
barBox += pb.BarEnd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check len
|
||||
out = pb.prefix + countersBox + barBox + percentBox + speedBox + timeLeftBox + pb.postfix
|
||||
if escapeAwareRuneCountInString(out) < width {
|
||||
end = strings.Repeat(" ", width-utf8.RuneCountInString(out))
|
||||
}
|
||||
|
||||
// and print!
|
||||
pb.mu.Lock()
|
||||
pb.lastPrint = out + end
|
||||
pb.mu.Unlock()
|
||||
switch {
|
||||
case pb.isFinish:
|
||||
return
|
||||
case pb.Output != nil:
|
||||
fmt.Fprint(pb.Output, "\r"+out+end)
|
||||
case pb.Callback != nil:
|
||||
pb.Callback(out + end)
|
||||
case !pb.NotPrint:
|
||||
fmt.Print("\r" + out + end)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTerminalWidth - returns terminal width for all platforms.
|
||||
func GetTerminalWidth() (int, error) {
|
||||
return terminalWidth()
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) GetWidth() int {
|
||||
if pb.ForceWidth {
|
||||
return pb.Width
|
||||
}
|
||||
|
||||
width := pb.Width
|
||||
termWidth, _ := terminalWidth()
|
||||
if width == 0 || termWidth <= width {
|
||||
width = termWidth
|
||||
}
|
||||
|
||||
return width
|
||||
}
|
||||
|
||||
// Write the current state of the progressbar
|
||||
func (pb *ProgressBar) Update() {
|
||||
c := atomic.LoadInt64(&pb.current)
|
||||
if pb.AlwaysUpdate || c != pb.currentValue {
|
||||
pb.write(c)
|
||||
pb.currentValue = c
|
||||
}
|
||||
if pb.AutoStat {
|
||||
if c == 0 {
|
||||
pb.startTime = time.Now()
|
||||
pb.startValue = 0
|
||||
} else if c >= pb.Total && pb.isFinish != true {
|
||||
pb.Finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pb *ProgressBar) String() string {
|
||||
return pb.lastPrint
|
||||
}
|
||||
|
||||
// Internal loop for refreshing the progressbar
|
||||
func (pb *ProgressBar) refresher() {
|
||||
for {
|
||||
select {
|
||||
case <-pb.finish:
|
||||
return
|
||||
case <-time.After(pb.RefreshRate):
|
||||
pb.Update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type window struct {
|
||||
Row uint16
|
||||
Col uint16
|
||||
Xpixel uint16
|
||||
Ypixel uint16
|
||||
}
|
||||
11
vendor/gopkg.in/cheggaaa/pb.v1/pb_appengine.go
generated
vendored
Normal file
11
vendor/gopkg.in/cheggaaa/pb.v1/pb_appengine.go
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// +build appengine
|
||||
|
||||
package pb
|
||||
|
||||
import "errors"
|
||||
|
||||
// terminalWidth returns width of the terminal, which is not supported
|
||||
// and should always failed on appengine classic which is a sandboxed PaaS.
|
||||
func terminalWidth() (int, error) {
|
||||
return 0, errors.New("Not supported")
|
||||
}
|
||||
8
vendor/gopkg.in/cheggaaa/pb.v1/pb_nix.go
generated
vendored
Normal file
8
vendor/gopkg.in/cheggaaa/pb.v1/pb_nix.go
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// +build linux darwin freebsd netbsd openbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package pb
|
||||
|
||||
import "syscall"
|
||||
|
||||
const sysIoctl = syscall.SYS_IOCTL
|
||||
6
vendor/gopkg.in/cheggaaa/pb.v1/pb_solaris.go
generated
vendored
Normal file
6
vendor/gopkg.in/cheggaaa/pb.v1/pb_solaris.go
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// +build solaris
|
||||
// +build !appengine
|
||||
|
||||
package pb
|
||||
|
||||
const sysIoctl = 54
|
||||
103
vendor/gopkg.in/cheggaaa/pb.v1/pb_test.go
generated
vendored
Normal file
103
vendor/gopkg.in/cheggaaa/pb.v1/pb_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
package pb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/mattn/go-colorable"
|
||||
)
|
||||
|
||||
func Test_IncrementAddsOne(t *testing.T) {
|
||||
count := 5000
|
||||
bar := New(count)
|
||||
expected := 1
|
||||
actual := bar.Increment()
|
||||
|
||||
if actual != expected {
|
||||
t.Errorf("Expected {%d} was {%d}", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Width(t *testing.T) {
|
||||
count := 5000
|
||||
bar := New(count)
|
||||
width := 100
|
||||
bar.SetWidth(100).Callback = func(out string) {
|
||||
if len(out) != width {
|
||||
t.Errorf("Bar width expected {%d} was {%d}", len(out), width)
|
||||
}
|
||||
}
|
||||
bar.Start()
|
||||
bar.Increment()
|
||||
bar.Finish()
|
||||
}
|
||||
|
||||
func Test_MultipleFinish(t *testing.T) {
|
||||
bar := New(5000)
|
||||
bar.Add(2000)
|
||||
bar.Finish()
|
||||
bar.Finish()
|
||||
}
|
||||
|
||||
func Test_Format(t *testing.T) {
|
||||
bar := New(5000).Format(strings.Join([]string{
|
||||
color.GreenString("["),
|
||||
color.New(color.BgGreen).SprintFunc()("o"),
|
||||
color.New(color.BgHiGreen).SprintFunc()("o"),
|
||||
color.New(color.BgRed).SprintFunc()("o"),
|
||||
color.GreenString("]"),
|
||||
}, "\x00"))
|
||||
w := colorable.NewColorableStdout()
|
||||
bar.Callback = func(out string) {
|
||||
w.Write([]byte(out))
|
||||
}
|
||||
bar.Add(2000)
|
||||
bar.Finish()
|
||||
bar.Finish()
|
||||
}
|
||||
|
||||
func Test_AutoStat(t *testing.T) {
|
||||
bar := New(5)
|
||||
bar.AutoStat = true
|
||||
bar.Start()
|
||||
time.Sleep(2 * time.Second)
|
||||
//real start work
|
||||
for i := 0; i < 5; i++ {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
bar.Increment()
|
||||
}
|
||||
//real finish work
|
||||
time.Sleep(2 * time.Second)
|
||||
bar.Finish()
|
||||
}
|
||||
|
||||
func Test_Finish_PrintNewline(t *testing.T) {
|
||||
bar := New(5)
|
||||
buf := &bytes.Buffer{}
|
||||
bar.Output = buf
|
||||
bar.Finish()
|
||||
|
||||
expected := "\n"
|
||||
actual := buf.String()
|
||||
//Finish should write newline to bar.Output
|
||||
if !strings.HasSuffix(actual, expected) {
|
||||
t.Errorf("Expected %q to have suffix %q", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_FinishPrint(t *testing.T) {
|
||||
bar := New(5)
|
||||
buf := &bytes.Buffer{}
|
||||
bar.Output = buf
|
||||
bar.FinishPrint("foo")
|
||||
|
||||
expected := "foo\n"
|
||||
actual := buf.String()
|
||||
//FinishPrint should write to bar.Output
|
||||
if !strings.HasSuffix(actual, expected) {
|
||||
t.Errorf("Expected %q to have suffix %q", expected, actual)
|
||||
}
|
||||
}
|
||||
141
vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go
generated
vendored
Normal file
141
vendor/gopkg.in/cheggaaa/pb.v1/pb_win.go
generated
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
// +build windows
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var tty = os.Stdin
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
|
||||
// GetConsoleScreenBufferInfo retrieves information about the
|
||||
// specified console screen buffer.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
|
||||
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
|
||||
|
||||
// GetConsoleMode retrieves the current input mode of a console's
|
||||
// input buffer or the current output mode of a console screen buffer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx
|
||||
getConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
|
||||
// SetConsoleMode sets the input mode of a console's input buffer
|
||||
// or the output mode of a console screen buffer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
|
||||
setConsoleMode = kernel32.NewProc("SetConsoleMode")
|
||||
|
||||
// SetConsoleCursorPosition sets the cursor position in the
|
||||
// specified console screen buffer.
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx
|
||||
setConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
|
||||
)
|
||||
|
||||
type (
|
||||
// Defines the coordinates of the upper left and lower right corners
|
||||
// of a rectangle.
|
||||
// See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311(v=vs.85).aspx
|
||||
smallRect struct {
|
||||
Left, Top, Right, Bottom int16
|
||||
}
|
||||
|
||||
// Defines the coordinates of a character cell in a console screen
|
||||
// buffer. The origin of the coordinate system (0,0) is at the top, left cell
|
||||
// of the buffer.
|
||||
// See
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx
|
||||
coordinates struct {
|
||||
X, Y int16
|
||||
}
|
||||
|
||||
word int16
|
||||
|
||||
// Contains information about a console screen buffer.
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
|
||||
consoleScreenBufferInfo struct {
|
||||
dwSize coordinates
|
||||
dwCursorPosition coordinates
|
||||
wAttributes word
|
||||
srWindow smallRect
|
||||
dwMaximumWindowSize coordinates
|
||||
}
|
||||
)
|
||||
|
||||
// terminalWidth returns width of the terminal.
|
||||
func terminalWidth() (width int, err error) {
|
||||
var info consoleScreenBufferInfo
|
||||
_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
|
||||
if e != 0 {
|
||||
return 0, error(e)
|
||||
}
|
||||
return int(info.dwSize.X) - 1, nil
|
||||
}
|
||||
|
||||
func getCursorPos() (pos coordinates, err error) {
|
||||
var info consoleScreenBufferInfo
|
||||
_, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&info)), 0)
|
||||
if e != 0 {
|
||||
return info.dwCursorPosition, error(e)
|
||||
}
|
||||
return info.dwCursorPosition, nil
|
||||
}
|
||||
|
||||
func setCursorPos(pos coordinates) error {
|
||||
_, _, e := syscall.Syscall(setConsoleCursorPosition.Addr(), 2, uintptr(syscall.Stdout), uintptr(uint32(uint16(pos.Y))<<16|uint32(uint16(pos.X))), 0)
|
||||
if e != 0 {
|
||||
return error(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var ErrPoolWasStarted = errors.New("Bar pool was started")
|
||||
|
||||
var echoLocked bool
|
||||
var echoLockMutex sync.Mutex
|
||||
|
||||
var oldState word
|
||||
|
||||
func lockEcho() (quit chan int, err error) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
if echoLocked {
|
||||
err = ErrPoolWasStarted
|
||||
return
|
||||
}
|
||||
echoLocked = true
|
||||
|
||||
if _, _, e := syscall.Syscall(getConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(unsafe.Pointer(&oldState)), 0); e != 0 {
|
||||
err = fmt.Errorf("Can't get terminal settings: %v", e)
|
||||
return
|
||||
}
|
||||
|
||||
newState := oldState
|
||||
const ENABLE_ECHO_INPUT = 0x0004
|
||||
const ENABLE_LINE_INPUT = 0x0002
|
||||
newState = newState & (^(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))
|
||||
if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(newState), 0); e != 0 {
|
||||
err = fmt.Errorf("Can't set terminal settings: %v", e)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func unlockEcho() (err error) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
if !echoLocked {
|
||||
return
|
||||
}
|
||||
echoLocked = false
|
||||
if _, _, e := syscall.Syscall(setConsoleMode.Addr(), 2, uintptr(syscall.Stdout), uintptr(oldState), 0); e != 0 {
|
||||
err = fmt.Errorf("Can't set terminal settings")
|
||||
}
|
||||
return
|
||||
}
|
||||
110
vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go
generated
vendored
Normal file
110
vendor/gopkg.in/cheggaaa/pb.v1/pb_x.go
generated
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
TIOCGWINSZ = 0x5413
|
||||
TIOCGWINSZ_OSX = 1074295912
|
||||
)
|
||||
|
||||
var tty *os.File
|
||||
|
||||
var ErrPoolWasStarted = errors.New("Bar pool was started")
|
||||
|
||||
var echoLocked bool
|
||||
var echoLockMutex sync.Mutex
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
tty, err = os.Open("/dev/tty")
|
||||
if err != nil {
|
||||
tty = os.Stdin
|
||||
}
|
||||
}
|
||||
|
||||
// terminalWidth returns width of the terminal.
|
||||
func terminalWidth() (int, error) {
|
||||
w := new(window)
|
||||
tio := syscall.TIOCGWINSZ
|
||||
if runtime.GOOS == "darwin" {
|
||||
tio = TIOCGWINSZ_OSX
|
||||
}
|
||||
res, _, err := syscall.Syscall(sysIoctl,
|
||||
tty.Fd(),
|
||||
uintptr(tio),
|
||||
uintptr(unsafe.Pointer(w)),
|
||||
)
|
||||
if int(res) == -1 {
|
||||
return 0, err
|
||||
}
|
||||
return int(w.Col), nil
|
||||
}
|
||||
|
||||
var oldState syscall.Termios
|
||||
|
||||
func lockEcho() (quit chan int, err error) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
if echoLocked {
|
||||
err = ErrPoolWasStarted
|
||||
return
|
||||
}
|
||||
echoLocked = true
|
||||
|
||||
fd := tty.Fd()
|
||||
if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 {
|
||||
err = fmt.Errorf("Can't get terminal settings: %v", e)
|
||||
return
|
||||
}
|
||||
|
||||
newState := oldState
|
||||
newState.Lflag &^= syscall.ECHO
|
||||
newState.Lflag |= syscall.ICANON | syscall.ISIG
|
||||
newState.Iflag |= syscall.ICRNL
|
||||
if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); e != 0 {
|
||||
err = fmt.Errorf("Can't set terminal settings: %v", e)
|
||||
return
|
||||
}
|
||||
quit = make(chan int, 1)
|
||||
go catchTerminate(quit)
|
||||
return
|
||||
}
|
||||
|
||||
func unlockEcho() (err error) {
|
||||
echoLockMutex.Lock()
|
||||
defer echoLockMutex.Unlock()
|
||||
if !echoLocked {
|
||||
return
|
||||
}
|
||||
echoLocked = false
|
||||
fd := tty.Fd()
|
||||
if _, _, e := syscall.Syscall6(sysIoctl, fd, ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); e != 0 {
|
||||
err = fmt.Errorf("Can't set terminal settings")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// listen exit signals and restore terminal state
|
||||
func catchTerminate(quit chan int) {
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL)
|
||||
defer signal.Stop(sig)
|
||||
select {
|
||||
case <-quit:
|
||||
unlockEcho()
|
||||
case <-sig:
|
||||
unlockEcho()
|
||||
}
|
||||
}
|
||||
76
vendor/gopkg.in/cheggaaa/pb.v1/pool.go
generated
vendored
Normal file
76
vendor/gopkg.in/cheggaaa/pb.v1/pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly windows
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Create and start new pool with given bars
|
||||
// You need call pool.Stop() after work
|
||||
func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) {
|
||||
pool = new(Pool)
|
||||
if err = pool.start(); err != nil {
|
||||
return
|
||||
}
|
||||
pool.Add(pbs...)
|
||||
return
|
||||
}
|
||||
|
||||
type Pool struct {
|
||||
RefreshRate time.Duration
|
||||
bars []*ProgressBar
|
||||
quit chan int
|
||||
finishOnce sync.Once
|
||||
}
|
||||
|
||||
// Add progress bars.
|
||||
func (p *Pool) Add(pbs ...*ProgressBar) {
|
||||
for _, bar := range pbs {
|
||||
bar.ManualUpdate = true
|
||||
bar.NotPrint = true
|
||||
bar.Start()
|
||||
p.bars = append(p.bars, bar)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pool) start() (err error) {
|
||||
p.RefreshRate = DefaultRefreshRate
|
||||
quit, err := lockEcho()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p.quit = make(chan int)
|
||||
go p.writer(quit)
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Pool) writer(finish chan int) {
|
||||
var first = true
|
||||
for {
|
||||
select {
|
||||
case <-time.After(p.RefreshRate):
|
||||
if p.print(first) {
|
||||
p.print(false)
|
||||
finish <- 1
|
||||
return
|
||||
}
|
||||
first = false
|
||||
case <-p.quit:
|
||||
finish <- 1
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore terminal state and close pool
|
||||
func (p *Pool) Stop() error {
|
||||
// Wait until one final refresh has passed.
|
||||
time.Sleep(p.RefreshRate)
|
||||
|
||||
p.finishOnce.Do(func() {
|
||||
close(p.quit)
|
||||
})
|
||||
return unlockEcho()
|
||||
}
|
||||
35
vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go
generated
vendored
Normal file
35
vendor/gopkg.in/cheggaaa/pb.v1/pool_win.go
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// +build windows
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func (p *Pool) print(first bool) bool {
|
||||
var out string
|
||||
if !first {
|
||||
coords, err := getCursorPos()
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
coords.Y -= int16(len(p.bars))
|
||||
coords.X = 0
|
||||
|
||||
err = setCursorPos(coords)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
isFinished := true
|
||||
for _, bar := range p.bars {
|
||||
if !bar.isFinish {
|
||||
isFinished = false
|
||||
}
|
||||
bar.Update()
|
||||
out += fmt.Sprintf("\r%s\n", bar.String())
|
||||
}
|
||||
fmt.Print(out)
|
||||
return isFinished
|
||||
}
|
||||
22
vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go
generated
vendored
Normal file
22
vendor/gopkg.in/cheggaaa/pb.v1/pool_x.go
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// +build linux darwin freebsd netbsd openbsd solaris dragonfly
|
||||
|
||||
package pb
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (p *Pool) print(first bool) bool {
|
||||
var out string
|
||||
if !first {
|
||||
out = fmt.Sprintf("\033[%dA", len(p.bars))
|
||||
}
|
||||
isFinished := true
|
||||
for _, bar := range p.bars {
|
||||
if !bar.isFinish {
|
||||
isFinished = false
|
||||
}
|
||||
bar.Update()
|
||||
out += fmt.Sprintf("\r%s\n", bar.String())
|
||||
}
|
||||
fmt.Print(out)
|
||||
return isFinished
|
||||
}
|
||||
25
vendor/gopkg.in/cheggaaa/pb.v1/reader.go
generated
vendored
Normal file
25
vendor/gopkg.in/cheggaaa/pb.v1/reader.go
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package pb
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// It's proxy reader, implement io.Reader
|
||||
type Reader struct {
|
||||
io.Reader
|
||||
bar *ProgressBar
|
||||
}
|
||||
|
||||
func (r *Reader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.Reader.Read(p)
|
||||
r.bar.Add(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Close the reader when it implements io.Closer
|
||||
func (r *Reader) Close() (err error) {
|
||||
if closer, ok := r.Reader.(io.Closer); ok {
|
||||
return closer.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
17
vendor/gopkg.in/cheggaaa/pb.v1/runecount.go
generated
vendored
Normal file
17
vendor/gopkg.in/cheggaaa/pb.v1/runecount.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package pb
|
||||
|
||||
import (
|
||||
"github.com/mattn/go-runewidth"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Finds the control character sequences (like colors)
|
||||
var ctrlFinder = regexp.MustCompile("\x1b\x5b[0-9]+\x6d")
|
||||
|
||||
func escapeAwareRuneCountInString(s string) int {
|
||||
n := runewidth.StringWidth(s)
|
||||
for _, sm := range ctrlFinder.FindAllString(s, -1) {
|
||||
n -= len(sm)
|
||||
}
|
||||
return n
|
||||
}
|
||||
20
vendor/gopkg.in/cheggaaa/pb.v1/runecount_test.go
generated
vendored
Normal file
20
vendor/gopkg.in/cheggaaa/pb.v1/runecount_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package pb
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test_RuneCount(t *testing.T) {
|
||||
s := string([]byte{
|
||||
27, 91, 51, 49, 109, // {Red}
|
||||
72, 101, 108, 108, 111, // Hello
|
||||
44, 32, // ,
|
||||
112, 108, 97, 121, 103, 114, 111, 117, 110, 100, // Playground
|
||||
27, 91, 48, 109, // {Reset}
|
||||
})
|
||||
if e, l := 17, escapeAwareRuneCountInString(s); l != e {
|
||||
t.Errorf("Invalid length %d, expected %d", l, e)
|
||||
}
|
||||
s = "進捗 "
|
||||
if e, l := 5, escapeAwareRuneCountInString(s); l != e {
|
||||
t.Errorf("Invalid length %d, expected %d", l, e)
|
||||
}
|
||||
}
|
||||
9
vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go
generated
vendored
Normal file
9
vendor/gopkg.in/cheggaaa/pb.v1/termios_bsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// +build darwin freebsd netbsd openbsd dragonfly
|
||||
// +build !appengine
|
||||
|
||||
package pb
|
||||
|
||||
import "syscall"
|
||||
|
||||
const ioctlReadTermios = syscall.TIOCGETA
|
||||
const ioctlWriteTermios = syscall.TIOCSETA
|
||||
7
vendor/gopkg.in/cheggaaa/pb.v1/termios_nix.go
generated
vendored
Normal file
7
vendor/gopkg.in/cheggaaa/pb.v1/termios_nix.go
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// +build linux solaris
|
||||
// +build !appengine
|
||||
|
||||
package pb
|
||||
|
||||
const ioctlReadTermios = 0x5401 // syscall.TCGETS
|
||||
const ioctlWriteTermios = 0x5402 // syscall.TCSETS
|
||||
188
vendor/gopkg.in/yaml.v2/LICENSE
generated
vendored
Normal file
188
vendor/gopkg.in/yaml.v2/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
|
||||
Copyright (c) 2011-2014 - Canonical Inc.
|
||||
|
||||
This software is licensed under the LGPLv3, included below.
|
||||
|
||||
As a special exception to the GNU Lesser General Public License version 3
|
||||
("LGPL3"), the copyright holders of this Library give you permission to
|
||||
convey to a third party a Combined Work that links statically or dynamically
|
||||
to this Library without providing any Minimal Corresponding Source or
|
||||
Minimal Application Code as set out in 4d or providing the installation
|
||||
information set out in section 4e, provided that you comply with the other
|
||||
provisions of LGPL3 and provided that you meet, for the Application the
|
||||
terms and conditions of the license(s) which apply to the Application.
|
||||
|
||||
Except as stated in this special exception, the provisions of LGPL3 will
|
||||
continue to comply in full to this Library. If you modify this Library, you
|
||||
may apply this exception to your version of this Library, but you are not
|
||||
obliged to do so. If you do not wish to do so, delete this exception
|
||||
statement from your version. This exception does not (and cannot) modify any
|
||||
license terms which apply to the Application, with which you must still
|
||||
comply.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
31
vendor/gopkg.in/yaml.v2/LICENSE.libyaml
generated
vendored
Normal file
31
vendor/gopkg.in/yaml.v2/LICENSE.libyaml
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
The following files were ported to Go from C files of libyaml, and thus
|
||||
are still covered by their original copyright and license:
|
||||
|
||||
apic.go
|
||||
emitterc.go
|
||||
parserc.go
|
||||
readerc.go
|
||||
scannerc.go
|
||||
writerc.go
|
||||
yamlh.go
|
||||
yamlprivateh.go
|
||||
|
||||
Copyright (c) 2006 Kirill Simonov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
131
vendor/gopkg.in/yaml.v2/README.md
generated
vendored
Normal file
131
vendor/gopkg.in/yaml.v2/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
# YAML support for the Go language
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The yaml package enables Go programs to comfortably encode and decode YAML
|
||||
values. It was developed within [Canonical](https://www.canonical.com) as
|
||||
part of the [juju](https://juju.ubuntu.com) project, and is based on a
|
||||
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
|
||||
C library to parse and generate YAML data quickly and reliably.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
The yaml package supports most of YAML 1.1 and 1.2, including support for
|
||||
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
|
||||
implemented, and base-60 floats from YAML 1.1 are purposefully not
|
||||
supported since they're a poor design and are gone in YAML 1.2.
|
||||
|
||||
Installation and usage
|
||||
----------------------
|
||||
|
||||
The import path for the package is *gopkg.in/yaml.v2*.
|
||||
|
||||
To install it, run:
|
||||
|
||||
go get gopkg.in/yaml.v2
|
||||
|
||||
API documentation
|
||||
-----------------
|
||||
|
||||
If opened in a browser, the import path itself leads to the API documentation:
|
||||
|
||||
* [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
|
||||
|
||||
API stability
|
||||
-------------
|
||||
|
||||
The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var data = `
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
`
|
||||
|
||||
type T struct {
|
||||
A string
|
||||
B struct {
|
||||
RenamedC int `yaml:"c"`
|
||||
D []int `yaml:",flow"`
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
t := T{}
|
||||
|
||||
err := yaml.Unmarshal([]byte(data), &t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t:\n%v\n\n", t)
|
||||
|
||||
d, err := yaml.Marshal(&t)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- t dump:\n%s\n\n", string(d))
|
||||
|
||||
m := make(map[interface{}]interface{})
|
||||
|
||||
err = yaml.Unmarshal([]byte(data), &m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m:\n%v\n\n", m)
|
||||
|
||||
d, err = yaml.Marshal(&m)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
fmt.Printf("--- m dump:\n%s\n\n", string(d))
|
||||
}
|
||||
```
|
||||
|
||||
This example will generate the following output:
|
||||
|
||||
```
|
||||
--- t:
|
||||
{Easy! {2 [3 4]}}
|
||||
|
||||
--- t dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4]
|
||||
|
||||
|
||||
--- m:
|
||||
map[a:Easy! b:map[c:2 d:[3 4]]]
|
||||
|
||||
--- m dump:
|
||||
a: Easy!
|
||||
b:
|
||||
c: 2
|
||||
d:
|
||||
- 3
|
||||
- 4
|
||||
```
|
||||
|
||||
742
vendor/gopkg.in/yaml.v2/apic.go
generated
vendored
Normal file
742
vendor/gopkg.in/yaml.v2/apic.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
683
vendor/gopkg.in/yaml.v2/decode.go
generated
vendored
Normal file
683
vendor/gopkg.in/yaml.v2/decode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
988
vendor/gopkg.in/yaml.v2/decode_test.go
generated
vendored
Normal file
988
vendor/gopkg.in/yaml.v2/decode_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1685
vendor/gopkg.in/yaml.v2/emitterc.go
generated
vendored
Normal file
1685
vendor/gopkg.in/yaml.v2/emitterc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
306
vendor/gopkg.in/yaml.v2/encode.go
generated
vendored
Normal file
306
vendor/gopkg.in/yaml.v2/encode.go
generated
vendored
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
emitter yaml_emitter_t
|
||||
event yaml_event_t
|
||||
out []byte
|
||||
flow bool
|
||||
}
|
||||
|
||||
func newEncoder() (e *encoder) {
|
||||
e = &encoder{}
|
||||
e.must(yaml_emitter_initialize(&e.emitter))
|
||||
yaml_emitter_set_output_string(&e.emitter, &e.out)
|
||||
yaml_emitter_set_unicode(&e.emitter, true)
|
||||
e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING))
|
||||
e.emit()
|
||||
e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true))
|
||||
e.emit()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *encoder) finish() {
|
||||
e.must(yaml_document_end_event_initialize(&e.event, true))
|
||||
e.emit()
|
||||
e.emitter.open_ended = false
|
||||
e.must(yaml_stream_end_event_initialize(&e.event))
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *encoder) destroy() {
|
||||
yaml_emitter_delete(&e.emitter)
|
||||
}
|
||||
|
||||
func (e *encoder) emit() {
|
||||
// This will internally delete the e.event value.
|
||||
if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT {
|
||||
e.must(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) must(ok bool) {
|
||||
if !ok {
|
||||
msg := e.emitter.problem
|
||||
if msg == "" {
|
||||
msg = "unknown problem generating YAML content"
|
||||
}
|
||||
failf("%s", msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) marshal(tag string, in reflect.Value) {
|
||||
if !in.IsValid() {
|
||||
e.nilv()
|
||||
return
|
||||
}
|
||||
iface := in.Interface()
|
||||
if m, ok := iface.(Marshaler); ok {
|
||||
v, err := m.MarshalYAML()
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
if v == nil {
|
||||
e.nilv()
|
||||
return
|
||||
}
|
||||
in = reflect.ValueOf(v)
|
||||
} else if m, ok := iface.(encoding.TextMarshaler); ok {
|
||||
text, err := m.MarshalText()
|
||||
if err != nil {
|
||||
fail(err)
|
||||
}
|
||||
in = reflect.ValueOf(string(text))
|
||||
}
|
||||
switch in.Kind() {
|
||||
case reflect.Interface:
|
||||
if in.IsNil() {
|
||||
e.nilv()
|
||||
} else {
|
||||
e.marshal(tag, in.Elem())
|
||||
}
|
||||
case reflect.Map:
|
||||
e.mapv(tag, in)
|
||||
case reflect.Ptr:
|
||||
if in.IsNil() {
|
||||
e.nilv()
|
||||
} else {
|
||||
e.marshal(tag, in.Elem())
|
||||
}
|
||||
case reflect.Struct:
|
||||
e.structv(tag, in)
|
||||
case reflect.Slice:
|
||||
if in.Type().Elem() == mapItemType {
|
||||
e.itemsv(tag, in)
|
||||
} else {
|
||||
e.slicev(tag, in)
|
||||
}
|
||||
case reflect.String:
|
||||
e.stringv(tag, in)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if in.Type() == durationType {
|
||||
e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
|
||||
} else {
|
||||
e.intv(tag, in)
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
e.uintv(tag, in)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
e.floatv(tag, in)
|
||||
case reflect.Bool:
|
||||
e.boolv(tag, in)
|
||||
default:
|
||||
panic("cannot marshal type: " + in.Type().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) mapv(tag string, in reflect.Value) {
|
||||
e.mappingv(tag, func() {
|
||||
keys := keyList(in.MapKeys())
|
||||
sort.Sort(keys)
|
||||
for _, k := range keys {
|
||||
e.marshal("", k)
|
||||
e.marshal("", in.MapIndex(k))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *encoder) itemsv(tag string, in reflect.Value) {
|
||||
e.mappingv(tag, func() {
|
||||
slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
|
||||
for _, item := range slice {
|
||||
e.marshal("", reflect.ValueOf(item.Key))
|
||||
e.marshal("", reflect.ValueOf(item.Value))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *encoder) structv(tag string, in reflect.Value) {
|
||||
sinfo, err := getStructInfo(in.Type())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
e.mappingv(tag, func() {
|
||||
for _, info := range sinfo.FieldsList {
|
||||
var value reflect.Value
|
||||
if info.Inline == nil {
|
||||
value = in.Field(info.Num)
|
||||
} else {
|
||||
value = in.FieldByIndex(info.Inline)
|
||||
}
|
||||
if info.OmitEmpty && isZero(value) {
|
||||
continue
|
||||
}
|
||||
e.marshal("", reflect.ValueOf(info.Key))
|
||||
e.flow = info.Flow
|
||||
e.marshal("", value)
|
||||
}
|
||||
if sinfo.InlineMap >= 0 {
|
||||
m := in.Field(sinfo.InlineMap)
|
||||
if m.Len() > 0 {
|
||||
e.flow = false
|
||||
keys := keyList(m.MapKeys())
|
||||
sort.Sort(keys)
|
||||
for _, k := range keys {
|
||||
if _, found := sinfo.FieldsMap[k.String()]; found {
|
||||
panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
|
||||
}
|
||||
e.marshal("", k)
|
||||
e.flow = false
|
||||
e.marshal("", m.MapIndex(k))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (e *encoder) mappingv(tag string, f func()) {
|
||||
implicit := tag == ""
|
||||
style := yaml_BLOCK_MAPPING_STYLE
|
||||
if e.flow {
|
||||
e.flow = false
|
||||
style = yaml_FLOW_MAPPING_STYLE
|
||||
}
|
||||
e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||
e.emit()
|
||||
f()
|
||||
e.must(yaml_mapping_end_event_initialize(&e.event))
|
||||
e.emit()
|
||||
}
|
||||
|
||||
func (e *encoder) slicev(tag string, in reflect.Value) {
|
||||
implicit := tag == ""
|
||||
style := yaml_BLOCK_SEQUENCE_STYLE
|
||||
if e.flow {
|
||||
e.flow = false
|
||||
style = yaml_FLOW_SEQUENCE_STYLE
|
||||
}
|
||||
e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
|
||||
e.emit()
|
||||
n := in.Len()
|
||||
for i := 0; i < n; i++ {
|
||||
e.marshal("", in.Index(i))
|
||||
}
|
||||
e.must(yaml_sequence_end_event_initialize(&e.event))
|
||||
e.emit()
|
||||
}
|
||||
|
||||
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
|
||||
//
|
||||
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
|
||||
// in YAML 1.2 and by this package, but these should be marshalled quoted for
|
||||
// the time being for compatibility with other parsers.
|
||||
func isBase60Float(s string) (result bool) {
|
||||
// Fast path.
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
c := s[0]
|
||||
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
|
||||
return false
|
||||
}
|
||||
// Do the full match.
|
||||
return base60float.MatchString(s)
|
||||
}
|
||||
|
||||
// From http://yaml.org/type/float.html, except the regular expression there
|
||||
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
|
||||
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
|
||||
|
||||
func (e *encoder) stringv(tag string, in reflect.Value) {
|
||||
var style yaml_scalar_style_t
|
||||
s := in.String()
|
||||
rtag, rs := resolve("", s)
|
||||
if rtag == yaml_BINARY_TAG {
|
||||
if tag == "" || tag == yaml_STR_TAG {
|
||||
tag = rtag
|
||||
s = rs.(string)
|
||||
} else if tag == yaml_BINARY_TAG {
|
||||
failf("explicitly tagged !!binary data must be base64-encoded")
|
||||
} else {
|
||||
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
|
||||
}
|
||||
}
|
||||
if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) {
|
||||
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
|
||||
} else if strings.Contains(s, "\n") {
|
||||
style = yaml_LITERAL_SCALAR_STYLE
|
||||
} else {
|
||||
style = yaml_PLAIN_SCALAR_STYLE
|
||||
}
|
||||
e.emitScalar(s, "", tag, style)
|
||||
}
|
||||
|
||||
func (e *encoder) boolv(tag string, in reflect.Value) {
|
||||
var s string
|
||||
if in.Bool() {
|
||||
s = "true"
|
||||
} else {
|
||||
s = "false"
|
||||
}
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) intv(tag string, in reflect.Value) {
|
||||
s := strconv.FormatInt(in.Int(), 10)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) uintv(tag string, in reflect.Value) {
|
||||
s := strconv.FormatUint(in.Uint(), 10)
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) floatv(tag string, in reflect.Value) {
|
||||
// FIXME: Handle 64 bits here.
|
||||
s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32)
|
||||
switch s {
|
||||
case "+Inf":
|
||||
s = ".inf"
|
||||
case "-Inf":
|
||||
s = "-.inf"
|
||||
case "NaN":
|
||||
s = ".nan"
|
||||
}
|
||||
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) nilv() {
|
||||
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
|
||||
}
|
||||
|
||||
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
|
||||
implicit := tag == ""
|
||||
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
|
||||
e.emit()
|
||||
}
|
||||
501
vendor/gopkg.in/yaml.v2/encode_test.go
generated
vendored
Normal file
501
vendor/gopkg.in/yaml.v2/encode_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1096
vendor/gopkg.in/yaml.v2/parserc.go
generated
vendored
Normal file
1096
vendor/gopkg.in/yaml.v2/parserc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
394
vendor/gopkg.in/yaml.v2/readerc.go
generated
vendored
Normal file
394
vendor/gopkg.in/yaml.v2/readerc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Set the reader error and return 0.
|
||||
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
|
||||
parser.error = yaml_READER_ERROR
|
||||
parser.problem = problem
|
||||
parser.problem_offset = offset
|
||||
parser.problem_value = value
|
||||
return false
|
||||
}
|
||||
|
||||
// Byte order marks.
|
||||
const (
|
||||
bom_UTF8 = "\xef\xbb\xbf"
|
||||
bom_UTF16LE = "\xff\xfe"
|
||||
bom_UTF16BE = "\xfe\xff"
|
||||
)
|
||||
|
||||
// Determine the input stream encoding by checking the BOM symbol. If no BOM is
|
||||
// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
|
||||
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
|
||||
// Ensure that we had enough bytes in the raw buffer.
|
||||
for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
|
||||
if !yaml_parser_update_raw_buffer(parser) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the encoding.
|
||||
buf := parser.raw_buffer
|
||||
pos := parser.raw_buffer_pos
|
||||
avail := len(buf) - pos
|
||||
if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
|
||||
parser.encoding = yaml_UTF16LE_ENCODING
|
||||
parser.raw_buffer_pos += 2
|
||||
parser.offset += 2
|
||||
} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
|
||||
parser.encoding = yaml_UTF16BE_ENCODING
|
||||
parser.raw_buffer_pos += 2
|
||||
parser.offset += 2
|
||||
} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
|
||||
parser.encoding = yaml_UTF8_ENCODING
|
||||
parser.raw_buffer_pos += 3
|
||||
parser.offset += 3
|
||||
} else {
|
||||
parser.encoding = yaml_UTF8_ENCODING
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Update the raw buffer.
|
||||
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
|
||||
size_read := 0
|
||||
|
||||
// Return if the raw buffer is full.
|
||||
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Return on EOF.
|
||||
if parser.eof {
|
||||
return true
|
||||
}
|
||||
|
||||
// Move the remaining bytes in the raw buffer to the beginning.
|
||||
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
|
||||
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
|
||||
}
|
||||
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
|
||||
parser.raw_buffer_pos = 0
|
||||
|
||||
// Call the read handler to fill the buffer.
|
||||
size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
|
||||
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
|
||||
if err == io.EOF {
|
||||
parser.eof = true
|
||||
} else if err != nil {
|
||||
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Ensure that the buffer contains at least `length` characters.
|
||||
// Return true on success, false on failure.
|
||||
//
|
||||
// The length is supposed to be significantly less that the buffer size.
|
||||
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
|
||||
if parser.read_handler == nil {
|
||||
panic("read handler must be set")
|
||||
}
|
||||
|
||||
// If the EOF flag is set and the raw buffer is empty, do nothing.
|
||||
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Return if the buffer contains enough characters.
|
||||
if parser.unread >= length {
|
||||
return true
|
||||
}
|
||||
|
||||
// Determine the input encoding if it is not known yet.
|
||||
if parser.encoding == yaml_ANY_ENCODING {
|
||||
if !yaml_parser_determine_encoding(parser) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Move the unread characters to the beginning of the buffer.
|
||||
buffer_len := len(parser.buffer)
|
||||
if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
|
||||
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
|
||||
buffer_len -= parser.buffer_pos
|
||||
parser.buffer_pos = 0
|
||||
} else if parser.buffer_pos == buffer_len {
|
||||
buffer_len = 0
|
||||
parser.buffer_pos = 0
|
||||
}
|
||||
|
||||
// Open the whole buffer for writing, and cut it before returning.
|
||||
parser.buffer = parser.buffer[:cap(parser.buffer)]
|
||||
|
||||
// Fill the buffer until it has enough characters.
|
||||
first := true
|
||||
for parser.unread < length {
|
||||
|
||||
// Fill the raw buffer if necessary.
|
||||
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
|
||||
if !yaml_parser_update_raw_buffer(parser) {
|
||||
parser.buffer = parser.buffer[:buffer_len]
|
||||
return false
|
||||
}
|
||||
}
|
||||
first = false
|
||||
|
||||
// Decode the raw buffer.
|
||||
inner:
|
||||
for parser.raw_buffer_pos != len(parser.raw_buffer) {
|
||||
var value rune
|
||||
var width int
|
||||
|
||||
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
|
||||
|
||||
// Decode the next character.
|
||||
switch parser.encoding {
|
||||
case yaml_UTF8_ENCODING:
|
||||
// Decode a UTF-8 character. Check RFC 3629
|
||||
// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
|
||||
//
|
||||
// The following table (taken from the RFC) is used for
|
||||
// decoding.
|
||||
//
|
||||
// Char. number range | UTF-8 octet sequence
|
||||
// (hexadecimal) | (binary)
|
||||
// --------------------+------------------------------------
|
||||
// 0000 0000-0000 007F | 0xxxxxxx
|
||||
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
||||
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
||||
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
//
|
||||
// Additionally, the characters in the range 0xD800-0xDFFF
|
||||
// are prohibited as they are reserved for use with UTF-16
|
||||
// surrogate pairs.
|
||||
|
||||
// Determine the length of the UTF-8 sequence.
|
||||
octet := parser.raw_buffer[parser.raw_buffer_pos]
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
width = 1
|
||||
case octet&0xE0 == 0xC0:
|
||||
width = 2
|
||||
case octet&0xF0 == 0xE0:
|
||||
width = 3
|
||||
case octet&0xF8 == 0xF0:
|
||||
width = 4
|
||||
default:
|
||||
// The leading octet is invalid.
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid leading UTF-8 octet",
|
||||
parser.offset, int(octet))
|
||||
}
|
||||
|
||||
// Check if the raw buffer contains an incomplete character.
|
||||
if width > raw_unread {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-8 octet sequence",
|
||||
parser.offset, -1)
|
||||
}
|
||||
break inner
|
||||
}
|
||||
|
||||
// Decode the leading octet.
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
value = rune(octet & 0x7F)
|
||||
case octet&0xE0 == 0xC0:
|
||||
value = rune(octet & 0x1F)
|
||||
case octet&0xF0 == 0xE0:
|
||||
value = rune(octet & 0x0F)
|
||||
case octet&0xF8 == 0xF0:
|
||||
value = rune(octet & 0x07)
|
||||
default:
|
||||
value = 0
|
||||
}
|
||||
|
||||
// Check and decode the trailing octets.
|
||||
for k := 1; k < width; k++ {
|
||||
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
|
||||
|
||||
// Check if the octet is valid.
|
||||
if (octet & 0xC0) != 0x80 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid trailing UTF-8 octet",
|
||||
parser.offset+k, int(octet))
|
||||
}
|
||||
|
||||
// Decode the octet.
|
||||
value = (value << 6) + rune(octet&0x3F)
|
||||
}
|
||||
|
||||
// Check the length of the sequence against the value.
|
||||
switch {
|
||||
case width == 1:
|
||||
case width == 2 && value >= 0x80:
|
||||
case width == 3 && value >= 0x800:
|
||||
case width == 4 && value >= 0x10000:
|
||||
default:
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid length of a UTF-8 sequence",
|
||||
parser.offset, -1)
|
||||
}
|
||||
|
||||
// Check the range of the value.
|
||||
if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"invalid Unicode character",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
|
||||
var low, high int
|
||||
if parser.encoding == yaml_UTF16LE_ENCODING {
|
||||
low, high = 0, 1
|
||||
} else {
|
||||
low, high = 1, 0
|
||||
}
|
||||
|
||||
// The UTF-16 encoding is not as simple as one might
|
||||
// naively think. Check RFC 2781
|
||||
// (http://www.ietf.org/rfc/rfc2781.txt).
|
||||
//
|
||||
// Normally, two subsequent bytes describe a Unicode
|
||||
// character. However a special technique (called a
|
||||
// surrogate pair) is used for specifying character
|
||||
// values larger than 0xFFFF.
|
||||
//
|
||||
// A surrogate pair consists of two pseudo-characters:
|
||||
// high surrogate area (0xD800-0xDBFF)
|
||||
// low surrogate area (0xDC00-0xDFFF)
|
||||
//
|
||||
// The following formulas are used for decoding
|
||||
// and encoding characters using surrogate pairs:
|
||||
//
|
||||
// U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
|
||||
// U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
|
||||
// W1 = 110110yyyyyyyyyy
|
||||
// W2 = 110111xxxxxxxxxx
|
||||
//
|
||||
// where U is the character value, W1 is the high surrogate
|
||||
// area, W2 is the low surrogate area.
|
||||
|
||||
// Check for incomplete UTF-16 character.
|
||||
if raw_unread < 2 {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-16 character",
|
||||
parser.offset, -1)
|
||||
}
|
||||
break inner
|
||||
}
|
||||
|
||||
// Get the character.
|
||||
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
|
||||
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
|
||||
|
||||
// Check for unexpected low surrogate area.
|
||||
if value&0xFC00 == 0xDC00 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"unexpected low surrogate area",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
// Check for a high surrogate area.
|
||||
if value&0xFC00 == 0xD800 {
|
||||
width = 4
|
||||
|
||||
// Check for incomplete surrogate pair.
|
||||
if raw_unread < 4 {
|
||||
if parser.eof {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"incomplete UTF-16 surrogate pair",
|
||||
parser.offset, -1)
|
||||
}
|
||||
break inner
|
||||
}
|
||||
|
||||
// Get the next character.
|
||||
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
|
||||
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
|
||||
|
||||
// Check for a low surrogate area.
|
||||
if value2&0xFC00 != 0xDC00 {
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"expected low surrogate area",
|
||||
parser.offset+2, int(value2))
|
||||
}
|
||||
|
||||
// Generate the value of the surrogate pair.
|
||||
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
|
||||
} else {
|
||||
width = 2
|
||||
}
|
||||
|
||||
default:
|
||||
panic("impossible")
|
||||
}
|
||||
|
||||
// Check if the character is in the allowed range:
|
||||
// #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
|
||||
// | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
|
||||
// | [#x10000-#x10FFFF] (32 bit)
|
||||
switch {
|
||||
case value == 0x09:
|
||||
case value == 0x0A:
|
||||
case value == 0x0D:
|
||||
case value >= 0x20 && value <= 0x7E:
|
||||
case value == 0x85:
|
||||
case value >= 0xA0 && value <= 0xD7FF:
|
||||
case value >= 0xE000 && value <= 0xFFFD:
|
||||
case value >= 0x10000 && value <= 0x10FFFF:
|
||||
default:
|
||||
return yaml_parser_set_reader_error(parser,
|
||||
"control characters are not allowed",
|
||||
parser.offset, int(value))
|
||||
}
|
||||
|
||||
// Move the raw pointers.
|
||||
parser.raw_buffer_pos += width
|
||||
parser.offset += width
|
||||
|
||||
// Finally put the character into the buffer.
|
||||
if value <= 0x7F {
|
||||
// 0000 0000-0000 007F . 0xxxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(value)
|
||||
buffer_len += 1
|
||||
} else if value <= 0x7FF {
|
||||
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
|
||||
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
|
||||
buffer_len += 2
|
||||
} else if value <= 0xFFFF {
|
||||
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
|
||||
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
|
||||
buffer_len += 3
|
||||
} else {
|
||||
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
|
||||
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
|
||||
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
|
||||
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
|
||||
buffer_len += 4
|
||||
}
|
||||
|
||||
parser.unread++
|
||||
}
|
||||
|
||||
// On EOF, put NUL into the buffer and return.
|
||||
if parser.eof {
|
||||
parser.buffer[buffer_len] = 0
|
||||
buffer_len++
|
||||
parser.unread++
|
||||
break
|
||||
}
|
||||
}
|
||||
parser.buffer = parser.buffer[:buffer_len]
|
||||
return true
|
||||
}
|
||||
203
vendor/gopkg.in/yaml.v2/resolve.go
generated
vendored
Normal file
203
vendor/gopkg.in/yaml.v2/resolve.go
generated
vendored
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type resolveMapItem struct {
|
||||
value interface{}
|
||||
tag string
|
||||
}
|
||||
|
||||
var resolveTable = make([]byte, 256)
|
||||
var resolveMap = make(map[string]resolveMapItem)
|
||||
|
||||
func init() {
|
||||
t := resolveTable
|
||||
t[int('+')] = 'S' // Sign
|
||||
t[int('-')] = 'S'
|
||||
for _, c := range "0123456789" {
|
||||
t[int(c)] = 'D' // Digit
|
||||
}
|
||||
for _, c := range "yYnNtTfFoO~" {
|
||||
t[int(c)] = 'M' // In map
|
||||
}
|
||||
t[int('.')] = '.' // Float (potentially in map)
|
||||
|
||||
var resolveMapList = []struct {
|
||||
v interface{}
|
||||
tag string
|
||||
l []string
|
||||
}{
|
||||
{true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
|
||||
{true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
|
||||
{true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
|
||||
{false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
|
||||
{false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
|
||||
{false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
|
||||
{nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
|
||||
{math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
|
||||
{math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
|
||||
{math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
|
||||
{math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
|
||||
{"<<", yaml_MERGE_TAG, []string{"<<"}},
|
||||
}
|
||||
|
||||
m := resolveMap
|
||||
for _, item := range resolveMapList {
|
||||
for _, s := range item.l {
|
||||
m[s] = resolveMapItem{item.v, item.tag}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const longTagPrefix = "tag:yaml.org,2002:"
|
||||
|
||||
func shortTag(tag string) string {
|
||||
// TODO This can easily be made faster and produce less garbage.
|
||||
if strings.HasPrefix(tag, longTagPrefix) {
|
||||
return "!!" + tag[len(longTagPrefix):]
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func longTag(tag string) string {
|
||||
if strings.HasPrefix(tag, "!!") {
|
||||
return longTagPrefix + tag[2:]
|
||||
}
|
||||
return tag
|
||||
}
|
||||
|
||||
func resolvableTag(tag string) bool {
|
||||
switch tag {
|
||||
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func resolve(tag string, in string) (rtag string, out interface{}) {
|
||||
if !resolvableTag(tag) {
|
||||
return tag, in
|
||||
}
|
||||
|
||||
defer func() {
|
||||
switch tag {
|
||||
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
|
||||
return
|
||||
}
|
||||
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
|
||||
}()
|
||||
|
||||
// Any data is accepted as a !!str or !!binary.
|
||||
// Otherwise, the prefix is enough of a hint about what it might be.
|
||||
hint := byte('N')
|
||||
if in != "" {
|
||||
hint = resolveTable[in[0]]
|
||||
}
|
||||
if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
|
||||
// Handle things we can lookup in a map.
|
||||
if item, ok := resolveMap[in]; ok {
|
||||
return item.tag, item.value
|
||||
}
|
||||
|
||||
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
|
||||
// are purposefully unsupported here. They're still quoted on
|
||||
// the way out for compatibility with other parser, though.
|
||||
|
||||
switch hint {
|
||||
case 'M':
|
||||
// We've already checked the map above.
|
||||
|
||||
case '.':
|
||||
// Not in the map, so maybe a normal float.
|
||||
floatv, err := strconv.ParseFloat(in, 64)
|
||||
if err == nil {
|
||||
return yaml_FLOAT_TAG, floatv
|
||||
}
|
||||
|
||||
case 'D', 'S':
|
||||
// Int, float, or timestamp.
|
||||
plain := strings.Replace(in, "_", "", -1)
|
||||
intv, err := strconv.ParseInt(plain, 0, 64)
|
||||
if err == nil {
|
||||
if intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, intv
|
||||
}
|
||||
}
|
||||
uintv, err := strconv.ParseUint(plain, 0, 64)
|
||||
if err == nil {
|
||||
return yaml_INT_TAG, uintv
|
||||
}
|
||||
floatv, err := strconv.ParseFloat(plain, 64)
|
||||
if err == nil {
|
||||
return yaml_FLOAT_TAG, floatv
|
||||
}
|
||||
if strings.HasPrefix(plain, "0b") {
|
||||
intv, err := strconv.ParseInt(plain[2:], 2, 64)
|
||||
if err == nil {
|
||||
if intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, intv
|
||||
}
|
||||
}
|
||||
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
|
||||
if err == nil {
|
||||
return yaml_INT_TAG, uintv
|
||||
}
|
||||
} else if strings.HasPrefix(plain, "-0b") {
|
||||
intv, err := strconv.ParseInt(plain[3:], 2, 64)
|
||||
if err == nil {
|
||||
if intv == int64(int(intv)) {
|
||||
return yaml_INT_TAG, -int(intv)
|
||||
} else {
|
||||
return yaml_INT_TAG, -intv
|
||||
}
|
||||
}
|
||||
}
|
||||
// XXX Handle timestamps here.
|
||||
|
||||
default:
|
||||
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
|
||||
}
|
||||
}
|
||||
if tag == yaml_BINARY_TAG {
|
||||
return yaml_BINARY_TAG, in
|
||||
}
|
||||
if utf8.ValidString(in) {
|
||||
return yaml_STR_TAG, in
|
||||
}
|
||||
return yaml_BINARY_TAG, encodeBase64(in)
|
||||
}
|
||||
|
||||
// encodeBase64 encodes s as base64 that is broken up into multiple lines
|
||||
// as appropriate for the resulting length.
|
||||
func encodeBase64(s string) string {
|
||||
const lineLen = 70
|
||||
encLen := base64.StdEncoding.EncodedLen(len(s))
|
||||
lines := encLen/lineLen + 1
|
||||
buf := make([]byte, encLen*2+lines)
|
||||
in := buf[0:encLen]
|
||||
out := buf[encLen:]
|
||||
base64.StdEncoding.Encode(in, []byte(s))
|
||||
k := 0
|
||||
for i := 0; i < len(in); i += lineLen {
|
||||
j := i + lineLen
|
||||
if j > len(in) {
|
||||
j = len(in)
|
||||
}
|
||||
k += copy(out[k:], in[i:j])
|
||||
if lines > 1 {
|
||||
out[k] = '\n'
|
||||
k++
|
||||
}
|
||||
}
|
||||
return string(out[:k])
|
||||
}
|
||||
2710
vendor/gopkg.in/yaml.v2/scannerc.go
generated
vendored
Normal file
2710
vendor/gopkg.in/yaml.v2/scannerc.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
104
vendor/gopkg.in/yaml.v2/sorter.go
generated
vendored
Normal file
104
vendor/gopkg.in/yaml.v2/sorter.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package yaml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type keyList []reflect.Value
|
||||
|
||||
func (l keyList) Len() int { return len(l) }
|
||||
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
func (l keyList) Less(i, j int) bool {
|
||||
a := l[i]
|
||||
b := l[j]
|
||||
ak := a.Kind()
|
||||
bk := b.Kind()
|
||||
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
|
||||
a = a.Elem()
|
||||
ak = a.Kind()
|
||||
}
|
||||
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
|
||||
b = b.Elem()
|
||||
bk = b.Kind()
|
||||
}
|
||||
af, aok := keyFloat(a)
|
||||
bf, bok := keyFloat(b)
|
||||
if aok && bok {
|
||||
if af != bf {
|
||||
return af < bf
|
||||
}
|
||||
if ak != bk {
|
||||
return ak < bk
|
||||
}
|
||||
return numLess(a, b)
|
||||
}
|
||||
if ak != reflect.String || bk != reflect.String {
|
||||
return ak < bk
|
||||
}
|
||||
ar, br := []rune(a.String()), []rune(b.String())
|
||||
for i := 0; i < len(ar) && i < len(br); i++ {
|
||||
if ar[i] == br[i] {
|
||||
continue
|
||||
}
|
||||
al := unicode.IsLetter(ar[i])
|
||||
bl := unicode.IsLetter(br[i])
|
||||
if al && bl {
|
||||
return ar[i] < br[i]
|
||||
}
|
||||
if al || bl {
|
||||
return bl
|
||||
}
|
||||
var ai, bi int
|
||||
var an, bn int64
|
||||
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
|
||||
an = an*10 + int64(ar[ai]-'0')
|
||||
}
|
||||
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
|
||||
bn = bn*10 + int64(br[bi]-'0')
|
||||
}
|
||||
if an != bn {
|
||||
return an < bn
|
||||
}
|
||||
if ai != bi {
|
||||
return ai < bi
|
||||
}
|
||||
return ar[i] < br[i]
|
||||
}
|
||||
return len(ar) < len(br)
|
||||
}
|
||||
|
||||
// keyFloat returns a float value for v if it is a number/bool
|
||||
// and whether it is a number/bool or not.
|
||||
func keyFloat(v reflect.Value) (f float64, ok bool) {
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return float64(v.Int()), true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float(), true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return float64(v.Uint()), true
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
return 1, true
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// numLess returns whether a < b.
|
||||
// a and b must necessarily have the same kind.
|
||||
func numLess(a, b reflect.Value) bool {
|
||||
switch a.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return a.Int() < b.Int()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return a.Float() < b.Float()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return a.Uint() < b.Uint()
|
||||
case reflect.Bool:
|
||||
return !a.Bool() && b.Bool()
|
||||
}
|
||||
panic("not a number")
|
||||
}
|
||||
12
vendor/gopkg.in/yaml.v2/suite_test.go
generated
vendored
Normal file
12
vendor/gopkg.in/yaml.v2/suite_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package yaml_test
|
||||
|
||||
import (
|
||||
. "gopkg.in/check.v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) { TestingT(t) }
|
||||
|
||||
type S struct{}
|
||||
|
||||
var _ = Suite(&S{})
|
||||
89
vendor/gopkg.in/yaml.v2/writerc.go
generated
vendored
Normal file
89
vendor/gopkg.in/yaml.v2/writerc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package yaml
|
||||
|
||||
// Set the writer error and return false.
|
||||
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
|
||||
emitter.error = yaml_WRITER_ERROR
|
||||
emitter.problem = problem
|
||||
return false
|
||||
}
|
||||
|
||||
// Flush the output buffer.
|
||||
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
|
||||
if emitter.write_handler == nil {
|
||||
panic("write handler not set")
|
||||
}
|
||||
|
||||
// Check if the buffer is empty.
|
||||
if emitter.buffer_pos == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
// If the output encoding is UTF-8, we don't need to recode the buffer.
|
||||
if emitter.encoding == yaml_UTF8_ENCODING {
|
||||
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
|
||||
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||
}
|
||||
emitter.buffer_pos = 0
|
||||
return true
|
||||
}
|
||||
|
||||
// Recode the buffer into the raw buffer.
|
||||
var low, high int
|
||||
if emitter.encoding == yaml_UTF16LE_ENCODING {
|
||||
low, high = 0, 1
|
||||
} else {
|
||||
high, low = 1, 0
|
||||
}
|
||||
|
||||
pos := 0
|
||||
for pos < emitter.buffer_pos {
|
||||
// See the "reader.c" code for more details on UTF-8 encoding. Note
|
||||
// that we assume that the buffer contains a valid UTF-8 sequence.
|
||||
|
||||
// Read the next UTF-8 character.
|
||||
octet := emitter.buffer[pos]
|
||||
|
||||
var w int
|
||||
var value rune
|
||||
switch {
|
||||
case octet&0x80 == 0x00:
|
||||
w, value = 1, rune(octet&0x7F)
|
||||
case octet&0xE0 == 0xC0:
|
||||
w, value = 2, rune(octet&0x1F)
|
||||
case octet&0xF0 == 0xE0:
|
||||
w, value = 3, rune(octet&0x0F)
|
||||
case octet&0xF8 == 0xF0:
|
||||
w, value = 4, rune(octet&0x07)
|
||||
}
|
||||
for k := 1; k < w; k++ {
|
||||
octet = emitter.buffer[pos+k]
|
||||
value = (value << 6) + (rune(octet) & 0x3F)
|
||||
}
|
||||
pos += w
|
||||
|
||||
// Write the character.
|
||||
if value < 0x10000 {
|
||||
var b [2]byte
|
||||
b[high] = byte(value >> 8)
|
||||
b[low] = byte(value & 0xFF)
|
||||
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1])
|
||||
} else {
|
||||
// Write the character using a surrogate pair (check "reader.c").
|
||||
var b [4]byte
|
||||
value -= 0x10000
|
||||
b[high] = byte(0xD8 + (value >> 18))
|
||||
b[low] = byte((value >> 10) & 0xFF)
|
||||
b[high+2] = byte(0xDC + ((value >> 8) & 0xFF))
|
||||
b[low+2] = byte(value & 0xFF)
|
||||
emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3])
|
||||
}
|
||||
}
|
||||
|
||||
// Write the raw buffer.
|
||||
if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil {
|
||||
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
|
||||
}
|
||||
emitter.buffer_pos = 0
|
||||
emitter.raw_buffer = emitter.raw_buffer[:0]
|
||||
return true
|
||||
}
|
||||
346
vendor/gopkg.in/yaml.v2/yaml.go
generated
vendored
Normal file
346
vendor/gopkg.in/yaml.v2/yaml.go
generated
vendored
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
// Package yaml implements YAML support for the Go language.
|
||||
//
|
||||
// Source code and other details for the project are available at GitHub:
|
||||
//
|
||||
// https://github.com/go-yaml/yaml
|
||||
//
|
||||
package yaml
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// MapSlice encodes and decodes as a YAML map.
|
||||
// The order of keys is preserved when encoding and decoding.
|
||||
type MapSlice []MapItem
|
||||
|
||||
// MapItem is an item in a MapSlice.
|
||||
type MapItem struct {
|
||||
Key, Value interface{}
|
||||
}
|
||||
|
||||
// The Unmarshaler interface may be implemented by types to customize their
|
||||
// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
|
||||
// method receives a function that may be called to unmarshal the original
|
||||
// YAML value into a field or variable. It is safe to call the unmarshal
|
||||
// function parameter more than once if necessary.
|
||||
type Unmarshaler interface {
|
||||
UnmarshalYAML(unmarshal func(interface{}) error) error
|
||||
}
|
||||
|
||||
// The Marshaler interface may be implemented by types to customize their
|
||||
// behavior when being marshaled into a YAML document. The returned value
|
||||
// is marshaled in place of the original value implementing Marshaler.
|
||||
//
|
||||
// If an error is returned by MarshalYAML, the marshaling procedure stops
|
||||
// and returns with the provided error.
|
||||
type Marshaler interface {
|
||||
MarshalYAML() (interface{}, error)
|
||||
}
|
||||
|
||||
// Unmarshal decodes the first document found within the in byte slice
|
||||
// and assigns decoded values into the out value.
|
||||
//
|
||||
// Maps and pointers (to a struct, string, int, etc) are accepted as out
|
||||
// values. If an internal pointer within a struct is not initialized,
|
||||
// the yaml package will initialize it if necessary for unmarshalling
|
||||
// the provided data. The out parameter must not be nil.
|
||||
//
|
||||
// The type of the decoded values should be compatible with the respective
|
||||
// values in out. If one or more values cannot be decoded due to a type
|
||||
// mismatches, decoding continues partially until the end of the YAML
|
||||
// content, and a *yaml.TypeError is returned with details for all
|
||||
// missed values.
|
||||
//
|
||||
// Struct fields are only unmarshalled if they are exported (have an
|
||||
// upper case first letter), and are unmarshalled using the field name
|
||||
// lowercased as the default key. Custom keys may be defined via the
|
||||
// "yaml" name in the field tag: the content preceding the first comma
|
||||
// is used as the key, and the following comma-separated options are
|
||||
// used to tweak the marshalling process (see Marshal).
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// type T struct {
|
||||
// F int `yaml:"a,omitempty"`
|
||||
// B int
|
||||
// }
|
||||
// var t T
|
||||
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
|
||||
//
|
||||
// See the documentation of Marshal for the format of tags and a list of
|
||||
// supported tag options.
|
||||
//
|
||||
func Unmarshal(in []byte, out interface{}) (err error) {
|
||||
defer handleErr(&err)
|
||||
d := newDecoder()
|
||||
p := newParser(in)
|
||||
defer p.destroy()
|
||||
node := p.parse()
|
||||
if node != nil {
|
||||
v := reflect.ValueOf(out)
|
||||
if v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||
v = v.Elem()
|
||||
}
|
||||
d.unmarshal(node, v)
|
||||
}
|
||||
if len(d.terrors) > 0 {
|
||||
return &TypeError{d.terrors}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal serializes the value provided into a YAML document. The structure
|
||||
// of the generated document will reflect the structure of the value itself.
|
||||
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
|
||||
//
|
||||
// Struct fields are only unmarshalled if they are exported (have an upper case
|
||||
// first letter), and are unmarshalled using the field name lowercased as the
|
||||
// default key. Custom keys may be defined via the "yaml" name in the field
|
||||
// tag: the content preceding the first comma is used as the key, and the
|
||||
// following comma-separated options are used to tweak the marshalling process.
|
||||
// Conflicting names result in a runtime error.
|
||||
//
|
||||
// The field tag format accepted is:
|
||||
//
|
||||
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
|
||||
//
|
||||
// The following flags are currently supported:
|
||||
//
|
||||
// omitempty Only include the field if it's not set to the zero
|
||||
// value for the type or to empty slices or maps.
|
||||
// Does not apply to zero valued structs.
|
||||
//
|
||||
// flow Marshal using a flow style (useful for structs,
|
||||
// sequences and maps).
|
||||
//
|
||||
// inline Inline the field, which must be a struct or a map,
|
||||
// causing all of its fields or keys to be processed as if
|
||||
// they were part of the outer struct. For maps, keys must
|
||||
// not conflict with the yaml keys of other struct fields.
|
||||
//
|
||||
// In addition, if the key is "-", the field is ignored.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// type T struct {
|
||||
// F int "a,omitempty"
|
||||
// B int
|
||||
// }
|
||||
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
|
||||
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
|
||||
//
|
||||
func Marshal(in interface{}) (out []byte, err error) {
|
||||
defer handleErr(&err)
|
||||
e := newEncoder()
|
||||
defer e.destroy()
|
||||
e.marshal("", reflect.ValueOf(in))
|
||||
e.finish()
|
||||
out = e.out
|
||||
return
|
||||
}
|
||||
|
||||
func handleErr(err *error) {
|
||||
if v := recover(); v != nil {
|
||||
if e, ok := v.(yamlError); ok {
|
||||
*err = e.err
|
||||
} else {
|
||||
panic(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type yamlError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func fail(err error) {
|
||||
panic(yamlError{err})
|
||||
}
|
||||
|
||||
func failf(format string, args ...interface{}) {
|
||||
panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
|
||||
}
|
||||
|
||||
// A TypeError is returned by Unmarshal when one or more fields in
|
||||
// the YAML document cannot be properly decoded into the requested
|
||||
// types. When this error is returned, the value is still
|
||||
// unmarshaled partially.
|
||||
type TypeError struct {
|
||||
Errors []string
|
||||
}
|
||||
|
||||
func (e *TypeError) Error() string {
|
||||
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Maintain a mapping of keys to structure field indexes
|
||||
|
||||
// The code in this section was copied from mgo/bson.
|
||||
|
||||
// structInfo holds details for the serialization of fields of
|
||||
// a given struct.
|
||||
type structInfo struct {
|
||||
FieldsMap map[string]fieldInfo
|
||||
FieldsList []fieldInfo
|
||||
|
||||
// InlineMap is the number of the field in the struct that
|
||||
// contains an ,inline map, or -1 if there's none.
|
||||
InlineMap int
|
||||
}
|
||||
|
||||
type fieldInfo struct {
|
||||
Key string
|
||||
Num int
|
||||
OmitEmpty bool
|
||||
Flow bool
|
||||
|
||||
// Inline holds the field index if the field is part of an inlined struct.
|
||||
Inline []int
|
||||
}
|
||||
|
||||
var structMap = make(map[reflect.Type]*structInfo)
|
||||
var fieldMapMutex sync.RWMutex
|
||||
|
||||
func getStructInfo(st reflect.Type) (*structInfo, error) {
|
||||
fieldMapMutex.RLock()
|
||||
sinfo, found := structMap[st]
|
||||
fieldMapMutex.RUnlock()
|
||||
if found {
|
||||
return sinfo, nil
|
||||
}
|
||||
|
||||
n := st.NumField()
|
||||
fieldsMap := make(map[string]fieldInfo)
|
||||
fieldsList := make([]fieldInfo, 0, n)
|
||||
inlineMap := -1
|
||||
for i := 0; i != n; i++ {
|
||||
field := st.Field(i)
|
||||
if field.PkgPath != "" {
|
||||
continue // Private field
|
||||
}
|
||||
|
||||
info := fieldInfo{Num: i}
|
||||
|
||||
tag := field.Tag.Get("yaml")
|
||||
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
|
||||
tag = string(field.Tag)
|
||||
}
|
||||
if tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
inline := false
|
||||
fields := strings.Split(tag, ",")
|
||||
if len(fields) > 1 {
|
||||
for _, flag := range fields[1:] {
|
||||
switch flag {
|
||||
case "omitempty":
|
||||
info.OmitEmpty = true
|
||||
case "flow":
|
||||
info.Flow = true
|
||||
case "inline":
|
||||
inline = true
|
||||
default:
|
||||
return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
|
||||
}
|
||||
}
|
||||
tag = fields[0]
|
||||
}
|
||||
|
||||
if inline {
|
||||
switch field.Type.Kind() {
|
||||
case reflect.Map:
|
||||
if inlineMap >= 0 {
|
||||
return nil, errors.New("Multiple ,inline maps in struct " + st.String())
|
||||
}
|
||||
if field.Type.Key() != reflect.TypeOf("") {
|
||||
return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
|
||||
}
|
||||
inlineMap = info.Num
|
||||
case reflect.Struct:
|
||||
sinfo, err := getStructInfo(field.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, finfo := range sinfo.FieldsList {
|
||||
if _, found := fieldsMap[finfo.Key]; found {
|
||||
msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
if finfo.Inline == nil {
|
||||
finfo.Inline = []int{i, finfo.Num}
|
||||
} else {
|
||||
finfo.Inline = append([]int{i}, finfo.Inline...)
|
||||
}
|
||||
fieldsMap[finfo.Key] = finfo
|
||||
fieldsList = append(fieldsList, finfo)
|
||||
}
|
||||
default:
|
||||
//return nil, errors.New("Option ,inline needs a struct value or map field")
|
||||
return nil, errors.New("Option ,inline needs a struct value field")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if tag != "" {
|
||||
info.Key = tag
|
||||
} else {
|
||||
info.Key = strings.ToLower(field.Name)
|
||||
}
|
||||
|
||||
if _, found = fieldsMap[info.Key]; found {
|
||||
msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
|
||||
return nil, errors.New(msg)
|
||||
}
|
||||
|
||||
fieldsList = append(fieldsList, info)
|
||||
fieldsMap[info.Key] = info
|
||||
}
|
||||
|
||||
sinfo = &structInfo{fieldsMap, fieldsList, inlineMap}
|
||||
|
||||
fieldMapMutex.Lock()
|
||||
structMap[st] = sinfo
|
||||
fieldMapMutex.Unlock()
|
||||
return sinfo, nil
|
||||
}
|
||||
|
||||
func isZero(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
return len(v.String()) == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
case reflect.Slice:
|
||||
return v.Len() == 0
|
||||
case reflect.Map:
|
||||
return v.Len() == 0
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Struct:
|
||||
vt := v.Type()
|
||||
for i := v.NumField() - 1; i >= 0; i-- {
|
||||
if vt.Field(i).PkgPath != "" {
|
||||
continue // Private field
|
||||
}
|
||||
if !isZero(v.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
716
vendor/gopkg.in/yaml.v2/yamlh.go
generated
vendored
Normal file
716
vendor/gopkg.in/yaml.v2/yamlh.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
173
vendor/gopkg.in/yaml.v2/yamlprivateh.go
generated
vendored
Normal file
173
vendor/gopkg.in/yaml.v2/yamlprivateh.go
generated
vendored
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package yaml
|
||||
|
||||
const (
|
||||
// The size of the input raw buffer.
|
||||
input_raw_buffer_size = 512
|
||||
|
||||
// The size of the input buffer.
|
||||
// It should be possible to decode the whole raw buffer.
|
||||
input_buffer_size = input_raw_buffer_size * 3
|
||||
|
||||
// The size of the output buffer.
|
||||
output_buffer_size = 128
|
||||
|
||||
// The size of the output raw buffer.
|
||||
// It should be possible to encode the whole output buffer.
|
||||
output_raw_buffer_size = (output_buffer_size*2 + 2)
|
||||
|
||||
// The size of other stacks and queues.
|
||||
initial_stack_size = 16
|
||||
initial_queue_size = 16
|
||||
initial_string_size = 16
|
||||
)
|
||||
|
||||
// Check if the character at the specified position is an alphabetical
|
||||
// character, a digit, '_', or '-'.
|
||||
func is_alpha(b []byte, i int) bool {
|
||||
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is a digit.
|
||||
func is_digit(b []byte, i int) bool {
|
||||
return b[i] >= '0' && b[i] <= '9'
|
||||
}
|
||||
|
||||
// Get the value of a digit.
|
||||
func as_digit(b []byte, i int) int {
|
||||
return int(b[i]) - '0'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is a hex-digit.
|
||||
func is_hex(b []byte, i int) bool {
|
||||
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
|
||||
}
|
||||
|
||||
// Get the value of a hex-digit.
|
||||
func as_hex(b []byte, i int) int {
|
||||
bi := b[i]
|
||||
if bi >= 'A' && bi <= 'F' {
|
||||
return int(bi) - 'A' + 10
|
||||
}
|
||||
if bi >= 'a' && bi <= 'f' {
|
||||
return int(bi) - 'a' + 10
|
||||
}
|
||||
return int(bi) - '0'
|
||||
}
|
||||
|
||||
// Check if the character is ASCII.
|
||||
func is_ascii(b []byte, i int) bool {
|
||||
return b[i] <= 0x7F
|
||||
}
|
||||
|
||||
// Check if the character at the start of the buffer can be printed unescaped.
|
||||
func is_printable(b []byte, i int) bool {
|
||||
return ((b[i] == 0x0A) || // . == #x0A
|
||||
(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
|
||||
(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
|
||||
(b[i] > 0xC2 && b[i] < 0xED) ||
|
||||
(b[i] == 0xED && b[i+1] < 0xA0) ||
|
||||
(b[i] == 0xEE) ||
|
||||
(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
|
||||
!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
|
||||
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is NUL.
|
||||
func is_z(b []byte, i int) bool {
|
||||
return b[i] == 0x00
|
||||
}
|
||||
|
||||
// Check if the beginning of the buffer is a BOM.
|
||||
func is_bom(b []byte, i int) bool {
|
||||
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is space.
|
||||
func is_space(b []byte, i int) bool {
|
||||
return b[i] == ' '
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is tab.
|
||||
func is_tab(b []byte, i int) bool {
|
||||
return b[i] == '\t'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is blank (space or tab).
|
||||
func is_blank(b []byte, i int) bool {
|
||||
//return is_space(b, i) || is_tab(b, i)
|
||||
return b[i] == ' ' || b[i] == '\t'
|
||||
}
|
||||
|
||||
// Check if the character at the specified position is a line break.
|
||||
func is_break(b []byte, i int) bool {
|
||||
return (b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
|
||||
}
|
||||
|
||||
func is_crlf(b []byte, i int) bool {
|
||||
return b[i] == '\r' && b[i+1] == '\n'
|
||||
}
|
||||
|
||||
// Check if the character is a line break or NUL.
|
||||
func is_breakz(b []byte, i int) bool {
|
||||
//return is_break(b, i) || is_z(b, i)
|
||||
return ( // is_break:
|
||||
b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||
// is_z:
|
||||
b[i] == 0)
|
||||
}
|
||||
|
||||
// Check if the character is a line break, space, or NUL.
|
||||
func is_spacez(b []byte, i int) bool {
|
||||
//return is_space(b, i) || is_breakz(b, i)
|
||||
return ( // is_space:
|
||||
b[i] == ' ' ||
|
||||
// is_breakz:
|
||||
b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||
b[i] == 0)
|
||||
}
|
||||
|
||||
// Check if the character is a line break, space, tab, or NUL.
|
||||
func is_blankz(b []byte, i int) bool {
|
||||
//return is_blank(b, i) || is_breakz(b, i)
|
||||
return ( // is_blank:
|
||||
b[i] == ' ' || b[i] == '\t' ||
|
||||
// is_breakz:
|
||||
b[i] == '\r' || // CR (#xD)
|
||||
b[i] == '\n' || // LF (#xA)
|
||||
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
|
||||
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
|
||||
b[i] == 0)
|
||||
}
|
||||
|
||||
// Determine the width of the character.
|
||||
func width(b byte) int {
|
||||
// Don't replace these by a switch without first
|
||||
// confirming that it is being inlined.
|
||||
if b&0x80 == 0x00 {
|
||||
return 1
|
||||
}
|
||||
if b&0xE0 == 0xC0 {
|
||||
return 2
|
||||
}
|
||||
if b&0xF0 == 0xE0 {
|
||||
return 3
|
||||
}
|
||||
if b&0xF8 == 0xF0 {
|
||||
return 4
|
||||
}
|
||||
return 0
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue