├── _config.yml ├── vendor ├── git.thwap.org │ └── rockhopper │ │ ├── friday │ │ ├── disk.go │ │ ├── ram.go │ │ ├── shell.go │ │ ├── README.md │ │ ├── cmd │ │ │ └── jtf │ │ │ │ └── jtf.go │ │ ├── cpu.go │ │ ├── host_sysctl.go │ │ ├── sys_syscall.go │ │ ├── friday.go │ │ ├── host_utsname.go │ │ ├── LICENSE │ │ └── sys_sysctl.go │ │ └── gout │ │ ├── .hound.yml │ │ ├── .travis.yml │ │ ├── console.go │ │ ├── structs.go │ │ ├── video.go │ │ ├── helpers.go │ │ ├── format.go │ │ ├── output.go │ │ ├── README.md │ │ └── gout.go └── gopkg.in │ └── yaml.v1 │ ├── suite_test.go │ ├── LICENSE.libyaml │ ├── writerc.go │ ├── sorter.go │ ├── README.md │ ├── resolve.go │ ├── yamlprivateh.go │ ├── encode.go │ ├── LICENSE │ ├── yaml.go │ ├── encode_test.go │ ├── readerc.go │ ├── decode.go │ ├── decode_test.go │ ├── apic.go │ └── yamlh.go ├── go-cloudshell-lcd.png ├── go-cloudshell.yml ├── host.go ├── ram.go ├── load.go ├── swaps.go ├── cpu.go ├── config.go ├── cs-lcd.go ├── README.md ├── net.go ├── utils.go └── disks.go /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/disk.go: -------------------------------------------------------------------------------- 1 | package friday 2 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/ram.go: -------------------------------------------------------------------------------- 1 | package friday 2 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/shell.go: -------------------------------------------------------------------------------- 1 | package friday 2 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/.hound.yml: -------------------------------------------------------------------------------- 1 | go: 2 | enabled: true 3 | -------------------------------------------------------------------------------- /go-cloudshell-lcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzy/go-cloudshell-lcd/HEAD/go-cloudshell-lcd.png -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4.3 5 | - 1.5.3 6 | - 1.6.3 7 | - 1.7.5 8 | 9 | script: go test 10 | 11 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/README.md: -------------------------------------------------------------------------------- 1 | # friday 2 | 3 | Friday is a cross platform library for the collecting of system facts. Named for Joe Friday's tagline from TV's Dragnet, the command-line utility is named jtf. Just the Facts. -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/suite_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { TestingT(t) } 9 | 10 | type S struct{} 11 | 12 | var _ = Suite(&S{}) 13 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/cmd/jtf/jtf.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "git.thwap.org/rockhopper/friday" 4 | 5 | func main() { 6 | f := friday.Friday{Facts: make(map[string]string)} 7 | f.CollectFacts() 8 | f.Print() 9 | } 10 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/cpu.go: -------------------------------------------------------------------------------- 1 | package friday 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | func (f *Friday) _getCpuInfo() { 9 | f.Add("ProcessorCount", fmt.Sprintf("%d", runtime.NumCPU())) 10 | f.Add("Architecture", runtime.GOARCH) 11 | } 12 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/console.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | // console info and utilities 9 | 10 | func ConsInfo() winsize { 11 | ws := winsize{} 12 | retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL, 13 | uintptr(syscall.Stdin), 14 | uintptr(syscall.TIOCGWINSZ), 15 | uintptr(unsafe.Pointer(&ws))) 16 | if int(retCode) == -1 { 17 | panic(errno) 18 | } 19 | return ws 20 | } 21 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/host_sysctl.go: -------------------------------------------------------------------------------- 1 | // +build freebsd openbsd netbsd 2 | 3 | package friday 4 | 5 | import "runtime" 6 | 7 | func (f *Friday) _getUnameInfo() { 8 | data := map[string]string{ 9 | "Sysname": "kern.ostype", 10 | "Release": "kern.osrelease", 11 | "Machine": "hw.machine", 12 | "Nodename": "kern.hostname", 13 | "Version": "kern.version", 14 | } 15 | for k, s := range data { 16 | f.Add(k, f._sysctl(s)) 17 | } 18 | f.Add("Sysname_lc", runtime.GOOS) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/structs.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | // data structures 4 | 5 | type output struct { 6 | Prompts map[string]string 7 | Debug bool 8 | Quiet bool 9 | Verbose bool 10 | ToFile bool 11 | Throbber []string 12 | lastThrob int 13 | } 14 | 15 | type winsize struct { 16 | Row uint16 17 | Col uint16 18 | Xpixel uint16 19 | Ypixel uint16 20 | } 21 | 22 | type Progress struct { 23 | Total int64 24 | CurrentIn int64 25 | CurrentOut int64 26 | TimeStarted int64 27 | } 28 | -------------------------------------------------------------------------------- /go-cloudshell.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Update interval in seconds 3 | interval: 1 4 | padding: 5 | # Top padding (lines) 6 | top: 1 7 | # left padding (spaces) 8 | left: 0 9 | # configure outputs 10 | outputs: 11 | host: true 12 | load: true 13 | cpu: true 14 | ram: true 15 | swap: true 16 | net: 17 | - name: eth0 18 | enabled: true 19 | disk: 20 | - name: sda 21 | enabled: true 22 | mount: /srv/share 23 | space: true 24 | - name: sdb 25 | enabled: true 26 | mount: / 27 | space: false 28 | -------------------------------------------------------------------------------- /host.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "git.thwap.org/rockhopper/friday" 8 | "git.thwap.org/rockhopper/gout" 9 | ) 10 | 11 | func HostProducer() { 12 | f := friday.Friday{Facts: make(map[string]string)} 13 | f.CollectFacts() 14 | 15 | for { 16 | Output <- &CloudShellOutput{ 17 | Type: "host", 18 | Lines: []string{ 19 | fmt.Sprintf( 20 | "%s - %s - %s", 21 | gout.Bold(gout.White(f.Get("Nodename"))), 22 | gout.Bold(gout.White(f.Get("Sysname"))), 23 | gout.Bold(gout.Cyan(f.Get("Release"))), 24 | ), 25 | }, 26 | } 27 | time.Sleep(300 * time.Second) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ram.go: -------------------------------------------------------------------------------- 1 | // ram.go 2 | package main 3 | 4 | // #include 5 | // #include 6 | // #include 7 | import "C" 8 | 9 | import ( 10 | "time" 11 | ) 12 | 13 | func RamProducer() { 14 | for { 15 | maxRam := int64(C.sysconf(C._SC_PHYS_PAGES) * C.sysconf(C._SC_PAGE_SIZE)) 16 | freeRam := int64(C.sysconf(C._SC_AVPHYS_PAGES) * C.sysconf(C._SC_PAGE_SIZE)) 17 | usedRam := (maxRam - freeRam) 18 | ramPercUsed := (float64(usedRam) / float64(maxRam)) * 100.0 19 | Output <- &CloudShellOutput{ 20 | Type: "ram", 21 | Lines: []string{progress("Ram", int(ramPercUsed))}, 22 | } 23 | time.Sleep(time.Second) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/sys_syscall.go: -------------------------------------------------------------------------------- 1 | // +build linux solaris 2 | 3 | package friday 4 | 5 | import ( 6 | "fmt" 7 | "syscall" 8 | ) 9 | 10 | func (f *Friday) _getSysInfo() { 11 | var sinfo syscall.Sysinfo_t 12 | if err := syscall.Sysinfo(&sinfo); err != nil { 13 | panic(err) 14 | } 15 | f.Add("Totalram", fmt.Sprint(sinfo.Totalram)) 16 | f.Add("Freeram", fmt.Sprint(sinfo.Freeram)) 17 | f.Add("Totalswap", fmt.Sprint(sinfo.Totalswap)) 18 | f.Add("Freeswap", fmt.Sprint(sinfo.Freeswap)) 19 | f.Add("Uptime", fmt.Sprint(sinfo.Uptime)) 20 | for i, v := range []string{"5minLoad", "10minLoad", "15minLoad"} { 21 | f.Add(v, fmt.Sprintf("%.02f", float64(sinfo.Loads[i])/65536.0)) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /load.go: -------------------------------------------------------------------------------- 1 | // load.go 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "time" 7 | 8 | "git.thwap.org/rockhopper/friday" 9 | "git.thwap.org/rockhopper/gout" 10 | ) 11 | 12 | func LoadProducer() { 13 | f := friday.Friday{Facts: make(map[string]string)} 14 | 15 | for { 16 | t := time.Now() 17 | t.Format(time.RFC3339) 18 | f.CollectFacts() 19 | 20 | Output <- &CloudShellOutput{ 21 | Type: "load", 22 | Lines: []string{ 23 | fmt.Sprintf( 24 | "%s: %s - %s: %s, %s, %s", 25 | gout.Bold(gout.White("TIME")), 26 | t.Format("03:04PM"), 27 | gout.Bold(gout.White("LOAD")), 28 | f.Get("5minLoad"), 29 | f.Get("10minLoad"), 30 | f.Get("15minLoad"), 31 | ), 32 | }, 33 | } 34 | time.Sleep(5 * time.Second) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/friday.go: -------------------------------------------------------------------------------- 1 | package friday 2 | 3 | import ( 4 | "fmt" 5 | 6 | "git.thwap.org/rockhopper/gout" 7 | ) 8 | 9 | type Friday struct { 10 | Facts map[string]string 11 | } 12 | 13 | func (f *Friday) _haveFact(k string) bool { 14 | for mk, _ := range f.Facts { 15 | if k == mk { 16 | return true 17 | } 18 | } 19 | return false 20 | } 21 | 22 | func (f *Friday) Add(k, v string) { 23 | f.Facts[k] = v 24 | } 25 | 26 | func (f *Friday) Get(k string) string { 27 | if f._haveFact(k) { 28 | return f.Facts[k] 29 | } 30 | return "" 31 | } 32 | 33 | func (f *Friday) Del(k string) { 34 | if f._haveFact(k) { 35 | delete(f.Facts, k) 36 | } 37 | } 38 | 39 | func (f *Friday) Print() { 40 | gout.Setup(false, false, true, "") 41 | gout.Output.Prompts["info"] = "" 42 | for k, v := range f.Facts { 43 | gout.Info(fmt.Sprintf("%s %s %s", k, gout.Bold(gout.Cyan("=>")), v)) 44 | } 45 | } 46 | 47 | func (f *Friday) CollectFacts() { 48 | f._getUnameInfo() 49 | f._getSysInfo() 50 | f._getCpuInfo() 51 | } 52 | 53 | func New() *Friday { 54 | retv := Friday{} 55 | retv.CollectFacts() 56 | return &retv 57 | } 58 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/host_utsname.go: -------------------------------------------------------------------------------- 1 | // +build linux solaris 2 | 3 | package friday 4 | 5 | import ( 6 | "runtime" 7 | "strings" 8 | 9 | "github.com/fatih/structs" 10 | 11 | "golang.org/x/sys/unix" 12 | ) 13 | 14 | func _toByte(i int8) byte { 15 | if i < 0 { 16 | return byte(256 + int(i)) 17 | } else { 18 | return byte(int(i)) 19 | } 20 | } 21 | 22 | func _utsnameToMap(u unix.Utsname) map[string]string { 23 | retv := make(map[string]string) 24 | for k, v := range structs.Map(u) { 25 | switch v := v.(type) { 26 | case [65]uint8: 27 | b := []byte{} 28 | for _, d := range v { 29 | b = append(b, _toByte(int8(d))) 30 | } 31 | retv[k] = strings.TrimRight(string(b), "\x00") 32 | case [257]int8: 33 | b := []byte{} 34 | for _, d := range v { 35 | b = append(b, _toByte(d)) 36 | } 37 | retv[k] = strings.TrimRight(string(b), "\x00") 38 | } 39 | } 40 | return retv 41 | } 42 | 43 | func (f *Friday) _getUnameInfo() { 44 | var uname unix.Utsname 45 | if err := unix.Uname(&uname); err != nil { 46 | panic(err) 47 | } 48 | for k, v := range _utsnameToMap(uname) { 49 | f.Add(k, v) 50 | } 51 | f.Add("Sysname_lc", runtime.GOOS) 52 | } 53 | -------------------------------------------------------------------------------- /swaps.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type SwapTotals struct { 12 | Total int64 13 | Used int64 14 | Free int64 15 | } 16 | 17 | func getSwapTotals() *SwapTotals { 18 | retv := &SwapTotals{} 19 | fp, er := os.Open("/proc/swaps") 20 | pcheck(er) 21 | defer fp.Close() 22 | scanner := bufio.NewScanner(fp) 23 | for scanner.Scan() { 24 | tkn := 0 25 | for _, v := range strings.Split(scanner.Text(), " ") { 26 | if len(v) >= 1 { 27 | if tkn == 2 { 28 | tsw, er := strconv.ParseInt(v, 10, 64) 29 | pcheck(er) 30 | retv.Total += tsw 31 | } else if tkn == 3 { 32 | tsu, er := strconv.ParseInt(v, 10, 64) 33 | pcheck(er) 34 | retv.Used += tsu 35 | } 36 | tkn += 1 37 | } 38 | } 39 | } 40 | retv.Free = (retv.Total - retv.Used) 41 | return retv 42 | } 43 | 44 | func SwapProducer() { 45 | for { 46 | swap := getSwapTotals() 47 | Output <- &CloudShellOutput{ 48 | Type: "swap", 49 | Lines: []string{ 50 | progress( 51 | "Swap", 52 | int((float64(swap.Used)/float64(swap.Total))*100.0), 53 | ), 54 | }, 55 | } 56 | time.Sleep(time.Second) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cpu.go: -------------------------------------------------------------------------------- 1 | // cpu.go 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "os" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | func jiffies() []string { 13 | fp, er := os.Open("/proc/stat") 14 | if er != nil { 15 | panic(er) 16 | } 17 | 18 | scanner := bufio.NewScanner(fp) 19 | scanner.Scan() 20 | fp.Close() 21 | return strings.Split(scanner.Text(), " ") 22 | } 23 | 24 | func countJiffies() (int64, int64) { 25 | var totj int64 26 | var wrkj int64 27 | 28 | for k, v := range jiffies() { 29 | if k >= 2 { 30 | tv, er := strconv.ParseInt(v, 10, 64) 31 | if er != nil { 32 | panic(er) 33 | } 34 | totj += tv 35 | } 36 | if k >= 2 && k <= 4 { 37 | tv, er := strconv.ParseInt(v, 10, 64) 38 | if er != nil { 39 | panic(er) 40 | } 41 | wrkj += tv 42 | } 43 | } 44 | return totj, wrkj 45 | } 46 | 47 | func CpuProducer() { 48 | for { 49 | tj1, wj1 := countJiffies() 50 | time.Sleep(time.Second) 51 | tj2, wj2 := countJiffies() 52 | 53 | top := (tj2 - tj1) 54 | wop := (wj2 - wj1) 55 | cpu := (float64(wop) / float64(top)) * 100.0 56 | 57 | Output <- &CloudShellOutput{ 58 | Type: "cpu", 59 | Lines: []string{progress("Cpu", int(cpu))}, 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/video.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import "fmt" 4 | 5 | func Black(i string) string { 6 | return fmt.Sprintf("\033[30m%s\033[0m", i) 7 | } 8 | 9 | func Red(i string) string { 10 | return fmt.Sprintf("\033[31m%s\033[0m", i) 11 | } 12 | 13 | func Green(i string) string { 14 | return fmt.Sprintf("\033[32m%s\033[0m", i) 15 | } 16 | 17 | func Yellow(i string) string { 18 | return fmt.Sprintf("\033[33m%s\033[0m", i) 19 | } 20 | 21 | func Blue(i string) string { 22 | return fmt.Sprintf("\033[34m%s\033[0m", i) 23 | } 24 | 25 | func Purple(i string) string { 26 | return fmt.Sprintf("\033[35m%s\033[0m", i) 27 | } 28 | 29 | func Cyan(i string) string { 30 | return fmt.Sprintf("\033[36m%s\033[0m", i) 31 | } 32 | 33 | func White(i string) string { 34 | return fmt.Sprintf("\033[37m%s\033[0m", i) 35 | } 36 | 37 | func Bold(i string) string { 38 | return fmt.Sprintf("\033[1m%s\033[0m", i) 39 | } 40 | 41 | func Underline(i string) string { 42 | return fmt.Sprintf("\033[4m%s\033[0m", i) 43 | } 44 | 45 | func Blink(i string) string { 46 | return fmt.Sprintf("\033[5m%s\033[0m", i) 47 | } 48 | 49 | func Reverse(i string) string { 50 | return fmt.Sprintf("\033[7m%s\033[0m", i) 51 | } 52 | 53 | func Conceal(i string) string { 54 | return fmt.Sprintf("\033[8m%s\033[0m", i) 55 | } 56 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) All rights reserved. 2 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 3 | 4 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 5 | 6 | 2. 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. 7 | 8 | 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. 9 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/helpers.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "time" 7 | ) 8 | 9 | func repeat(c string, n int) string { 10 | retv := "" 11 | for i := 0; i <= n; i++ { 12 | retv += "#" 13 | } 14 | return retv 15 | } 16 | 17 | func padding(spaces int) string { 18 | pad := " " 19 | retv := "" 20 | for i := 0; i < spaces; i++ { 21 | retv = fmt.Sprintf("%s%s", retv, pad) 22 | } 23 | return retv 24 | } 25 | 26 | func Copy(dst io.Writer, src io.Reader, data *Progress) (int64, error) { 27 | var err error 28 | buf := make([]byte, 64*1024) 29 | 30 | for { 31 | // we move the ConsoleInfo() call inside the loop, that way terminal size 32 | // changes get handled properly. 33 | cons := ConsInfo() 34 | nr, er := src.Read(buf) 35 | if er == io.EOF { 36 | break 37 | } 38 | if er != nil { 39 | err = er 40 | break 41 | } 42 | data.CurrentIn += int64(nr) 43 | if nr > 0 { 44 | nw, ew := dst.Write(buf[0:nr]) 45 | if ew != nil { 46 | err = ew 47 | break 48 | } 49 | if nr != nw { 50 | err = io.ErrShortWrite 51 | break 52 | } 53 | data.CurrentOut += int64(nw) 54 | } 55 | if (time.Now().Unix() - data.TimeStarted) >= 1 { 56 | Status("%s", ProgressStatus(data, int(cons.Col-5))) 57 | } 58 | } 59 | return data.CurrentOut, err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/friday/sys_sysctl.go: -------------------------------------------------------------------------------- 1 | // +build freebsd openbsd netbsd 2 | 3 | package friday 4 | 5 | import ( 6 | "os/exec" 7 | "regexp" 8 | "strings" 9 | ) 10 | 11 | func (f *Friday) _sysctl(oid string) string { 12 | if out, err := exec.Command("/sbin/sysctl", oid).Output(); err == nil { 13 | fbsd, _ := regexp.Compile("^([a-zA-Z0-9\\._%\\-]*)(:\\ )(.*)$") 14 | obsd, _ := regexp.Compile("^([a-zA-Z0-9\\._\\-]*)(=)(.*)$") 15 | nbsd, _ := regexp.Compile("^([a-zA-Z0-9\\._]+)(\\ =\\ )(.*)") 16 | for _, v := range []*regexp.Regexp{fbsd, obsd, nbsd} { 17 | if v.MatchString(strings.TrimSpace(string(out))) { 18 | data := v.FindAllStringSubmatch(strings.TrimSpace(string(out)), -1) 19 | return data[0][len(data[0])-1] 20 | } 21 | } 22 | return "" 23 | } 24 | return "" 25 | } 26 | 27 | func (f *Friday) _getSysInfo() { 28 | var data map[string]string 29 | var load []string 30 | 31 | data = map[string]string{ 32 | "Totalmem": "hw.physmem", 33 | "Usermem": "hw.usermem", 34 | "Realmem": "hw.realmem", 35 | } 36 | 37 | switch m := f.Get("Sysname"); m { 38 | case "FreeBSD": 39 | load = strings.Split(f._sysctl("vm.loadavg"), " ")[1:4] 40 | case "NetBSD": 41 | load = strings.Split(f._sysctl("vm.loadavg"), " ") 42 | case "OpenBSD": 43 | load = strings.Split(f._sysctl("vm.loadavg"), " ") 44 | } 45 | 46 | for k, s := range data { 47 | f.Add(k, f._sysctl(s)) 48 | } 49 | 50 | if len(load) == 3 { 51 | f.Add("5minLoad", load[0]) 52 | f.Add("10minLoad", load[1]) 53 | f.Add("15minLoad", load[2]) 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "os" 7 | 8 | "gopkg.in/yaml.v1" 9 | ) 10 | 11 | type CloudShellConfig struct { 12 | Interval int `yaml:"interval"` 13 | Padding struct { 14 | Top int `yaml:"top"` 15 | Left int `yaml:"left"` 16 | Right int `yaml:"right"` 17 | Bottom int `yaml:"bottom"` 18 | } `yaml:"padding"` 19 | Outputs struct { 20 | Host bool `yaml:"host,omitempty"` 21 | Load bool `yaml:"load,omitempty"` 22 | Cpu bool `yaml:"cpu,omitempty"` 23 | Ram bool `yaml:"ram,omitempty"` 24 | Swap bool `yaml:"swap,omitempty"` 25 | Net []struct { 26 | Name string `yaml:"name"` 27 | Enabled bool `yaml:"enabled"` 28 | } `yaml:"net,omitempty"` 29 | Disk []struct { 30 | Name string `yaml:"name"` 31 | Enabled bool `yaml:"enabled"` 32 | Mount string `yaml:"mount"` 33 | Space bool `yaml:"space"` 34 | } `yaml:"disk,omitempty"` 35 | } `yaml:"outputs"` 36 | outputs []string 37 | } 38 | 39 | func ReadConfig(p string) *CloudShellConfig { 40 | // declare our return value 41 | retv := &CloudShellConfig{} 42 | 43 | // open the config file 44 | fp, er := os.Open(p) 45 | pcheck(er) 46 | defer fp.Close() 47 | 48 | // read the file 49 | data := bytes.NewBuffer(nil) 50 | io.Copy(data, fp) 51 | 52 | // and parse the data 53 | pcheck(yaml.Unmarshal([]byte(data.Bytes()), retv)) 54 | 55 | // build our order list for outputters 56 | if retv.Outputs.Host { 57 | retv.outputs = append(retv.outputs, "host") 58 | } 59 | if retv.Outputs.Load { 60 | retv.outputs = append(retv.outputs, "load") 61 | } 62 | if retv.Outputs.Cpu { 63 | retv.outputs = append(retv.outputs, "cpu") 64 | } 65 | if retv.Outputs.Ram { 66 | retv.outputs = append(retv.outputs, "ram") 67 | } 68 | if retv.Outputs.Swap { 69 | retv.outputs = append(retv.outputs, "swap") 70 | } 71 | 72 | // and hand it back 73 | return retv 74 | } 75 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/format.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strings" 7 | ) 8 | 9 | func Strappend(p, a string) string { 10 | return strings.Join([]string{p, a}, "") 11 | } 12 | 13 | func HumanTimeParse(s int64) map[string]int64 { 14 | smap := map[string]int64{ 15 | "sec": 1, 16 | "min": 60, 17 | "hr": (60 * 60), 18 | } 19 | keys := []string{"hr", "min", "sec"} 20 | retv := map[string]int64{} 21 | for _, value := range keys { 22 | if s >= smap[value] { 23 | val := (s / smap[value]) 24 | tgt := (val * smap[value]) 25 | rmn := (s - tgt) 26 | retv[value] = val 27 | s = rmn 28 | } 29 | } 30 | return retv 31 | } 32 | 33 | func HumanTimeColon(s int64) string { 34 | data := HumanTimeParse(s) 35 | return fmt.Sprintf("%02d:%02d:%02d", data["hr"], data["min"], data["sec"]) 36 | } 37 | 38 | func HumanTimeConcise(s int64) string { 39 | retv := "" 40 | data := HumanTimeParse(s) 41 | keys := []string{"hr", "min", "sec"} 42 | for _, val := range keys { 43 | if data[val] > 0 { 44 | retv = Strappend(retv, fmt.Sprintf("%02d%s", data[val], string(val[0]))) 45 | } 46 | } 47 | return retv 48 | } 49 | 50 | func HumanSize(s int64) string { 51 | smap := map[string]int64{ 52 | "Byte": int64(1), 53 | "Kilo": int64(1024), 54 | "Mega": int64(math.Pow(float64(1024), float64(2))), 55 | "Giga": int64(math.Pow(float64(1024), float64(3))), 56 | "Tera": int64(math.Pow(float64(1024), float64(4))), 57 | "Peta": int64(math.Pow(float64(1024), float64(5))), 58 | "Exxa": int64(math.Pow(float64(1024), float64(6))), 59 | } 60 | keys := []string{"Exxa", "Peta", "Tera", "Giga", "Mega", "Kilo", "Byte"} 61 | for index, value := range keys { 62 | if s >= smap[value] { 63 | bigB := "B" 64 | if index == len(keys)-1 { 65 | bigB = "" 66 | return fmt.Sprintf("%d%s%s", 67 | s, 68 | string(value[0]), 69 | bigB) 70 | } 71 | return fmt.Sprintf("%.02f%s%s", 72 | float64(s)/float64(smap[value]), 73 | string(value[0]), 74 | bigB) 75 | } 76 | } 77 | return "" 78 | } 79 | -------------------------------------------------------------------------------- /cs-lcd.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | ) 8 | 9 | type CloudShellOutput struct { 10 | Type string 11 | Lines []string 12 | } 13 | 14 | var Config *CloudShellConfig 15 | var Output chan *CloudShellOutput 16 | 17 | func Outputter() { 18 | // clear the screen 19 | fmt.Printf("\033[2J") 20 | 21 | for { 22 | // define our default starting point 23 | start := Config.Padding.Top 24 | 25 | // Get a line of output 26 | tmp := <-Output 27 | 28 | // stuff that should output before net/disks 29 | for k, v := range Config.outputs { 30 | if tmp.Type == v { 31 | start += (k + 1) 32 | fmt.Printf("\033[%d;1H%s", start, strings.Repeat(" ", Config.Padding.Left)) 33 | for _, v := range tmp.Lines { 34 | fmt.Println(v) 35 | } 36 | } 37 | } 38 | 39 | // net output 40 | for _, pt := range []string{"et", "en", "wl"} { 41 | if tmp.Type[:2] == pt { 42 | for i, n := range Config.Outputs.Net { 43 | if n.Name == tmp.Type && n.Enabled { 44 | fmt.Printf( 45 | "\033[%d;1H%s%s", 46 | start+len(Config.outputs)+i+2, 47 | strings.Repeat(" ", Config.Padding.Left), 48 | tmp.Lines[0], 49 | ) 50 | } 51 | } 52 | } 53 | } 54 | 55 | // disk output 56 | for _, pt := range []string{"sd"} { 57 | if tmp.Type[:2] == pt { 58 | cnt := 0 59 | for _, tv := range Config.Outputs.Net { 60 | if tv.Enabled { 61 | cnt += 1 62 | } 63 | } 64 | for _, n := range Config.Outputs.Disk { 65 | if n.Name == tmp.Type && n.Enabled { 66 | for ti, tl := range tmp.Lines { 67 | fmt.Printf( 68 | "\033[%d;1H%s%s", 69 | start+len(Config.outputs)+cnt+ti+3, 70 | strings.Repeat(" ", Config.Padding.Left), 71 | tl, 72 | ) 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | fmt.Printf("\033[0;1H") 80 | time.Sleep(50 * time.Millisecond) 81 | } 82 | } 83 | 84 | func main() { 85 | Config = ReadConfig("/etc/go-cloudshell.yml") 86 | Output = make(chan *CloudShellOutput, 7) 87 | 88 | // Producer startup 89 | if Config.Outputs.Host { 90 | go HostProducer() 91 | } 92 | if Config.Outputs.Load { 93 | go LoadProducer() 94 | } 95 | if Config.Outputs.Cpu { 96 | go CpuProducer() 97 | } 98 | if Config.Outputs.Ram { 99 | go RamProducer() 100 | } 101 | if Config.Outputs.Swap { 102 | go SwapProducer() 103 | } 104 | go NetProducer() 105 | go DiskProducer() 106 | 107 | fmt.Printf("%+v\n", Config) 108 | Outputter() 109 | } 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-cloudshell-lcd 2 | 3 | ### Installation 4 | 5 | * First install the binary: 6 | 7 | ``` 8 | $ go get -v github.com/fuzzy/go-cloudshell-lcd 9 | $ sudo cp ${GOPATH}/bin/go-cloudshell-lcd /usr/bin 10 | ``` 11 | 12 | * Next copy the config file to /etc and edit to taste: 13 | 14 | ``` 15 | $ sudo cp ${GOPATH}/src/github.com/fuzzy/go-cloudshell-lcd/go-cloudshell.yml /etc 16 | ``` 17 | 18 | * Boot time configuration for distros with systemd 19 | 20 | Use a unit file such as this one (adapted from https://github.com/mdrjr/cloudshell_lcd/blob/master/cloudshell): 21 | 22 | ``` 23 | [Unit] 24 | Description="ODROID Cloudshell LCD Info" 25 | DefaultDependencies=no 26 | Requires=sysinit.target 27 | After=sysinit.target 28 | 29 | [Service] 30 | Type=simple 31 | ExecStart=/bin/cloudshell-lcd 32 | 33 | [Install] 34 | WantedBy=basic.target 35 | WantedBy=sysinit.target 36 | ``` 37 | 38 | or an entry in /etc/rc.local or whatever facility your distribution provides executing the wrapper script /bin/cloudshell-lcd. You can use something like the following (adapted from https://github.com/mdrjr/cloudshell_lcd/blob/master/cloudshell) 39 | 40 | ``` 41 | #!/bin/bash 42 | # hardkernel CloudShell Screen update 43 | 44 | # Disable LCD Slepp mode 45 | echo -e '\033[9;0]' > /dev/tty1 46 | # console font 47 | # More fonts on: /usr/share/consolefonts 48 | export TERM="linux" 49 | export CONSOLE_FONT="Lat7-Fixed18" 50 | #export CONSOLE_FONT="Lat15-TerminusBold20x10" 51 | # Output Console (ttyX) 52 | export OUTPUT_CONSOLE="1" 53 | oc="/dev/tty$OUTPUT_CONSOLE" 54 | 55 | # font setup 56 | setfont $CONSOLE_FONT > $oc 57 | 58 | while true; do 59 | # Ensure that we are in the right TTY 60 | chvt $OUTPUT_CONSOLE 61 | /usr/local/golang/path/bin/go-cloudshell-lcd >$oc 62 | done 63 | 64 | ``` 65 | 66 | ### Configuration 67 | 68 | edit /etc/go-cloudshell.yml 69 | 70 | ``` 71 | 72 | --- 73 | # Update interval in seconds 74 | interval: 1 75 | padding: 76 | # Top padding (lines) 77 | top: 1 78 | # left padding (spaces) 79 | left: 0 80 | # configure outputs 81 | outputs: 82 | host: true 83 | load: true 84 | cpu: true 85 | ram: true 86 | swap: true 87 | net: 88 | - name: eth0 89 | enabled: true 90 | disk: 91 | - name: sda 92 | enabled: true 93 | mount: / 94 | space: true 95 | - name: sdb 96 | enabled: true 97 | mount: /srv/share 98 | space: true 99 | ``` 100 | 101 | ### Screenshot 102 | 103 | ![alt text](https://raw.githubusercontent.com/fuzzy/go-cloudshell-lcd/master/go-cloudshell-lcd.png "Screenshot") 104 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | // If the output encoding is UTF-8, we don't need to recode the buffer. 22 | if emitter.encoding == yaml_UTF8_ENCODING { 23 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 24 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 25 | } 26 | emitter.buffer_pos = 0 27 | return true 28 | } 29 | 30 | // Recode the buffer into the raw buffer. 31 | var low, high int 32 | if emitter.encoding == yaml_UTF16LE_ENCODING { 33 | low, high = 0, 1 34 | } else { 35 | high, low = 1, 0 36 | } 37 | 38 | pos := 0 39 | for pos < emitter.buffer_pos { 40 | // See the "reader.c" code for more details on UTF-8 encoding. Note 41 | // that we assume that the buffer contains a valid UTF-8 sequence. 42 | 43 | // Read the next UTF-8 character. 44 | octet := emitter.buffer[pos] 45 | 46 | var w int 47 | var value rune 48 | switch { 49 | case octet&0x80 == 0x00: 50 | w, value = 1, rune(octet&0x7F) 51 | case octet&0xE0 == 0xC0: 52 | w, value = 2, rune(octet&0x1F) 53 | case octet&0xF0 == 0xE0: 54 | w, value = 3, rune(octet&0x0F) 55 | case octet&0xF8 == 0xF0: 56 | w, value = 4, rune(octet&0x07) 57 | } 58 | for k := 1; k < w; k++ { 59 | octet = emitter.buffer[pos+k] 60 | value = (value << 6) + (rune(octet) & 0x3F) 61 | } 62 | pos += w 63 | 64 | // Write the character. 65 | if value < 0x10000 { 66 | var b [2]byte 67 | b[high] = byte(value >> 8) 68 | b[low] = byte(value & 0xFF) 69 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1]) 70 | } else { 71 | // Write the character using a surrogate pair (check "reader.c"). 72 | var b [4]byte 73 | value -= 0x10000 74 | b[high] = byte(0xD8 + (value >> 18)) 75 | b[low] = byte((value >> 10) & 0xFF) 76 | b[high+2] = byte(0xDC + ((value >> 8) & 0xFF)) 77 | b[low+2] = byte(value & 0xFF) 78 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3]) 79 | } 80 | } 81 | 82 | // Write the raw buffer. 83 | if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil { 84 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 85 | } 86 | emitter.buffer_pos = 0 87 | emitter.raw_buffer = emitter.raw_buffer[:0] 88 | return true 89 | } 90 | -------------------------------------------------------------------------------- /net.go: -------------------------------------------------------------------------------- 1 | // net.go 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "fmt" 7 | "io/ioutil" 8 | "math" 9 | "os" 10 | "strconv" 11 | "time" 12 | ) 13 | 14 | type NetIf struct { 15 | Name string 16 | Speed int64 17 | Rx_b, Tx_b int64 18 | } 19 | 20 | func getTransfer(i string) *NetIf { 21 | fp, er := os.Open(fmt.Sprintf("/sys/class/net/%s/statistics/rx_bytes", i)) 22 | if er != nil { 23 | panic(er) 24 | } 25 | scanner := bufio.NewScanner(fp) 26 | scanner.Scan() 27 | rx, er := strconv.ParseInt(scanner.Text(), 10, 64) 28 | if er != nil { 29 | panic(er) 30 | } 31 | fp.Close() 32 | 33 | fp, er = os.Open(fmt.Sprintf("/sys/class/net/%s/statistics/tx_bytes", i)) 34 | if er != nil { 35 | panic(er) 36 | } 37 | scanner = bufio.NewScanner(fp) 38 | scanner.Scan() 39 | tx, er := strconv.ParseInt(scanner.Text(), 10, 64) 40 | if er != nil { 41 | panic(er) 42 | } 43 | fp.Close() 44 | 45 | retv := &NetIf{Name: i, Rx_b: rx, Tx_b: tx} 46 | return retv 47 | } 48 | 49 | func interfaces() map[string]*NetIf { 50 | retv := make(map[string]*NetIf) 51 | f, e := ioutil.ReadDir("/sys/class/net") 52 | if e != nil { 53 | panic(e) 54 | } 55 | for _, v := range f { 56 | if string(v.Name()[0]) == "e" { 57 | retv[string(v.Name())] = &NetIf{Name: v.Name()} 58 | point_a := getTransfer(v.Name()) 59 | time.Sleep(time.Second) 60 | point_b := getTransfer(v.Name()) 61 | 62 | // now get the interface speed 63 | tf, te := os.Open(fmt.Sprintf("/sys/class/net/%s/speed", v.Name())) 64 | scanner := bufio.NewScanner(tf) 65 | scanner.Scan() 66 | ts, te := strconv.ParseInt(scanner.Text(), 10, 64) 67 | if te != nil { 68 | panic(te) 69 | } 70 | retv[string(v.Name())].Speed = ts 71 | 72 | // now calc the difference between points a and b (speed) 73 | retv[string(v.Name())].Rx_b = (point_b.Rx_b - point_a.Rx_b) 74 | retv[string(v.Name())].Tx_b = (point_b.Tx_b - point_a.Tx_b) 75 | 76 | // cleanup the filehandle 77 | tf.Close() 78 | } 79 | } 80 | 81 | return retv 82 | } 83 | 84 | func NetProducer() { 85 | for { 86 | retv := &CloudShellOutput{Lines: []string{}} 87 | data := interfaces() 88 | var rwp, twp float64 89 | for k, v := range data { 90 | if v.Rx_b > 0 { 91 | rwp = 100.0 * (100.0 * ((float64(v.Rx_b) / float64(v.Speed*int64(math.Pow(1024, 3)))) * 100.0)) 92 | } else { 93 | rwp = 0 94 | } 95 | if v.Tx_b > 0 { 96 | twp = 100.0 * (100.0 * ((float64(v.Tx_b) / float64(v.Speed*int64(math.Pow(1024, 3)))) * 100.0)) 97 | } else { 98 | twp = 0 99 | } 100 | retv.Type = k 101 | retv.Lines = append( 102 | retv.Lines, 103 | doubleProgress(k, int(rwp), int(twp), "rx", "tx"), 104 | ) 105 | } 106 | Output <- retv 107 | time.Sleep(time.Second) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/output.go: -------------------------------------------------------------------------------- 1 | package gout 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | eval "github.com/Knetic/govaluate" 9 | ) 10 | 11 | // Output functions 12 | func consoleOutput(t string, e string, f string, args ...interface{}) { 13 | Winsize = ConsInfo() 14 | if Output.ToFile { 15 | log.Printf("%s %s\n", t, fmt.Sprintf(f, args...)) 16 | } 17 | fmt.Printf("%s %s %s%s", 18 | Output.Prompts[t], 19 | fmt.Sprintf(f, args...), 20 | padding(int(Winsize.Col)-(7+len(fmt.Sprintf(f, args...)))), 21 | e) 22 | } 23 | 24 | func Info(f string, args ...interface{}) { 25 | if !Output.Quiet { 26 | consoleOutput("info", "\n", f, args...) 27 | } 28 | } 29 | 30 | func Debug(f string, args ...interface{}) { 31 | if Output.Debug { 32 | consoleOutput("debug", "\n", f, args...) 33 | } 34 | } 35 | 36 | func Warn(f string, args ...interface{}) { 37 | if Output.Verbose { 38 | consoleOutput("warn", "\n", f, args...) 39 | } 40 | } 41 | 42 | func Error(f string, args ...interface{}) { 43 | consoleOutput("error", "\n", f, args...) 44 | } 45 | 46 | func Status(f string, args ...interface{}) { 47 | consoleOutput("status", "\r", f, args...) 48 | } 49 | 50 | func ProgressStatus(d *Progress, l int) string { 51 | // compute runtime 52 | runtime := (time.Now().Unix() - d.TimeStarted) 53 | // compute speed 54 | if runtime <= 0 { 55 | runtime = 1 56 | } 57 | speed := (d.CurrentOut / runtime) 58 | // compute estimated time remaining 59 | if speed <= 0 { 60 | speed = 0 61 | } 62 | etr := ((d.Total - d.CurrentOut) / speed) 63 | // compute progress percentage 64 | progress := ((float64(d.CurrentOut) / float64(d.Total)) * 100.0) 65 | 66 | // now build our return string 67 | current_s := HumanSize(d.CurrentOut) 68 | speed_s := HumanSize(speed) 69 | etr_s := HumanTimeColon(etr) 70 | var progress_s string 71 | 72 | // get the current string length 73 | first := fmt.Sprintf("%9s @ %9s %6.02f%s", current_s, speed_s, progress, "%%") 74 | 75 | if (len(first) + len(etr_s)) <= (l - 16) { 76 | progress_s = ProgressMeter((l - (len(first) + len(etr_s) + 2)), int(progress)) 77 | } else { 78 | progress_s = "" 79 | } 80 | 81 | return fmt.Sprintf("%s %s %s", first, progress_s, etr_s) 82 | } 83 | 84 | func ProgressMeter(l int, p int) string { 85 | rl := l - 2 86 | var rslt interface{} 87 | var sp string 88 | if p < 100 { 89 | expr, _ := eval.NewEvaluableExpression(fmt.Sprintf("%d * 0.%02d", rl, p)) 90 | rslt, _ = expr.Evaluate(nil) 91 | sp = repeat("#", int(rslt.(float64))) 92 | } else { 93 | rslt = rl 94 | sp = repeat("#", rslt.(int)) 95 | } 96 | pd := padding(rl - len(sp)) 97 | return fmt.Sprintf("[%s%s]", sp, pd) 98 | } 99 | 100 | func Throbber() string { 101 | if Output.lastThrob == len(Output.Throbber)+1 { 102 | Output.lastThrob = 1 103 | } else { 104 | Output.lastThrob++ 105 | } 106 | return Output.Throbber[Output.lastThrob-1] 107 | } 108 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 55 | an = an*10 + int64(ar[ai]-'0') 56 | } 57 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 58 | bn = bn*10 + int64(br[bi]-'0') 59 | } 60 | if an != bn { 61 | return an < bn 62 | } 63 | if ai != bi { 64 | return ai < bi 65 | } 66 | return ar[i] < br[i] 67 | } 68 | return len(ar) < len(br) 69 | } 70 | 71 | // keyFloat returns a float value for v if it is a number/bool 72 | // and whether it is a number/bool or not. 73 | func keyFloat(v reflect.Value) (f float64, ok bool) { 74 | switch v.Kind() { 75 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 76 | return float64(v.Int()), true 77 | case reflect.Float32, reflect.Float64: 78 | return v.Float(), true 79 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 80 | return float64(v.Uint()), true 81 | case reflect.Bool: 82 | if v.Bool() { 83 | return 1, true 84 | } 85 | return 0, true 86 | } 87 | return 0, false 88 | } 89 | 90 | // numLess returns whether a < b. 91 | // a and b must necessarily have the same kind. 92 | func numLess(a, b reflect.Value) bool { 93 | switch a.Kind() { 94 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 95 | return a.Int() < b.Int() 96 | case reflect.Float32, reflect.Float64: 97 | return a.Float() < b.Float() 98 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 99 | return a.Uint() < b.Uint() 100 | case reflect.Bool: 101 | return !a.Bool() && b.Bool() 102 | } 103 | panic("not a number") 104 | } 105 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v1*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v1 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v1](https://gopkg.in/yaml.v1) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v1 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | 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. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v1" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | type T struct { 69 | A string 70 | B struct{C int; D []int ",flow"} 71 | } 72 | 73 | func main() { 74 | t := T{} 75 | 76 | err := yaml.Unmarshal([]byte(data), &t) 77 | if err != nil { 78 | log.Fatalf("error: %v", err) 79 | } 80 | fmt.Printf("--- t:\n%v\n\n", t) 81 | 82 | d, err := yaml.Marshal(&t) 83 | if err != nil { 84 | log.Fatalf("error: %v", err) 85 | } 86 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 87 | 88 | m := make(map[interface{}]interface{}) 89 | 90 | err = yaml.Unmarshal([]byte(data), &m) 91 | if err != nil { 92 | log.Fatalf("error: %v", err) 93 | } 94 | fmt.Printf("--- m:\n%v\n\n", m) 95 | 96 | d, err = yaml.Marshal(&m) 97 | if err != nil { 98 | log.Fatalf("error: %v", err) 99 | } 100 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 101 | } 102 | ``` 103 | 104 | This example will generate the following output: 105 | 106 | ``` 107 | --- t: 108 | {Easy! {2 [3 4]}} 109 | 110 | --- t dump: 111 | a: Easy! 112 | b: 113 | c: 2 114 | d: [3, 4] 115 | 116 | 117 | --- m: 118 | map[a:Easy! b:map[c:2 d:[3 4]]] 119 | 120 | --- m dump: 121 | a: Easy! 122 | b: 123 | c: 2 124 | d: 125 | - 3 126 | - 4 127 | ``` 128 | 129 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Build Status](https://travis-ci.org/splatpm/gout.svg?branch=master)](https://travis-ci.org/splatpm/gout) 4 | # Gout (Go OUTput) 5 | 6 | Gout is a library for handling ascii color and video attributes, output formatting, 7 | program output and logging. 8 | 9 | ## Formatting functions 10 | 11 | There are time and data size formatting functions available, HumanTimeParse() is 12 | mostly only internally useful, but is useful enough that it was included in the 13 | publicly exported API 14 | 15 | * HumanSize(size int64) string 16 | * HumanTimeColon(secs int64) string 17 | * HumanTimeConcise(secs int64) string 18 | * HumanTimeParse(secs int64) map[string]int64 19 | 20 | *Example: Basic usage* 21 | ```go 22 | package main 23 | 24 | import ( 25 | "fmt" 26 | "github.com/splatpm/gout" 27 | ) 28 | 29 | func main() { 30 | fmt.Println(gout.HumanSize(1024)) 31 | } // prints "1.0MB" 32 | ``` 33 | 34 | #### Output functions 35 | 36 | Output functions will optionally also push the messages to a logfile. 37 | Look below for examples of how to use a logfile and how to set verbosity 38 | or prompt options for the console. 39 | 40 | * Info(string, args ...interface{}) 41 | * Debug(string, args ...interface{}election results ) 42 | * Warn(string, args ...interface{}) 43 | * Error(string, args ...interface{}) 44 | * Status(string, args ...interface{}) 45 | 46 | *Example: Basic usage* 47 | 48 | ```go 49 | package main 50 | 51 | import ( 52 | "github.com/splatpm/gout" 53 | ) 54 | 55 | func main() { 56 | gout.Setup(true, false, true, "") // debug, quiet, verbose, logfile 57 | gout.Info("Test %s message", "info") 58 | gout.Debug("Test %s message", "debug") 59 | gout.Warn("Test %s %d", "warning", 1) 60 | gout.Error("error message") 61 | } 62 | ``` 63 | 64 | *Example: Changing the output headers* 65 | ```go 66 | package main 67 | 68 | import ( 69 | "github.com/splatpm/gout" 70 | ) 71 | 72 | func main() { 73 | gout.Setup(true, false, true, "") 74 | gout.Info("Before") 75 | gout.Output.Prompts["info"] = gout.Underline(gout.Green("###")) 76 | gout.Info("After") 77 | } 78 | ``` 79 | 80 | *Example: Setting an output logfile* 81 | ```go 82 | package main 83 | 84 | import ( 85 | "github.com/splatpm/gout" 86 | ) 87 | 88 | func main() { 89 | gout.Setup(true, false, true, "/tmp/my-output.log") 90 | gout.Info("Log message") 91 | // prompts have nothing to do with logfile as only the type of promp 92 | // or the key (ie: info, debug, etc) is used. 93 | } 94 | ``` 95 | 96 | #### String type methods 97 | 98 | The String type is a alias for string, with the following methods. 99 | 100 | * Black() String 101 | * Red() String 102 | * Green() String 103 | * Yellow() String 104 | * Blue() String 105 | * Purple() String 106 | * Cyan() String 107 | * White() String 108 | * Bold() String 109 | * Underline() String 110 | * Blink() String 111 | * Reverse() String 112 | * Conceal() String 113 | 114 | *Example:* 115 | 116 | ```go 117 | package main 118 | 119 | import ( 120 | "fmt" 121 | "github.com/splatpm/gout" 122 | ) 123 | 124 | func main() { 125 | fmt.Println(gout.Bold(gout.Red("TEST"))) 126 | fmt.Println(gout.Blink(gout.Green("TEST"))) 127 | } 128 | ``` 129 | -------------------------------------------------------------------------------- /vendor/git.thwap.org/rockhopper/gout/gout.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014, Mike 'Fuzzy' Partin 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | package gout 28 | 29 | import ( 30 | "log" 31 | "os" 32 | ) 33 | 34 | var ( 35 | Output output 36 | Winsize winsize 37 | Logfile *os.File 38 | ) 39 | 40 | // Output setup function 41 | func Setup(d bool, q bool, v bool, f string) { 42 | var toFile bool 43 | if len(f) > 0 { 44 | Logfile, e := os.OpenFile(f, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 45 | if e != nil { 46 | panic(e) 47 | } 48 | log.SetOutput(Logfile) 49 | toFile = true 50 | } else { 51 | toFile = false 52 | } 53 | Output = output{ 54 | Prompts: make(map[string]string), 55 | Debug: d, 56 | Quiet: q, 57 | Verbose: v, 58 | ToFile: toFile, 59 | Throbber: []string{}, 60 | lastThrob: 0, 61 | } 62 | Output.Prompts["info"] = "INFO" 63 | Output.Prompts["warn"] = "WARN" 64 | Output.Prompts["debug"] = "DEBUG" 65 | Output.Prompts["error"] = "ERROR" 66 | Output.Prompts["status"] = "" 67 | Output.Throbber = []string{"-", "\\", "|", "/"} 68 | } 69 | 70 | // Setup example 71 | /* 72 | func init() { 73 | Winsize = consInfo() 74 | Setup(true, false, true, false) 75 | Output.Prompts["info"] = fmt.Sprintf("%s%s%s", 76 | String(".").Cyan(), 77 | String(".").Bold().Cyan(), 78 | String(".").Bold().White()) 79 | Output.Prompts["warn"] = fmt.Sprintf("%s%s%s", 80 | String(".").Yellow(), 81 | String(".").Bold().Yellow(), 82 | String(".").Bold().White()) 83 | Output.Prompts["debug"] = fmt.Sprintf("%s%s%s", 84 | String(".").Purple(), 85 | String(".").Bold().Purple(), 86 | String(".").Bold().White()) 87 | Output.Prompts["error"] = fmt.Sprintf("%s%s%s", 88 | String(".").Red(), 89 | String(".").Bold().Red(), 90 | String(".").Bold().White()) 91 | Output.Prompts["status"] = fmt.Sprintf("%s%s%s", 92 | String("-").Cyan(), 93 | String("-").Bold().Cyan(), 94 | String("-").Bold().White()) 95 | } 96 | */ 97 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | // utils.go 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "math" 7 | "strings" 8 | 9 | "git.thwap.org/rockhopper/gout" 10 | ) 11 | 12 | func humanSize(i int64) string { 13 | if i >= 1024 && i <= int64(math.Pow(1024, 2)) { 14 | return fmt.Sprintf("%.02fK", (float64(i) / 1024.0)) 15 | } else if i >= int64(math.Pow(1024, 2)) && i <= int64(math.Pow(1024, 3)) { 16 | return fmt.Sprintf("%.02fM", (float64(i) / math.Pow(1024, 2))) 17 | } else if i >= int64(math.Pow(1024, 3)) && i <= int64(math.Pow(1024, 4)) { 18 | return fmt.Sprintf("%.02fG", (float64(i) / math.Pow(1024, 3))) 19 | } else if i >= int64(math.Pow(1024, 4)) && i <= int64(math.Pow(1024, 5)) { 20 | return fmt.Sprintf("%.02fT", (float64(i) / math.Pow(1024, 4))) 21 | } else { 22 | return fmt.Sprintf("%dB", i) 23 | } 24 | } 25 | 26 | func pcheck(e error) { 27 | if e != nil { 28 | panic(e) 29 | } 30 | } 31 | 32 | func doubleProgress(tag string, a, b int, l1, l2 string) string { 33 | var p1, p2 string 34 | // max length 35 | mlen := (40 - (Config.Padding.Left + Config.Padding.Right)) 36 | // ensure we are not over 100% 37 | if a > 100 { 38 | a = 100 39 | } 40 | if b > 100 { 41 | b = 100 42 | } 43 | // ensure our labels are only of len() 2 44 | if len(l1) > 2 { 45 | t := l1[:2] 46 | l1 = t 47 | } 48 | if len(l2) > 2 { 49 | t := l2[:2] 50 | l2 = t 51 | } 52 | // and trunc or pad our tag 53 | if len(tag) > 7 { 54 | t := tag[:7] 55 | tag = t 56 | } else if len(tag) < 7 { 57 | t := fmt.Sprintf("%s%s", tag, strings.Repeat(" ", (7-len(tag)))) 58 | tag = t 59 | } 60 | // bar length 61 | blen := ((mlen - 19) / 2) 62 | // bar 1 63 | bar1 := int(float64(blen) * (float64(a) / 100.0)) 64 | spc1 := (blen - bar1) 65 | if a >= 90 { 66 | p1 = gout.Bold(gout.Red(strings.Repeat("#", int(bar1)))) 67 | } else if a >= 80 { 68 | p1 = gout.Bold(gout.Yellow(strings.Repeat("#", int(bar1)))) 69 | } else { 70 | p1 = gout.Bold(gout.Green(strings.Repeat("#", int(bar1)))) 71 | } 72 | // bar 2 73 | bar2 := int(float64(blen) * (float64(b) / 100.0)) 74 | spc2 := (blen - bar2) 75 | if b >= 90 { 76 | p2 = gout.Bold(gout.Red(strings.Repeat("#", int(bar2)))) 77 | } else if b >= 80 { 78 | p2 = gout.Bold(gout.Yellow(strings.Repeat("#", int(bar2)))) 79 | } else { 80 | p2 = gout.Bold(gout.Green(strings.Repeat("#", int(bar2)))) 81 | } 82 | // and hand it off 83 | return fmt.Sprintf( 84 | "%s: %s:%s%s%s%s %s:%s%s%s%s", 85 | gout.Bold(gout.White(tag)), 86 | gout.Bold(gout.Cyan(l1)), 87 | gout.Yellow("["), 88 | p1, 89 | gout.Cyan(strings.Repeat("-", int(spc1))), 90 | gout.Yellow("]"), 91 | gout.Bold(gout.Cyan(l2)), 92 | gout.Yellow("["), 93 | p2, 94 | gout.Cyan(strings.Repeat("-", int(spc2))), 95 | gout.Yellow("]"), 96 | ) 97 | } 98 | 99 | func progress(l string, i int) string { 100 | var bars, space string 101 | mlen := (40 - (Config.Padding.Left + Config.Padding.Right)) 102 | // make sure we don't go over 100% 103 | if i > 100 { 104 | i = 100 105 | } 106 | // if the label is more than 15chars, trunc it, sorry, space is a premium 107 | if len(l) > 7 { 108 | t := l[:7] 109 | l = t 110 | } else if len(l) < 7 { 111 | t := fmt.Sprintf("%s%s", l, strings.Repeat(" ", (7-len(l)))) 112 | l = t 113 | } 114 | // record our label 115 | label := fmt.Sprintf("%s: ", gout.Bold(gout.White(l))) 116 | // calculate the bar length 117 | blen := int((mlen - (len(l) + 9))) 118 | // calculate the number of hashes and dashes 119 | hash := int(float64(blen) * (float64(i) / 100.0)) 120 | dash := int(blen - hash) 121 | // record our progress bar 122 | le := gout.Yellow("[") 123 | re := gout.Yellow("]") 124 | if i >= 90 { 125 | bars = gout.Bold(gout.Red(strings.Repeat("#", hash))) 126 | } else if i >= 80 { 127 | bars = gout.Bold(gout.Yellow(strings.Repeat("#", hash))) 128 | } else { 129 | bars = gout.Bold(gout.Green(strings.Repeat("#", hash))) 130 | } 131 | space = gout.Cyan(strings.Repeat("-", dash)) 132 | // and hand off our result 133 | return fmt.Sprintf( 134 | "%s%s%s%s%s %s%%", 135 | label, 136 | le, 137 | bars, 138 | space, 139 | re, 140 | gout.Bold(gout.Green(fmt.Sprintf("%3d", i))), 141 | ) 142 | } 143 | -------------------------------------------------------------------------------- /disks.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "math" 7 | "os" 8 | "regexp" 9 | "strconv" 10 | "strings" 11 | "syscall" 12 | "time" 13 | ) 14 | 15 | type Disk struct { 16 | Major int 17 | Minor int 18 | Name string 19 | ReadsCompleted int 20 | ReadsMerged int 21 | SectorsRead int 22 | ReadTime int64 23 | WritesCompleted int 24 | WritesMerged int 25 | SectorsWritten int 26 | WriteTime int64 27 | CurrentIops int 28 | IoTime int64 29 | WeightedIoTime int64 30 | SizeTotal uint64 31 | SizeFree uint64 32 | SizeUsed uint64 33 | } 34 | 35 | func d_isIn(a int, b []int) bool { 36 | for _, v := range b { 37 | if a == v { 38 | return true 39 | } 40 | } 41 | return false 42 | } 43 | 44 | func parseDiskStats() []*Disk { 45 | retv := []*Disk{} 46 | stat := &syscall.Statfs_t{} 47 | 48 | fp, er := os.Open("/proc/diskstats") 49 | pcheck(er) 50 | scanner := bufio.NewScanner(fp) 51 | 52 | for scanner.Scan() { 53 | elem := &Disk{} 54 | idx := 0 55 | for _, v := range strings.Split(scanner.Text(), " ") { 56 | if len(v) > 0 { 57 | value := int64(9999) 58 | var er error 59 | if idx != 2 { 60 | value, er = strconv.ParseInt(v, 10, 64) 61 | pcheck(er) 62 | } 63 | if value == 9999 { 64 | if idx == 2 { 65 | elem.Name = v 66 | } 67 | } else { 68 | if idx == 0 { 69 | elem.Major = int(value) 70 | } else if idx == 1 { 71 | elem.Minor = int(value) 72 | } else if idx == 3 { 73 | elem.ReadsCompleted = int(value) 74 | } else if idx == 4 { 75 | elem.ReadsMerged = int(value) 76 | } else if idx == 5 { 77 | elem.SectorsRead = int(value) 78 | } else if idx == 6 { 79 | elem.ReadTime = value 80 | } else if idx == 7 { 81 | elem.WritesCompleted = int(value) 82 | } else if idx == 8 { 83 | elem.WritesMerged = int(value) 84 | } else if idx == 9 { 85 | elem.SectorsWritten = int(value) 86 | } else if idx == 10 { 87 | elem.WriteTime = value 88 | } else if idx == 11 { 89 | elem.CurrentIops = int(value) 90 | } else if idx == 12 { 91 | elem.IoTime = value 92 | } else if idx == 13 { 93 | elem.WeightedIoTime = value 94 | } 95 | } 96 | idx += 1 97 | value = 9999 98 | } 99 | } 100 | // get our filesystem stats 101 | for _, tv := range Config.Outputs.Disk { 102 | if tv.Name == elem.Name { 103 | syscall.Statfs(fmt.Sprintf(tv.Mount), stat) 104 | elem.SizeTotal = (stat.Blocks * uint64(stat.Bsize)) 105 | elem.SizeFree = (stat.Bfree * uint64(stat.Bsize)) 106 | elem.SizeUsed = (elem.SizeTotal - elem.SizeFree) 107 | } 108 | } 109 | 110 | // and append our element 111 | retv = append(retv, elem) 112 | } 113 | return retv 114 | } 115 | 116 | func DiskProducer() { 117 | // get regex pattern ready 118 | diskRegex, er := regexp.Compile(`^sd[a-z]$`) 119 | pcheck(er) 120 | // let's assume a maximum average throughput of 50MB/sec 121 | max := 50 * math.Pow(1024, 2) 122 | 123 | // no do the things 124 | for { 125 | retv := &CloudShellOutput{Lines: []string{}} 126 | snap1 := parseDiskStats() 127 | time.Sleep(time.Second) 128 | snap2 := parseDiskStats() 129 | 130 | // iterate through first list for sd devices 131 | for _, v := range snap1 { 132 | if diskRegex.MatchString(v.Name) { 133 | time.Sleep(2 * time.Second) 134 | // see if this entry has a matching one in snap2 135 | for _, iv := range snap2 { 136 | if v.Name == iv.Name { 137 | rdSt := (iv.SectorsRead - v.SectorsRead) * 512 138 | rdPc := (float64(rdSt) / float64(max)) * 100.0 139 | wrSt := (iv.SectorsWritten - v.SectorsWritten) * 512 140 | wrPc := (float64(wrSt) / float64(max)) * 100.0 141 | retv.Lines = append( 142 | retv.Lines, 143 | doubleProgress(v.Name, int(rdPc), int(wrPc), "rd", "wr"), 144 | ) 145 | } 146 | } 147 | retv.Type = v.Name 148 | for _, tv := range Config.Outputs.Disk { 149 | if tv.Name == v.Name && tv.Space { 150 | // now get disk used percentage 151 | dup := (float64(v.SizeUsed) / float64(v.SizeTotal)) * 100.0 152 | retv.Lines = append( 153 | retv.Lines, 154 | progress("Used", int(dup)), 155 | ) 156 | } 157 | } 158 | retv.Lines = append(retv.Lines, "") 159 | } 160 | } 161 | Output <- retv 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "math" 7 | "strconv" 8 | "strings" 9 | "unicode/utf8" 10 | ) 11 | 12 | // TODO: merge, timestamps, base 60 floats, omap. 13 | 14 | type resolveMapItem struct { 15 | value interface{} 16 | tag string 17 | } 18 | 19 | var resolveTable = make([]byte, 256) 20 | var resolveMap = make(map[string]resolveMapItem) 21 | 22 | func init() { 23 | t := resolveTable 24 | t[int('+')] = 'S' // Sign 25 | t[int('-')] = 'S' 26 | for _, c := range "0123456789" { 27 | t[int(c)] = 'D' // Digit 28 | } 29 | for _, c := range "yYnNtTfFoO~" { 30 | t[int(c)] = 'M' // In map 31 | } 32 | t[int('.')] = '.' // Float (potentially in map) 33 | 34 | var resolveMapList = []struct { 35 | v interface{} 36 | tag string 37 | l []string 38 | }{ 39 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 40 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 41 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 42 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 43 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 44 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 45 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 46 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 47 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 48 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 49 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 50 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 51 | } 52 | 53 | m := resolveMap 54 | for _, item := range resolveMapList { 55 | for _, s := range item.l { 56 | m[s] = resolveMapItem{item.v, item.tag} 57 | } 58 | } 59 | } 60 | 61 | const longTagPrefix = "tag:yaml.org,2002:" 62 | 63 | func shortTag(tag string) string { 64 | // TODO This can easily be made faster and produce less garbage. 65 | if strings.HasPrefix(tag, longTagPrefix) { 66 | return "!!" + tag[len(longTagPrefix):] 67 | } 68 | return tag 69 | } 70 | 71 | func longTag(tag string) string { 72 | if strings.HasPrefix(tag, "!!") { 73 | return longTagPrefix + tag[2:] 74 | } 75 | return tag 76 | } 77 | 78 | func resolvableTag(tag string) bool { 79 | switch tag { 80 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: 81 | return true 82 | } 83 | return false 84 | } 85 | 86 | func resolve(tag string, in string) (rtag string, out interface{}) { 87 | if !resolvableTag(tag) { 88 | return tag, in 89 | } 90 | 91 | defer func() { 92 | switch tag { 93 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: 94 | return 95 | } 96 | fail(fmt.Sprintf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))) 97 | }() 98 | 99 | // Any data is accepted as a !!str or !!binary. 100 | // Otherwise, the prefix is enough of a hint about what it might be. 101 | hint := byte('N') 102 | if in != "" { 103 | hint = resolveTable[in[0]] 104 | } 105 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 106 | // Handle things we can lookup in a map. 107 | if item, ok := resolveMap[in]; ok { 108 | return item.tag, item.value 109 | } 110 | 111 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 112 | // are purposefully unsupported here. They're still quoted on 113 | // the way out for compatibility with other parser, though. 114 | 115 | switch hint { 116 | case 'M': 117 | // We've already checked the map above. 118 | 119 | case '.': 120 | // Not in the map, so maybe a normal float. 121 | floatv, err := strconv.ParseFloat(in, 64) 122 | if err == nil { 123 | return yaml_FLOAT_TAG, floatv 124 | } 125 | 126 | case 'D', 'S': 127 | // Int, float, or timestamp. 128 | plain := strings.Replace(in, "_", "", -1) 129 | intv, err := strconv.ParseInt(plain, 0, 64) 130 | if err == nil { 131 | if intv == int64(int(intv)) { 132 | return yaml_INT_TAG, int(intv) 133 | } else { 134 | return yaml_INT_TAG, intv 135 | } 136 | } 137 | floatv, err := strconv.ParseFloat(plain, 64) 138 | if err == nil { 139 | return yaml_FLOAT_TAG, floatv 140 | } 141 | if strings.HasPrefix(plain, "0b") { 142 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 143 | if err == nil { 144 | return yaml_INT_TAG, int(intv) 145 | } 146 | } else if strings.HasPrefix(plain, "-0b") { 147 | intv, err := strconv.ParseInt(plain[3:], 2, 64) 148 | if err == nil { 149 | return yaml_INT_TAG, -int(intv) 150 | } 151 | } 152 | // XXX Handle timestamps here. 153 | 154 | default: 155 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 156 | } 157 | } 158 | if tag == yaml_BINARY_TAG { 159 | return yaml_BINARY_TAG, in 160 | } 161 | if utf8.ValidString(in) { 162 | return yaml_STR_TAG, in 163 | } 164 | return yaml_BINARY_TAG, encodeBase64(in) 165 | } 166 | 167 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 168 | // as appropriate for the resulting length. 169 | func encodeBase64(s string) string { 170 | const lineLen = 70 171 | encLen := base64.StdEncoding.EncodedLen(len(s)) 172 | lines := encLen/lineLen + 1 173 | buf := make([]byte, encLen*2+lines) 174 | in := buf[0:encLen] 175 | out := buf[encLen:] 176 | base64.StdEncoding.Encode(in, []byte(s)) 177 | k := 0 178 | for i := 0; i < len(in); i += lineLen { 179 | j := i + lineLen 180 | if j > len(in) { 181 | j = len(in) 182 | } 183 | k += copy(out[k:], in[i:j]) 184 | if lines > 1 { 185 | out[k] = '\n' 186 | k++ 187 | } 188 | } 189 | return string(out[:k]) 190 | } 191 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | const ( 4 | // The size of the input raw buffer. 5 | input_raw_buffer_size = 512 6 | 7 | // The size of the input buffer. 8 | // It should be possible to decode the whole raw buffer. 9 | input_buffer_size = input_raw_buffer_size * 3 10 | 11 | // The size of the output buffer. 12 | output_buffer_size = 128 13 | 14 | // The size of the output raw buffer. 15 | // It should be possible to encode the whole output buffer. 16 | output_raw_buffer_size = (output_buffer_size*2 + 2) 17 | 18 | // The size of other stacks and queues. 19 | initial_stack_size = 16 20 | initial_queue_size = 16 21 | initial_string_size = 16 22 | ) 23 | 24 | // Check if the character at the specified position is an alphabetical 25 | // character, a digit, '_', or '-'. 26 | func is_alpha(b []byte, i int) bool { 27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 28 | } 29 | 30 | // Check if the character at the specified position is a digit. 31 | func is_digit(b []byte, i int) bool { 32 | return b[i] >= '0' && b[i] <= '9' 33 | } 34 | 35 | // Get the value of a digit. 36 | func as_digit(b []byte, i int) int { 37 | return int(b[i]) - '0' 38 | } 39 | 40 | // Check if the character at the specified position is a hex-digit. 41 | func is_hex(b []byte, i int) bool { 42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 43 | } 44 | 45 | // Get the value of a hex-digit. 46 | func as_hex(b []byte, i int) int { 47 | bi := b[i] 48 | if bi >= 'A' && bi <= 'F' { 49 | return int(bi) - 'A' + 10 50 | } 51 | if bi >= 'a' && bi <= 'f' { 52 | return int(bi) - 'a' + 10 53 | } 54 | return int(bi) - '0' 55 | } 56 | 57 | // Check if the character is ASCII. 58 | func is_ascii(b []byte, i int) bool { 59 | return b[i] <= 0x7F 60 | } 61 | 62 | // Check if the character at the start of the buffer can be printed unescaped. 63 | func is_printable(b []byte, i int) bool { 64 | return ((b[i] == 0x0A) || // . == #x0A 65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 67 | (b[i] > 0xC2 && b[i] < 0xED) || 68 | (b[i] == 0xED && b[i+1] < 0xA0) || 69 | (b[i] == 0xEE) || 70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 73 | } 74 | 75 | // Check if the character at the specified position is NUL. 76 | func is_z(b []byte, i int) bool { 77 | return b[i] == 0x00 78 | } 79 | 80 | // Check if the beginning of the buffer is a BOM. 81 | func is_bom(b []byte, i int) bool { 82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 83 | } 84 | 85 | // Check if the character at the specified position is space. 86 | func is_space(b []byte, i int) bool { 87 | return b[i] == ' ' 88 | } 89 | 90 | // Check if the character at the specified position is tab. 91 | func is_tab(b []byte, i int) bool { 92 | return b[i] == '\t' 93 | } 94 | 95 | // Check if the character at the specified position is blank (space or tab). 96 | func is_blank(b []byte, i int) bool { 97 | //return is_space(b, i) || is_tab(b, i) 98 | return b[i] == ' ' || b[i] == '\t' 99 | } 100 | 101 | // Check if the character at the specified position is a line break. 102 | func is_break(b []byte, i int) bool { 103 | return (b[i] == '\r' || // CR (#xD) 104 | b[i] == '\n' || // LF (#xA) 105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 108 | } 109 | 110 | func is_crlf(b []byte, i int) bool { 111 | return b[i] == '\r' && b[i+1] == '\n' 112 | } 113 | 114 | // Check if the character is a line break or NUL. 115 | func is_breakz(b []byte, i int) bool { 116 | //return is_break(b, i) || is_z(b, i) 117 | return ( // is_break: 118 | b[i] == '\r' || // CR (#xD) 119 | b[i] == '\n' || // LF (#xA) 120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 123 | // is_z: 124 | b[i] == 0) 125 | } 126 | 127 | // Check if the character is a line break, space, or NUL. 128 | func is_spacez(b []byte, i int) bool { 129 | //return is_space(b, i) || is_breakz(b, i) 130 | return ( // is_space: 131 | b[i] == ' ' || 132 | // is_breakz: 133 | b[i] == '\r' || // CR (#xD) 134 | b[i] == '\n' || // LF (#xA) 135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 138 | b[i] == 0) 139 | } 140 | 141 | // Check if the character is a line break, space, tab, or NUL. 142 | func is_blankz(b []byte, i int) bool { 143 | //return is_blank(b, i) || is_breakz(b, i) 144 | return ( // is_blank: 145 | b[i] == ' ' || b[i] == '\t' || 146 | // is_breakz: 147 | b[i] == '\r' || // CR (#xD) 148 | b[i] == '\n' || // LF (#xA) 149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 152 | b[i] == 0) 153 | } 154 | 155 | // Determine the width of the character. 156 | func width(b byte) int { 157 | // Don't replace these by a switch without first 158 | // confirming that it is being inlined. 159 | if b&0x80 == 0x00 { 160 | return 1 161 | } 162 | if b&0xE0 == 0xC0 { 163 | return 2 164 | } 165 | if b&0xF0 == 0xE0 { 166 | return 3 167 | } 168 | if b&0xF8 == 0xF0 { 169 | return 4 170 | } 171 | return 0 172 | 173 | } 174 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/encode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "regexp" 6 | "sort" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | type encoder struct { 13 | emitter yaml_emitter_t 14 | event yaml_event_t 15 | out []byte 16 | flow bool 17 | } 18 | 19 | func newEncoder() (e *encoder) { 20 | e = &encoder{} 21 | e.must(yaml_emitter_initialize(&e.emitter)) 22 | yaml_emitter_set_output_string(&e.emitter, &e.out) 23 | e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)) 24 | e.emit() 25 | e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true)) 26 | e.emit() 27 | return e 28 | } 29 | 30 | func (e *encoder) finish() { 31 | e.must(yaml_document_end_event_initialize(&e.event, true)) 32 | e.emit() 33 | e.emitter.open_ended = false 34 | e.must(yaml_stream_end_event_initialize(&e.event)) 35 | e.emit() 36 | } 37 | 38 | func (e *encoder) destroy() { 39 | yaml_emitter_delete(&e.emitter) 40 | } 41 | 42 | func (e *encoder) emit() { 43 | // This will internally delete the e.event value. 44 | if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { 45 | e.must(false) 46 | } 47 | } 48 | 49 | func (e *encoder) must(ok bool) { 50 | if !ok { 51 | msg := e.emitter.problem 52 | if msg == "" { 53 | msg = "Unknown problem generating YAML content" 54 | } 55 | fail(msg) 56 | } 57 | } 58 | 59 | func (e *encoder) marshal(tag string, in reflect.Value) { 60 | if !in.IsValid() { 61 | e.nilv() 62 | return 63 | } 64 | var value interface{} 65 | if getter, ok := in.Interface().(Getter); ok { 66 | tag, value = getter.GetYAML() 67 | tag = longTag(tag) 68 | if value == nil { 69 | e.nilv() 70 | return 71 | } 72 | in = reflect.ValueOf(value) 73 | } 74 | switch in.Kind() { 75 | case reflect.Interface: 76 | if in.IsNil() { 77 | e.nilv() 78 | } else { 79 | e.marshal(tag, in.Elem()) 80 | } 81 | case reflect.Map: 82 | e.mapv(tag, in) 83 | case reflect.Ptr: 84 | if in.IsNil() { 85 | e.nilv() 86 | } else { 87 | e.marshal(tag, in.Elem()) 88 | } 89 | case reflect.Struct: 90 | e.structv(tag, in) 91 | case reflect.Slice: 92 | e.slicev(tag, in) 93 | case reflect.String: 94 | e.stringv(tag, in) 95 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 96 | if in.Type() == durationType { 97 | e.stringv(tag, reflect.ValueOf(in.Interface().(time.Duration).String())) 98 | } else { 99 | e.intv(tag, in) 100 | } 101 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 102 | e.uintv(tag, in) 103 | case reflect.Float32, reflect.Float64: 104 | e.floatv(tag, in) 105 | case reflect.Bool: 106 | e.boolv(tag, in) 107 | default: 108 | panic("Can't marshal type: " + in.Type().String()) 109 | } 110 | } 111 | 112 | func (e *encoder) mapv(tag string, in reflect.Value) { 113 | e.mappingv(tag, func() { 114 | keys := keyList(in.MapKeys()) 115 | sort.Sort(keys) 116 | for _, k := range keys { 117 | e.marshal("", k) 118 | e.marshal("", in.MapIndex(k)) 119 | } 120 | }) 121 | } 122 | 123 | func (e *encoder) structv(tag string, in reflect.Value) { 124 | sinfo, err := getStructInfo(in.Type()) 125 | if err != nil { 126 | panic(err) 127 | } 128 | e.mappingv(tag, func() { 129 | for _, info := range sinfo.FieldsList { 130 | var value reflect.Value 131 | if info.Inline == nil { 132 | value = in.Field(info.Num) 133 | } else { 134 | value = in.FieldByIndex(info.Inline) 135 | } 136 | if info.OmitEmpty && isZero(value) { 137 | continue 138 | } 139 | e.marshal("", reflect.ValueOf(info.Key)) 140 | e.flow = info.Flow 141 | e.marshal("", value) 142 | } 143 | }) 144 | } 145 | 146 | func (e *encoder) mappingv(tag string, f func()) { 147 | implicit := tag == "" 148 | style := yaml_BLOCK_MAPPING_STYLE 149 | if e.flow { 150 | e.flow = false 151 | style = yaml_FLOW_MAPPING_STYLE 152 | } 153 | e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 154 | e.emit() 155 | f() 156 | e.must(yaml_mapping_end_event_initialize(&e.event)) 157 | e.emit() 158 | } 159 | 160 | func (e *encoder) slicev(tag string, in reflect.Value) { 161 | implicit := tag == "" 162 | style := yaml_BLOCK_SEQUENCE_STYLE 163 | if e.flow { 164 | e.flow = false 165 | style = yaml_FLOW_SEQUENCE_STYLE 166 | } 167 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 168 | e.emit() 169 | n := in.Len() 170 | for i := 0; i < n; i++ { 171 | e.marshal("", in.Index(i)) 172 | } 173 | e.must(yaml_sequence_end_event_initialize(&e.event)) 174 | e.emit() 175 | } 176 | 177 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 178 | // 179 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 180 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 181 | // the time being for compatibility with other parsers. 182 | func isBase60Float(s string) (result bool) { 183 | // Fast path. 184 | if s == "" { 185 | return false 186 | } 187 | c := s[0] 188 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 189 | return false 190 | } 191 | // Do the full match. 192 | return base60float.MatchString(s) 193 | } 194 | 195 | // From http://yaml.org/type/float.html, except the regular expression there 196 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 197 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 198 | 199 | func (e *encoder) stringv(tag string, in reflect.Value) { 200 | var style yaml_scalar_style_t 201 | s := in.String() 202 | rtag, rs := resolve("", s) 203 | if rtag == yaml_BINARY_TAG { 204 | if tag == "" || tag == yaml_STR_TAG { 205 | tag = rtag 206 | s = rs.(string) 207 | } else if tag == yaml_BINARY_TAG { 208 | fail("explicitly tagged !!binary data must be base64-encoded") 209 | } else { 210 | fail("cannot marshal invalid UTF-8 data as " + shortTag(tag)) 211 | } 212 | } 213 | if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { 214 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 215 | } else if strings.Contains(s, "\n") { 216 | style = yaml_LITERAL_SCALAR_STYLE 217 | } else { 218 | style = yaml_PLAIN_SCALAR_STYLE 219 | } 220 | e.emitScalar(s, "", tag, style) 221 | } 222 | 223 | func (e *encoder) boolv(tag string, in reflect.Value) { 224 | var s string 225 | if in.Bool() { 226 | s = "true" 227 | } else { 228 | s = "false" 229 | } 230 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 231 | } 232 | 233 | func (e *encoder) intv(tag string, in reflect.Value) { 234 | s := strconv.FormatInt(in.Int(), 10) 235 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 236 | } 237 | 238 | func (e *encoder) uintv(tag string, in reflect.Value) { 239 | s := strconv.FormatUint(in.Uint(), 10) 240 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 241 | } 242 | 243 | func (e *encoder) floatv(tag string, in reflect.Value) { 244 | // FIXME: Handle 64 bits here. 245 | s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) 246 | switch s { 247 | case "+Inf": 248 | s = ".inf" 249 | case "-Inf": 250 | s = "-.inf" 251 | case "NaN": 252 | s = ".nan" 253 | } 254 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 255 | } 256 | 257 | func (e *encoder) nilv() { 258 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) 259 | } 260 | 261 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { 262 | implicit := tag == "" 263 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 264 | e.emit() 265 | } 266 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2011-2014 - Canonical Inc. 3 | 4 | This software is licensed under the LGPLv3, included below. 5 | 6 | As a special exception to the GNU Lesser General Public License version 3 7 | ("LGPL3"), the copyright holders of this Library give you permission to 8 | convey to a third party a Combined Work that links statically or dynamically 9 | to this Library without providing any Minimal Corresponding Source or 10 | Minimal Application Code as set out in 4d or providing the installation 11 | information set out in section 4e, provided that you comply with the other 12 | provisions of LGPL3 and provided that you meet, for the Application the 13 | terms and conditions of the license(s) which apply to the Application. 14 | 15 | Except as stated in this special exception, the provisions of LGPL3 will 16 | continue to comply in full to this Library. If you modify this Library, you 17 | may apply this exception to your version of this Library, but you are not 18 | obliged to do so. If you do not wish to do so, delete this exception 19 | statement from your version. This exception does not (and cannot) modify any 20 | license terms which apply to the Application, with which you must still 21 | comply. 22 | 23 | 24 | GNU LESSER GENERAL PUBLIC LICENSE 25 | Version 3, 29 June 2007 26 | 27 | Copyright (C) 2007 Free Software Foundation, Inc. 28 | Everyone is permitted to copy and distribute verbatim copies 29 | of this license document, but changing it is not allowed. 30 | 31 | 32 | This version of the GNU Lesser General Public License incorporates 33 | the terms and conditions of version 3 of the GNU General Public 34 | License, supplemented by the additional permissions listed below. 35 | 36 | 0. Additional Definitions. 37 | 38 | As used herein, "this License" refers to version 3 of the GNU Lesser 39 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 40 | General Public License. 41 | 42 | "The Library" refers to a covered work governed by this License, 43 | other than an Application or a Combined Work as defined below. 44 | 45 | An "Application" is any work that makes use of an interface provided 46 | by the Library, but which is not otherwise based on the Library. 47 | Defining a subclass of a class defined by the Library is deemed a mode 48 | of using an interface provided by the Library. 49 | 50 | A "Combined Work" is a work produced by combining or linking an 51 | Application with the Library. The particular version of the Library 52 | with which the Combined Work was made is also called the "Linked 53 | Version". 54 | 55 | The "Minimal Corresponding Source" for a Combined Work means the 56 | Corresponding Source for the Combined Work, excluding any source code 57 | for portions of the Combined Work that, considered in isolation, are 58 | based on the Application, and not on the Linked Version. 59 | 60 | The "Corresponding Application Code" for a Combined Work means the 61 | object code and/or source code for the Application, including any data 62 | and utility programs needed for reproducing the Combined Work from the 63 | Application, but excluding the System Libraries of the Combined Work. 64 | 65 | 1. Exception to Section 3 of the GNU GPL. 66 | 67 | You may convey a covered work under sections 3 and 4 of this License 68 | without being bound by section 3 of the GNU GPL. 69 | 70 | 2. Conveying Modified Versions. 71 | 72 | If you modify a copy of the Library, and, in your modifications, a 73 | facility refers to a function or data to be supplied by an Application 74 | that uses the facility (other than as an argument passed when the 75 | facility is invoked), then you may convey a copy of the modified 76 | version: 77 | 78 | a) under this License, provided that you make a good faith effort to 79 | ensure that, in the event an Application does not supply the 80 | function or data, the facility still operates, and performs 81 | whatever part of its purpose remains meaningful, or 82 | 83 | b) under the GNU GPL, with none of the additional permissions of 84 | this License applicable to that copy. 85 | 86 | 3. Object Code Incorporating Material from Library Header Files. 87 | 88 | The object code form of an Application may incorporate material from 89 | a header file that is part of the Library. You may convey such object 90 | code under terms of your choice, provided that, if the incorporated 91 | material is not limited to numerical parameters, data structure 92 | layouts and accessors, or small macros, inline functions and templates 93 | (ten or fewer lines in length), you do both of the following: 94 | 95 | a) Give prominent notice with each copy of the object code that the 96 | Library is used in it and that the Library and its use are 97 | covered by this License. 98 | 99 | b) Accompany the object code with a copy of the GNU GPL and this license 100 | document. 101 | 102 | 4. Combined Works. 103 | 104 | You may convey a Combined Work under terms of your choice that, 105 | taken together, effectively do not restrict modification of the 106 | portions of the Library contained in the Combined Work and reverse 107 | engineering for debugging such modifications, if you also do each of 108 | the following: 109 | 110 | a) Give prominent notice with each copy of the Combined Work that 111 | the Library is used in it and that the Library and its use are 112 | covered by this License. 113 | 114 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 115 | document. 116 | 117 | c) For a Combined Work that displays copyright notices during 118 | execution, include the copyright notice for the Library among 119 | these notices, as well as a reference directing the user to the 120 | copies of the GNU GPL and this license document. 121 | 122 | d) Do one of the following: 123 | 124 | 0) Convey the Minimal Corresponding Source under the terms of this 125 | License, and the Corresponding Application Code in a form 126 | suitable for, and under terms that permit, the user to 127 | recombine or relink the Application with a modified version of 128 | the Linked Version to produce a modified Combined Work, in the 129 | manner specified by section 6 of the GNU GPL for conveying 130 | Corresponding Source. 131 | 132 | 1) Use a suitable shared library mechanism for linking with the 133 | Library. A suitable mechanism is one that (a) uses at run time 134 | a copy of the Library already present on the user's computer 135 | system, and (b) will operate properly with a modified version 136 | of the Library that is interface-compatible with the Linked 137 | Version. 138 | 139 | e) Provide Installation Information, but only if you would otherwise 140 | be required to provide such information under section 6 of the 141 | GNU GPL, and only to the extent that such information is 142 | necessary to install and execute a modified version of the 143 | Combined Work produced by recombining or relinking the 144 | Application with a modified version of the Linked Version. (If 145 | you use option 4d0, the Installation Information must accompany 146 | the Minimal Corresponding Source and Corresponding Application 147 | Code. If you use option 4d1, you must provide the Installation 148 | Information in the manner specified by section 6 of the GNU GPL 149 | for conveying Corresponding Source.) 150 | 151 | 5. Combined Libraries. 152 | 153 | You may place library facilities that are a work based on the 154 | Library side by side in a single library together with other library 155 | facilities that are not Applications and are not covered by this 156 | License, and convey such a combined library under terms of your 157 | choice, if you do both of the following: 158 | 159 | a) Accompany the combined library with a copy of the same work based 160 | on the Library, uncombined with any other library facilities, 161 | conveyed under the terms of this License. 162 | 163 | b) Give prominent notice with the combined library that part of it 164 | is a work based on the Library, and explaining where to find the 165 | accompanying uncombined form of the same work. 166 | 167 | 6. Revised Versions of the GNU Lesser General Public License. 168 | 169 | The Free Software Foundation may publish revised and/or new versions 170 | of the GNU Lesser General Public License from time to time. Such new 171 | versions will be similar in spirit to the present version, but may 172 | differ in detail to address new problems or concerns. 173 | 174 | Each version is given a distinguishing version number. If the 175 | Library as you received it specifies that a certain numbered version 176 | of the GNU Lesser General Public License "or any later version" 177 | applies to it, you have the option of following the terms and 178 | conditions either of that published version or of any later version 179 | published by the Free Software Foundation. If the Library as you 180 | received it does not specify a version number of the GNU Lesser 181 | General Public License, you may choose any version of the GNU Lesser 182 | General Public License ever published by the Free Software Foundation. 183 | 184 | If the Library as you received it specifies that a proxy can decide 185 | whether future versions of the GNU Lesser General Public License shall 186 | apply, that proxy's public statement of acceptance of any version is 187 | permanent authorization for you to choose that version for the 188 | Library. 189 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/yaml.go: -------------------------------------------------------------------------------- 1 | // Package yaml implements YAML support for the Go language. 2 | // 3 | // Source code and other details for the project are available at GitHub: 4 | // 5 | // https://github.com/go-yaml/yaml 6 | // 7 | package yaml 8 | 9 | import ( 10 | "errors" 11 | "fmt" 12 | "reflect" 13 | "strings" 14 | "sync" 15 | ) 16 | 17 | type yamlError string 18 | 19 | func fail(msg string) { 20 | panic(yamlError(msg)) 21 | } 22 | 23 | func handleErr(err *error) { 24 | if r := recover(); r != nil { 25 | if e, ok := r.(yamlError); ok { 26 | *err = errors.New("YAML error: " + string(e)) 27 | } else { 28 | panic(r) 29 | } 30 | } 31 | } 32 | 33 | // The Setter interface may be implemented by types to do their own custom 34 | // unmarshalling of YAML values, rather than being implicitly assigned by 35 | // the yaml package machinery. If setting the value works, the method should 36 | // return true. If it returns false, the value is considered unsupported 37 | // and is omitted from maps and slices. 38 | type Setter interface { 39 | SetYAML(tag string, value interface{}) bool 40 | } 41 | 42 | // The Getter interface is implemented by types to do their own custom 43 | // marshalling into a YAML tag and value. 44 | type Getter interface { 45 | GetYAML() (tag string, value interface{}) 46 | } 47 | 48 | // Unmarshal decodes the first document found within the in byte slice 49 | // and assigns decoded values into the out value. 50 | // 51 | // Maps and pointers (to a struct, string, int, etc) are accepted as out 52 | // values. If an internal pointer within a struct is not initialized, 53 | // the yaml package will initialize it if necessary for unmarshalling 54 | // the provided data. The out parameter must not be nil. 55 | // 56 | // The type of the decoded values and the type of out will be considered, 57 | // and Unmarshal will do the best possible job to unmarshal values 58 | // appropriately. It is NOT considered an error, though, to skip values 59 | // because they are not available in the decoded YAML, or if they are not 60 | // compatible with the out value. To ensure something was properly 61 | // unmarshaled use a map or compare against the previous value for the 62 | // field (usually the zero value). 63 | // 64 | // Struct fields are only unmarshalled if they are exported (have an 65 | // upper case first letter), and are unmarshalled using the field name 66 | // lowercased as the default key. Custom keys may be defined via the 67 | // "yaml" name in the field tag: the content preceding the first comma 68 | // is used as the key, and the following comma-separated options are 69 | // used to tweak the marshalling process (see Marshal). 70 | // Conflicting names result in a runtime error. 71 | // 72 | // For example: 73 | // 74 | // type T struct { 75 | // F int `yaml:"a,omitempty"` 76 | // B int 77 | // } 78 | // var t T 79 | // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) 80 | // 81 | // See the documentation of Marshal for the format of tags and a list of 82 | // supported tag options. 83 | // 84 | func Unmarshal(in []byte, out interface{}) (err error) { 85 | defer handleErr(&err) 86 | d := newDecoder() 87 | p := newParser(in) 88 | defer p.destroy() 89 | node := p.parse() 90 | if node != nil { 91 | v := reflect.ValueOf(out) 92 | if v.Kind() == reflect.Ptr && !v.IsNil() { 93 | v = v.Elem() 94 | } 95 | d.unmarshal(node, v) 96 | } 97 | return nil 98 | } 99 | 100 | // Marshal serializes the value provided into a YAML document. The structure 101 | // of the generated document will reflect the structure of the value itself. 102 | // Maps and pointers (to struct, string, int, etc) are accepted as the in value. 103 | // 104 | // Struct fields are only unmarshalled if they are exported (have an upper case 105 | // first letter), and are unmarshalled using the field name lowercased as the 106 | // default key. Custom keys may be defined via the "yaml" name in the field 107 | // tag: the content preceding the first comma is used as the key, and the 108 | // following comma-separated options are used to tweak the marshalling process. 109 | // Conflicting names result in a runtime error. 110 | // 111 | // The field tag format accepted is: 112 | // 113 | // `(...) yaml:"[][,[,]]" (...)` 114 | // 115 | // The following flags are currently supported: 116 | // 117 | // omitempty Only include the field if it's not set to the zero 118 | // value for the type or to empty slices or maps. 119 | // Does not apply to zero valued structs. 120 | // 121 | // flow Marshal using a flow style (useful for structs, 122 | // sequences and maps. 123 | // 124 | // inline Inline the struct it's applied to, so its fields 125 | // are processed as if they were part of the outer 126 | // struct. 127 | // 128 | // In addition, if the key is "-", the field is ignored. 129 | // 130 | // For example: 131 | // 132 | // type T struct { 133 | // F int "a,omitempty" 134 | // B int 135 | // } 136 | // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" 137 | // yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" 138 | // 139 | func Marshal(in interface{}) (out []byte, err error) { 140 | defer handleErr(&err) 141 | e := newEncoder() 142 | defer e.destroy() 143 | e.marshal("", reflect.ValueOf(in)) 144 | e.finish() 145 | out = e.out 146 | return 147 | } 148 | 149 | // -------------------------------------------------------------------------- 150 | // Maintain a mapping of keys to structure field indexes 151 | 152 | // The code in this section was copied from mgo/bson. 153 | 154 | // structInfo holds details for the serialization of fields of 155 | // a given struct. 156 | type structInfo struct { 157 | FieldsMap map[string]fieldInfo 158 | FieldsList []fieldInfo 159 | 160 | // InlineMap is the number of the field in the struct that 161 | // contains an ,inline map, or -1 if there's none. 162 | InlineMap int 163 | } 164 | 165 | type fieldInfo struct { 166 | Key string 167 | Num int 168 | OmitEmpty bool 169 | Flow bool 170 | 171 | // Inline holds the field index if the field is part of an inlined struct. 172 | Inline []int 173 | } 174 | 175 | var structMap = make(map[reflect.Type]*structInfo) 176 | var fieldMapMutex sync.RWMutex 177 | 178 | func getStructInfo(st reflect.Type) (*structInfo, error) { 179 | fieldMapMutex.RLock() 180 | sinfo, found := structMap[st] 181 | fieldMapMutex.RUnlock() 182 | if found { 183 | return sinfo, nil 184 | } 185 | 186 | n := st.NumField() 187 | fieldsMap := make(map[string]fieldInfo) 188 | fieldsList := make([]fieldInfo, 0, n) 189 | inlineMap := -1 190 | for i := 0; i != n; i++ { 191 | field := st.Field(i) 192 | if field.PkgPath != "" { 193 | continue // Private field 194 | } 195 | 196 | info := fieldInfo{Num: i} 197 | 198 | tag := field.Tag.Get("yaml") 199 | if tag == "" && strings.Index(string(field.Tag), ":") < 0 { 200 | tag = string(field.Tag) 201 | } 202 | if tag == "-" { 203 | continue 204 | } 205 | 206 | inline := false 207 | fields := strings.Split(tag, ",") 208 | if len(fields) > 1 { 209 | for _, flag := range fields[1:] { 210 | switch flag { 211 | case "omitempty": 212 | info.OmitEmpty = true 213 | case "flow": 214 | info.Flow = true 215 | case "inline": 216 | inline = true 217 | default: 218 | return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) 219 | } 220 | } 221 | tag = fields[0] 222 | } 223 | 224 | if inline { 225 | switch field.Type.Kind() { 226 | // TODO: Implement support for inline maps. 227 | //case reflect.Map: 228 | // if inlineMap >= 0 { 229 | // return nil, errors.New("Multiple ,inline maps in struct " + st.String()) 230 | // } 231 | // if field.Type.Key() != reflect.TypeOf("") { 232 | // return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) 233 | // } 234 | // inlineMap = info.Num 235 | case reflect.Struct: 236 | sinfo, err := getStructInfo(field.Type) 237 | if err != nil { 238 | return nil, err 239 | } 240 | for _, finfo := range sinfo.FieldsList { 241 | if _, found := fieldsMap[finfo.Key]; found { 242 | msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() 243 | return nil, errors.New(msg) 244 | } 245 | if finfo.Inline == nil { 246 | finfo.Inline = []int{i, finfo.Num} 247 | } else { 248 | finfo.Inline = append([]int{i}, finfo.Inline...) 249 | } 250 | fieldsMap[finfo.Key] = finfo 251 | fieldsList = append(fieldsList, finfo) 252 | } 253 | default: 254 | //return nil, errors.New("Option ,inline needs a struct value or map field") 255 | return nil, errors.New("Option ,inline needs a struct value field") 256 | } 257 | continue 258 | } 259 | 260 | if tag != "" { 261 | info.Key = tag 262 | } else { 263 | info.Key = strings.ToLower(field.Name) 264 | } 265 | 266 | if _, found = fieldsMap[info.Key]; found { 267 | msg := "Duplicated key '" + info.Key + "' in struct " + st.String() 268 | return nil, errors.New(msg) 269 | } 270 | 271 | fieldsList = append(fieldsList, info) 272 | fieldsMap[info.Key] = info 273 | } 274 | 275 | sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} 276 | 277 | fieldMapMutex.Lock() 278 | structMap[st] = sinfo 279 | fieldMapMutex.Unlock() 280 | return sinfo, nil 281 | } 282 | 283 | func isZero(v reflect.Value) bool { 284 | switch v.Kind() { 285 | case reflect.String: 286 | return len(v.String()) == 0 287 | case reflect.Interface, reflect.Ptr: 288 | return v.IsNil() 289 | case reflect.Slice: 290 | return v.Len() == 0 291 | case reflect.Map: 292 | return v.Len() == 0 293 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 294 | return v.Int() == 0 295 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 296 | return v.Uint() == 0 297 | case reflect.Bool: 298 | return !v.Bool() 299 | } 300 | return false 301 | } 302 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/encode_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strconv" 7 | "strings" 8 | "time" 9 | 10 | . "gopkg.in/check.v1" 11 | "gopkg.in/yaml.v1" 12 | ) 13 | 14 | var marshalIntTest = 123 15 | 16 | var marshalTests = []struct { 17 | value interface{} 18 | data string 19 | }{ 20 | { 21 | nil, 22 | "null\n", 23 | }, { 24 | &struct{}{}, 25 | "{}\n", 26 | }, { 27 | map[string]string{"v": "hi"}, 28 | "v: hi\n", 29 | }, { 30 | map[string]interface{}{"v": "hi"}, 31 | "v: hi\n", 32 | }, { 33 | map[string]string{"v": "true"}, 34 | "v: \"true\"\n", 35 | }, { 36 | map[string]string{"v": "false"}, 37 | "v: \"false\"\n", 38 | }, { 39 | map[string]interface{}{"v": true}, 40 | "v: true\n", 41 | }, { 42 | map[string]interface{}{"v": false}, 43 | "v: false\n", 44 | }, { 45 | map[string]interface{}{"v": 10}, 46 | "v: 10\n", 47 | }, { 48 | map[string]interface{}{"v": -10}, 49 | "v: -10\n", 50 | }, { 51 | map[string]uint{"v": 42}, 52 | "v: 42\n", 53 | }, { 54 | map[string]interface{}{"v": int64(4294967296)}, 55 | "v: 4294967296\n", 56 | }, { 57 | map[string]int64{"v": int64(4294967296)}, 58 | "v: 4294967296\n", 59 | }, { 60 | map[string]uint64{"v": 4294967296}, 61 | "v: 4294967296\n", 62 | }, { 63 | map[string]interface{}{"v": "10"}, 64 | "v: \"10\"\n", 65 | }, { 66 | map[string]interface{}{"v": 0.1}, 67 | "v: 0.1\n", 68 | }, { 69 | map[string]interface{}{"v": float64(0.1)}, 70 | "v: 0.1\n", 71 | }, { 72 | map[string]interface{}{"v": -0.1}, 73 | "v: -0.1\n", 74 | }, { 75 | map[string]interface{}{"v": math.Inf(+1)}, 76 | "v: .inf\n", 77 | }, { 78 | map[string]interface{}{"v": math.Inf(-1)}, 79 | "v: -.inf\n", 80 | }, { 81 | map[string]interface{}{"v": math.NaN()}, 82 | "v: .nan\n", 83 | }, { 84 | map[string]interface{}{"v": nil}, 85 | "v: null\n", 86 | }, { 87 | map[string]interface{}{"v": ""}, 88 | "v: \"\"\n", 89 | }, { 90 | map[string][]string{"v": []string{"A", "B"}}, 91 | "v:\n- A\n- B\n", 92 | }, { 93 | map[string][]string{"v": []string{"A", "B\nC"}}, 94 | "v:\n- A\n- |-\n B\n C\n", 95 | }, { 96 | map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, 97 | "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", 98 | }, { 99 | map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 100 | "a:\n b: c\n", 101 | }, { 102 | map[string]interface{}{"a": "-"}, 103 | "a: '-'\n", 104 | }, 105 | 106 | // Simple values. 107 | { 108 | &marshalIntTest, 109 | "123\n", 110 | }, 111 | 112 | // Structures 113 | { 114 | &struct{ Hello string }{"world"}, 115 | "hello: world\n", 116 | }, { 117 | &struct { 118 | A struct { 119 | B string 120 | } 121 | }{struct{ B string }{"c"}}, 122 | "a:\n b: c\n", 123 | }, { 124 | &struct { 125 | A *struct { 126 | B string 127 | } 128 | }{&struct{ B string }{"c"}}, 129 | "a:\n b: c\n", 130 | }, { 131 | &struct { 132 | A *struct { 133 | B string 134 | } 135 | }{}, 136 | "a: null\n", 137 | }, { 138 | &struct{ A int }{1}, 139 | "a: 1\n", 140 | }, { 141 | &struct{ A []int }{[]int{1, 2}}, 142 | "a:\n- 1\n- 2\n", 143 | }, { 144 | &struct { 145 | B int "a" 146 | }{1}, 147 | "a: 1\n", 148 | }, { 149 | &struct{ A bool }{true}, 150 | "a: true\n", 151 | }, 152 | 153 | // Conditional flag 154 | { 155 | &struct { 156 | A int "a,omitempty" 157 | B int "b,omitempty" 158 | }{1, 0}, 159 | "a: 1\n", 160 | }, { 161 | &struct { 162 | A int "a,omitempty" 163 | B int "b,omitempty" 164 | }{0, 0}, 165 | "{}\n", 166 | }, { 167 | &struct { 168 | A *struct{ X int } "a,omitempty" 169 | B int "b,omitempty" 170 | }{nil, 0}, 171 | "{}\n", 172 | }, 173 | 174 | // Flow flag 175 | { 176 | &struct { 177 | A []int "a,flow" 178 | }{[]int{1, 2}}, 179 | "a: [1, 2]\n", 180 | }, { 181 | &struct { 182 | A map[string]string "a,flow" 183 | }{map[string]string{"b": "c", "d": "e"}}, 184 | "a: {b: c, d: e}\n", 185 | }, { 186 | &struct { 187 | A struct { 188 | B, D string 189 | } "a,flow" 190 | }{struct{ B, D string }{"c", "e"}}, 191 | "a: {b: c, d: e}\n", 192 | }, 193 | 194 | // Unexported field 195 | { 196 | &struct { 197 | u int 198 | A int 199 | }{0, 1}, 200 | "a: 1\n", 201 | }, 202 | 203 | // Ignored field 204 | { 205 | &struct { 206 | A int 207 | B int "-" 208 | }{1, 2}, 209 | "a: 1\n", 210 | }, 211 | 212 | // Struct inlining 213 | { 214 | &struct { 215 | A int 216 | C inlineB `yaml:",inline"` 217 | }{1, inlineB{2, inlineC{3}}}, 218 | "a: 1\nb: 2\nc: 3\n", 219 | }, 220 | 221 | // Duration 222 | { 223 | map[string]time.Duration{"a": 3 * time.Second}, 224 | "a: 3s\n", 225 | }, 226 | 227 | // Issue #24: bug in map merging logic. 228 | { 229 | map[string]string{"a": ""}, 230 | "a: \n", 231 | }, 232 | 233 | // Issue #34: marshal unsupported base 60 floats quoted for compatibility 234 | // with old YAML 1.1 parsers. 235 | { 236 | map[string]string{"a": "1:1"}, 237 | "a: \"1:1\"\n", 238 | }, 239 | 240 | // Binary data. 241 | { 242 | map[string]string{"a": "\x00"}, 243 | "a: \"\\0\"\n", 244 | }, { 245 | map[string]string{"a": "\x80\x81\x82"}, 246 | "a: !!binary gIGC\n", 247 | }, { 248 | map[string]string{"a": strings.Repeat("\x90", 54)}, 249 | "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 250 | }, { 251 | map[string]interface{}{"a": typeWithGetter{"!!str", "\x80\x81\x82"}}, 252 | "a: !!binary gIGC\n", 253 | }, 254 | 255 | // Escaping of tags. 256 | { 257 | map[string]interface{}{"a": typeWithGetter{"foo!bar", 1}}, 258 | "a: ! 1\n", 259 | }, 260 | } 261 | 262 | func (s *S) TestMarshal(c *C) { 263 | for _, item := range marshalTests { 264 | data, err := yaml.Marshal(item.value) 265 | c.Assert(err, IsNil) 266 | c.Assert(string(data), Equals, item.data) 267 | } 268 | } 269 | 270 | var marshalErrorTests = []struct { 271 | value interface{} 272 | error string 273 | panic string 274 | }{{ 275 | value: &struct { 276 | B int 277 | inlineB ",inline" 278 | }{1, inlineB{2, inlineC{3}}}, 279 | panic: `Duplicated key 'b' in struct struct \{ B int; .*`, 280 | }, { 281 | value: typeWithGetter{"!!binary", "\x80"}, 282 | error: "YAML error: explicitly tagged !!binary data must be base64-encoded", 283 | }, { 284 | value: typeWithGetter{"!!float", "\x80"}, 285 | error: `YAML error: cannot marshal invalid UTF-8 data as !!float`, 286 | }} 287 | 288 | func (s *S) TestMarshalErrors(c *C) { 289 | for _, item := range marshalErrorTests { 290 | if item.panic != "" { 291 | c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) 292 | } else { 293 | _, err := yaml.Marshal(item.value) 294 | c.Assert(err, ErrorMatches, item.error) 295 | } 296 | } 297 | } 298 | 299 | var marshalTaggedIfaceTest interface{} = &struct{ A string }{"B"} 300 | 301 | var getterTests = []struct { 302 | data, tag string 303 | value interface{} 304 | }{ 305 | {"_:\n hi: there\n", "", map[interface{}]interface{}{"hi": "there"}}, 306 | {"_:\n- 1\n- A\n", "", []interface{}{1, "A"}}, 307 | {"_: 10\n", "", 10}, 308 | {"_: null\n", "", nil}, 309 | {"_: !foo BAR!\n", "!foo", "BAR!"}, 310 | {"_: !foo 1\n", "!foo", "1"}, 311 | {"_: !foo '\"1\"'\n", "!foo", "\"1\""}, 312 | {"_: !foo 1.1\n", "!foo", 1.1}, 313 | {"_: !foo 1\n", "!foo", 1}, 314 | {"_: !foo 1\n", "!foo", uint(1)}, 315 | {"_: !foo true\n", "!foo", true}, 316 | {"_: !foo\n- A\n- B\n", "!foo", []string{"A", "B"}}, 317 | {"_: !foo\n A: B\n", "!foo", map[string]string{"A": "B"}}, 318 | {"_: !foo\n a: B\n", "!foo", &marshalTaggedIfaceTest}, 319 | } 320 | 321 | func (s *S) TestMarshalTypeCache(c *C) { 322 | var data []byte 323 | var err error 324 | func() { 325 | type T struct{ A int } 326 | data, err = yaml.Marshal(&T{}) 327 | c.Assert(err, IsNil) 328 | }() 329 | func() { 330 | type T struct{ B int } 331 | data, err = yaml.Marshal(&T{}) 332 | c.Assert(err, IsNil) 333 | }() 334 | c.Assert(string(data), Equals, "b: 0\n") 335 | } 336 | 337 | type typeWithGetter struct { 338 | tag string 339 | value interface{} 340 | } 341 | 342 | func (o typeWithGetter) GetYAML() (tag string, value interface{}) { 343 | return o.tag, o.value 344 | } 345 | 346 | type typeWithGetterField struct { 347 | Field typeWithGetter "_" 348 | } 349 | 350 | func (s *S) TestMashalWithGetter(c *C) { 351 | for _, item := range getterTests { 352 | obj := &typeWithGetterField{} 353 | obj.Field.tag = item.tag 354 | obj.Field.value = item.value 355 | data, err := yaml.Marshal(obj) 356 | c.Assert(err, IsNil) 357 | c.Assert(string(data), Equals, string(item.data)) 358 | } 359 | } 360 | 361 | func (s *S) TestUnmarshalWholeDocumentWithGetter(c *C) { 362 | obj := &typeWithGetter{} 363 | obj.tag = "" 364 | obj.value = map[string]string{"hello": "world!"} 365 | data, err := yaml.Marshal(obj) 366 | c.Assert(err, IsNil) 367 | c.Assert(string(data), Equals, "hello: world!\n") 368 | } 369 | 370 | func (s *S) TestSortedOutput(c *C) { 371 | order := []interface{}{ 372 | false, 373 | true, 374 | 1, 375 | uint(1), 376 | 1.0, 377 | 1.1, 378 | 1.2, 379 | 2, 380 | uint(2), 381 | 2.0, 382 | 2.1, 383 | "", 384 | ".1", 385 | ".2", 386 | ".a", 387 | "1", 388 | "2", 389 | "a!10", 390 | "a/2", 391 | "a/10", 392 | "a~10", 393 | "ab/1", 394 | "b/1", 395 | "b/01", 396 | "b/2", 397 | "b/02", 398 | "b/3", 399 | "b/03", 400 | "b1", 401 | "b01", 402 | "b3", 403 | "c2.10", 404 | "c10.2", 405 | "d1", 406 | "d12", 407 | "d12a", 408 | } 409 | m := make(map[interface{}]int) 410 | for _, k := range order { 411 | m[k] = 1 412 | } 413 | data, err := yaml.Marshal(m) 414 | c.Assert(err, IsNil) 415 | out := "\n" + string(data) 416 | last := 0 417 | for i, k := range order { 418 | repr := fmt.Sprint(k) 419 | if s, ok := k.(string); ok { 420 | if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { 421 | repr = `"` + repr + `"` 422 | } 423 | } 424 | index := strings.Index(out, "\n"+repr+":") 425 | if index == -1 { 426 | c.Fatalf("%#v is not in the output: %#v", k, out) 427 | } 428 | if index < last { 429 | c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) 430 | } 431 | last = index 432 | } 433 | } 434 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/readerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // Set the reader error and return 0. 8 | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { 9 | parser.error = yaml_READER_ERROR 10 | parser.problem = problem 11 | parser.problem_offset = offset 12 | parser.problem_value = value 13 | return false 14 | } 15 | 16 | // Byte order marks. 17 | const ( 18 | bom_UTF8 = "\xef\xbb\xbf" 19 | bom_UTF16LE = "\xff\xfe" 20 | bom_UTF16BE = "\xfe\xff" 21 | ) 22 | 23 | // Determine the input stream encoding by checking the BOM symbol. If no BOM is 24 | // found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. 25 | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { 26 | // Ensure that we had enough bytes in the raw buffer. 27 | for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { 28 | if !yaml_parser_update_raw_buffer(parser) { 29 | return false 30 | } 31 | } 32 | 33 | // Determine the encoding. 34 | buf := parser.raw_buffer 35 | pos := parser.raw_buffer_pos 36 | avail := len(buf) - pos 37 | if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { 38 | parser.encoding = yaml_UTF16LE_ENCODING 39 | parser.raw_buffer_pos += 2 40 | parser.offset += 2 41 | } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { 42 | parser.encoding = yaml_UTF16BE_ENCODING 43 | parser.raw_buffer_pos += 2 44 | parser.offset += 2 45 | } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { 46 | parser.encoding = yaml_UTF8_ENCODING 47 | parser.raw_buffer_pos += 3 48 | parser.offset += 3 49 | } else { 50 | parser.encoding = yaml_UTF8_ENCODING 51 | } 52 | return true 53 | } 54 | 55 | // Update the raw buffer. 56 | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { 57 | size_read := 0 58 | 59 | // Return if the raw buffer is full. 60 | if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { 61 | return true 62 | } 63 | 64 | // Return on EOF. 65 | if parser.eof { 66 | return true 67 | } 68 | 69 | // Move the remaining bytes in the raw buffer to the beginning. 70 | if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { 71 | copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) 72 | } 73 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] 74 | parser.raw_buffer_pos = 0 75 | 76 | // Call the read handler to fill the buffer. 77 | size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) 78 | parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] 79 | if err == io.EOF { 80 | parser.eof = true 81 | } else if err != nil { 82 | return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) 83 | } 84 | return true 85 | } 86 | 87 | // Ensure that the buffer contains at least `length` characters. 88 | // Return true on success, false on failure. 89 | // 90 | // The length is supposed to be significantly less that the buffer size. 91 | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { 92 | if parser.read_handler == nil { 93 | panic("read handler must be set") 94 | } 95 | 96 | // If the EOF flag is set and the raw buffer is empty, do nothing. 97 | if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { 98 | return true 99 | } 100 | 101 | // Return if the buffer contains enough characters. 102 | if parser.unread >= length { 103 | return true 104 | } 105 | 106 | // Determine the input encoding if it is not known yet. 107 | if parser.encoding == yaml_ANY_ENCODING { 108 | if !yaml_parser_determine_encoding(parser) { 109 | return false 110 | } 111 | } 112 | 113 | // Move the unread characters to the beginning of the buffer. 114 | buffer_len := len(parser.buffer) 115 | if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { 116 | copy(parser.buffer, parser.buffer[parser.buffer_pos:]) 117 | buffer_len -= parser.buffer_pos 118 | parser.buffer_pos = 0 119 | } else if parser.buffer_pos == buffer_len { 120 | buffer_len = 0 121 | parser.buffer_pos = 0 122 | } 123 | 124 | // Open the whole buffer for writing, and cut it before returning. 125 | parser.buffer = parser.buffer[:cap(parser.buffer)] 126 | 127 | // Fill the buffer until it has enough characters. 128 | first := true 129 | for parser.unread < length { 130 | 131 | // Fill the raw buffer if necessary. 132 | if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { 133 | if !yaml_parser_update_raw_buffer(parser) { 134 | parser.buffer = parser.buffer[:buffer_len] 135 | return false 136 | } 137 | } 138 | first = false 139 | 140 | // Decode the raw buffer. 141 | inner: 142 | for parser.raw_buffer_pos != len(parser.raw_buffer) { 143 | var value rune 144 | var width int 145 | 146 | raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos 147 | 148 | // Decode the next character. 149 | switch parser.encoding { 150 | case yaml_UTF8_ENCODING: 151 | // Decode a UTF-8 character. Check RFC 3629 152 | // (http://www.ietf.org/rfc/rfc3629.txt) for more details. 153 | // 154 | // The following table (taken from the RFC) is used for 155 | // decoding. 156 | // 157 | // Char. number range | UTF-8 octet sequence 158 | // (hexadecimal) | (binary) 159 | // --------------------+------------------------------------ 160 | // 0000 0000-0000 007F | 0xxxxxxx 161 | // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx 162 | // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 163 | // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 164 | // 165 | // Additionally, the characters in the range 0xD800-0xDFFF 166 | // are prohibited as they are reserved for use with UTF-16 167 | // surrogate pairs. 168 | 169 | // Determine the length of the UTF-8 sequence. 170 | octet := parser.raw_buffer[parser.raw_buffer_pos] 171 | switch { 172 | case octet&0x80 == 0x00: 173 | width = 1 174 | case octet&0xE0 == 0xC0: 175 | width = 2 176 | case octet&0xF0 == 0xE0: 177 | width = 3 178 | case octet&0xF8 == 0xF0: 179 | width = 4 180 | default: 181 | // The leading octet is invalid. 182 | return yaml_parser_set_reader_error(parser, 183 | "invalid leading UTF-8 octet", 184 | parser.offset, int(octet)) 185 | } 186 | 187 | // Check if the raw buffer contains an incomplete character. 188 | if width > raw_unread { 189 | if parser.eof { 190 | return yaml_parser_set_reader_error(parser, 191 | "incomplete UTF-8 octet sequence", 192 | parser.offset, -1) 193 | } 194 | break inner 195 | } 196 | 197 | // Decode the leading octet. 198 | switch { 199 | case octet&0x80 == 0x00: 200 | value = rune(octet & 0x7F) 201 | case octet&0xE0 == 0xC0: 202 | value = rune(octet & 0x1F) 203 | case octet&0xF0 == 0xE0: 204 | value = rune(octet & 0x0F) 205 | case octet&0xF8 == 0xF0: 206 | value = rune(octet & 0x07) 207 | default: 208 | value = 0 209 | } 210 | 211 | // Check and decode the trailing octets. 212 | for k := 1; k < width; k++ { 213 | octet = parser.raw_buffer[parser.raw_buffer_pos+k] 214 | 215 | // Check if the octet is valid. 216 | if (octet & 0xC0) != 0x80 { 217 | return yaml_parser_set_reader_error(parser, 218 | "invalid trailing UTF-8 octet", 219 | parser.offset+k, int(octet)) 220 | } 221 | 222 | // Decode the octet. 223 | value = (value << 6) + rune(octet&0x3F) 224 | } 225 | 226 | // Check the length of the sequence against the value. 227 | switch { 228 | case width == 1: 229 | case width == 2 && value >= 0x80: 230 | case width == 3 && value >= 0x800: 231 | case width == 4 && value >= 0x10000: 232 | default: 233 | return yaml_parser_set_reader_error(parser, 234 | "invalid length of a UTF-8 sequence", 235 | parser.offset, -1) 236 | } 237 | 238 | // Check the range of the value. 239 | if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { 240 | return yaml_parser_set_reader_error(parser, 241 | "invalid Unicode character", 242 | parser.offset, int(value)) 243 | } 244 | 245 | case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: 246 | var low, high int 247 | if parser.encoding == yaml_UTF16LE_ENCODING { 248 | low, high = 0, 1 249 | } else { 250 | high, low = 1, 0 251 | } 252 | 253 | // The UTF-16 encoding is not as simple as one might 254 | // naively think. Check RFC 2781 255 | // (http://www.ietf.org/rfc/rfc2781.txt). 256 | // 257 | // Normally, two subsequent bytes describe a Unicode 258 | // character. However a special technique (called a 259 | // surrogate pair) is used for specifying character 260 | // values larger than 0xFFFF. 261 | // 262 | // A surrogate pair consists of two pseudo-characters: 263 | // high surrogate area (0xD800-0xDBFF) 264 | // low surrogate area (0xDC00-0xDFFF) 265 | // 266 | // The following formulas are used for decoding 267 | // and encoding characters using surrogate pairs: 268 | // 269 | // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) 270 | // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) 271 | // W1 = 110110yyyyyyyyyy 272 | // W2 = 110111xxxxxxxxxx 273 | // 274 | // where U is the character value, W1 is the high surrogate 275 | // area, W2 is the low surrogate area. 276 | 277 | // Check for incomplete UTF-16 character. 278 | if raw_unread < 2 { 279 | if parser.eof { 280 | return yaml_parser_set_reader_error(parser, 281 | "incomplete UTF-16 character", 282 | parser.offset, -1) 283 | } 284 | break inner 285 | } 286 | 287 | // Get the character. 288 | value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + 289 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) 290 | 291 | // Check for unexpected low surrogate area. 292 | if value&0xFC00 == 0xDC00 { 293 | return yaml_parser_set_reader_error(parser, 294 | "unexpected low surrogate area", 295 | parser.offset, int(value)) 296 | } 297 | 298 | // Check for a high surrogate area. 299 | if value&0xFC00 == 0xD800 { 300 | width = 4 301 | 302 | // Check for incomplete surrogate pair. 303 | if raw_unread < 4 { 304 | if parser.eof { 305 | return yaml_parser_set_reader_error(parser, 306 | "incomplete UTF-16 surrogate pair", 307 | parser.offset, -1) 308 | } 309 | break inner 310 | } 311 | 312 | // Get the next character. 313 | value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + 314 | (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) 315 | 316 | // Check for a low surrogate area. 317 | if value2&0xFC00 != 0xDC00 { 318 | return yaml_parser_set_reader_error(parser, 319 | "expected low surrogate area", 320 | parser.offset+2, int(value2)) 321 | } 322 | 323 | // Generate the value of the surrogate pair. 324 | value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) 325 | } else { 326 | width = 2 327 | } 328 | 329 | default: 330 | panic("impossible") 331 | } 332 | 333 | // Check if the character is in the allowed range: 334 | // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) 335 | // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) 336 | // | [#x10000-#x10FFFF] (32 bit) 337 | switch { 338 | case value == 0x09: 339 | case value == 0x0A: 340 | case value == 0x0D: 341 | case value >= 0x20 && value <= 0x7E: 342 | case value == 0x85: 343 | case value >= 0xA0 && value <= 0xD7FF: 344 | case value >= 0xE000 && value <= 0xFFFD: 345 | case value >= 0x10000 && value <= 0x10FFFF: 346 | default: 347 | return yaml_parser_set_reader_error(parser, 348 | "control characters are not allowed", 349 | parser.offset, int(value)) 350 | } 351 | 352 | // Move the raw pointers. 353 | parser.raw_buffer_pos += width 354 | parser.offset += width 355 | 356 | // Finally put the character into the buffer. 357 | if value <= 0x7F { 358 | // 0000 0000-0000 007F . 0xxxxxxx 359 | parser.buffer[buffer_len+0] = byte(value) 360 | } else if value <= 0x7FF { 361 | // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx 362 | parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) 363 | parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) 364 | } else if value <= 0xFFFF { 365 | // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx 366 | parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) 367 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) 368 | parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) 369 | } else { 370 | // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 371 | parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) 372 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) 373 | parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) 374 | parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) 375 | } 376 | buffer_len += width 377 | 378 | parser.unread++ 379 | } 380 | 381 | // On EOF, put NUL into the buffer and return. 382 | if parser.eof { 383 | parser.buffer[buffer_len] = 0 384 | buffer_len++ 385 | parser.unread++ 386 | break 387 | } 388 | } 389 | parser.buffer = parser.buffer[:buffer_len] 390 | return true 391 | } 392 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/decode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "reflect" 7 | "strconv" 8 | "time" 9 | ) 10 | 11 | const ( 12 | documentNode = 1 << iota 13 | mappingNode 14 | sequenceNode 15 | scalarNode 16 | aliasNode 17 | ) 18 | 19 | type node struct { 20 | kind int 21 | line, column int 22 | tag string 23 | value string 24 | implicit bool 25 | children []*node 26 | anchors map[string]*node 27 | } 28 | 29 | // ---------------------------------------------------------------------------- 30 | // Parser, produces a node tree out of a libyaml event stream. 31 | 32 | type parser struct { 33 | parser yaml_parser_t 34 | event yaml_event_t 35 | doc *node 36 | } 37 | 38 | func newParser(b []byte) *parser { 39 | p := parser{} 40 | if !yaml_parser_initialize(&p.parser) { 41 | panic("Failed to initialize YAML emitter") 42 | } 43 | 44 | if len(b) == 0 { 45 | b = []byte{'\n'} 46 | } 47 | 48 | yaml_parser_set_input_string(&p.parser, b) 49 | 50 | p.skip() 51 | if p.event.typ != yaml_STREAM_START_EVENT { 52 | panic("Expected stream start event, got " + strconv.Itoa(int(p.event.typ))) 53 | } 54 | p.skip() 55 | return &p 56 | } 57 | 58 | func (p *parser) destroy() { 59 | if p.event.typ != yaml_NO_EVENT { 60 | yaml_event_delete(&p.event) 61 | } 62 | yaml_parser_delete(&p.parser) 63 | } 64 | 65 | func (p *parser) skip() { 66 | if p.event.typ != yaml_NO_EVENT { 67 | if p.event.typ == yaml_STREAM_END_EVENT { 68 | fail("Attempted to go past the end of stream. Corrupted value?") 69 | } 70 | yaml_event_delete(&p.event) 71 | } 72 | if !yaml_parser_parse(&p.parser, &p.event) { 73 | p.fail() 74 | } 75 | } 76 | 77 | func (p *parser) fail() { 78 | var where string 79 | var line int 80 | if p.parser.problem_mark.line != 0 { 81 | line = p.parser.problem_mark.line 82 | } else if p.parser.context_mark.line != 0 { 83 | line = p.parser.context_mark.line 84 | } 85 | if line != 0 { 86 | where = "line " + strconv.Itoa(line) + ": " 87 | } 88 | var msg string 89 | if len(p.parser.problem) > 0 { 90 | msg = p.parser.problem 91 | } else { 92 | msg = "Unknown problem parsing YAML content" 93 | } 94 | fail(where + msg) 95 | } 96 | 97 | func (p *parser) anchor(n *node, anchor []byte) { 98 | if anchor != nil { 99 | p.doc.anchors[string(anchor)] = n 100 | } 101 | } 102 | 103 | func (p *parser) parse() *node { 104 | switch p.event.typ { 105 | case yaml_SCALAR_EVENT: 106 | return p.scalar() 107 | case yaml_ALIAS_EVENT: 108 | return p.alias() 109 | case yaml_MAPPING_START_EVENT: 110 | return p.mapping() 111 | case yaml_SEQUENCE_START_EVENT: 112 | return p.sequence() 113 | case yaml_DOCUMENT_START_EVENT: 114 | return p.document() 115 | case yaml_STREAM_END_EVENT: 116 | // Happens when attempting to decode an empty buffer. 117 | return nil 118 | default: 119 | panic("Attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ))) 120 | } 121 | panic("unreachable") 122 | } 123 | 124 | func (p *parser) node(kind int) *node { 125 | return &node{ 126 | kind: kind, 127 | line: p.event.start_mark.line, 128 | column: p.event.start_mark.column, 129 | } 130 | } 131 | 132 | func (p *parser) document() *node { 133 | n := p.node(documentNode) 134 | n.anchors = make(map[string]*node) 135 | p.doc = n 136 | p.skip() 137 | n.children = append(n.children, p.parse()) 138 | if p.event.typ != yaml_DOCUMENT_END_EVENT { 139 | panic("Expected end of document event but got " + strconv.Itoa(int(p.event.typ))) 140 | } 141 | p.skip() 142 | return n 143 | } 144 | 145 | func (p *parser) alias() *node { 146 | n := p.node(aliasNode) 147 | n.value = string(p.event.anchor) 148 | p.skip() 149 | return n 150 | } 151 | 152 | func (p *parser) scalar() *node { 153 | n := p.node(scalarNode) 154 | n.value = string(p.event.value) 155 | n.tag = string(p.event.tag) 156 | n.implicit = p.event.implicit 157 | p.anchor(n, p.event.anchor) 158 | p.skip() 159 | return n 160 | } 161 | 162 | func (p *parser) sequence() *node { 163 | n := p.node(sequenceNode) 164 | p.anchor(n, p.event.anchor) 165 | p.skip() 166 | for p.event.typ != yaml_SEQUENCE_END_EVENT { 167 | n.children = append(n.children, p.parse()) 168 | } 169 | p.skip() 170 | return n 171 | } 172 | 173 | func (p *parser) mapping() *node { 174 | n := p.node(mappingNode) 175 | p.anchor(n, p.event.anchor) 176 | p.skip() 177 | for p.event.typ != yaml_MAPPING_END_EVENT { 178 | n.children = append(n.children, p.parse(), p.parse()) 179 | } 180 | p.skip() 181 | return n 182 | } 183 | 184 | // ---------------------------------------------------------------------------- 185 | // Decoder, unmarshals a node into a provided value. 186 | 187 | type decoder struct { 188 | doc *node 189 | aliases map[string]bool 190 | } 191 | 192 | func newDecoder() *decoder { 193 | d := &decoder{} 194 | d.aliases = make(map[string]bool) 195 | return d 196 | } 197 | 198 | // d.setter deals with setters and pointer dereferencing and initialization. 199 | // 200 | // It's a slightly convoluted case to handle properly: 201 | // 202 | // - nil pointers should be initialized, unless being set to nil 203 | // - we don't know at this point yet what's the value to SetYAML() with. 204 | // - we can't separate pointer deref/init and setter checking, because 205 | // a setter may be found while going down a pointer chain. 206 | // 207 | // Thus, here is how it takes care of it: 208 | // 209 | // - out is provided as a pointer, so that it can be replaced. 210 | // - when looking at a non-setter ptr, *out=ptr.Elem(), unless tag=!!null 211 | // - when a setter is found, *out=interface{}, and a set() function is 212 | // returned to call SetYAML() with the value of *out once it's defined. 213 | // 214 | func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) { 215 | if (*out).Kind() != reflect.Ptr && (*out).CanAddr() { 216 | setter, _ := (*out).Addr().Interface().(Setter) 217 | if setter != nil { 218 | var arg interface{} 219 | *out = reflect.ValueOf(&arg).Elem() 220 | return func() { 221 | *good = setter.SetYAML(shortTag(tag), arg) 222 | } 223 | } 224 | } 225 | again := true 226 | for again { 227 | again = false 228 | setter, _ := (*out).Interface().(Setter) 229 | if tag != yaml_NULL_TAG || setter != nil { 230 | if pv := (*out); pv.Kind() == reflect.Ptr { 231 | if pv.IsNil() { 232 | *out = reflect.New(pv.Type().Elem()).Elem() 233 | pv.Set((*out).Addr()) 234 | } else { 235 | *out = pv.Elem() 236 | } 237 | setter, _ = pv.Interface().(Setter) 238 | again = true 239 | } 240 | } 241 | if setter != nil { 242 | var arg interface{} 243 | *out = reflect.ValueOf(&arg).Elem() 244 | return func() { 245 | *good = setter.SetYAML(shortTag(tag), arg) 246 | } 247 | } 248 | } 249 | return nil 250 | } 251 | 252 | func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { 253 | switch n.kind { 254 | case documentNode: 255 | good = d.document(n, out) 256 | case scalarNode: 257 | good = d.scalar(n, out) 258 | case aliasNode: 259 | good = d.alias(n, out) 260 | case mappingNode: 261 | good = d.mapping(n, out) 262 | case sequenceNode: 263 | good = d.sequence(n, out) 264 | default: 265 | panic("Internal error: unknown node kind: " + strconv.Itoa(n.kind)) 266 | } 267 | return 268 | } 269 | 270 | func (d *decoder) document(n *node, out reflect.Value) (good bool) { 271 | if len(n.children) == 1 { 272 | d.doc = n 273 | d.unmarshal(n.children[0], out) 274 | return true 275 | } 276 | return false 277 | } 278 | 279 | func (d *decoder) alias(n *node, out reflect.Value) (good bool) { 280 | an, ok := d.doc.anchors[n.value] 281 | if !ok { 282 | fail("Unknown anchor '" + n.value + "' referenced") 283 | } 284 | if d.aliases[n.value] { 285 | fail("Anchor '" + n.value + "' value contains itself") 286 | } 287 | d.aliases[n.value] = true 288 | good = d.unmarshal(an, out) 289 | delete(d.aliases, n.value) 290 | return good 291 | } 292 | 293 | var zeroValue reflect.Value 294 | 295 | func resetMap(out reflect.Value) { 296 | for _, k := range out.MapKeys() { 297 | out.SetMapIndex(k, zeroValue) 298 | } 299 | } 300 | 301 | var durationType = reflect.TypeOf(time.Duration(0)) 302 | 303 | func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { 304 | var tag string 305 | var resolved interface{} 306 | if n.tag == "" && !n.implicit { 307 | tag = yaml_STR_TAG 308 | resolved = n.value 309 | } else { 310 | tag, resolved = resolve(n.tag, n.value) 311 | if tag == yaml_BINARY_TAG { 312 | data, err := base64.StdEncoding.DecodeString(resolved.(string)) 313 | if err != nil { 314 | fail("!!binary value contains invalid base64 data") 315 | } 316 | resolved = string(data) 317 | } 318 | } 319 | if set := d.setter(tag, &out, &good); set != nil { 320 | defer set() 321 | } 322 | if resolved == nil { 323 | if out.Kind() == reflect.Map && !out.CanAddr() { 324 | resetMap(out) 325 | } else { 326 | out.Set(reflect.Zero(out.Type())) 327 | } 328 | good = true 329 | return 330 | } 331 | switch out.Kind() { 332 | case reflect.String: 333 | if tag == yaml_BINARY_TAG { 334 | out.SetString(resolved.(string)) 335 | good = true 336 | } else if resolved != nil { 337 | out.SetString(n.value) 338 | good = true 339 | } 340 | case reflect.Interface: 341 | if resolved == nil { 342 | out.Set(reflect.Zero(out.Type())) 343 | } else { 344 | out.Set(reflect.ValueOf(resolved)) 345 | } 346 | good = true 347 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 348 | switch resolved := resolved.(type) { 349 | case int: 350 | if !out.OverflowInt(int64(resolved)) { 351 | out.SetInt(int64(resolved)) 352 | good = true 353 | } 354 | case int64: 355 | if !out.OverflowInt(resolved) { 356 | out.SetInt(resolved) 357 | good = true 358 | } 359 | case float64: 360 | if resolved < 1<<63-1 && !out.OverflowInt(int64(resolved)) { 361 | out.SetInt(int64(resolved)) 362 | good = true 363 | } 364 | case string: 365 | if out.Type() == durationType { 366 | d, err := time.ParseDuration(resolved) 367 | if err == nil { 368 | out.SetInt(int64(d)) 369 | good = true 370 | } 371 | } 372 | } 373 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 374 | switch resolved := resolved.(type) { 375 | case int: 376 | if resolved >= 0 { 377 | out.SetUint(uint64(resolved)) 378 | good = true 379 | } 380 | case int64: 381 | if resolved >= 0 { 382 | out.SetUint(uint64(resolved)) 383 | good = true 384 | } 385 | case float64: 386 | if resolved < 1<<64-1 && !out.OverflowUint(uint64(resolved)) { 387 | out.SetUint(uint64(resolved)) 388 | good = true 389 | } 390 | } 391 | case reflect.Bool: 392 | switch resolved := resolved.(type) { 393 | case bool: 394 | out.SetBool(resolved) 395 | good = true 396 | } 397 | case reflect.Float32, reflect.Float64: 398 | switch resolved := resolved.(type) { 399 | case int: 400 | out.SetFloat(float64(resolved)) 401 | good = true 402 | case int64: 403 | out.SetFloat(float64(resolved)) 404 | good = true 405 | case float64: 406 | out.SetFloat(resolved) 407 | good = true 408 | } 409 | case reflect.Ptr: 410 | if out.Type().Elem() == reflect.TypeOf(resolved) { 411 | elem := reflect.New(out.Type().Elem()) 412 | elem.Elem().Set(reflect.ValueOf(resolved)) 413 | out.Set(elem) 414 | good = true 415 | } 416 | } 417 | return good 418 | } 419 | 420 | func settableValueOf(i interface{}) reflect.Value { 421 | v := reflect.ValueOf(i) 422 | sv := reflect.New(v.Type()).Elem() 423 | sv.Set(v) 424 | return sv 425 | } 426 | 427 | func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { 428 | if set := d.setter(yaml_SEQ_TAG, &out, &good); set != nil { 429 | defer set() 430 | } 431 | var iface reflect.Value 432 | if out.Kind() == reflect.Interface { 433 | // No type hints. Will have to use a generic sequence. 434 | iface = out 435 | out = settableValueOf(make([]interface{}, 0)) 436 | } 437 | 438 | if out.Kind() != reflect.Slice { 439 | return false 440 | } 441 | et := out.Type().Elem() 442 | 443 | l := len(n.children) 444 | for i := 0; i < l; i++ { 445 | e := reflect.New(et).Elem() 446 | if ok := d.unmarshal(n.children[i], e); ok { 447 | out.Set(reflect.Append(out, e)) 448 | } 449 | } 450 | if iface.IsValid() { 451 | iface.Set(out) 452 | } 453 | return true 454 | } 455 | 456 | func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { 457 | if set := d.setter(yaml_MAP_TAG, &out, &good); set != nil { 458 | defer set() 459 | } 460 | if out.Kind() == reflect.Struct { 461 | return d.mappingStruct(n, out) 462 | } 463 | 464 | if out.Kind() == reflect.Interface { 465 | // No type hints. Will have to use a generic map. 466 | iface := out 467 | out = settableValueOf(make(map[interface{}]interface{})) 468 | iface.Set(out) 469 | } 470 | 471 | if out.Kind() != reflect.Map { 472 | return false 473 | } 474 | outt := out.Type() 475 | kt := outt.Key() 476 | et := outt.Elem() 477 | 478 | if out.IsNil() { 479 | out.Set(reflect.MakeMap(outt)) 480 | } 481 | l := len(n.children) 482 | for i := 0; i < l; i += 2 { 483 | if isMerge(n.children[i]) { 484 | d.merge(n.children[i+1], out) 485 | continue 486 | } 487 | k := reflect.New(kt).Elem() 488 | if d.unmarshal(n.children[i], k) { 489 | kkind := k.Kind() 490 | if kkind == reflect.Interface { 491 | kkind = k.Elem().Kind() 492 | } 493 | if kkind == reflect.Map || kkind == reflect.Slice { 494 | fail(fmt.Sprintf("invalid map key: %#v", k.Interface())) 495 | } 496 | e := reflect.New(et).Elem() 497 | if d.unmarshal(n.children[i+1], e) { 498 | out.SetMapIndex(k, e) 499 | } 500 | } 501 | } 502 | return true 503 | } 504 | 505 | func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { 506 | sinfo, err := getStructInfo(out.Type()) 507 | if err != nil { 508 | panic(err) 509 | } 510 | name := settableValueOf("") 511 | l := len(n.children) 512 | for i := 0; i < l; i += 2 { 513 | ni := n.children[i] 514 | if isMerge(ni) { 515 | d.merge(n.children[i+1], out) 516 | continue 517 | } 518 | if !d.unmarshal(ni, name) { 519 | continue 520 | } 521 | if info, ok := sinfo.FieldsMap[name.String()]; ok { 522 | var field reflect.Value 523 | if info.Inline == nil { 524 | field = out.Field(info.Num) 525 | } else { 526 | field = out.FieldByIndex(info.Inline) 527 | } 528 | d.unmarshal(n.children[i+1], field) 529 | } 530 | } 531 | return true 532 | } 533 | 534 | func (d *decoder) merge(n *node, out reflect.Value) { 535 | const wantMap = "map merge requires map or sequence of maps as the value" 536 | switch n.kind { 537 | case mappingNode: 538 | d.unmarshal(n, out) 539 | case aliasNode: 540 | an, ok := d.doc.anchors[n.value] 541 | if ok && an.kind != mappingNode { 542 | fail(wantMap) 543 | } 544 | d.unmarshal(n, out) 545 | case sequenceNode: 546 | // Step backwards as earlier nodes take precedence. 547 | for i := len(n.children) - 1; i >= 0; i-- { 548 | ni := n.children[i] 549 | if ni.kind == aliasNode { 550 | an, ok := d.doc.anchors[ni.value] 551 | if ok && an.kind != mappingNode { 552 | fail(wantMap) 553 | } 554 | } else if ni.kind != mappingNode { 555 | fail(wantMap) 556 | } 557 | d.unmarshal(ni, out) 558 | } 559 | default: 560 | fail(wantMap) 561 | } 562 | } 563 | 564 | func isMerge(n *node) bool { 565 | return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) 566 | } 567 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/decode_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | "gopkg.in/yaml.v1" 6 | "math" 7 | "reflect" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | var unmarshalIntTest = 123 13 | 14 | var unmarshalTests = []struct { 15 | data string 16 | value interface{} 17 | }{ 18 | { 19 | "", 20 | &struct{}{}, 21 | }, { 22 | "{}", &struct{}{}, 23 | }, { 24 | "v: hi", 25 | map[string]string{"v": "hi"}, 26 | }, { 27 | "v: hi", map[string]interface{}{"v": "hi"}, 28 | }, { 29 | "v: true", 30 | map[string]string{"v": "true"}, 31 | }, { 32 | "v: true", 33 | map[string]interface{}{"v": true}, 34 | }, { 35 | "v: 10", 36 | map[string]interface{}{"v": 10}, 37 | }, { 38 | "v: 0b10", 39 | map[string]interface{}{"v": 2}, 40 | }, { 41 | "v: 0xA", 42 | map[string]interface{}{"v": 10}, 43 | }, { 44 | "v: 4294967296", 45 | map[string]int64{"v": 4294967296}, 46 | }, { 47 | "v: 0.1", 48 | map[string]interface{}{"v": 0.1}, 49 | }, { 50 | "v: .1", 51 | map[string]interface{}{"v": 0.1}, 52 | }, { 53 | "v: .Inf", 54 | map[string]interface{}{"v": math.Inf(+1)}, 55 | }, { 56 | "v: -.Inf", 57 | map[string]interface{}{"v": math.Inf(-1)}, 58 | }, { 59 | "v: -10", 60 | map[string]interface{}{"v": -10}, 61 | }, { 62 | "v: -.1", 63 | map[string]interface{}{"v": -0.1}, 64 | }, 65 | 66 | // Simple values. 67 | { 68 | "123", 69 | &unmarshalIntTest, 70 | }, 71 | 72 | // Floats from spec 73 | { 74 | "canonical: 6.8523e+5", 75 | map[string]interface{}{"canonical": 6.8523e+5}, 76 | }, { 77 | "expo: 685.230_15e+03", 78 | map[string]interface{}{"expo": 685.23015e+03}, 79 | }, { 80 | "fixed: 685_230.15", 81 | map[string]interface{}{"fixed": 685230.15}, 82 | }, { 83 | "neginf: -.inf", 84 | map[string]interface{}{"neginf": math.Inf(-1)}, 85 | }, { 86 | "fixed: 685_230.15", 87 | map[string]float64{"fixed": 685230.15}, 88 | }, 89 | //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 90 | //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 91 | 92 | // Bools from spec 93 | { 94 | "canonical: y", 95 | map[string]interface{}{"canonical": true}, 96 | }, { 97 | "answer: NO", 98 | map[string]interface{}{"answer": false}, 99 | }, { 100 | "logical: True", 101 | map[string]interface{}{"logical": true}, 102 | }, { 103 | "option: on", 104 | map[string]interface{}{"option": true}, 105 | }, { 106 | "option: on", 107 | map[string]bool{"option": true}, 108 | }, 109 | // Ints from spec 110 | { 111 | "canonical: 685230", 112 | map[string]interface{}{"canonical": 685230}, 113 | }, { 114 | "decimal: +685_230", 115 | map[string]interface{}{"decimal": 685230}, 116 | }, { 117 | "octal: 02472256", 118 | map[string]interface{}{"octal": 685230}, 119 | }, { 120 | "hexa: 0x_0A_74_AE", 121 | map[string]interface{}{"hexa": 685230}, 122 | }, { 123 | "bin: 0b1010_0111_0100_1010_1110", 124 | map[string]interface{}{"bin": 685230}, 125 | }, { 126 | "bin: -0b101010", 127 | map[string]interface{}{"bin": -42}, 128 | }, { 129 | "decimal: +685_230", 130 | map[string]int{"decimal": 685230}, 131 | }, 132 | 133 | //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 134 | 135 | // Nulls from spec 136 | { 137 | "empty:", 138 | map[string]interface{}{"empty": nil}, 139 | }, { 140 | "canonical: ~", 141 | map[string]interface{}{"canonical": nil}, 142 | }, { 143 | "english: null", 144 | map[string]interface{}{"english": nil}, 145 | }, { 146 | "~: null key", 147 | map[interface{}]string{nil: "null key"}, 148 | }, { 149 | "empty:", 150 | map[string]*bool{"empty": nil}, 151 | }, 152 | 153 | // Flow sequence 154 | { 155 | "seq: [A,B]", 156 | map[string]interface{}{"seq": []interface{}{"A", "B"}}, 157 | }, { 158 | "seq: [A,B,C,]", 159 | map[string][]string{"seq": []string{"A", "B", "C"}}, 160 | }, { 161 | "seq: [A,1,C]", 162 | map[string][]string{"seq": []string{"A", "1", "C"}}, 163 | }, { 164 | "seq: [A,1,C]", 165 | map[string][]int{"seq": []int{1}}, 166 | }, { 167 | "seq: [A,1,C]", 168 | map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 169 | }, 170 | // Block sequence 171 | { 172 | "seq:\n - A\n - B", 173 | map[string]interface{}{"seq": []interface{}{"A", "B"}}, 174 | }, { 175 | "seq:\n - A\n - B\n - C", 176 | map[string][]string{"seq": []string{"A", "B", "C"}}, 177 | }, { 178 | "seq:\n - A\n - 1\n - C", 179 | map[string][]string{"seq": []string{"A", "1", "C"}}, 180 | }, { 181 | "seq:\n - A\n - 1\n - C", 182 | map[string][]int{"seq": []int{1}}, 183 | }, { 184 | "seq:\n - A\n - 1\n - C", 185 | map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 186 | }, 187 | 188 | // Literal block scalar 189 | { 190 | "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 191 | map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, 192 | }, 193 | 194 | // Folded block scalar 195 | { 196 | "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 197 | map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, 198 | }, 199 | 200 | // Map inside interface with no type hints. 201 | { 202 | "a: {b: c}", 203 | map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 204 | }, 205 | 206 | // Structs and type conversions. 207 | { 208 | "hello: world", 209 | &struct{ Hello string }{"world"}, 210 | }, { 211 | "a: {b: c}", 212 | &struct{ A struct{ B string } }{struct{ B string }{"c"}}, 213 | }, { 214 | "a: {b: c}", 215 | &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, 216 | }, { 217 | "a: {b: c}", 218 | &struct{ A map[string]string }{map[string]string{"b": "c"}}, 219 | }, { 220 | "a: {b: c}", 221 | &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, 222 | }, { 223 | "a:", 224 | &struct{ A map[string]string }{}, 225 | }, { 226 | "a: 1", 227 | &struct{ A int }{1}, 228 | }, { 229 | "a: 1", 230 | &struct{ A float64 }{1}, 231 | }, { 232 | "a: 1.0", 233 | &struct{ A int }{1}, 234 | }, { 235 | "a: 1.0", 236 | &struct{ A uint }{1}, 237 | }, { 238 | "a: [1, 2]", 239 | &struct{ A []int }{[]int{1, 2}}, 240 | }, { 241 | "a: 1", 242 | &struct{ B int }{0}, 243 | }, { 244 | "a: 1", 245 | &struct { 246 | B int "a" 247 | }{1}, 248 | }, { 249 | "a: y", 250 | &struct{ A bool }{true}, 251 | }, 252 | 253 | // Some cross type conversions 254 | { 255 | "v: 42", 256 | map[string]uint{"v": 42}, 257 | }, { 258 | "v: -42", 259 | map[string]uint{}, 260 | }, { 261 | "v: 4294967296", 262 | map[string]uint64{"v": 4294967296}, 263 | }, { 264 | "v: -4294967296", 265 | map[string]uint64{}, 266 | }, 267 | 268 | // Overflow cases. 269 | { 270 | "v: 4294967297", 271 | map[string]int32{}, 272 | }, { 273 | "v: 128", 274 | map[string]int8{}, 275 | }, 276 | 277 | // Quoted values. 278 | { 279 | "'1': '\"2\"'", 280 | map[interface{}]interface{}{"1": "\"2\""}, 281 | }, { 282 | "v:\n- A\n- 'B\n\n C'\n", 283 | map[string][]string{"v": []string{"A", "B\nC"}}, 284 | }, 285 | 286 | // Explicit tags. 287 | { 288 | "v: !!float '1.1'", 289 | map[string]interface{}{"v": 1.1}, 290 | }, { 291 | "v: !!null ''", 292 | map[string]interface{}{"v": nil}, 293 | }, { 294 | "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 295 | map[string]interface{}{"v": 1}, 296 | }, 297 | 298 | // Anchors and aliases. 299 | { 300 | "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 301 | &struct{ A, B, C, D int }{1, 2, 1, 2}, 302 | }, { 303 | "a: &a {c: 1}\nb: *a", 304 | &struct { 305 | A, B struct { 306 | C int 307 | } 308 | }{struct{ C int }{1}, struct{ C int }{1}}, 309 | }, { 310 | "a: &a [1, 2]\nb: *a", 311 | &struct{ B []int }{[]int{1, 2}}, 312 | }, 313 | 314 | // Bug #1133337 315 | { 316 | "foo: ''", 317 | map[string]*string{"foo": new(string)}, 318 | }, { 319 | "foo: null", 320 | map[string]string{"foo": ""}, 321 | }, { 322 | "foo: null", 323 | map[string]interface{}{"foo": nil}, 324 | }, 325 | 326 | // Ignored field 327 | { 328 | "a: 1\nb: 2\n", 329 | &struct { 330 | A int 331 | B int "-" 332 | }{1, 0}, 333 | }, 334 | 335 | // Bug #1191981 336 | { 337 | "" + 338 | "%YAML 1.1\n" + 339 | "--- !!str\n" + 340 | `"Generic line break (no glyph)\n\` + "\n" + 341 | ` Generic line break (glyphed)\n\` + "\n" + 342 | ` Line separator\u2028\` + "\n" + 343 | ` Paragraph separator\u2029"` + "\n", 344 | "" + 345 | "Generic line break (no glyph)\n" + 346 | "Generic line break (glyphed)\n" + 347 | "Line separator\u2028Paragraph separator\u2029", 348 | }, 349 | 350 | // Struct inlining 351 | { 352 | "a: 1\nb: 2\nc: 3\n", 353 | &struct { 354 | A int 355 | C inlineB `yaml:",inline"` 356 | }{1, inlineB{2, inlineC{3}}}, 357 | }, 358 | 359 | // bug 1243827 360 | { 361 | "a: -b_c", 362 | map[string]interface{}{"a": "-b_c"}, 363 | }, 364 | { 365 | "a: +b_c", 366 | map[string]interface{}{"a": "+b_c"}, 367 | }, 368 | { 369 | "a: 50cent_of_dollar", 370 | map[string]interface{}{"a": "50cent_of_dollar"}, 371 | }, 372 | 373 | // Duration 374 | { 375 | "a: 3s", 376 | map[string]time.Duration{"a": 3 * time.Second}, 377 | }, 378 | 379 | // Issue #24. 380 | { 381 | "a: ", 382 | map[string]string{"a": ""}, 383 | }, 384 | 385 | // Base 60 floats are obsolete and unsupported. 386 | { 387 | "a: 1:1\n", 388 | map[string]string{"a": "1:1"}, 389 | }, 390 | 391 | // Binary data. 392 | { 393 | "a: !!binary gIGC\n", 394 | map[string]string{"a": "\x80\x81\x82"}, 395 | }, { 396 | "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 397 | map[string]string{"a": strings.Repeat("\x90", 54)}, 398 | }, { 399 | "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", 400 | map[string]string{"a": strings.Repeat("\x00", 52)}, 401 | }, 402 | } 403 | 404 | type inlineB struct { 405 | B int 406 | inlineC `yaml:",inline"` 407 | } 408 | 409 | type inlineC struct { 410 | C int 411 | } 412 | 413 | func (s *S) TestUnmarshal(c *C) { 414 | for i, item := range unmarshalTests { 415 | t := reflect.ValueOf(item.value).Type() 416 | var value interface{} 417 | switch t.Kind() { 418 | case reflect.Map: 419 | value = reflect.MakeMap(t).Interface() 420 | case reflect.String: 421 | t := reflect.ValueOf(item.value).Type() 422 | v := reflect.New(t) 423 | value = v.Interface() 424 | default: 425 | pt := reflect.ValueOf(item.value).Type() 426 | pv := reflect.New(pt.Elem()) 427 | value = pv.Interface() 428 | } 429 | err := yaml.Unmarshal([]byte(item.data), value) 430 | c.Assert(err, IsNil, Commentf("Item #%d", i)) 431 | if t.Kind() == reflect.String { 432 | c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i)) 433 | } else { 434 | c.Assert(value, DeepEquals, item.value, Commentf("Item #%d", i)) 435 | } 436 | } 437 | } 438 | 439 | func (s *S) TestUnmarshalNaN(c *C) { 440 | value := map[string]interface{}{} 441 | err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) 442 | c.Assert(err, IsNil) 443 | c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 444 | } 445 | 446 | var unmarshalErrorTests = []struct { 447 | data, error string 448 | }{ 449 | {"v: !!float 'error'", "YAML error: cannot decode !!str `error` as a !!float"}, 450 | {"v: [A,", "YAML error: line 1: did not find expected node content"}, 451 | {"v:\n- [A,", "YAML error: line 2: did not find expected node content"}, 452 | {"a: *b\n", "YAML error: Unknown anchor 'b' referenced"}, 453 | {"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"}, 454 | {"value: -", "YAML error: block sequence entries are not allowed in this context"}, 455 | {"a: !!binary ==", "YAML error: !!binary value contains invalid base64 data"}, 456 | {"{[.]}", `YAML error: invalid map key: \[\]interface \{\}\{"\."\}`}, 457 | {"{{.}}", `YAML error: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, 458 | } 459 | 460 | func (s *S) TestUnmarshalErrors(c *C) { 461 | for _, item := range unmarshalErrorTests { 462 | var value interface{} 463 | err := yaml.Unmarshal([]byte(item.data), &value) 464 | c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 465 | } 466 | } 467 | 468 | var setterTests = []struct { 469 | data, tag string 470 | value interface{} 471 | }{ 472 | {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 473 | {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 474 | {"_: 10", "!!int", 10}, 475 | {"_: null", "!!null", nil}, 476 | {`_: BAR!`, "!!str", "BAR!"}, 477 | {`_: "BAR!"`, "!!str", "BAR!"}, 478 | {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 479 | } 480 | 481 | var setterResult = map[int]bool{} 482 | 483 | type typeWithSetter struct { 484 | tag string 485 | value interface{} 486 | } 487 | 488 | func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) { 489 | o.tag = tag 490 | o.value = value 491 | if i, ok := value.(int); ok { 492 | if result, ok := setterResult[i]; ok { 493 | return result 494 | } 495 | } 496 | return true 497 | } 498 | 499 | type setterPointerType struct { 500 | Field *typeWithSetter "_" 501 | } 502 | 503 | type setterValueType struct { 504 | Field typeWithSetter "_" 505 | } 506 | 507 | func (s *S) TestUnmarshalWithPointerSetter(c *C) { 508 | for _, item := range setterTests { 509 | obj := &setterPointerType{} 510 | err := yaml.Unmarshal([]byte(item.data), obj) 511 | c.Assert(err, IsNil) 512 | c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 513 | c.Assert(obj.Field.tag, Equals, item.tag) 514 | c.Assert(obj.Field.value, DeepEquals, item.value) 515 | } 516 | } 517 | 518 | func (s *S) TestUnmarshalWithValueSetter(c *C) { 519 | for _, item := range setterTests { 520 | obj := &setterValueType{} 521 | err := yaml.Unmarshal([]byte(item.data), obj) 522 | c.Assert(err, IsNil) 523 | c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 524 | c.Assert(obj.Field.tag, Equals, item.tag) 525 | c.Assert(obj.Field.value, DeepEquals, item.value) 526 | } 527 | } 528 | 529 | func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) { 530 | obj := &typeWithSetter{} 531 | err := yaml.Unmarshal([]byte(setterTests[0].data), obj) 532 | c.Assert(err, IsNil) 533 | c.Assert(obj.tag, Equals, setterTests[0].tag) 534 | value, ok := obj.value.(map[interface{}]interface{}) 535 | c.Assert(ok, Equals, true) 536 | c.Assert(value["_"], DeepEquals, setterTests[0].value) 537 | } 538 | 539 | func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) { 540 | setterResult[2] = false 541 | setterResult[4] = false 542 | defer func() { 543 | delete(setterResult, 2) 544 | delete(setterResult, 4) 545 | }() 546 | 547 | m := map[string]*typeWithSetter{} 548 | data := `{abc: 1, def: 2, ghi: 3, jkl: 4}` 549 | err := yaml.Unmarshal([]byte(data), m) 550 | c.Assert(err, IsNil) 551 | c.Assert(m["abc"], NotNil) 552 | c.Assert(m["def"], IsNil) 553 | c.Assert(m["ghi"], NotNil) 554 | c.Assert(m["jkl"], IsNil) 555 | 556 | c.Assert(m["abc"].value, Equals, 1) 557 | c.Assert(m["ghi"].value, Equals, 3) 558 | } 559 | 560 | // From http://yaml.org/type/merge.html 561 | var mergeTests = ` 562 | anchors: 563 | - &CENTER { "x": 1, "y": 2 } 564 | - &LEFT { "x": 0, "y": 2 } 565 | - &BIG { "r": 10 } 566 | - &SMALL { "r": 1 } 567 | 568 | # All the following maps are equal: 569 | 570 | plain: 571 | # Explicit keys 572 | "x": 1 573 | "y": 2 574 | "r": 10 575 | label: center/big 576 | 577 | mergeOne: 578 | # Merge one map 579 | << : *CENTER 580 | "r": 10 581 | label: center/big 582 | 583 | mergeMultiple: 584 | # Merge multiple maps 585 | << : [ *CENTER, *BIG ] 586 | label: center/big 587 | 588 | override: 589 | # Override 590 | << : [ *BIG, *LEFT, *SMALL ] 591 | "x": 1 592 | label: center/big 593 | 594 | shortTag: 595 | # Explicit short merge tag 596 | !!merge "<<" : [ *CENTER, *BIG ] 597 | label: center/big 598 | 599 | longTag: 600 | # Explicit merge long tag 601 | ! "<<" : [ *CENTER, *BIG ] 602 | label: center/big 603 | 604 | inlineMap: 605 | # Inlined map 606 | << : {"x": 1, "y": 2, "r": 10} 607 | label: center/big 608 | 609 | inlineSequenceMap: 610 | # Inlined map in sequence 611 | << : [ *CENTER, {"r": 10} ] 612 | label: center/big 613 | ` 614 | 615 | func (s *S) TestMerge(c *C) { 616 | var want = map[interface{}]interface{}{ 617 | "x": 1, 618 | "y": 2, 619 | "r": 10, 620 | "label": "center/big", 621 | } 622 | 623 | var m map[string]interface{} 624 | err := yaml.Unmarshal([]byte(mergeTests), &m) 625 | c.Assert(err, IsNil) 626 | for name, test := range m { 627 | if name == "anchors" { 628 | continue 629 | } 630 | c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) 631 | } 632 | } 633 | 634 | func (s *S) TestMergeStruct(c *C) { 635 | type Data struct { 636 | X, Y, R int 637 | Label string 638 | } 639 | want := Data{1, 2, 10, "center/big"} 640 | 641 | var m map[string]Data 642 | err := yaml.Unmarshal([]byte(mergeTests), &m) 643 | c.Assert(err, IsNil) 644 | for name, test := range m { 645 | if name == "anchors" { 646 | continue 647 | } 648 | c.Assert(test, Equals, want, Commentf("test %q failed", name)) 649 | } 650 | } 651 | 652 | var unmarshalNullTests = []func() interface{}{ 653 | func() interface{} { var v interface{}; v = "v"; return &v }, 654 | func() interface{} { var s = "s"; return &s }, 655 | func() interface{} { var s = "s"; sptr := &s; return &sptr }, 656 | func() interface{} { var i = 1; return &i }, 657 | func() interface{} { var i = 1; iptr := &i; return &iptr }, 658 | func() interface{} { m := map[string]int{"s": 1}; return &m }, 659 | func() interface{} { m := map[string]int{"s": 1}; return m }, 660 | } 661 | 662 | func (s *S) TestUnmarshalNull(c *C) { 663 | for _, test := range unmarshalNullTests { 664 | item := test() 665 | zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() 666 | err := yaml.Unmarshal([]byte("null"), item) 667 | c.Assert(err, IsNil) 668 | if reflect.TypeOf(item).Kind() == reflect.Map { 669 | c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) 670 | } else { 671 | c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) 672 | } 673 | } 674 | } 675 | 676 | //var data []byte 677 | //func init() { 678 | // var err error 679 | // data, err = ioutil.ReadFile("/tmp/file.yaml") 680 | // if err != nil { 681 | // panic(err) 682 | // } 683 | //} 684 | // 685 | //func (s *S) BenchmarkUnmarshal(c *C) { 686 | // var err error 687 | // for i := 0; i < c.N; i++ { 688 | // var v map[string]interface{} 689 | // err = yaml.Unmarshal(data, &v) 690 | // } 691 | // if err != nil { 692 | // panic(err) 693 | // } 694 | //} 695 | // 696 | //func (s *S) BenchmarkMarshal(c *C) { 697 | // var v map[string]interface{} 698 | // yaml.Unmarshal(data, &v) 699 | // c.ResetTimer() 700 | // for i := 0; i < c.N; i++ { 701 | // yaml.Marshal(&v) 702 | // } 703 | //} 704 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/apic.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | "os" 6 | ) 7 | 8 | func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { 9 | //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) 10 | 11 | // Check if we can move the queue at the beginning of the buffer. 12 | if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { 13 | if parser.tokens_head != len(parser.tokens) { 14 | copy(parser.tokens, parser.tokens[parser.tokens_head:]) 15 | } 16 | parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] 17 | parser.tokens_head = 0 18 | } 19 | parser.tokens = append(parser.tokens, *token) 20 | if pos < 0 { 21 | return 22 | } 23 | copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) 24 | parser.tokens[parser.tokens_head+pos] = *token 25 | } 26 | 27 | // Create a new parser object. 28 | func yaml_parser_initialize(parser *yaml_parser_t) bool { 29 | *parser = yaml_parser_t{ 30 | raw_buffer: make([]byte, 0, input_raw_buffer_size), 31 | buffer: make([]byte, 0, input_buffer_size), 32 | } 33 | return true 34 | } 35 | 36 | // Destroy a parser object. 37 | func yaml_parser_delete(parser *yaml_parser_t) { 38 | *parser = yaml_parser_t{} 39 | } 40 | 41 | // String read handler. 42 | func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { 43 | if parser.input_pos == len(parser.input) { 44 | return 0, io.EOF 45 | } 46 | n = copy(buffer, parser.input[parser.input_pos:]) 47 | parser.input_pos += n 48 | return n, nil 49 | } 50 | 51 | // File read handler. 52 | func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { 53 | return parser.input_file.Read(buffer) 54 | } 55 | 56 | // Set a string input. 57 | func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { 58 | if parser.read_handler != nil { 59 | panic("must set the input source only once") 60 | } 61 | parser.read_handler = yaml_string_read_handler 62 | parser.input = input 63 | parser.input_pos = 0 64 | } 65 | 66 | // Set a file input. 67 | func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) { 68 | if parser.read_handler != nil { 69 | panic("must set the input source only once") 70 | } 71 | parser.read_handler = yaml_file_read_handler 72 | parser.input_file = file 73 | } 74 | 75 | // Set the source encoding. 76 | func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { 77 | if parser.encoding != yaml_ANY_ENCODING { 78 | panic("must set the encoding only once") 79 | } 80 | parser.encoding = encoding 81 | } 82 | 83 | // Create a new emitter object. 84 | func yaml_emitter_initialize(emitter *yaml_emitter_t) bool { 85 | *emitter = yaml_emitter_t{ 86 | buffer: make([]byte, output_buffer_size), 87 | raw_buffer: make([]byte, 0, output_raw_buffer_size), 88 | states: make([]yaml_emitter_state_t, 0, initial_stack_size), 89 | events: make([]yaml_event_t, 0, initial_queue_size), 90 | } 91 | return true 92 | } 93 | 94 | // Destroy an emitter object. 95 | func yaml_emitter_delete(emitter *yaml_emitter_t) { 96 | *emitter = yaml_emitter_t{} 97 | } 98 | 99 | // String write handler. 100 | func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { 101 | *emitter.output_buffer = append(*emitter.output_buffer, buffer...) 102 | return nil 103 | } 104 | 105 | // File write handler. 106 | func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error { 107 | _, err := emitter.output_file.Write(buffer) 108 | return err 109 | } 110 | 111 | // Set a string output. 112 | func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { 113 | if emitter.write_handler != nil { 114 | panic("must set the output target only once") 115 | } 116 | emitter.write_handler = yaml_string_write_handler 117 | emitter.output_buffer = output_buffer 118 | } 119 | 120 | // Set a file output. 121 | func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Writer) { 122 | if emitter.write_handler != nil { 123 | panic("must set the output target only once") 124 | } 125 | emitter.write_handler = yaml_file_write_handler 126 | emitter.output_file = file 127 | } 128 | 129 | // Set the output encoding. 130 | func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { 131 | if emitter.encoding != yaml_ANY_ENCODING { 132 | panic("must set the output encoding only once") 133 | } 134 | emitter.encoding = encoding 135 | } 136 | 137 | // Set the canonical output style. 138 | func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { 139 | emitter.canonical = canonical 140 | } 141 | 142 | //// Set the indentation increment. 143 | func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { 144 | if indent < 2 || indent > 9 { 145 | indent = 2 146 | } 147 | emitter.best_indent = indent 148 | } 149 | 150 | // Set the preferred line width. 151 | func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { 152 | if width < 0 { 153 | width = -1 154 | } 155 | emitter.best_width = width 156 | } 157 | 158 | // Set if unescaped non-ASCII characters are allowed. 159 | func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { 160 | emitter.unicode = unicode 161 | } 162 | 163 | // Set the preferred line break character. 164 | func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { 165 | emitter.line_break = line_break 166 | } 167 | 168 | ///* 169 | // * Destroy a token object. 170 | // */ 171 | // 172 | //YAML_DECLARE(void) 173 | //yaml_token_delete(yaml_token_t *token) 174 | //{ 175 | // assert(token); // Non-NULL token object expected. 176 | // 177 | // switch (token.type) 178 | // { 179 | // case YAML_TAG_DIRECTIVE_TOKEN: 180 | // yaml_free(token.data.tag_directive.handle); 181 | // yaml_free(token.data.tag_directive.prefix); 182 | // break; 183 | // 184 | // case YAML_ALIAS_TOKEN: 185 | // yaml_free(token.data.alias.value); 186 | // break; 187 | // 188 | // case YAML_ANCHOR_TOKEN: 189 | // yaml_free(token.data.anchor.value); 190 | // break; 191 | // 192 | // case YAML_TAG_TOKEN: 193 | // yaml_free(token.data.tag.handle); 194 | // yaml_free(token.data.tag.suffix); 195 | // break; 196 | // 197 | // case YAML_SCALAR_TOKEN: 198 | // yaml_free(token.data.scalar.value); 199 | // break; 200 | // 201 | // default: 202 | // break; 203 | // } 204 | // 205 | // memset(token, 0, sizeof(yaml_token_t)); 206 | //} 207 | // 208 | ///* 209 | // * Check if a string is a valid UTF-8 sequence. 210 | // * 211 | // * Check 'reader.c' for more details on UTF-8 encoding. 212 | // */ 213 | // 214 | //static int 215 | //yaml_check_utf8(yaml_char_t *start, size_t length) 216 | //{ 217 | // yaml_char_t *end = start+length; 218 | // yaml_char_t *pointer = start; 219 | // 220 | // while (pointer < end) { 221 | // unsigned char octet; 222 | // unsigned int width; 223 | // unsigned int value; 224 | // size_t k; 225 | // 226 | // octet = pointer[0]; 227 | // width = (octet & 0x80) == 0x00 ? 1 : 228 | // (octet & 0xE0) == 0xC0 ? 2 : 229 | // (octet & 0xF0) == 0xE0 ? 3 : 230 | // (octet & 0xF8) == 0xF0 ? 4 : 0; 231 | // value = (octet & 0x80) == 0x00 ? octet & 0x7F : 232 | // (octet & 0xE0) == 0xC0 ? octet & 0x1F : 233 | // (octet & 0xF0) == 0xE0 ? octet & 0x0F : 234 | // (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; 235 | // if (!width) return 0; 236 | // if (pointer+width > end) return 0; 237 | // for (k = 1; k < width; k ++) { 238 | // octet = pointer[k]; 239 | // if ((octet & 0xC0) != 0x80) return 0; 240 | // value = (value << 6) + (octet & 0x3F); 241 | // } 242 | // if (!((width == 1) || 243 | // (width == 2 && value >= 0x80) || 244 | // (width == 3 && value >= 0x800) || 245 | // (width == 4 && value >= 0x10000))) return 0; 246 | // 247 | // pointer += width; 248 | // } 249 | // 250 | // return 1; 251 | //} 252 | // 253 | 254 | // Create STREAM-START. 255 | func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) bool { 256 | *event = yaml_event_t{ 257 | typ: yaml_STREAM_START_EVENT, 258 | encoding: encoding, 259 | } 260 | return true 261 | } 262 | 263 | // Create STREAM-END. 264 | func yaml_stream_end_event_initialize(event *yaml_event_t) bool { 265 | *event = yaml_event_t{ 266 | typ: yaml_STREAM_END_EVENT, 267 | } 268 | return true 269 | } 270 | 271 | // Create DOCUMENT-START. 272 | func yaml_document_start_event_initialize(event *yaml_event_t, version_directive *yaml_version_directive_t, 273 | tag_directives []yaml_tag_directive_t, implicit bool) bool { 274 | *event = yaml_event_t{ 275 | typ: yaml_DOCUMENT_START_EVENT, 276 | version_directive: version_directive, 277 | tag_directives: tag_directives, 278 | implicit: implicit, 279 | } 280 | return true 281 | } 282 | 283 | // Create DOCUMENT-END. 284 | func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) bool { 285 | *event = yaml_event_t{ 286 | typ: yaml_DOCUMENT_END_EVENT, 287 | implicit: implicit, 288 | } 289 | return true 290 | } 291 | 292 | ///* 293 | // * Create ALIAS. 294 | // */ 295 | // 296 | //YAML_DECLARE(int) 297 | //yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t) 298 | //{ 299 | // mark yaml_mark_t = { 0, 0, 0 } 300 | // anchor_copy *yaml_char_t = NULL 301 | // 302 | // assert(event) // Non-NULL event object is expected. 303 | // assert(anchor) // Non-NULL anchor is expected. 304 | // 305 | // if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0 306 | // 307 | // anchor_copy = yaml_strdup(anchor) 308 | // if (!anchor_copy) 309 | // return 0 310 | // 311 | // ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark) 312 | // 313 | // return 1 314 | //} 315 | 316 | // Create SCALAR. 317 | func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { 318 | *event = yaml_event_t{ 319 | typ: yaml_SCALAR_EVENT, 320 | anchor: anchor, 321 | tag: tag, 322 | value: value, 323 | implicit: plain_implicit, 324 | quoted_implicit: quoted_implicit, 325 | style: yaml_style_t(style), 326 | } 327 | return true 328 | } 329 | 330 | // Create SEQUENCE-START. 331 | func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { 332 | *event = yaml_event_t{ 333 | typ: yaml_SEQUENCE_START_EVENT, 334 | anchor: anchor, 335 | tag: tag, 336 | implicit: implicit, 337 | style: yaml_style_t(style), 338 | } 339 | return true 340 | } 341 | 342 | // Create SEQUENCE-END. 343 | func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { 344 | *event = yaml_event_t{ 345 | typ: yaml_SEQUENCE_END_EVENT, 346 | } 347 | return true 348 | } 349 | 350 | // Create MAPPING-START. 351 | func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) bool { 352 | *event = yaml_event_t{ 353 | typ: yaml_MAPPING_START_EVENT, 354 | anchor: anchor, 355 | tag: tag, 356 | implicit: implicit, 357 | style: yaml_style_t(style), 358 | } 359 | return true 360 | } 361 | 362 | // Create MAPPING-END. 363 | func yaml_mapping_end_event_initialize(event *yaml_event_t) bool { 364 | *event = yaml_event_t{ 365 | typ: yaml_MAPPING_END_EVENT, 366 | } 367 | return true 368 | } 369 | 370 | // Destroy an event object. 371 | func yaml_event_delete(event *yaml_event_t) { 372 | *event = yaml_event_t{} 373 | } 374 | 375 | ///* 376 | // * Create a document object. 377 | // */ 378 | // 379 | //YAML_DECLARE(int) 380 | //yaml_document_initialize(document *yaml_document_t, 381 | // version_directive *yaml_version_directive_t, 382 | // tag_directives_start *yaml_tag_directive_t, 383 | // tag_directives_end *yaml_tag_directive_t, 384 | // start_implicit int, end_implicit int) 385 | //{ 386 | // struct { 387 | // error yaml_error_type_t 388 | // } context 389 | // struct { 390 | // start *yaml_node_t 391 | // end *yaml_node_t 392 | // top *yaml_node_t 393 | // } nodes = { NULL, NULL, NULL } 394 | // version_directive_copy *yaml_version_directive_t = NULL 395 | // struct { 396 | // start *yaml_tag_directive_t 397 | // end *yaml_tag_directive_t 398 | // top *yaml_tag_directive_t 399 | // } tag_directives_copy = { NULL, NULL, NULL } 400 | // value yaml_tag_directive_t = { NULL, NULL } 401 | // mark yaml_mark_t = { 0, 0, 0 } 402 | // 403 | // assert(document) // Non-NULL document object is expected. 404 | // assert((tag_directives_start && tag_directives_end) || 405 | // (tag_directives_start == tag_directives_end)) 406 | // // Valid tag directives are expected. 407 | // 408 | // if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error 409 | // 410 | // if (version_directive) { 411 | // version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) 412 | // if (!version_directive_copy) goto error 413 | // version_directive_copy.major = version_directive.major 414 | // version_directive_copy.minor = version_directive.minor 415 | // } 416 | // 417 | // if (tag_directives_start != tag_directives_end) { 418 | // tag_directive *yaml_tag_directive_t 419 | // if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) 420 | // goto error 421 | // for (tag_directive = tag_directives_start 422 | // tag_directive != tag_directives_end; tag_directive ++) { 423 | // assert(tag_directive.handle) 424 | // assert(tag_directive.prefix) 425 | // if (!yaml_check_utf8(tag_directive.handle, 426 | // strlen((char *)tag_directive.handle))) 427 | // goto error 428 | // if (!yaml_check_utf8(tag_directive.prefix, 429 | // strlen((char *)tag_directive.prefix))) 430 | // goto error 431 | // value.handle = yaml_strdup(tag_directive.handle) 432 | // value.prefix = yaml_strdup(tag_directive.prefix) 433 | // if (!value.handle || !value.prefix) goto error 434 | // if (!PUSH(&context, tag_directives_copy, value)) 435 | // goto error 436 | // value.handle = NULL 437 | // value.prefix = NULL 438 | // } 439 | // } 440 | // 441 | // DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, 442 | // tag_directives_copy.start, tag_directives_copy.top, 443 | // start_implicit, end_implicit, mark, mark) 444 | // 445 | // return 1 446 | // 447 | //error: 448 | // STACK_DEL(&context, nodes) 449 | // yaml_free(version_directive_copy) 450 | // while (!STACK_EMPTY(&context, tag_directives_copy)) { 451 | // value yaml_tag_directive_t = POP(&context, tag_directives_copy) 452 | // yaml_free(value.handle) 453 | // yaml_free(value.prefix) 454 | // } 455 | // STACK_DEL(&context, tag_directives_copy) 456 | // yaml_free(value.handle) 457 | // yaml_free(value.prefix) 458 | // 459 | // return 0 460 | //} 461 | // 462 | ///* 463 | // * Destroy a document object. 464 | // */ 465 | // 466 | //YAML_DECLARE(void) 467 | //yaml_document_delete(document *yaml_document_t) 468 | //{ 469 | // struct { 470 | // error yaml_error_type_t 471 | // } context 472 | // tag_directive *yaml_tag_directive_t 473 | // 474 | // context.error = YAML_NO_ERROR // Eliminate a compliler warning. 475 | // 476 | // assert(document) // Non-NULL document object is expected. 477 | // 478 | // while (!STACK_EMPTY(&context, document.nodes)) { 479 | // node yaml_node_t = POP(&context, document.nodes) 480 | // yaml_free(node.tag) 481 | // switch (node.type) { 482 | // case YAML_SCALAR_NODE: 483 | // yaml_free(node.data.scalar.value) 484 | // break 485 | // case YAML_SEQUENCE_NODE: 486 | // STACK_DEL(&context, node.data.sequence.items) 487 | // break 488 | // case YAML_MAPPING_NODE: 489 | // STACK_DEL(&context, node.data.mapping.pairs) 490 | // break 491 | // default: 492 | // assert(0) // Should not happen. 493 | // } 494 | // } 495 | // STACK_DEL(&context, document.nodes) 496 | // 497 | // yaml_free(document.version_directive) 498 | // for (tag_directive = document.tag_directives.start 499 | // tag_directive != document.tag_directives.end 500 | // tag_directive++) { 501 | // yaml_free(tag_directive.handle) 502 | // yaml_free(tag_directive.prefix) 503 | // } 504 | // yaml_free(document.tag_directives.start) 505 | // 506 | // memset(document, 0, sizeof(yaml_document_t)) 507 | //} 508 | // 509 | ///** 510 | // * Get a document node. 511 | // */ 512 | // 513 | //YAML_DECLARE(yaml_node_t *) 514 | //yaml_document_get_node(document *yaml_document_t, index int) 515 | //{ 516 | // assert(document) // Non-NULL document object is expected. 517 | // 518 | // if (index > 0 && document.nodes.start + index <= document.nodes.top) { 519 | // return document.nodes.start + index - 1 520 | // } 521 | // return NULL 522 | //} 523 | // 524 | ///** 525 | // * Get the root object. 526 | // */ 527 | // 528 | //YAML_DECLARE(yaml_node_t *) 529 | //yaml_document_get_root_node(document *yaml_document_t) 530 | //{ 531 | // assert(document) // Non-NULL document object is expected. 532 | // 533 | // if (document.nodes.top != document.nodes.start) { 534 | // return document.nodes.start 535 | // } 536 | // return NULL 537 | //} 538 | // 539 | ///* 540 | // * Add a scalar node to a document. 541 | // */ 542 | // 543 | //YAML_DECLARE(int) 544 | //yaml_document_add_scalar(document *yaml_document_t, 545 | // tag *yaml_char_t, value *yaml_char_t, length int, 546 | // style yaml_scalar_style_t) 547 | //{ 548 | // struct { 549 | // error yaml_error_type_t 550 | // } context 551 | // mark yaml_mark_t = { 0, 0, 0 } 552 | // tag_copy *yaml_char_t = NULL 553 | // value_copy *yaml_char_t = NULL 554 | // node yaml_node_t 555 | // 556 | // assert(document) // Non-NULL document object is expected. 557 | // assert(value) // Non-NULL value is expected. 558 | // 559 | // if (!tag) { 560 | // tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG 561 | // } 562 | // 563 | // if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error 564 | // tag_copy = yaml_strdup(tag) 565 | // if (!tag_copy) goto error 566 | // 567 | // if (length < 0) { 568 | // length = strlen((char *)value) 569 | // } 570 | // 571 | // if (!yaml_check_utf8(value, length)) goto error 572 | // value_copy = yaml_malloc(length+1) 573 | // if (!value_copy) goto error 574 | // memcpy(value_copy, value, length) 575 | // value_copy[length] = '\0' 576 | // 577 | // SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) 578 | // if (!PUSH(&context, document.nodes, node)) goto error 579 | // 580 | // return document.nodes.top - document.nodes.start 581 | // 582 | //error: 583 | // yaml_free(tag_copy) 584 | // yaml_free(value_copy) 585 | // 586 | // return 0 587 | //} 588 | // 589 | ///* 590 | // * Add a sequence node to a document. 591 | // */ 592 | // 593 | //YAML_DECLARE(int) 594 | //yaml_document_add_sequence(document *yaml_document_t, 595 | // tag *yaml_char_t, style yaml_sequence_style_t) 596 | //{ 597 | // struct { 598 | // error yaml_error_type_t 599 | // } context 600 | // mark yaml_mark_t = { 0, 0, 0 } 601 | // tag_copy *yaml_char_t = NULL 602 | // struct { 603 | // start *yaml_node_item_t 604 | // end *yaml_node_item_t 605 | // top *yaml_node_item_t 606 | // } items = { NULL, NULL, NULL } 607 | // node yaml_node_t 608 | // 609 | // assert(document) // Non-NULL document object is expected. 610 | // 611 | // if (!tag) { 612 | // tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG 613 | // } 614 | // 615 | // if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error 616 | // tag_copy = yaml_strdup(tag) 617 | // if (!tag_copy) goto error 618 | // 619 | // if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error 620 | // 621 | // SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, 622 | // style, mark, mark) 623 | // if (!PUSH(&context, document.nodes, node)) goto error 624 | // 625 | // return document.nodes.top - document.nodes.start 626 | // 627 | //error: 628 | // STACK_DEL(&context, items) 629 | // yaml_free(tag_copy) 630 | // 631 | // return 0 632 | //} 633 | // 634 | ///* 635 | // * Add a mapping node to a document. 636 | // */ 637 | // 638 | //YAML_DECLARE(int) 639 | //yaml_document_add_mapping(document *yaml_document_t, 640 | // tag *yaml_char_t, style yaml_mapping_style_t) 641 | //{ 642 | // struct { 643 | // error yaml_error_type_t 644 | // } context 645 | // mark yaml_mark_t = { 0, 0, 0 } 646 | // tag_copy *yaml_char_t = NULL 647 | // struct { 648 | // start *yaml_node_pair_t 649 | // end *yaml_node_pair_t 650 | // top *yaml_node_pair_t 651 | // } pairs = { NULL, NULL, NULL } 652 | // node yaml_node_t 653 | // 654 | // assert(document) // Non-NULL document object is expected. 655 | // 656 | // if (!tag) { 657 | // tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG 658 | // } 659 | // 660 | // if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error 661 | // tag_copy = yaml_strdup(tag) 662 | // if (!tag_copy) goto error 663 | // 664 | // if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error 665 | // 666 | // MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, 667 | // style, mark, mark) 668 | // if (!PUSH(&context, document.nodes, node)) goto error 669 | // 670 | // return document.nodes.top - document.nodes.start 671 | // 672 | //error: 673 | // STACK_DEL(&context, pairs) 674 | // yaml_free(tag_copy) 675 | // 676 | // return 0 677 | //} 678 | // 679 | ///* 680 | // * Append an item to a sequence node. 681 | // */ 682 | // 683 | //YAML_DECLARE(int) 684 | //yaml_document_append_sequence_item(document *yaml_document_t, 685 | // sequence int, item int) 686 | //{ 687 | // struct { 688 | // error yaml_error_type_t 689 | // } context 690 | // 691 | // assert(document) // Non-NULL document is required. 692 | // assert(sequence > 0 693 | // && document.nodes.start + sequence <= document.nodes.top) 694 | // // Valid sequence id is required. 695 | // assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) 696 | // // A sequence node is required. 697 | // assert(item > 0 && document.nodes.start + item <= document.nodes.top) 698 | // // Valid item id is required. 699 | // 700 | // if (!PUSH(&context, 701 | // document.nodes.start[sequence-1].data.sequence.items, item)) 702 | // return 0 703 | // 704 | // return 1 705 | //} 706 | // 707 | ///* 708 | // * Append a pair of a key and a value to a mapping node. 709 | // */ 710 | // 711 | //YAML_DECLARE(int) 712 | //yaml_document_append_mapping_pair(document *yaml_document_t, 713 | // mapping int, key int, value int) 714 | //{ 715 | // struct { 716 | // error yaml_error_type_t 717 | // } context 718 | // 719 | // pair yaml_node_pair_t 720 | // 721 | // assert(document) // Non-NULL document is required. 722 | // assert(mapping > 0 723 | // && document.nodes.start + mapping <= document.nodes.top) 724 | // // Valid mapping id is required. 725 | // assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) 726 | // // A mapping node is required. 727 | // assert(key > 0 && document.nodes.start + key <= document.nodes.top) 728 | // // Valid key id is required. 729 | // assert(value > 0 && document.nodes.start + value <= document.nodes.top) 730 | // // Valid value id is required. 731 | // 732 | // pair.key = key 733 | // pair.value = value 734 | // 735 | // if (!PUSH(&context, 736 | // document.nodes.start[mapping-1].data.mapping.pairs, pair)) 737 | // return 0 738 | // 739 | // return 1 740 | //} 741 | // 742 | // 743 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v1/yamlh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // The version directive data. 8 | type yaml_version_directive_t struct { 9 | major int8 // The major version number. 10 | minor int8 // The minor version number. 11 | } 12 | 13 | // The tag directive data. 14 | type yaml_tag_directive_t struct { 15 | handle []byte // The tag handle. 16 | prefix []byte // The tag prefix. 17 | } 18 | 19 | type yaml_encoding_t int 20 | 21 | // The stream encoding. 22 | const ( 23 | // Let the parser choose the encoding. 24 | yaml_ANY_ENCODING yaml_encoding_t = iota 25 | 26 | yaml_UTF8_ENCODING // The default UTF-8 encoding. 27 | yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. 28 | yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. 29 | ) 30 | 31 | type yaml_break_t int 32 | 33 | // Line break types. 34 | const ( 35 | // Let the parser choose the break type. 36 | yaml_ANY_BREAK yaml_break_t = iota 37 | 38 | yaml_CR_BREAK // Use CR for line breaks (Mac style). 39 | yaml_LN_BREAK // Use LN for line breaks (Unix style). 40 | yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). 41 | ) 42 | 43 | type yaml_error_type_t int 44 | 45 | // Many bad things could happen with the parser and emitter. 46 | const ( 47 | // No error is produced. 48 | yaml_NO_ERROR yaml_error_type_t = iota 49 | 50 | yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. 51 | yaml_READER_ERROR // Cannot read or decode the input stream. 52 | yaml_SCANNER_ERROR // Cannot scan the input stream. 53 | yaml_PARSER_ERROR // Cannot parse the input stream. 54 | yaml_COMPOSER_ERROR // Cannot compose a YAML document. 55 | yaml_WRITER_ERROR // Cannot write to the output stream. 56 | yaml_EMITTER_ERROR // Cannot emit a YAML stream. 57 | ) 58 | 59 | // The pointer position. 60 | type yaml_mark_t struct { 61 | index int // The position index. 62 | line int // The position line. 63 | column int // The position column. 64 | } 65 | 66 | // Node Styles 67 | 68 | type yaml_style_t int8 69 | 70 | type yaml_scalar_style_t yaml_style_t 71 | 72 | // Scalar styles. 73 | const ( 74 | // Let the emitter choose the style. 75 | yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota 76 | 77 | yaml_PLAIN_SCALAR_STYLE // The plain scalar style. 78 | yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. 79 | yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. 80 | yaml_LITERAL_SCALAR_STYLE // The literal scalar style. 81 | yaml_FOLDED_SCALAR_STYLE // The folded scalar style. 82 | ) 83 | 84 | type yaml_sequence_style_t yaml_style_t 85 | 86 | // Sequence styles. 87 | const ( 88 | // Let the emitter choose the style. 89 | yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota 90 | 91 | yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. 92 | yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. 93 | ) 94 | 95 | type yaml_mapping_style_t yaml_style_t 96 | 97 | // Mapping styles. 98 | const ( 99 | // Let the emitter choose the style. 100 | yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota 101 | 102 | yaml_BLOCK_MAPPING_STYLE // The block mapping style. 103 | yaml_FLOW_MAPPING_STYLE // The flow mapping style. 104 | ) 105 | 106 | // Tokens 107 | 108 | type yaml_token_type_t int 109 | 110 | // Token types. 111 | const ( 112 | // An empty token. 113 | yaml_NO_TOKEN yaml_token_type_t = iota 114 | 115 | yaml_STREAM_START_TOKEN // A STREAM-START token. 116 | yaml_STREAM_END_TOKEN // A STREAM-END token. 117 | 118 | yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. 119 | yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. 120 | yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. 121 | yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. 122 | 123 | yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. 124 | yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. 125 | yaml_BLOCK_END_TOKEN // A BLOCK-END token. 126 | 127 | yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. 128 | yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. 129 | yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. 130 | yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. 131 | 132 | yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. 133 | yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. 134 | yaml_KEY_TOKEN // A KEY token. 135 | yaml_VALUE_TOKEN // A VALUE token. 136 | 137 | yaml_ALIAS_TOKEN // An ALIAS token. 138 | yaml_ANCHOR_TOKEN // An ANCHOR token. 139 | yaml_TAG_TOKEN // A TAG token. 140 | yaml_SCALAR_TOKEN // A SCALAR token. 141 | ) 142 | 143 | func (tt yaml_token_type_t) String() string { 144 | switch tt { 145 | case yaml_NO_TOKEN: 146 | return "yaml_NO_TOKEN" 147 | case yaml_STREAM_START_TOKEN: 148 | return "yaml_STREAM_START_TOKEN" 149 | case yaml_STREAM_END_TOKEN: 150 | return "yaml_STREAM_END_TOKEN" 151 | case yaml_VERSION_DIRECTIVE_TOKEN: 152 | return "yaml_VERSION_DIRECTIVE_TOKEN" 153 | case yaml_TAG_DIRECTIVE_TOKEN: 154 | return "yaml_TAG_DIRECTIVE_TOKEN" 155 | case yaml_DOCUMENT_START_TOKEN: 156 | return "yaml_DOCUMENT_START_TOKEN" 157 | case yaml_DOCUMENT_END_TOKEN: 158 | return "yaml_DOCUMENT_END_TOKEN" 159 | case yaml_BLOCK_SEQUENCE_START_TOKEN: 160 | return "yaml_BLOCK_SEQUENCE_START_TOKEN" 161 | case yaml_BLOCK_MAPPING_START_TOKEN: 162 | return "yaml_BLOCK_MAPPING_START_TOKEN" 163 | case yaml_BLOCK_END_TOKEN: 164 | return "yaml_BLOCK_END_TOKEN" 165 | case yaml_FLOW_SEQUENCE_START_TOKEN: 166 | return "yaml_FLOW_SEQUENCE_START_TOKEN" 167 | case yaml_FLOW_SEQUENCE_END_TOKEN: 168 | return "yaml_FLOW_SEQUENCE_END_TOKEN" 169 | case yaml_FLOW_MAPPING_START_TOKEN: 170 | return "yaml_FLOW_MAPPING_START_TOKEN" 171 | case yaml_FLOW_MAPPING_END_TOKEN: 172 | return "yaml_FLOW_MAPPING_END_TOKEN" 173 | case yaml_BLOCK_ENTRY_TOKEN: 174 | return "yaml_BLOCK_ENTRY_TOKEN" 175 | case yaml_FLOW_ENTRY_TOKEN: 176 | return "yaml_FLOW_ENTRY_TOKEN" 177 | case yaml_KEY_TOKEN: 178 | return "yaml_KEY_TOKEN" 179 | case yaml_VALUE_TOKEN: 180 | return "yaml_VALUE_TOKEN" 181 | case yaml_ALIAS_TOKEN: 182 | return "yaml_ALIAS_TOKEN" 183 | case yaml_ANCHOR_TOKEN: 184 | return "yaml_ANCHOR_TOKEN" 185 | case yaml_TAG_TOKEN: 186 | return "yaml_TAG_TOKEN" 187 | case yaml_SCALAR_TOKEN: 188 | return "yaml_SCALAR_TOKEN" 189 | } 190 | return "" 191 | } 192 | 193 | // The token structure. 194 | type yaml_token_t struct { 195 | // The token type. 196 | typ yaml_token_type_t 197 | 198 | // The start/end of the token. 199 | start_mark, end_mark yaml_mark_t 200 | 201 | // The stream encoding (for yaml_STREAM_START_TOKEN). 202 | encoding yaml_encoding_t 203 | 204 | // The alias/anchor/scalar value or tag/tag directive handle 205 | // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). 206 | value []byte 207 | 208 | // The tag suffix (for yaml_TAG_TOKEN). 209 | suffix []byte 210 | 211 | // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). 212 | prefix []byte 213 | 214 | // The scalar style (for yaml_SCALAR_TOKEN). 215 | style yaml_scalar_style_t 216 | 217 | // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). 218 | major, minor int8 219 | } 220 | 221 | // Events 222 | 223 | type yaml_event_type_t int8 224 | 225 | // Event types. 226 | const ( 227 | // An empty event. 228 | yaml_NO_EVENT yaml_event_type_t = iota 229 | 230 | yaml_STREAM_START_EVENT // A STREAM-START event. 231 | yaml_STREAM_END_EVENT // A STREAM-END event. 232 | yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. 233 | yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. 234 | yaml_ALIAS_EVENT // An ALIAS event. 235 | yaml_SCALAR_EVENT // A SCALAR event. 236 | yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. 237 | yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. 238 | yaml_MAPPING_START_EVENT // A MAPPING-START event. 239 | yaml_MAPPING_END_EVENT // A MAPPING-END event. 240 | ) 241 | 242 | // The event structure. 243 | type yaml_event_t struct { 244 | 245 | // The event type. 246 | typ yaml_event_type_t 247 | 248 | // The start and end of the event. 249 | start_mark, end_mark yaml_mark_t 250 | 251 | // The document encoding (for yaml_STREAM_START_EVENT). 252 | encoding yaml_encoding_t 253 | 254 | // The version directive (for yaml_DOCUMENT_START_EVENT). 255 | version_directive *yaml_version_directive_t 256 | 257 | // The list of tag directives (for yaml_DOCUMENT_START_EVENT). 258 | tag_directives []yaml_tag_directive_t 259 | 260 | // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). 261 | anchor []byte 262 | 263 | // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). 264 | tag []byte 265 | 266 | // The scalar value (for yaml_SCALAR_EVENT). 267 | value []byte 268 | 269 | // Is the document start/end indicator implicit, or the tag optional? 270 | // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). 271 | implicit bool 272 | 273 | // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). 274 | quoted_implicit bool 275 | 276 | // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). 277 | style yaml_style_t 278 | } 279 | 280 | func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } 281 | func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } 282 | func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } 283 | 284 | // Nodes 285 | 286 | const ( 287 | yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. 288 | yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. 289 | yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. 290 | yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. 291 | yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. 292 | yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. 293 | 294 | yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. 295 | yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. 296 | 297 | // Not in original libyaml. 298 | yaml_BINARY_TAG = "tag:yaml.org,2002:binary" 299 | yaml_MERGE_TAG = "tag:yaml.org,2002:merge" 300 | 301 | yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. 302 | yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. 303 | yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. 304 | ) 305 | 306 | type yaml_node_type_t int 307 | 308 | // Node types. 309 | const ( 310 | // An empty node. 311 | yaml_NO_NODE yaml_node_type_t = iota 312 | 313 | yaml_SCALAR_NODE // A scalar node. 314 | yaml_SEQUENCE_NODE // A sequence node. 315 | yaml_MAPPING_NODE // A mapping node. 316 | ) 317 | 318 | // An element of a sequence node. 319 | type yaml_node_item_t int 320 | 321 | // An element of a mapping node. 322 | type yaml_node_pair_t struct { 323 | key int // The key of the element. 324 | value int // The value of the element. 325 | } 326 | 327 | // The node structure. 328 | type yaml_node_t struct { 329 | typ yaml_node_type_t // The node type. 330 | tag []byte // The node tag. 331 | 332 | // The node data. 333 | 334 | // The scalar parameters (for yaml_SCALAR_NODE). 335 | scalar struct { 336 | value []byte // The scalar value. 337 | length int // The length of the scalar value. 338 | style yaml_scalar_style_t // The scalar style. 339 | } 340 | 341 | // The sequence parameters (for YAML_SEQUENCE_NODE). 342 | sequence struct { 343 | items_data []yaml_node_item_t // The stack of sequence items. 344 | style yaml_sequence_style_t // The sequence style. 345 | } 346 | 347 | // The mapping parameters (for yaml_MAPPING_NODE). 348 | mapping struct { 349 | pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). 350 | pairs_start *yaml_node_pair_t // The beginning of the stack. 351 | pairs_end *yaml_node_pair_t // The end of the stack. 352 | pairs_top *yaml_node_pair_t // The top of the stack. 353 | style yaml_mapping_style_t // The mapping style. 354 | } 355 | 356 | start_mark yaml_mark_t // The beginning of the node. 357 | end_mark yaml_mark_t // The end of the node. 358 | 359 | } 360 | 361 | // The document structure. 362 | type yaml_document_t struct { 363 | 364 | // The document nodes. 365 | nodes []yaml_node_t 366 | 367 | // The version directive. 368 | version_directive *yaml_version_directive_t 369 | 370 | // The list of tag directives. 371 | tag_directives_data []yaml_tag_directive_t 372 | tag_directives_start int // The beginning of the tag directives list. 373 | tag_directives_end int // The end of the tag directives list. 374 | 375 | start_implicit int // Is the document start indicator implicit? 376 | end_implicit int // Is the document end indicator implicit? 377 | 378 | // The start/end of the document. 379 | start_mark, end_mark yaml_mark_t 380 | } 381 | 382 | // The prototype of a read handler. 383 | // 384 | // The read handler is called when the parser needs to read more bytes from the 385 | // source. The handler should write not more than size bytes to the buffer. 386 | // The number of written bytes should be set to the size_read variable. 387 | // 388 | // [in,out] data A pointer to an application data specified by 389 | // yaml_parser_set_input(). 390 | // [out] buffer The buffer to write the data from the source. 391 | // [in] size The size of the buffer. 392 | // [out] size_read The actual number of bytes read from the source. 393 | // 394 | // On success, the handler should return 1. If the handler failed, 395 | // the returned value should be 0. On EOF, the handler should set the 396 | // size_read to 0 and return 1. 397 | type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) 398 | 399 | // This structure holds information about a potential simple key. 400 | type yaml_simple_key_t struct { 401 | possible bool // Is a simple key possible? 402 | required bool // Is a simple key required? 403 | token_number int // The number of the token. 404 | mark yaml_mark_t // The position mark. 405 | } 406 | 407 | // The states of the parser. 408 | type yaml_parser_state_t int 409 | 410 | const ( 411 | yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota 412 | 413 | yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. 414 | yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. 415 | yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. 416 | yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. 417 | yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. 418 | yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. 419 | yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. 420 | yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. 421 | yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. 422 | yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. 423 | yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. 424 | yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. 425 | yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. 426 | yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. 427 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. 428 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. 429 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. 430 | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. 431 | yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. 432 | yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. 433 | yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. 434 | yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. 435 | yaml_PARSE_END_STATE // Expect nothing. 436 | ) 437 | 438 | func (ps yaml_parser_state_t) String() string { 439 | switch ps { 440 | case yaml_PARSE_STREAM_START_STATE: 441 | return "yaml_PARSE_STREAM_START_STATE" 442 | case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: 443 | return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" 444 | case yaml_PARSE_DOCUMENT_START_STATE: 445 | return "yaml_PARSE_DOCUMENT_START_STATE" 446 | case yaml_PARSE_DOCUMENT_CONTENT_STATE: 447 | return "yaml_PARSE_DOCUMENT_CONTENT_STATE" 448 | case yaml_PARSE_DOCUMENT_END_STATE: 449 | return "yaml_PARSE_DOCUMENT_END_STATE" 450 | case yaml_PARSE_BLOCK_NODE_STATE: 451 | return "yaml_PARSE_BLOCK_NODE_STATE" 452 | case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: 453 | return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" 454 | case yaml_PARSE_FLOW_NODE_STATE: 455 | return "yaml_PARSE_FLOW_NODE_STATE" 456 | case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: 457 | return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" 458 | case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: 459 | return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" 460 | case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: 461 | return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" 462 | case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: 463 | return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" 464 | case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: 465 | return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" 466 | case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: 467 | return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" 468 | case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: 469 | return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" 470 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: 471 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" 472 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: 473 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" 474 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: 475 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" 476 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: 477 | return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" 478 | case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: 479 | return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" 480 | case yaml_PARSE_FLOW_MAPPING_KEY_STATE: 481 | return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" 482 | case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: 483 | return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" 484 | case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: 485 | return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" 486 | case yaml_PARSE_END_STATE: 487 | return "yaml_PARSE_END_STATE" 488 | } 489 | return "" 490 | } 491 | 492 | // This structure holds aliases data. 493 | type yaml_alias_data_t struct { 494 | anchor []byte // The anchor. 495 | index int // The node id. 496 | mark yaml_mark_t // The anchor mark. 497 | } 498 | 499 | // The parser structure. 500 | // 501 | // All members are internal. Manage the structure using the 502 | // yaml_parser_ family of functions. 503 | type yaml_parser_t struct { 504 | 505 | // Error handling 506 | 507 | error yaml_error_type_t // Error type. 508 | 509 | problem string // Error description. 510 | 511 | // The byte about which the problem occured. 512 | problem_offset int 513 | problem_value int 514 | problem_mark yaml_mark_t 515 | 516 | // The error context. 517 | context string 518 | context_mark yaml_mark_t 519 | 520 | // Reader stuff 521 | 522 | read_handler yaml_read_handler_t // Read handler. 523 | 524 | input_file io.Reader // File input data. 525 | input []byte // String input data. 526 | input_pos int 527 | 528 | eof bool // EOF flag 529 | 530 | buffer []byte // The working buffer. 531 | buffer_pos int // The current position of the buffer. 532 | 533 | unread int // The number of unread characters in the buffer. 534 | 535 | raw_buffer []byte // The raw buffer. 536 | raw_buffer_pos int // The current position of the buffer. 537 | 538 | encoding yaml_encoding_t // The input encoding. 539 | 540 | offset int // The offset of the current position (in bytes). 541 | mark yaml_mark_t // The mark of the current position. 542 | 543 | // Scanner stuff 544 | 545 | stream_start_produced bool // Have we started to scan the input stream? 546 | stream_end_produced bool // Have we reached the end of the input stream? 547 | 548 | flow_level int // The number of unclosed '[' and '{' indicators. 549 | 550 | tokens []yaml_token_t // The tokens queue. 551 | tokens_head int // The head of the tokens queue. 552 | tokens_parsed int // The number of tokens fetched from the queue. 553 | token_available bool // Does the tokens queue contain a token ready for dequeueing. 554 | 555 | indent int // The current indentation level. 556 | indents []int // The indentation levels stack. 557 | 558 | simple_key_allowed bool // May a simple key occur at the current position? 559 | simple_keys []yaml_simple_key_t // The stack of simple keys. 560 | 561 | // Parser stuff 562 | 563 | state yaml_parser_state_t // The current parser state. 564 | states []yaml_parser_state_t // The parser states stack. 565 | marks []yaml_mark_t // The stack of marks. 566 | tag_directives []yaml_tag_directive_t // The list of TAG directives. 567 | 568 | // Dumper stuff 569 | 570 | aliases []yaml_alias_data_t // The alias data. 571 | 572 | document *yaml_document_t // The currently parsed document. 573 | } 574 | 575 | // Emitter Definitions 576 | 577 | // The prototype of a write handler. 578 | // 579 | // The write handler is called when the emitter needs to flush the accumulated 580 | // characters to the output. The handler should write @a size bytes of the 581 | // @a buffer to the output. 582 | // 583 | // @param[in,out] data A pointer to an application data specified by 584 | // yaml_emitter_set_output(). 585 | // @param[in] buffer The buffer with bytes to be written. 586 | // @param[in] size The size of the buffer. 587 | // 588 | // @returns On success, the handler should return @c 1. If the handler failed, 589 | // the returned value should be @c 0. 590 | // 591 | type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error 592 | 593 | type yaml_emitter_state_t int 594 | 595 | // The emitter states. 596 | const ( 597 | // Expect STREAM-START. 598 | yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota 599 | 600 | yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. 601 | yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. 602 | yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. 603 | yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. 604 | yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. 605 | yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. 606 | yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. 607 | yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. 608 | yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. 609 | yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. 610 | yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. 611 | yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. 612 | yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. 613 | yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. 614 | yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. 615 | yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. 616 | yaml_EMIT_END_STATE // Expect nothing. 617 | ) 618 | 619 | // The emitter structure. 620 | // 621 | // All members are internal. Manage the structure using the @c yaml_emitter_ 622 | // family of functions. 623 | type yaml_emitter_t struct { 624 | 625 | // Error handling 626 | 627 | error yaml_error_type_t // Error type. 628 | problem string // Error description. 629 | 630 | // Writer stuff 631 | 632 | write_handler yaml_write_handler_t // Write handler. 633 | 634 | output_buffer *[]byte // String output data. 635 | output_file io.Writer // File output data. 636 | 637 | buffer []byte // The working buffer. 638 | buffer_pos int // The current position of the buffer. 639 | 640 | raw_buffer []byte // The raw buffer. 641 | raw_buffer_pos int // The current position of the buffer. 642 | 643 | encoding yaml_encoding_t // The stream encoding. 644 | 645 | // Emitter stuff 646 | 647 | canonical bool // If the output is in the canonical style? 648 | best_indent int // The number of indentation spaces. 649 | best_width int // The preferred width of the output lines. 650 | unicode bool // Allow unescaped non-ASCII characters? 651 | line_break yaml_break_t // The preferred line break. 652 | 653 | state yaml_emitter_state_t // The current emitter state. 654 | states []yaml_emitter_state_t // The stack of states. 655 | 656 | events []yaml_event_t // The event queue. 657 | events_head int // The head of the event queue. 658 | 659 | indents []int // The stack of indentation levels. 660 | 661 | tag_directives []yaml_tag_directive_t // The list of tag directives. 662 | 663 | indent int // The current indentation level. 664 | 665 | flow_level int // The current flow level. 666 | 667 | root_context bool // Is it the document root context? 668 | sequence_context bool // Is it a sequence context? 669 | mapping_context bool // Is it a mapping context? 670 | simple_key_context bool // Is it a simple mapping key context? 671 | 672 | line int // The current line. 673 | column int // The current column. 674 | whitespace bool // If the last character was a whitespace? 675 | indention bool // If the last character was an indentation character (' ', '-', '?', ':')? 676 | open_ended bool // If an explicit document end is required? 677 | 678 | // Anchor analysis. 679 | anchor_data struct { 680 | anchor []byte // The anchor value. 681 | alias bool // Is it an alias? 682 | } 683 | 684 | // Tag analysis. 685 | tag_data struct { 686 | handle []byte // The tag handle. 687 | suffix []byte // The tag suffix. 688 | } 689 | 690 | // Scalar analysis. 691 | scalar_data struct { 692 | value []byte // The scalar value. 693 | multiline bool // Does the scalar contain line breaks? 694 | flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? 695 | block_plain_allowed bool // Can the scalar be expressed in the block plain style? 696 | single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? 697 | block_allowed bool // Can the scalar be expressed in the literal or folded styles? 698 | style yaml_scalar_style_t // The output style. 699 | } 700 | 701 | // Dumper stuff 702 | 703 | opened bool // If the stream was already opened? 704 | closed bool // If the stream was already closed? 705 | 706 | // The information associated with the document nodes. 707 | anchors *struct { 708 | references int // The number of references. 709 | anchor int // The anchor id. 710 | serialized bool // If the node has been emitted? 711 | } 712 | 713 | last_anchor_id int // The last assigned anchor id. 714 | 715 | document *yaml_document_t // The currently emitted document. 716 | } 717 | --------------------------------------------------------------------------------