├── .codeclimate.yml ├── .gitignore ├── .gometalint.json ├── .travis.d └── publish.sh ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── VERSION ├── main.go ├── main_test.go ├── models └── deployment.go ├── requiredflags.go ├── requiredflags_test.go ├── services ├── deployment.go └── deployment_test.go ├── test-files └── deployment.yaml └── vendor ├── github.com └── fatih │ └── color │ ├── LICENSE.md │ ├── README.md │ ├── color.go │ └── doc.go ├── gopkg.in └── yaml.v2 │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── vendor.json /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | govet: 3 | enabled: true 4 | golint: 5 | enabled: true 6 | gofmt: 7 | enabled: true 8 | 9 | ratings: 10 | paths: 11 | - "**.go" 12 | exclude_paths: 13 | - vendor/**/* 14 | - test-files/**/* 15 | - dist/**/* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Go template 3 | # Binaries for programs and plugins 4 | *.exe 5 | *.dll 6 | *.so 7 | *.dylib 8 | 9 | # Test binary, build with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 16 | .glide/ 17 | 18 | # Goland/IntelliJ files 19 | .idea/ 20 | 21 | # Distribution folder 22 | dist/ 23 | -------------------------------------------------------------------------------- /.gometalint.json: -------------------------------------------------------------------------------- 1 | { 2 | "Enable": [ 3 | "vet" 4 | ] 5 | } -------------------------------------------------------------------------------- /.travis.d/publish.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # This script builds the utility targeting the Travis sudo build environment 4 | set -o nounset 5 | set -o errexit -o errtrace 6 | 7 | # Golang architecture and operating system documentation 8 | # https://golang.org/doc/install/source#environment 9 | 10 | CGO_ENABLED=0 11 | GOOS=linux 12 | GOARCH=amd64 13 | 14 | go build -a -installsuffix -v 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.8 4 | 5 | # Don't build other branches that are being used for PRs. 6 | # Currently only the master branch is used in this repo. 7 | branches: 8 | only: 9 | - master 10 | 11 | before_install: 12 | - go get github.com/mitchellh/gox 13 | - go get -u github.com/kyoh86/richgo 14 | - go get github.com/axw/gocov/gocov 15 | - go get github.com/mattn/goveralls 16 | - go get -u github.com/golang/lint/golint 17 | - go get -u github.com/haya14busa/goverage 18 | 19 | script: 20 | - go vet ./... 21 | - golint -set_exit_status . models services 22 | - goverage -v -coverprofile=c.out ./... 23 | - goveralls -coverprofile=c.out -service travis-ci -repotoken $COVERALLS_TOKEN 24 | 25 | after_success: 26 | - gox -output "dist/{{.OS}}_{{.Arch}}_{{.Dir}}" 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.2.0 (August 09, 2017) 2 | 3 | - Updated deployment service to now properly handle null and zero values with `omitempty` for `fieldRef` environment variable properties. 4 | 5 | ## 1.1.0 (July 30, 2017) 6 | 7 | - Updated deployment service to now properly handle null and zero values with `omitempty`. 8 | 9 | ## 1.0.2 (July 30, 2017) 10 | 11 | - Updated deployment test file which includes a strict `value` instead of pulling from configuration 12 | 13 | ## 1.0.1 (July 15, 2017) 14 | 15 | - Add deployment script error handling 16 | - If the script fails for any reason it will exit with the appropriate status code(non 0) 17 | 18 | ## 1.0.0 (July 15, 2017) 19 | 20 | - Addition of a deployment script. 21 | - The deployment script is used to create the binary for consumption in a Travis environment. At this time, only linux amd386 is built. In the future, this will spit out all the binaries using `gox` 22 | 23 | ## 0.1.2 (July 2, 2017) 24 | 25 | - Add code coverage via `gocov` 26 | - Wire up of CodeClimate 27 | 28 | ## 0.1.1 (July 2, 2017) 29 | 30 | - Add initial layer of tests. 31 | 32 | ## 0.1.0 (July 2, 2017) 33 | 34 | - Add initial code to read arguments. 35 | 36 | ## 0.0.4 (July 2, 2017) 37 | 38 | - Updates to the Travis configuration to only `gox` build after success 39 | 40 | ## 0.0.4 (July 2, 2017) 41 | 42 | - Addition of Travis build job 43 | 44 | ## 0.0.3 (July 2, 2017) 45 | 46 | - Removing required `type` field 47 | 48 | ## 0.0.2 (July 1, 2017) 49 | 50 | - Additional documentation and project layout 51 | 52 | ## 0.0.1 (July 1, 2017) 53 | 54 | - Initial project structure buildout -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 "Oleg Shalygin" https://github.com/oshalygin/k8s-config 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/oshalygin/k8s-config.svg?branch=master)](https://travis-ci.org/oshalygin/k8s-config) 2 | [![Coverage Status](https://coveralls.io/repos/github/oshalygin/k8s-config/badge.svg?branch=master)](https://coveralls.io/github/oshalygin/k8s-config?branch=master) 3 | [![Code Climate](https://codeclimate.com/repos/59598bef371afb02870005c1/badges/d8e88772201d137ea8b7/gpa.svg)](https://codeclimate.com/repos/59598bef371afb02870005c1/feed) 4 | [![Issue Count](https://codeclimate.com/repos/59598bef371afb02870005c1/badges/d8e88772201d137ea8b7/issue_count.svg)](https://codeclimate.com/repos/593e287a150338028600480b/feed) 5 | # Introduction 6 | 7 | This is a simple and straightforward CLI that allows you to update your Kubernetes configuration files dynamically during a build. 8 | 9 | # Installation 10 | 11 | ```bash 12 | go get -u github.com/oshalygin/k8s-config 13 | ``` 14 | 15 | # Usage 16 | 17 | ``` 18 | Usage of k8s-config: 19 | -type string 20 | The Kubernetes configuration type(default: "deployment") 21 | -file-path string 22 | The location of the configuration file 23 | -image string 24 | The full image name, 'oshalygin/foobar:1.0.0' 25 | -tag string 26 | If just the tag is provided without the image, 27 | then only the tag will be updated on the existing 28 | image name. 29 | ``` 30 | 31 | ### Example 32 | 33 | ```bash 34 | # Call the utility at the specified path with the 35 | # appropriate command line arguments. 36 | 37 | k8s-config --type=deployment \ 38 | --file-path=../test-files/deployment.yaml \ 39 | --image='oshalygin/my-website-image:1.0.3' 40 | 41 | # Although it is recommended to be explicit, here is 42 | # the minimum amount of flags you can pass and still 43 | # use the utility effectively 44 | 45 | k8s-config --tag=1.03 46 | --file-path=../test-files/deployment.yaml 47 | ``` 48 | 49 | ### Command Line Arguments 50 | 51 | **type**: The Kubernetes type that you want to update. Depending on the type, the utility will parse it different, this value is required. 52 | 53 | **image**: The new image name 54 | 55 | **file-path**: The location of the configuration file 56 | 57 | **tag**: If the image is excluded and just the version is passed in, you can easily just bump the version of the container image(assuming there's a single image per pod) 58 | 59 | # Limitations 60 | _Note_: This list will change accordingly over the development of this utility. 61 | * Only `yaml` configuration files(Not `JSON`) 62 | * Only `deployment` types. 63 | * Only single container deployment configurations. 64 | 65 | # License 66 | 67 | [MIT](LICENSE) 68 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.2 2 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | "io/ioutil" 9 | 10 | "strings" 11 | 12 | "github.com/fatih/color" 13 | "github.com/oshalygin/k8s-config/services" 14 | ) 15 | 16 | var configurationType string 17 | var image string 18 | var imageTag string 19 | var filePath string 20 | 21 | func init() { 22 | flag.StringVar(&configurationType, "type", "deployment", "Kubernetes configuration type, eg: deployment, rc, secret") 23 | flag.StringVar(&image, "image", "", "Docker image name") 24 | flag.StringVar(&imageTag, "tag", "", "Docker image tag") 25 | flag.StringVar(&filePath, "file-path", "", "Configuration file location") 26 | flag.Parse() 27 | } 28 | 29 | func main() { 30 | var err error 31 | 32 | err = checkRequiredFlags(configurationType, image, imageTag, filePath) 33 | 34 | if err != nil { 35 | errorOutput := fmt.Sprintf("Error: %v", err) 36 | color.Red(errorOutput) 37 | fmt.Println(strings.Repeat("-", len(errorOutput))) 38 | 39 | flag.PrintDefaults() 40 | os.Exit(1) 41 | } 42 | 43 | file, err := ioutil.ReadFile(filePath) 44 | if err != nil { 45 | color.Red("Error: %v", err) 46 | os.Exit(1) 47 | } 48 | 49 | currentImage, updatedDeployment, err := services.UpdateDeploymentConfiguration(file, image, imageTag, filePath) 50 | 51 | if err != nil { 52 | color.Red("Error: %v", err) 53 | os.Exit(1) 54 | } 55 | 56 | newImage := updatedDeployment.Spec.Template.Spec.Containers[0].Image 57 | 58 | fmt.Println("Current Image:") 59 | color.Blue("%s", currentImage) 60 | fmt.Println("New Image:") 61 | color.Green("%s\n", newImage) 62 | } 63 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_main_ShouldUpdateTheDeploymentConfigurationWithTheNewTag(t *testing.T) { 8 | 9 | //TODO: This will require reading the output location accordingly. 10 | //TODO: At the moment this serves as a stub for an "integration" test 11 | 12 | filePath = "./test-files/deployment.yaml" 13 | imageTag = "1.3.3" 14 | main() 15 | } 16 | -------------------------------------------------------------------------------- /models/deployment.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Deployment provides declarative updates for Pods and ReplicaSets (the next-generation ReplicationController). 4 | type Deployment struct { 5 | APIVersion string `yaml:"apiVersion"` 6 | Kind string 7 | Metadata struct { 8 | Name string 9 | Namespace string 10 | Labels struct { 11 | Version string 12 | Date string 13 | } 14 | } 15 | Spec struct { 16 | Replicas int 17 | RevisionHistoryLimit int `yaml:"revisionHistoryLimit"` 18 | Strategy struct { 19 | RollingUpdate `yaml:"rollingUpdate"` 20 | Type string 21 | } 22 | Template struct { 23 | Metadata struct { 24 | Labels struct { 25 | App string 26 | } 27 | } 28 | Spec struct { 29 | Containers []Container 30 | Volumes []struct { 31 | Name string 32 | EmptyDir `yaml:"emptyDir"` 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | // Container represents the running container in a pod 40 | type Container struct { 41 | Name string 42 | Image string 43 | VolumeMounts `yaml:"volumeMounts"` 44 | Env []struct { 45 | Name string 46 | ValueFrom `yaml:"valueFrom,omitempty"` 47 | Value string `yaml:"value,omitempty"` 48 | } 49 | ImagePullPolicy string `yaml:"imagePullPolicy"` 50 | Ports []struct { 51 | ContainerPort int `yaml:"containerPort"` 52 | } 53 | ReadinessProbe `yaml:"readinessProbe"` 54 | } 55 | 56 | // RollingUpdate represents the rolling update strategy 57 | type RollingUpdate struct { 58 | MaxUnavailable int `yaml:"maxUnavailable"` 59 | } 60 | 61 | // HTTPGet configures the readiness probes 62 | type HTTPGet struct { 63 | Path string 64 | Port int 65 | } 66 | 67 | // ReadinessProbe describes the configuration around readiness checks 68 | type ReadinessProbe struct { 69 | HTTPGet `yaml:"httpGet"` 70 | InitialDelaySeconds int `yaml:"initialDelaySeconds"` 71 | TimeoutSeconds int `yaml:"timeoutSeconds"` 72 | SuccessThreshold int `yaml:"successThreshold"` 73 | FailureThreshold int `yaml:"failureThreshold"` 74 | } 75 | 76 | // SecretKeyRef provides a description to how secrets are pulled 77 | type SecretKeyRef struct { 78 | Name string 79 | Key string 80 | } 81 | 82 | // FieldRef is the configuration object of how values are pulled from the cluster 83 | type FieldRef struct { 84 | FieldPath string `yaml:"fieldPath,omitempty"` 85 | } 86 | 87 | // ValueFrom is the configuration object of how values are pulled 88 | type ValueFrom struct { 89 | SecretKeyRef `yaml:"secretKeyRef,omitempty"` 90 | FieldRef `yaml:"fieldRef,omitempty"` 91 | } 92 | 93 | // VolumeMounts provides a configuration for additional pod volumes 94 | type VolumeMounts []struct { 95 | MountPath string `yaml:"mountPath"` 96 | Name string 97 | } 98 | 99 | // EmptyDir provides a descriptor for volume configuration 100 | type EmptyDir struct { 101 | } 102 | -------------------------------------------------------------------------------- /requiredflags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | ) 7 | 8 | func checkRequiredFlags(configurationType string, image string, imageTag string, filePath string) error { 9 | 10 | if filePath == "" { 11 | err := `The "file-path" flag must be set` 12 | return errors.New(err) 13 | } 14 | 15 | if image == "" && imageTag == "" { 16 | err := `Either the "image" or "tag" flag MUST be passed in. Both cannot be empty` 17 | return errors.New(err) 18 | } 19 | 20 | // Currently only deployments are supported 21 | if configurationType != "" && configurationType != "deployment" { 22 | err := `Only the "deployment" type is supported at this time` 23 | return errors.New(err) 24 | } 25 | 26 | if image != "" { 27 | tag := strings.Split(image, ":") 28 | if len(tag) <= 1 { 29 | err := `No tag was supplied in the image flag` 30 | return errors.New(err) 31 | } 32 | } 33 | 34 | if image != "" && imageTag != "" { 35 | err := `Set either the "image" or "imageTag" flag, NOT both` 36 | return errors.New(err) 37 | } 38 | 39 | return nil 40 | 41 | } 42 | -------------------------------------------------------------------------------- /requiredflags_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_checkRequiredFlags_ShouldThrowAnErrorIfImageAndTagAreNotPassed(t *testing.T) { 8 | imageTag := "" 9 | configurationType := "" 10 | image := "" 11 | filePath := "deployment.yaml" 12 | 13 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 14 | if err == nil { 15 | t.Errorf("should throw an error if both image and imageTag are empty") 16 | } 17 | } 18 | 19 | func Test_checkRequiredFlags_ShouldThrowAnErrorIfTheFilePathWasNotSet(t *testing.T) { 20 | imageTag := "1.0.0" 21 | configurationType := "" 22 | image := "" 23 | filePath := "" 24 | 25 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 26 | if err == nil { 27 | t.Errorf("should throw an error if the file path was not set") 28 | } 29 | 30 | } 31 | 32 | func Test_checkRequiredFlags_ShouldThrowAnErrorIfAnythingButDeploymentIsSetToType(t *testing.T) { 33 | imageTag := "1.0.0" 34 | configurationType := "secret" 35 | image := "" 36 | filePath := "secret.yaml" 37 | 38 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 39 | if err == nil { 40 | t.Errorf("should throw an error if anything but deployment is set as the type") 41 | } 42 | } 43 | 44 | func Test_checkRequiredFlags_ShouldNotThrowAnErrorIfTheMinimalConfigurationIsPassedIn(t *testing.T) { 45 | imageTag := "1.0.0" 46 | configurationType := "deployment" 47 | image := "" 48 | filePath := "deployment.yaml" 49 | 50 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 51 | if err != nil { 52 | t.Errorf("should succeed on a valid arguments being passed in") 53 | } 54 | } 55 | 56 | func Test_checkRequiredFlags_ShouldNotThrowAnErrorIfTheFullConfigurationIsPassedIn(t *testing.T) { 57 | imageTag := "" 58 | configurationType := "deployment" 59 | image := "oshalygin/my-web-site:1.0.0" 60 | filePath := "deployment.yaml" 61 | 62 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 63 | if err != nil { 64 | t.Errorf("should succeed on a valid arguments being passed in") 65 | } 66 | } 67 | 68 | func Test_checkRequiredFlags_ShouldThrowAnErrorIfTheImageDoesNotContainATag(t *testing.T) { 69 | imageTag := "" 70 | configurationType := "deployment" 71 | image := "oshalygin/my-web-site" 72 | filePath := "deployment.yaml" 73 | 74 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 75 | if err == nil { 76 | t.Errorf("should throw an error if the tag is missing from the image") 77 | } 78 | } 79 | 80 | func Test_checkRequiredFlags_ShouldThrowAnErrorIfBothImageAndImageTagAreSet(t *testing.T) { 81 | imageTag := "1.2.0" 82 | configurationType := "deployment" 83 | image := "oshalygin/my-web-site:1.2.0" 84 | filePath := "deployment.yaml" 85 | 86 | err := checkRequiredFlags(configurationType, image, imageTag, filePath) 87 | if err == nil { 88 | t.Errorf("should throw an error if both the image and image tag are set") 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /services/deployment.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "strings" 5 | 6 | "errors" 7 | 8 | "io/ioutil" 9 | 10 | "github.com/oshalygin/k8s-config/models" 11 | "gopkg.in/yaml.v2" 12 | ) 13 | 14 | // UpdateDeploymentConfiguration takes in a file, image or imageTag to provide an updated configuration object 15 | func UpdateDeploymentConfiguration(file []byte, image string, imageTag string, destination string) (string, models.Deployment, error) { 16 | deployment, err := parseConfigurationFile(file) 17 | updatedDeployment := models.Deployment{} 18 | if err != nil { 19 | return "", models.Deployment{}, err 20 | } 21 | 22 | originalImage := deployment.Spec.Template.Spec.Containers[0].Image 23 | 24 | if imageTag != "" { 25 | updatedDeployment, err = updateImageTag(deployment, imageTag) 26 | } else { 27 | updatedDeployment, err = updateImage(deployment, image) 28 | } 29 | 30 | if err != nil { 31 | return originalImage, models.Deployment{}, err 32 | } 33 | 34 | if destination != "" { 35 | err := saveConfiguration(updatedDeployment, destination) 36 | if err != nil { 37 | return originalImage, updatedDeployment, err 38 | } 39 | 40 | } 41 | return originalImage, updatedDeployment, nil 42 | 43 | } 44 | 45 | func parseConfigurationFile(file []byte) (configurationFile models.Deployment, err error) { 46 | err = yaml.Unmarshal(file, &configurationFile) 47 | return 48 | } 49 | 50 | func saveConfiguration(configurationFile models.Deployment, destination string) error { 51 | data, err := yaml.Marshal(configurationFile) 52 | 53 | if err != nil { 54 | return errors.New("Could not save the file to the destination") 55 | } 56 | err = ioutil.WriteFile(destination, data, 0644) 57 | if err != nil { 58 | return errors.New("Could not save the file to the destination") 59 | } 60 | 61 | return err 62 | } 63 | 64 | func updateImageTag(deployment models.Deployment, imageTag string) (models.Deployment, error) { 65 | 66 | multipleContainers := isMultipleContainerDeployment(deployment) 67 | 68 | if multipleContainers { 69 | return models.Deployment{}, errors.New("Only a single container is supported at this time") 70 | } 71 | 72 | currentImage := deployment.Spec.Template.Spec.Containers[0].Image 73 | image := strings.Split(currentImage, ":")[0] 74 | updatedImage := image + ":" + imageTag 75 | 76 | deployment.Spec.Template.Spec.Containers[0].Image = updatedImage 77 | return deployment, nil 78 | } 79 | 80 | func updateImage(deployment models.Deployment, image string) (models.Deployment, error) { 81 | multipleContainers := isMultipleContainerDeployment(deployment) 82 | 83 | if multipleContainers { 84 | return models.Deployment{}, errors.New("Only a single container is supported at this time") 85 | } 86 | 87 | //TODO: Perform error checking on whether or not it is a valid image 88 | deployment.Spec.Template.Spec.Containers[0].Image = image 89 | return deployment, nil 90 | } 91 | 92 | func isMultipleContainerDeployment(deployment models.Deployment) bool { 93 | numberOfContainers := len(deployment.Spec.Template.Spec.Containers) 94 | if numberOfContainers > 1 { 95 | return true 96 | } 97 | return false 98 | } 99 | -------------------------------------------------------------------------------- /services/deployment_test.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/oshalygin/k8s-config/models" 7 | ) 8 | 9 | const configurationFile string = ` 10 | apiVersion: extensions/v1beta1 11 | kind: Deployment 12 | metadata: 13 | name: fe-web 14 | namespace: default 15 | labels: 16 | version: v1 17 | date: 20170311T222958Z 18 | spec: 19 | replicas: 2 20 | revisionHistoryLimit: 2 21 | strategy: 22 | rollingUpdate: 23 | maxUnavailable: 0 24 | type: RollingUpdate 25 | template: 26 | metadata: 27 | labels: 28 | app: fe-web 29 | spec: 30 | containers: 31 | - name: fe-web 32 | image: 'us.gcr.io/mdjs-io/merchant-dashboard:2.47.4' 33 | volumeMounts: 34 | - mountPath: /cache 35 | name: temp-volume 36 | env: 37 | - name: MONGO_IP 38 | valueFrom: 39 | secretKeyRef: 40 | name: env-variables-secret 41 | key: mongo_ip 42 | - name: MONGO_PORT 43 | valueFrom: 44 | secretKeyRef: 45 | name: env-variables-secret 46 | key: mongo_port 47 | - name: GCLOUD_PROJECT 48 | valueFrom: 49 | secretKeyRef: 50 | name: env-variables-secret 51 | key: gcloud_project 52 | - name: IMAGE_STORAGE_BUCKET 53 | valueFrom: 54 | secretKeyRef: 55 | name: env-variables-secret 56 | key: image_storage_bucket 57 | - name: DOMAIN_ENDPOINT 58 | valueFrom: 59 | secretKeyRef: 60 | name: env-variables-secret 61 | key: domain_endpoint 62 | imagePullPolicy: Always 63 | ports: 64 | - containerPort: 8080 65 | readinessProbe: 66 | httpGet: 67 | path: /healthz 68 | port: 8080 69 | initialDelaySeconds: 30 70 | timeoutSeconds: 5 71 | successThreshold: 1 72 | failureThreshold: 10 73 | volumes: 74 | - name: temp-volume 75 | emptyDir: {} 76 | ` 77 | 78 | var file = []byte(configurationFile) 79 | 80 | func Test_UpdateDeploymentConfiguration_ShouldReturnAnErrorIfTheFileCouldNotBeParsed(t *testing.T) { 81 | file := []byte{0, 0, 0} 82 | image := "" 83 | imageTag := "1.4.4" 84 | destination := "" 85 | _, _, err := UpdateDeploymentConfiguration(file, image, imageTag, destination) 86 | 87 | if err == nil { 88 | t.Errorf("should throw an error if the file could not be parsed") 89 | } 90 | } 91 | 92 | func Test_parseConfigurationFile_ShouldParseTheConfigurationFileToAYAMLFile(t *testing.T) { 93 | 94 | _, err := parseConfigurationFile(file) 95 | 96 | if err != nil { 97 | t.Errorf("should successfully parse the configuration file") 98 | } 99 | } 100 | 101 | func Test_parseConfigurationFile_ShouldSetTheConfigurationTypeToDeployment(t *testing.T) { 102 | 103 | expected := "Deployment" 104 | deployment, _ := parseConfigurationFile(file) 105 | 106 | actual := deployment.Kind 107 | 108 | if expected != actual { 109 | t.Errorf("expected %s\nactual %s", expected, actual) 110 | } 111 | } 112 | 113 | func Test_parseConfigurationFile_ShouldSetTheContainerImageNameAccordingly(t *testing.T) { 114 | 115 | expected := "us.gcr.io/mdjs-io/merchant-dashboard:2.47.4" 116 | deployment, _ := parseConfigurationFile(file) 117 | 118 | actual := deployment.Spec.Template.Spec.Containers[0].Image 119 | 120 | if expected != actual { 121 | t.Errorf("\nexpected: %s\nactual: %s", expected, actual) 122 | } 123 | } 124 | 125 | func Test_updateImageTag_ShouldUpdateTheImageTagToThePassedInTagValue(t *testing.T) { 126 | 127 | imageTag := "1.1.1" 128 | 129 | expected := "us.gcr.io/mdjs-io/merchant-dashboard:1.1.1" 130 | deployment, _ := parseConfigurationFile(file) 131 | updatedDeployment, _ := updateImageTag(deployment, imageTag) 132 | 133 | actual := updatedDeployment.Spec.Template.Spec.Containers[0].Image 134 | 135 | if expected != actual { 136 | t.Errorf("\nexpected: %s\nactual: %s", expected, actual) 137 | } 138 | } 139 | 140 | func Test_updateImageTag_ShouldReturnAnErrorIfADeploymentModelIsPassedWithMultipleContainers(t *testing.T) { 141 | 142 | imageTag := "1.1.1" 143 | 144 | deployment := models.Deployment{} 145 | deployment.Spec.Template.Spec.Containers = []models.Container{ 146 | {Name: "us.gcr.io/mdjs-io/web-client:1.1.1"}, 147 | {Name: "us.gcr.io/mdjs-io/backend-service:2.1.5"}, 148 | } 149 | _, err := updateImageTag(deployment, imageTag) 150 | 151 | if err == nil { 152 | t.Errorf("should throw an error that only a single container is supported") 153 | } 154 | 155 | } 156 | 157 | func Test_isMultipleContainerDeployment_ShouldReturnTrueWhenMultipleContainerDeployment(t *testing.T) { 158 | 159 | deployment := models.Deployment{} 160 | deployment.Spec.Template.Spec.Containers = []models.Container{ 161 | {Name: "us.gcr.io/mdjs-io/web-client:1.1.1"}, 162 | {Name: "us.gcr.io/mdjs-io/backend-service:2.1.5"}, 163 | } 164 | actual := isMultipleContainerDeployment(deployment) 165 | 166 | if actual != true { 167 | t.Errorf("\nexpected: %v\nactual: %v", true, actual) 168 | } 169 | } 170 | 171 | func Test_isMultipleContainerDeployment_ShouldReturnFalseWhenSingleContainerDeployment(t *testing.T) { 172 | 173 | deployment := models.Deployment{} 174 | deployment.Spec.Template.Spec.Containers = []models.Container{ 175 | {Name: "us.gcr.io/mdjs-io/web-client:1.1.1"}, 176 | } 177 | actual := isMultipleContainerDeployment(deployment) 178 | 179 | if actual != false { 180 | t.Errorf("\nexpected: %v\nactual: %v", false, actual) 181 | } 182 | } 183 | 184 | func Test_updateImage_ShouldReturnAnErrorIfMultiContainerDeployment(t *testing.T) { 185 | 186 | image := "us.gcr.io/mdjs-io/web-client:1.1.4" 187 | 188 | deployment := models.Deployment{} 189 | deployment.Spec.Template.Spec.Containers = []models.Container{ 190 | {Name: "us.gcr.io/mdjs-io/web-client:1.1.1"}, 191 | {Name: "us.gcr.io/mdjs-io/backend-service:2.1.5"}, 192 | } 193 | _, err := updateImage(deployment, image) 194 | 195 | if err == nil { 196 | t.Errorf("should throw an error that only a single container is supported") 197 | } 198 | 199 | } 200 | 201 | func Test_updateImage_ShouldReturnAnUpdatedDeploymentImage(t *testing.T) { 202 | 203 | newImage := "us.gcr.io/mdjs-io/merchant-dashboard:2.0.0" 204 | 205 | expected := newImage 206 | deployment, _ := parseConfigurationFile(file) 207 | updatedDeployment, _ := updateImage(deployment, newImage) 208 | 209 | actual := updatedDeployment.Spec.Template.Spec.Containers[0].Image 210 | 211 | if expected != actual { 212 | t.Errorf("\nexpected: %s\nactual: %s", expected, actual) 213 | } 214 | 215 | } 216 | -------------------------------------------------------------------------------- /test-files/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: fe-web 5 | namespace: default 6 | labels: 7 | version: v1 8 | date: 20170311T222958Z 9 | spec: 10 | replicas: 2 11 | revisionHistoryLimit: 2 12 | strategy: 13 | rollingUpdate: 14 | maxUnavailable: 0 15 | type: RollingUpdate 16 | template: 17 | metadata: 18 | labels: 19 | app: fe-web 20 | spec: 21 | containers: 22 | - name: fe-web 23 | image: us.gcr.io/mdjs-io/merchant-dashboard:1.3.3 24 | volumeMounts: 25 | - mountPath: /cache 26 | name: temp-volume 27 | env: 28 | - name: MONGO_IP 29 | valueFrom: 30 | secretKeyRef: 31 | name: env-variables-secret 32 | key: mongo_ip 33 | - name: MONGO_PORT 34 | valueFrom: 35 | secretKeyRef: 36 | name: env-variables-secret 37 | key: mongo_port 38 | - name: GCLOUD_PROJECT 39 | valueFrom: 40 | secretKeyRef: 41 | name: env-variables-secret 42 | key: gcloud_project 43 | - name: IMAGE_STORAGE_BUCKET 44 | valueFrom: 45 | secretKeyRef: 46 | name: env-variables-secret 47 | key: image_storage_bucket 48 | - name: DOMAIN_ENDPOINT 49 | valueFrom: 50 | secretKeyRef: 51 | name: env-variables-secret 52 | key: domain_endpoint 53 | - name: GCLOUD_DIAGNOSTICS_CONFIG 54 | value: ./utilities/trace.js 55 | - name: POD_ID 56 | valueFrom: 57 | fieldRef: 58 | fieldPath: metadata.name 59 | - name: CONTAINER_NAME 60 | value: fe-web 61 | - name: CLUSTER_NAME 62 | valueFrom: 63 | secretKeyRef: 64 | name: env-variables-secret 65 | key: cluster_name 66 | imagePullPolicy: Always 67 | ports: 68 | - containerPort: 8080 69 | readinessProbe: 70 | httpGet: 71 | path: /healthz 72 | port: 8080 73 | initialDelaySeconds: 30 74 | timeoutSeconds: 5 75 | successThreshold: 1 76 | failureThreshold: 10 77 | volumes: 78 | - name: temp-volume 79 | emptyDir: {} 80 | -------------------------------------------------------------------------------- /vendor/github.com/fatih/color/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Fatih Arslan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/fatih/color/README.md: -------------------------------------------------------------------------------- 1 | # Color [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/color) [![Build Status](http://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color) 2 | 3 | 4 | 5 | Color lets you use colorized outputs in terms of [ANSI Escape 6 | Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It 7 | has support for Windows too! The API can be used in several ways, pick one that 8 | suits you. 9 | 10 | 11 | ![Color](http://i.imgur.com/c1JI0lA.png) 12 | 13 | 14 | ## Install 15 | 16 | ```bash 17 | go get github.com/fatih/color 18 | ``` 19 | 20 | Note that the `vendor` folder is here for stability. Remove the folder if you 21 | already have the dependencies in your GOPATH. 22 | 23 | ## Examples 24 | 25 | ### Standard colors 26 | 27 | ```go 28 | // Print with default helper functions 29 | color.Cyan("Prints text in cyan.") 30 | 31 | // A newline will be appended automatically 32 | color.Blue("Prints %s in blue.", "text") 33 | 34 | // These are using the default foreground colors 35 | color.Red("We have red") 36 | color.Magenta("And many others ..") 37 | 38 | ``` 39 | 40 | ### Mix and reuse colors 41 | 42 | ```go 43 | // Create a new color object 44 | c := color.New(color.FgCyan).Add(color.Underline) 45 | c.Println("Prints cyan text with an underline.") 46 | 47 | // Or just add them to New() 48 | d := color.New(color.FgCyan, color.Bold) 49 | d.Printf("This prints bold cyan %s\n", "too!.") 50 | 51 | // Mix up foreground and background colors, create new mixes! 52 | red := color.New(color.FgRed) 53 | 54 | boldRed := red.Add(color.Bold) 55 | boldRed.Println("This will print text in bold red.") 56 | 57 | whiteBackground := red.Add(color.BgWhite) 58 | whiteBackground.Println("Red text with white background.") 59 | ``` 60 | 61 | ### Use your own output (io.Writer) 62 | 63 | ```go 64 | // Use your own io.Writer output 65 | color.New(color.FgBlue).Fprintln(myWriter, "blue color!") 66 | 67 | blue := color.New(color.FgBlue) 68 | blue.Fprint(writer, "This will print text in blue.") 69 | ``` 70 | 71 | ### Custom print functions (PrintFunc) 72 | 73 | ```go 74 | // Create a custom print function for convenience 75 | red := color.New(color.FgRed).PrintfFunc() 76 | red("Warning") 77 | red("Error: %s", err) 78 | 79 | // Mix up multiple attributes 80 | notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() 81 | notice("Don't forget this...") 82 | ``` 83 | 84 | ### Custom fprint functions (FprintFunc) 85 | 86 | ```go 87 | blue := color.New(FgBlue).FprintfFunc() 88 | blue(myWriter, "important notice: %s", stars) 89 | 90 | // Mix up with multiple attributes 91 | success := color.New(color.Bold, color.FgGreen).FprintlnFunc() 92 | success(myWriter, "Don't forget this...") 93 | ``` 94 | 95 | ### Insert into noncolor strings (SprintFunc) 96 | 97 | ```go 98 | // Create SprintXxx functions to mix strings with other non-colorized strings: 99 | yellow := color.New(color.FgYellow).SprintFunc() 100 | red := color.New(color.FgRed).SprintFunc() 101 | fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error")) 102 | 103 | info := color.New(color.FgWhite, color.BgGreen).SprintFunc() 104 | fmt.Printf("This %s rocks!\n", info("package")) 105 | 106 | // Use helper functions 107 | fmt.Println("This", color.RedString("warning"), "should be not neglected.") 108 | fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.") 109 | 110 | // Windows supported too! Just don't forget to change the output to color.Output 111 | fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) 112 | ``` 113 | 114 | ### Plug into existing code 115 | 116 | ```go 117 | // Use handy standard colors 118 | color.Set(color.FgYellow) 119 | 120 | fmt.Println("Existing text will now be in yellow") 121 | fmt.Printf("This one %s\n", "too") 122 | 123 | color.Unset() // Don't forget to unset 124 | 125 | // You can mix up parameters 126 | color.Set(color.FgMagenta, color.Bold) 127 | defer color.Unset() // Use it in your function 128 | 129 | fmt.Println("All text will now be bold magenta.") 130 | ``` 131 | 132 | ### Disable color 133 | 134 | There might be a case where you want to disable color output (for example to 135 | pipe the standard output of your app to somewhere else). `Color` has support to 136 | disable colors both globally and for single color definition. For example 137 | suppose you have a CLI app and a `--no-color` bool flag. You can easily disable 138 | the color output with: 139 | 140 | ```go 141 | 142 | var flagNoColor = flag.Bool("no-color", false, "Disable color output") 143 | 144 | if *flagNoColor { 145 | color.NoColor = true // disables colorized output 146 | } 147 | ``` 148 | 149 | It also has support for single color definitions (local). You can 150 | disable/enable color output on the fly: 151 | 152 | ```go 153 | c := color.New(color.FgCyan) 154 | c.Println("Prints cyan text") 155 | 156 | c.DisableColor() 157 | c.Println("This is printed without any color") 158 | 159 | c.EnableColor() 160 | c.Println("This prints again cyan...") 161 | ``` 162 | 163 | ## Todo 164 | 165 | * Save/Return previous values 166 | * Evaluate fmt.Formatter interface 167 | 168 | 169 | ## Credits 170 | 171 | * [Fatih Arslan](https://github.com/fatih) 172 | * Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable) 173 | 174 | ## License 175 | 176 | The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details 177 | 178 | -------------------------------------------------------------------------------- /vendor/github.com/fatih/color/color.go: -------------------------------------------------------------------------------- 1 | package color 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "strconv" 8 | "strings" 9 | "sync" 10 | 11 | "github.com/mattn/go-colorable" 12 | "github.com/mattn/go-isatty" 13 | ) 14 | 15 | var ( 16 | // NoColor defines if the output is colorized or not. It's dynamically set to 17 | // false or true based on the stdout's file descriptor referring to a terminal 18 | // or not. This is a global option and affects all colors. For more control 19 | // over each color block use the methods DisableColor() individually. 20 | NoColor = os.Getenv("TERM") == "dumb" || 21 | (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) 22 | 23 | // Output defines the standard output of the print functions. By default 24 | // os.Stdout is used. 25 | Output = colorable.NewColorableStdout() 26 | 27 | // colorsCache is used to reduce the count of created Color objects and 28 | // allows to reuse already created objects with required Attribute. 29 | colorsCache = make(map[Attribute]*Color) 30 | colorsCacheMu sync.Mutex // protects colorsCache 31 | ) 32 | 33 | // Color defines a custom color object which is defined by SGR parameters. 34 | type Color struct { 35 | params []Attribute 36 | noColor *bool 37 | } 38 | 39 | // Attribute defines a single SGR Code 40 | type Attribute int 41 | 42 | const escape = "\x1b" 43 | 44 | // Base attributes 45 | const ( 46 | Reset Attribute = iota 47 | Bold 48 | Faint 49 | Italic 50 | Underline 51 | BlinkSlow 52 | BlinkRapid 53 | ReverseVideo 54 | Concealed 55 | CrossedOut 56 | ) 57 | 58 | // Foreground text colors 59 | const ( 60 | FgBlack Attribute = iota + 30 61 | FgRed 62 | FgGreen 63 | FgYellow 64 | FgBlue 65 | FgMagenta 66 | FgCyan 67 | FgWhite 68 | ) 69 | 70 | // Foreground Hi-Intensity text colors 71 | const ( 72 | FgHiBlack Attribute = iota + 90 73 | FgHiRed 74 | FgHiGreen 75 | FgHiYellow 76 | FgHiBlue 77 | FgHiMagenta 78 | FgHiCyan 79 | FgHiWhite 80 | ) 81 | 82 | // Background text colors 83 | const ( 84 | BgBlack Attribute = iota + 40 85 | BgRed 86 | BgGreen 87 | BgYellow 88 | BgBlue 89 | BgMagenta 90 | BgCyan 91 | BgWhite 92 | ) 93 | 94 | // Background Hi-Intensity text colors 95 | const ( 96 | BgHiBlack Attribute = iota + 100 97 | BgHiRed 98 | BgHiGreen 99 | BgHiYellow 100 | BgHiBlue 101 | BgHiMagenta 102 | BgHiCyan 103 | BgHiWhite 104 | ) 105 | 106 | // New returns a newly created color object. 107 | func New(value ...Attribute) *Color { 108 | c := &Color{params: make([]Attribute, 0)} 109 | c.Add(value...) 110 | return c 111 | } 112 | 113 | // Set sets the given parameters immediately. It will change the color of 114 | // output with the given SGR parameters until color.Unset() is called. 115 | func Set(p ...Attribute) *Color { 116 | c := New(p...) 117 | c.Set() 118 | return c 119 | } 120 | 121 | // Unset resets all escape attributes and clears the output. Usually should 122 | // be called after Set(). 123 | func Unset() { 124 | if NoColor { 125 | return 126 | } 127 | 128 | fmt.Fprintf(Output, "%s[%dm", escape, Reset) 129 | } 130 | 131 | // Set sets the SGR sequence. 132 | func (c *Color) Set() *Color { 133 | if c.isNoColorSet() { 134 | return c 135 | } 136 | 137 | fmt.Fprintf(Output, c.format()) 138 | return c 139 | } 140 | 141 | func (c *Color) unset() { 142 | if c.isNoColorSet() { 143 | return 144 | } 145 | 146 | Unset() 147 | } 148 | 149 | func (c *Color) setWriter(w io.Writer) *Color { 150 | if c.isNoColorSet() { 151 | return c 152 | } 153 | 154 | fmt.Fprintf(w, c.format()) 155 | return c 156 | } 157 | 158 | func (c *Color) unsetWriter(w io.Writer) { 159 | if c.isNoColorSet() { 160 | return 161 | } 162 | 163 | if NoColor { 164 | return 165 | } 166 | 167 | fmt.Fprintf(w, "%s[%dm", escape, Reset) 168 | } 169 | 170 | // Add is used to chain SGR parameters. Use as many as parameters to combine 171 | // and create custom color objects. Example: Add(color.FgRed, color.Underline). 172 | func (c *Color) Add(value ...Attribute) *Color { 173 | c.params = append(c.params, value...) 174 | return c 175 | } 176 | 177 | func (c *Color) prepend(value Attribute) { 178 | c.params = append(c.params, 0) 179 | copy(c.params[1:], c.params[0:]) 180 | c.params[0] = value 181 | } 182 | 183 | // Fprint formats using the default formats for its operands and writes to w. 184 | // Spaces are added between operands when neither is a string. 185 | // It returns the number of bytes written and any write error encountered. 186 | // On Windows, users should wrap w with colorable.NewColorable() if w is of 187 | // type *os.File. 188 | func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { 189 | c.setWriter(w) 190 | defer c.unsetWriter(w) 191 | 192 | return fmt.Fprint(w, a...) 193 | } 194 | 195 | // Print formats using the default formats for its operands and writes to 196 | // standard output. Spaces are added between operands when neither is a 197 | // string. It returns the number of bytes written and any write error 198 | // encountered. This is the standard fmt.Print() method wrapped with the given 199 | // color. 200 | func (c *Color) Print(a ...interface{}) (n int, err error) { 201 | c.Set() 202 | defer c.unset() 203 | 204 | return fmt.Fprint(Output, a...) 205 | } 206 | 207 | // Fprintf formats according to a format specifier and writes to w. 208 | // It returns the number of bytes written and any write error encountered. 209 | // On Windows, users should wrap w with colorable.NewColorable() if w is of 210 | // type *os.File. 211 | func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { 212 | c.setWriter(w) 213 | defer c.unsetWriter(w) 214 | 215 | return fmt.Fprintf(w, format, a...) 216 | } 217 | 218 | // Printf formats according to a format specifier and writes to standard output. 219 | // It returns the number of bytes written and any write error encountered. 220 | // This is the standard fmt.Printf() method wrapped with the given color. 221 | func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { 222 | c.Set() 223 | defer c.unset() 224 | 225 | return fmt.Fprintf(Output, format, a...) 226 | } 227 | 228 | // Fprintln formats using the default formats for its operands and writes to w. 229 | // Spaces are always added between operands and a newline is appended. 230 | // On Windows, users should wrap w with colorable.NewColorable() if w is of 231 | // type *os.File. 232 | func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { 233 | c.setWriter(w) 234 | defer c.unsetWriter(w) 235 | 236 | return fmt.Fprintln(w, a...) 237 | } 238 | 239 | // Println formats using the default formats for its operands and writes to 240 | // standard output. Spaces are always added between operands and a newline is 241 | // appended. It returns the number of bytes written and any write error 242 | // encountered. This is the standard fmt.Print() method wrapped with the given 243 | // color. 244 | func (c *Color) Println(a ...interface{}) (n int, err error) { 245 | c.Set() 246 | defer c.unset() 247 | 248 | return fmt.Fprintln(Output, a...) 249 | } 250 | 251 | // Sprint is just like Print, but returns a string instead of printing it. 252 | func (c *Color) Sprint(a ...interface{}) string { 253 | return c.wrap(fmt.Sprint(a...)) 254 | } 255 | 256 | // Sprintln is just like Println, but returns a string instead of printing it. 257 | func (c *Color) Sprintln(a ...interface{}) string { 258 | return c.wrap(fmt.Sprintln(a...)) 259 | } 260 | 261 | // Sprintf is just like Printf, but returns a string instead of printing it. 262 | func (c *Color) Sprintf(format string, a ...interface{}) string { 263 | return c.wrap(fmt.Sprintf(format, a...)) 264 | } 265 | 266 | // FprintFunc returns a new function that prints the passed arguments as 267 | // colorized with color.Fprint(). 268 | func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) { 269 | return func(w io.Writer, a ...interface{}) { 270 | c.Fprint(w, a...) 271 | } 272 | } 273 | 274 | // PrintFunc returns a new function that prints the passed arguments as 275 | // colorized with color.Print(). 276 | func (c *Color) PrintFunc() func(a ...interface{}) { 277 | return func(a ...interface{}) { 278 | c.Print(a...) 279 | } 280 | } 281 | 282 | // FprintfFunc returns a new function that prints the passed arguments as 283 | // colorized with color.Fprintf(). 284 | func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) { 285 | return func(w io.Writer, format string, a ...interface{}) { 286 | c.Fprintf(w, format, a...) 287 | } 288 | } 289 | 290 | // PrintfFunc returns a new function that prints the passed arguments as 291 | // colorized with color.Printf(). 292 | func (c *Color) PrintfFunc() func(format string, a ...interface{}) { 293 | return func(format string, a ...interface{}) { 294 | c.Printf(format, a...) 295 | } 296 | } 297 | 298 | // FprintlnFunc returns a new function that prints the passed arguments as 299 | // colorized with color.Fprintln(). 300 | func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) { 301 | return func(w io.Writer, a ...interface{}) { 302 | c.Fprintln(w, a...) 303 | } 304 | } 305 | 306 | // PrintlnFunc returns a new function that prints the passed arguments as 307 | // colorized with color.Println(). 308 | func (c *Color) PrintlnFunc() func(a ...interface{}) { 309 | return func(a ...interface{}) { 310 | c.Println(a...) 311 | } 312 | } 313 | 314 | // SprintFunc returns a new function that returns colorized strings for the 315 | // given arguments with fmt.Sprint(). Useful to put into or mix into other 316 | // string. Windows users should use this in conjunction with color.Output, example: 317 | // 318 | // put := New(FgYellow).SprintFunc() 319 | // fmt.Fprintf(color.Output, "This is a %s", put("warning")) 320 | func (c *Color) SprintFunc() func(a ...interface{}) string { 321 | return func(a ...interface{}) string { 322 | return c.wrap(fmt.Sprint(a...)) 323 | } 324 | } 325 | 326 | // SprintfFunc returns a new function that returns colorized strings for the 327 | // given arguments with fmt.Sprintf(). Useful to put into or mix into other 328 | // string. Windows users should use this in conjunction with color.Output. 329 | func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { 330 | return func(format string, a ...interface{}) string { 331 | return c.wrap(fmt.Sprintf(format, a...)) 332 | } 333 | } 334 | 335 | // SprintlnFunc returns a new function that returns colorized strings for the 336 | // given arguments with fmt.Sprintln(). Useful to put into or mix into other 337 | // string. Windows users should use this in conjunction with color.Output. 338 | func (c *Color) SprintlnFunc() func(a ...interface{}) string { 339 | return func(a ...interface{}) string { 340 | return c.wrap(fmt.Sprintln(a...)) 341 | } 342 | } 343 | 344 | // sequence returns a formated SGR sequence to be plugged into a "\x1b[...m" 345 | // an example output might be: "1;36" -> bold cyan 346 | func (c *Color) sequence() string { 347 | format := make([]string, len(c.params)) 348 | for i, v := range c.params { 349 | format[i] = strconv.Itoa(int(v)) 350 | } 351 | 352 | return strings.Join(format, ";") 353 | } 354 | 355 | // wrap wraps the s string with the colors attributes. The string is ready to 356 | // be printed. 357 | func (c *Color) wrap(s string) string { 358 | if c.isNoColorSet() { 359 | return s 360 | } 361 | 362 | return c.format() + s + c.unformat() 363 | } 364 | 365 | func (c *Color) format() string { 366 | return fmt.Sprintf("%s[%sm", escape, c.sequence()) 367 | } 368 | 369 | func (c *Color) unformat() string { 370 | return fmt.Sprintf("%s[%dm", escape, Reset) 371 | } 372 | 373 | // DisableColor disables the color output. Useful to not change any existing 374 | // code and still being able to output. Can be used for flags like 375 | // "--no-color". To enable back use EnableColor() method. 376 | func (c *Color) DisableColor() { 377 | c.noColor = boolPtr(true) 378 | } 379 | 380 | // EnableColor enables the color output. Use it in conjunction with 381 | // DisableColor(). Otherwise this method has no side effects. 382 | func (c *Color) EnableColor() { 383 | c.noColor = boolPtr(false) 384 | } 385 | 386 | func (c *Color) isNoColorSet() bool { 387 | // check first if we have user setted action 388 | if c.noColor != nil { 389 | return *c.noColor 390 | } 391 | 392 | // if not return the global option, which is disabled by default 393 | return NoColor 394 | } 395 | 396 | // Equals returns a boolean value indicating whether two colors are equal. 397 | func (c *Color) Equals(c2 *Color) bool { 398 | if len(c.params) != len(c2.params) { 399 | return false 400 | } 401 | 402 | for _, attr := range c.params { 403 | if !c2.attrExists(attr) { 404 | return false 405 | } 406 | } 407 | 408 | return true 409 | } 410 | 411 | func (c *Color) attrExists(a Attribute) bool { 412 | for _, attr := range c.params { 413 | if attr == a { 414 | return true 415 | } 416 | } 417 | 418 | return false 419 | } 420 | 421 | func boolPtr(v bool) *bool { 422 | return &v 423 | } 424 | 425 | func getCachedColor(p Attribute) *Color { 426 | colorsCacheMu.Lock() 427 | defer colorsCacheMu.Unlock() 428 | 429 | c, ok := colorsCache[p] 430 | if !ok { 431 | c = New(p) 432 | colorsCache[p] = c 433 | } 434 | 435 | return c 436 | } 437 | 438 | func colorPrint(format string, p Attribute, a ...interface{}) { 439 | c := getCachedColor(p) 440 | 441 | if !strings.HasSuffix(format, "\n") { 442 | format += "\n" 443 | } 444 | 445 | if len(a) == 0 { 446 | c.Print(format) 447 | } else { 448 | c.Printf(format, a...) 449 | } 450 | } 451 | 452 | func colorString(format string, p Attribute, a ...interface{}) string { 453 | c := getCachedColor(p) 454 | 455 | if len(a) == 0 { 456 | return c.SprintFunc()(format) 457 | } 458 | 459 | return c.SprintfFunc()(format, a...) 460 | } 461 | 462 | // Black is a convenient helper function to print with black foreground. A 463 | // newline is appended to format by default. 464 | func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) } 465 | 466 | // Red is a convenient helper function to print with red foreground. A 467 | // newline is appended to format by default. 468 | func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) } 469 | 470 | // Green is a convenient helper function to print with green foreground. A 471 | // newline is appended to format by default. 472 | func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) } 473 | 474 | // Yellow is a convenient helper function to print with yellow foreground. 475 | // A newline is appended to format by default. 476 | func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) } 477 | 478 | // Blue is a convenient helper function to print with blue foreground. A 479 | // newline is appended to format by default. 480 | func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) } 481 | 482 | // Magenta is a convenient helper function to print with magenta foreground. 483 | // A newline is appended to format by default. 484 | func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) } 485 | 486 | // Cyan is a convenient helper function to print with cyan foreground. A 487 | // newline is appended to format by default. 488 | func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) } 489 | 490 | // White is a convenient helper function to print with white foreground. A 491 | // newline is appended to format by default. 492 | func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) } 493 | 494 | // BlackString is a convenient helper function to return a string with black 495 | // foreground. 496 | func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) } 497 | 498 | // RedString is a convenient helper function to return a string with red 499 | // foreground. 500 | func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) } 501 | 502 | // GreenString is a convenient helper function to return a string with green 503 | // foreground. 504 | func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) } 505 | 506 | // YellowString is a convenient helper function to return a string with yellow 507 | // foreground. 508 | func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) } 509 | 510 | // BlueString is a convenient helper function to return a string with blue 511 | // foreground. 512 | func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) } 513 | 514 | // MagentaString is a convenient helper function to return a string with magenta 515 | // foreground. 516 | func MagentaString(format string, a ...interface{}) string { 517 | return colorString(format, FgMagenta, a...) 518 | } 519 | 520 | // CyanString is a convenient helper function to return a string with cyan 521 | // foreground. 522 | func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) } 523 | 524 | // WhiteString is a convenient helper function to return a string with white 525 | // foreground. 526 | func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) } 527 | 528 | // HiBlack is a convenient helper function to print with hi-intensity black foreground. A 529 | // newline is appended to format by default. 530 | func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) } 531 | 532 | // HiRed is a convenient helper function to print with hi-intensity red foreground. A 533 | // newline is appended to format by default. 534 | func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) } 535 | 536 | // HiGreen is a convenient helper function to print with hi-intensity green foreground. A 537 | // newline is appended to format by default. 538 | func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) } 539 | 540 | // HiYellow is a convenient helper function to print with hi-intensity yellow foreground. 541 | // A newline is appended to format by default. 542 | func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) } 543 | 544 | // HiBlue is a convenient helper function to print with hi-intensity blue foreground. A 545 | // newline is appended to format by default. 546 | func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) } 547 | 548 | // HiMagenta is a convenient helper function to print with hi-intensity magenta foreground. 549 | // A newline is appended to format by default. 550 | func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) } 551 | 552 | // HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A 553 | // newline is appended to format by default. 554 | func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) } 555 | 556 | // HiWhite is a convenient helper function to print with hi-intensity white foreground. A 557 | // newline is appended to format by default. 558 | func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) } 559 | 560 | // HiBlackString is a convenient helper function to return a string with hi-intensity black 561 | // foreground. 562 | func HiBlackString(format string, a ...interface{}) string { 563 | return colorString(format, FgHiBlack, a...) 564 | } 565 | 566 | // HiRedString is a convenient helper function to return a string with hi-intensity red 567 | // foreground. 568 | func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) } 569 | 570 | // HiGreenString is a convenient helper function to return a string with hi-intensity green 571 | // foreground. 572 | func HiGreenString(format string, a ...interface{}) string { 573 | return colorString(format, FgHiGreen, a...) 574 | } 575 | 576 | // HiYellowString is a convenient helper function to return a string with hi-intensity yellow 577 | // foreground. 578 | func HiYellowString(format string, a ...interface{}) string { 579 | return colorString(format, FgHiYellow, a...) 580 | } 581 | 582 | // HiBlueString is a convenient helper function to return a string with hi-intensity blue 583 | // foreground. 584 | func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) } 585 | 586 | // HiMagentaString is a convenient helper function to return a string with hi-intensity magenta 587 | // foreground. 588 | func HiMagentaString(format string, a ...interface{}) string { 589 | return colorString(format, FgHiMagenta, a...) 590 | } 591 | 592 | // HiCyanString is a convenient helper function to return a string with hi-intensity cyan 593 | // foreground. 594 | func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) } 595 | 596 | // HiWhiteString is a convenient helper function to return a string with hi-intensity white 597 | // foreground. 598 | func HiWhiteString(format string, a ...interface{}) string { 599 | return colorString(format, FgHiWhite, a...) 600 | } 601 | -------------------------------------------------------------------------------- /vendor/github.com/fatih/color/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package color is an ANSI color package to output colorized or SGR defined 3 | output to the standard output. The API can be used in several way, pick one 4 | that suits you. 5 | 6 | Use simple and default helper functions with predefined foreground colors: 7 | 8 | color.Cyan("Prints text in cyan.") 9 | 10 | // a newline will be appended automatically 11 | color.Blue("Prints %s in blue.", "text") 12 | 13 | // More default foreground colors.. 14 | color.Red("We have red") 15 | color.Yellow("Yellow color too!") 16 | color.Magenta("And many others ..") 17 | 18 | // Hi-intensity colors 19 | color.HiGreen("Bright green color.") 20 | color.HiBlack("Bright black means gray..") 21 | color.HiWhite("Shiny white color!") 22 | 23 | However there are times where custom color mixes are required. Below are some 24 | examples to create custom color objects and use the print functions of each 25 | separate color object. 26 | 27 | // Create a new color object 28 | c := color.New(color.FgCyan).Add(color.Underline) 29 | c.Println("Prints cyan text with an underline.") 30 | 31 | // Or just add them to New() 32 | d := color.New(color.FgCyan, color.Bold) 33 | d.Printf("This prints bold cyan %s\n", "too!.") 34 | 35 | 36 | // Mix up foreground and background colors, create new mixes! 37 | red := color.New(color.FgRed) 38 | 39 | boldRed := red.Add(color.Bold) 40 | boldRed.Println("This will print text in bold red.") 41 | 42 | whiteBackground := red.Add(color.BgWhite) 43 | whiteBackground.Println("Red text with White background.") 44 | 45 | // Use your own io.Writer output 46 | color.New(color.FgBlue).Fprintln(myWriter, "blue color!") 47 | 48 | blue := color.New(color.FgBlue) 49 | blue.Fprint(myWriter, "This will print text in blue.") 50 | 51 | You can create PrintXxx functions to simplify even more: 52 | 53 | // Create a custom print function for convenient 54 | red := color.New(color.FgRed).PrintfFunc() 55 | red("warning") 56 | red("error: %s", err) 57 | 58 | // Mix up multiple attributes 59 | notice := color.New(color.Bold, color.FgGreen).PrintlnFunc() 60 | notice("don't forget this...") 61 | 62 | You can also FprintXxx functions to pass your own io.Writer: 63 | 64 | blue := color.New(FgBlue).FprintfFunc() 65 | blue(myWriter, "important notice: %s", stars) 66 | 67 | // Mix up with multiple attributes 68 | success := color.New(color.Bold, color.FgGreen).FprintlnFunc() 69 | success(myWriter, don't forget this...") 70 | 71 | 72 | Or create SprintXxx functions to mix strings with other non-colorized strings: 73 | 74 | yellow := New(FgYellow).SprintFunc() 75 | red := New(FgRed).SprintFunc() 76 | 77 | fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error")) 78 | 79 | info := New(FgWhite, BgGreen).SprintFunc() 80 | fmt.Printf("this %s rocks!\n", info("package")) 81 | 82 | Windows support is enabled by default. All Print functions work as intended. 83 | However only for color.SprintXXX functions, user should use fmt.FprintXXX and 84 | set the output to color.Output: 85 | 86 | fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS")) 87 | 88 | info := New(FgWhite, BgGreen).SprintFunc() 89 | fmt.Fprintf(color.Output, "this %s rocks!\n", info("package")) 90 | 91 | Using with existing code is possible. Just use the Set() method to set the 92 | standard output to the given parameters. That way a rewrite of an existing 93 | code is not required. 94 | 95 | // Use handy standard colors. 96 | color.Set(color.FgYellow) 97 | 98 | fmt.Println("Existing text will be now in Yellow") 99 | fmt.Printf("This one %s\n", "too") 100 | 101 | color.Unset() // don't forget to unset 102 | 103 | // You can mix up parameters 104 | color.Set(color.FgMagenta, color.Bold) 105 | defer color.Unset() // use it in your function 106 | 107 | fmt.Println("All text will be now bold magenta.") 108 | 109 | There might be a case where you want to disable color output (for example to 110 | pipe the standard output of your app to somewhere else). `Color` has support to 111 | disable colors both globally and for single color definition. For example 112 | suppose you have a CLI app and a `--no-color` bool flag. You can easily disable 113 | the color output with: 114 | 115 | var flagNoColor = flag.Bool("no-color", false, "Disable color output") 116 | 117 | if *flagNoColor { 118 | color.NoColor = true // disables colorized output 119 | } 120 | 121 | It also has support for single color definitions (local). You can 122 | disable/enable color output on the fly: 123 | 124 | c := color.New(color.FgCyan) 125 | c.Println("Prints cyan text") 126 | 127 | c.DisableColor() 128 | c.Println("This is printed without any color") 129 | 130 | c.EnableColor() 131 | c.Println("This prints again cyan...") 132 | */ 133 | package color 134 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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/gopkg.in/yaml.v2/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.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 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.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 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 Apache License 2.0. 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.v2" 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 { 71 | RenamedC int `yaml:"c"` 72 | D []int `yaml:",flow"` 73 | } 74 | } 75 | 76 | func main() { 77 | t := T{} 78 | 79 | err := yaml.Unmarshal([]byte(data), &t) 80 | if err != nil { 81 | log.Fatalf("error: %v", err) 82 | } 83 | fmt.Printf("--- t:\n%v\n\n", t) 84 | 85 | d, err := yaml.Marshal(&t) 86 | if err != nil { 87 | log.Fatalf("error: %v", err) 88 | } 89 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 90 | 91 | m := make(map[interface{}]interface{}) 92 | 93 | err = yaml.Unmarshal([]byte(data), &m) 94 | if err != nil { 95 | log.Fatalf("error: %v", err) 96 | } 97 | fmt.Printf("--- m:\n%v\n\n", m) 98 | 99 | d, err = yaml.Marshal(&m) 100 | if err != nil { 101 | log.Fatalf("error: %v", err) 102 | } 103 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 104 | } 105 | ``` 106 | 107 | This example will generate the following output: 108 | 109 | ``` 110 | --- t: 111 | {Easy! {2 [3 4]}} 112 | 113 | --- t dump: 114 | a: Easy! 115 | b: 116 | c: 2 117 | d: [3, 4] 118 | 119 | 120 | --- m: 121 | map[a:Easy! b:map[c:2 d:[3 4]]] 122 | 123 | --- m dump: 124 | a: Easy! 125 | b: 126 | c: 2 127 | d: 128 | - 3 129 | - 4 130 | ``` 131 | 132 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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.v2/decode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding" 5 | "encoding/base64" 6 | "fmt" 7 | "math" 8 | "reflect" 9 | "strconv" 10 | "time" 11 | ) 12 | 13 | const ( 14 | documentNode = 1 << iota 15 | mappingNode 16 | sequenceNode 17 | scalarNode 18 | aliasNode 19 | ) 20 | 21 | type node struct { 22 | kind int 23 | line, column int 24 | tag string 25 | value string 26 | implicit bool 27 | children []*node 28 | anchors map[string]*node 29 | } 30 | 31 | // ---------------------------------------------------------------------------- 32 | // Parser, produces a node tree out of a libyaml event stream. 33 | 34 | type parser struct { 35 | parser yaml_parser_t 36 | event yaml_event_t 37 | doc *node 38 | } 39 | 40 | func newParser(b []byte) *parser { 41 | p := parser{} 42 | if !yaml_parser_initialize(&p.parser) { 43 | panic("failed to initialize YAML emitter") 44 | } 45 | 46 | if len(b) == 0 { 47 | b = []byte{'\n'} 48 | } 49 | 50 | yaml_parser_set_input_string(&p.parser, b) 51 | 52 | p.skip() 53 | if p.event.typ != yaml_STREAM_START_EVENT { 54 | panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ))) 55 | } 56 | p.skip() 57 | return &p 58 | } 59 | 60 | func (p *parser) destroy() { 61 | if p.event.typ != yaml_NO_EVENT { 62 | yaml_event_delete(&p.event) 63 | } 64 | yaml_parser_delete(&p.parser) 65 | } 66 | 67 | func (p *parser) skip() { 68 | if p.event.typ != yaml_NO_EVENT { 69 | if p.event.typ == yaml_STREAM_END_EVENT { 70 | failf("attempted to go past the end of stream; corrupted value?") 71 | } 72 | yaml_event_delete(&p.event) 73 | } 74 | if !yaml_parser_parse(&p.parser, &p.event) { 75 | p.fail() 76 | } 77 | } 78 | 79 | func (p *parser) fail() { 80 | var where string 81 | var line int 82 | if p.parser.problem_mark.line != 0 { 83 | line = p.parser.problem_mark.line 84 | } else if p.parser.context_mark.line != 0 { 85 | line = p.parser.context_mark.line 86 | } 87 | if line != 0 { 88 | where = "line " + strconv.Itoa(line) + ": " 89 | } 90 | var msg string 91 | if len(p.parser.problem) > 0 { 92 | msg = p.parser.problem 93 | } else { 94 | msg = "unknown problem parsing YAML content" 95 | } 96 | failf("%s%s", where, msg) 97 | } 98 | 99 | func (p *parser) anchor(n *node, anchor []byte) { 100 | if anchor != nil { 101 | p.doc.anchors[string(anchor)] = n 102 | } 103 | } 104 | 105 | func (p *parser) parse() *node { 106 | switch p.event.typ { 107 | case yaml_SCALAR_EVENT: 108 | return p.scalar() 109 | case yaml_ALIAS_EVENT: 110 | return p.alias() 111 | case yaml_MAPPING_START_EVENT: 112 | return p.mapping() 113 | case yaml_SEQUENCE_START_EVENT: 114 | return p.sequence() 115 | case yaml_DOCUMENT_START_EVENT: 116 | return p.document() 117 | case yaml_STREAM_END_EVENT: 118 | // Happens when attempting to decode an empty buffer. 119 | return nil 120 | default: 121 | panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ))) 122 | } 123 | } 124 | 125 | func (p *parser) node(kind int) *node { 126 | return &node{ 127 | kind: kind, 128 | line: p.event.start_mark.line, 129 | column: p.event.start_mark.column, 130 | } 131 | } 132 | 133 | func (p *parser) document() *node { 134 | n := p.node(documentNode) 135 | n.anchors = make(map[string]*node) 136 | p.doc = n 137 | p.skip() 138 | n.children = append(n.children, p.parse()) 139 | if p.event.typ != yaml_DOCUMENT_END_EVENT { 140 | panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ))) 141 | } 142 | p.skip() 143 | return n 144 | } 145 | 146 | func (p *parser) alias() *node { 147 | n := p.node(aliasNode) 148 | n.value = string(p.event.anchor) 149 | p.skip() 150 | return n 151 | } 152 | 153 | func (p *parser) scalar() *node { 154 | n := p.node(scalarNode) 155 | n.value = string(p.event.value) 156 | n.tag = string(p.event.tag) 157 | n.implicit = p.event.implicit 158 | p.anchor(n, p.event.anchor) 159 | p.skip() 160 | return n 161 | } 162 | 163 | func (p *parser) sequence() *node { 164 | n := p.node(sequenceNode) 165 | p.anchor(n, p.event.anchor) 166 | p.skip() 167 | for p.event.typ != yaml_SEQUENCE_END_EVENT { 168 | n.children = append(n.children, p.parse()) 169 | } 170 | p.skip() 171 | return n 172 | } 173 | 174 | func (p *parser) mapping() *node { 175 | n := p.node(mappingNode) 176 | p.anchor(n, p.event.anchor) 177 | p.skip() 178 | for p.event.typ != yaml_MAPPING_END_EVENT { 179 | n.children = append(n.children, p.parse(), p.parse()) 180 | } 181 | p.skip() 182 | return n 183 | } 184 | 185 | // ---------------------------------------------------------------------------- 186 | // Decoder, unmarshals a node into a provided value. 187 | 188 | type decoder struct { 189 | doc *node 190 | aliases map[string]bool 191 | mapType reflect.Type 192 | terrors []string 193 | } 194 | 195 | var ( 196 | mapItemType = reflect.TypeOf(MapItem{}) 197 | durationType = reflect.TypeOf(time.Duration(0)) 198 | defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) 199 | ifaceType = defaultMapType.Elem() 200 | ) 201 | 202 | func newDecoder() *decoder { 203 | d := &decoder{mapType: defaultMapType} 204 | d.aliases = make(map[string]bool) 205 | return d 206 | } 207 | 208 | func (d *decoder) terror(n *node, tag string, out reflect.Value) { 209 | if n.tag != "" { 210 | tag = n.tag 211 | } 212 | value := n.value 213 | if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG { 214 | if len(value) > 10 { 215 | value = " `" + value[:7] + "...`" 216 | } else { 217 | value = " `" + value + "`" 218 | } 219 | } 220 | d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type())) 221 | } 222 | 223 | func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) { 224 | terrlen := len(d.terrors) 225 | err := u.UnmarshalYAML(func(v interface{}) (err error) { 226 | defer handleErr(&err) 227 | d.unmarshal(n, reflect.ValueOf(v)) 228 | if len(d.terrors) > terrlen { 229 | issues := d.terrors[terrlen:] 230 | d.terrors = d.terrors[:terrlen] 231 | return &TypeError{issues} 232 | } 233 | return nil 234 | }) 235 | if e, ok := err.(*TypeError); ok { 236 | d.terrors = append(d.terrors, e.Errors...) 237 | return false 238 | } 239 | if err != nil { 240 | fail(err) 241 | } 242 | return true 243 | } 244 | 245 | // d.prepare initializes and dereferences pointers and calls UnmarshalYAML 246 | // if a value is found to implement it. 247 | // It returns the initialized and dereferenced out value, whether 248 | // unmarshalling was already done by UnmarshalYAML, and if so whether 249 | // its types unmarshalled appropriately. 250 | // 251 | // If n holds a null value, prepare returns before doing anything. 252 | func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { 253 | if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "" && n.implicit) { 254 | return out, false, false 255 | } 256 | again := true 257 | for again { 258 | again = false 259 | if out.Kind() == reflect.Ptr { 260 | if out.IsNil() { 261 | out.Set(reflect.New(out.Type().Elem())) 262 | } 263 | out = out.Elem() 264 | again = true 265 | } 266 | if out.CanAddr() { 267 | if u, ok := out.Addr().Interface().(Unmarshaler); ok { 268 | good = d.callUnmarshaler(n, u) 269 | return out, true, good 270 | } 271 | } 272 | } 273 | return out, false, false 274 | } 275 | 276 | func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { 277 | switch n.kind { 278 | case documentNode: 279 | return d.document(n, out) 280 | case aliasNode: 281 | return d.alias(n, out) 282 | } 283 | out, unmarshaled, good := d.prepare(n, out) 284 | if unmarshaled { 285 | return good 286 | } 287 | switch n.kind { 288 | case scalarNode: 289 | good = d.scalar(n, out) 290 | case mappingNode: 291 | good = d.mapping(n, out) 292 | case sequenceNode: 293 | good = d.sequence(n, out) 294 | default: 295 | panic("internal error: unknown node kind: " + strconv.Itoa(n.kind)) 296 | } 297 | return good 298 | } 299 | 300 | func (d *decoder) document(n *node, out reflect.Value) (good bool) { 301 | if len(n.children) == 1 { 302 | d.doc = n 303 | d.unmarshal(n.children[0], out) 304 | return true 305 | } 306 | return false 307 | } 308 | 309 | func (d *decoder) alias(n *node, out reflect.Value) (good bool) { 310 | an, ok := d.doc.anchors[n.value] 311 | if !ok { 312 | failf("unknown anchor '%s' referenced", n.value) 313 | } 314 | if d.aliases[n.value] { 315 | failf("anchor '%s' value contains itself", n.value) 316 | } 317 | d.aliases[n.value] = true 318 | good = d.unmarshal(an, out) 319 | delete(d.aliases, n.value) 320 | return good 321 | } 322 | 323 | var zeroValue reflect.Value 324 | 325 | func resetMap(out reflect.Value) { 326 | for _, k := range out.MapKeys() { 327 | out.SetMapIndex(k, zeroValue) 328 | } 329 | } 330 | 331 | func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { 332 | var tag string 333 | var resolved interface{} 334 | if n.tag == "" && !n.implicit { 335 | tag = yaml_STR_TAG 336 | resolved = n.value 337 | } else { 338 | tag, resolved = resolve(n.tag, n.value) 339 | if tag == yaml_BINARY_TAG { 340 | data, err := base64.StdEncoding.DecodeString(resolved.(string)) 341 | if err != nil { 342 | failf("!!binary value contains invalid base64 data") 343 | } 344 | resolved = string(data) 345 | } 346 | } 347 | if resolved == nil { 348 | if out.Kind() == reflect.Map && !out.CanAddr() { 349 | resetMap(out) 350 | } else { 351 | out.Set(reflect.Zero(out.Type())) 352 | } 353 | return true 354 | } 355 | if s, ok := resolved.(string); ok && out.CanAddr() { 356 | if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok { 357 | err := u.UnmarshalText([]byte(s)) 358 | if err != nil { 359 | fail(err) 360 | } 361 | return true 362 | } 363 | } 364 | switch out.Kind() { 365 | case reflect.String: 366 | if tag == yaml_BINARY_TAG { 367 | out.SetString(resolved.(string)) 368 | good = true 369 | } else if resolved != nil { 370 | out.SetString(n.value) 371 | good = true 372 | } 373 | case reflect.Interface: 374 | if resolved == nil { 375 | out.Set(reflect.Zero(out.Type())) 376 | } else { 377 | out.Set(reflect.ValueOf(resolved)) 378 | } 379 | good = true 380 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 381 | switch resolved := resolved.(type) { 382 | case int: 383 | if !out.OverflowInt(int64(resolved)) { 384 | out.SetInt(int64(resolved)) 385 | good = true 386 | } 387 | case int64: 388 | if !out.OverflowInt(resolved) { 389 | out.SetInt(resolved) 390 | good = true 391 | } 392 | case uint64: 393 | if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { 394 | out.SetInt(int64(resolved)) 395 | good = true 396 | } 397 | case float64: 398 | if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { 399 | out.SetInt(int64(resolved)) 400 | good = true 401 | } 402 | case string: 403 | if out.Type() == durationType { 404 | d, err := time.ParseDuration(resolved) 405 | if err == nil { 406 | out.SetInt(int64(d)) 407 | good = true 408 | } 409 | } 410 | } 411 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 412 | switch resolved := resolved.(type) { 413 | case int: 414 | if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { 415 | out.SetUint(uint64(resolved)) 416 | good = true 417 | } 418 | case int64: 419 | if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { 420 | out.SetUint(uint64(resolved)) 421 | good = true 422 | } 423 | case uint64: 424 | if !out.OverflowUint(uint64(resolved)) { 425 | out.SetUint(uint64(resolved)) 426 | good = true 427 | } 428 | case float64: 429 | if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { 430 | out.SetUint(uint64(resolved)) 431 | good = true 432 | } 433 | } 434 | case reflect.Bool: 435 | switch resolved := resolved.(type) { 436 | case bool: 437 | out.SetBool(resolved) 438 | good = true 439 | } 440 | case reflect.Float32, reflect.Float64: 441 | switch resolved := resolved.(type) { 442 | case int: 443 | out.SetFloat(float64(resolved)) 444 | good = true 445 | case int64: 446 | out.SetFloat(float64(resolved)) 447 | good = true 448 | case uint64: 449 | out.SetFloat(float64(resolved)) 450 | good = true 451 | case float64: 452 | out.SetFloat(resolved) 453 | good = true 454 | } 455 | case reflect.Ptr: 456 | if out.Type().Elem() == reflect.TypeOf(resolved) { 457 | // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? 458 | elem := reflect.New(out.Type().Elem()) 459 | elem.Elem().Set(reflect.ValueOf(resolved)) 460 | out.Set(elem) 461 | good = true 462 | } 463 | } 464 | if !good { 465 | d.terror(n, tag, out) 466 | } 467 | return good 468 | } 469 | 470 | func settableValueOf(i interface{}) reflect.Value { 471 | v := reflect.ValueOf(i) 472 | sv := reflect.New(v.Type()).Elem() 473 | sv.Set(v) 474 | return sv 475 | } 476 | 477 | func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { 478 | l := len(n.children) 479 | 480 | var iface reflect.Value 481 | switch out.Kind() { 482 | case reflect.Slice: 483 | out.Set(reflect.MakeSlice(out.Type(), l, l)) 484 | case reflect.Interface: 485 | // No type hints. Will have to use a generic sequence. 486 | iface = out 487 | out = settableValueOf(make([]interface{}, l)) 488 | default: 489 | d.terror(n, yaml_SEQ_TAG, out) 490 | return false 491 | } 492 | et := out.Type().Elem() 493 | 494 | j := 0 495 | for i := 0; i < l; i++ { 496 | e := reflect.New(et).Elem() 497 | if ok := d.unmarshal(n.children[i], e); ok { 498 | out.Index(j).Set(e) 499 | j++ 500 | } 501 | } 502 | out.Set(out.Slice(0, j)) 503 | if iface.IsValid() { 504 | iface.Set(out) 505 | } 506 | return true 507 | } 508 | 509 | func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { 510 | switch out.Kind() { 511 | case reflect.Struct: 512 | return d.mappingStruct(n, out) 513 | case reflect.Slice: 514 | return d.mappingSlice(n, out) 515 | case reflect.Map: 516 | // okay 517 | case reflect.Interface: 518 | if d.mapType.Kind() == reflect.Map { 519 | iface := out 520 | out = reflect.MakeMap(d.mapType) 521 | iface.Set(out) 522 | } else { 523 | slicev := reflect.New(d.mapType).Elem() 524 | if !d.mappingSlice(n, slicev) { 525 | return false 526 | } 527 | out.Set(slicev) 528 | return true 529 | } 530 | default: 531 | d.terror(n, yaml_MAP_TAG, out) 532 | return false 533 | } 534 | outt := out.Type() 535 | kt := outt.Key() 536 | et := outt.Elem() 537 | 538 | mapType := d.mapType 539 | if outt.Key() == ifaceType && outt.Elem() == ifaceType { 540 | d.mapType = outt 541 | } 542 | 543 | if out.IsNil() { 544 | out.Set(reflect.MakeMap(outt)) 545 | } 546 | l := len(n.children) 547 | for i := 0; i < l; i += 2 { 548 | if isMerge(n.children[i]) { 549 | d.merge(n.children[i+1], out) 550 | continue 551 | } 552 | k := reflect.New(kt).Elem() 553 | if d.unmarshal(n.children[i], k) { 554 | kkind := k.Kind() 555 | if kkind == reflect.Interface { 556 | kkind = k.Elem().Kind() 557 | } 558 | if kkind == reflect.Map || kkind == reflect.Slice { 559 | failf("invalid map key: %#v", k.Interface()) 560 | } 561 | e := reflect.New(et).Elem() 562 | if d.unmarshal(n.children[i+1], e) { 563 | out.SetMapIndex(k, e) 564 | } 565 | } 566 | } 567 | d.mapType = mapType 568 | return true 569 | } 570 | 571 | func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { 572 | outt := out.Type() 573 | if outt.Elem() != mapItemType { 574 | d.terror(n, yaml_MAP_TAG, out) 575 | return false 576 | } 577 | 578 | mapType := d.mapType 579 | d.mapType = outt 580 | 581 | var slice []MapItem 582 | var l = len(n.children) 583 | for i := 0; i < l; i += 2 { 584 | if isMerge(n.children[i]) { 585 | d.merge(n.children[i+1], out) 586 | continue 587 | } 588 | item := MapItem{} 589 | k := reflect.ValueOf(&item.Key).Elem() 590 | if d.unmarshal(n.children[i], k) { 591 | v := reflect.ValueOf(&item.Value).Elem() 592 | if d.unmarshal(n.children[i+1], v) { 593 | slice = append(slice, item) 594 | } 595 | } 596 | } 597 | out.Set(reflect.ValueOf(slice)) 598 | d.mapType = mapType 599 | return true 600 | } 601 | 602 | func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { 603 | sinfo, err := getStructInfo(out.Type()) 604 | if err != nil { 605 | panic(err) 606 | } 607 | name := settableValueOf("") 608 | l := len(n.children) 609 | 610 | var inlineMap reflect.Value 611 | var elemType reflect.Type 612 | if sinfo.InlineMap != -1 { 613 | inlineMap = out.Field(sinfo.InlineMap) 614 | inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) 615 | elemType = inlineMap.Type().Elem() 616 | } 617 | 618 | for i := 0; i < l; i += 2 { 619 | ni := n.children[i] 620 | if isMerge(ni) { 621 | d.merge(n.children[i+1], out) 622 | continue 623 | } 624 | if !d.unmarshal(ni, name) { 625 | continue 626 | } 627 | if info, ok := sinfo.FieldsMap[name.String()]; ok { 628 | var field reflect.Value 629 | if info.Inline == nil { 630 | field = out.Field(info.Num) 631 | } else { 632 | field = out.FieldByIndex(info.Inline) 633 | } 634 | d.unmarshal(n.children[i+1], field) 635 | } else if sinfo.InlineMap != -1 { 636 | if inlineMap.IsNil() { 637 | inlineMap.Set(reflect.MakeMap(inlineMap.Type())) 638 | } 639 | value := reflect.New(elemType).Elem() 640 | d.unmarshal(n.children[i+1], value) 641 | inlineMap.SetMapIndex(name, value) 642 | } 643 | } 644 | return true 645 | } 646 | 647 | func failWantMap() { 648 | failf("map merge requires map or sequence of maps as the value") 649 | } 650 | 651 | func (d *decoder) merge(n *node, out reflect.Value) { 652 | switch n.kind { 653 | case mappingNode: 654 | d.unmarshal(n, out) 655 | case aliasNode: 656 | an, ok := d.doc.anchors[n.value] 657 | if ok && an.kind != mappingNode { 658 | failWantMap() 659 | } 660 | d.unmarshal(n, out) 661 | case sequenceNode: 662 | // Step backwards as earlier nodes take precedence. 663 | for i := len(n.children) - 1; i >= 0; i-- { 664 | ni := n.children[i] 665 | if ni.kind == aliasNode { 666 | an, ok := d.doc.anchors[ni.value] 667 | if ok && an.kind != mappingNode { 668 | failWantMap() 669 | } 670 | } else if ni.kind != mappingNode { 671 | failWantMap() 672 | } 673 | d.unmarshal(ni, out) 674 | } 675 | default: 676 | failWantMap() 677 | } 678 | } 679 | 680 | func isMerge(n *node) bool { 681 | return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) 682 | } 683 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/encode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding" 5 | "fmt" 6 | "reflect" 7 | "regexp" 8 | "sort" 9 | "strconv" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | type encoder struct { 15 | emitter yaml_emitter_t 16 | event yaml_event_t 17 | out []byte 18 | flow bool 19 | } 20 | 21 | func newEncoder() (e *encoder) { 22 | e = &encoder{} 23 | e.must(yaml_emitter_initialize(&e.emitter)) 24 | yaml_emitter_set_output_string(&e.emitter, &e.out) 25 | yaml_emitter_set_unicode(&e.emitter, true) 26 | e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)) 27 | e.emit() 28 | e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true)) 29 | e.emit() 30 | return e 31 | } 32 | 33 | func (e *encoder) finish() { 34 | e.must(yaml_document_end_event_initialize(&e.event, true)) 35 | e.emit() 36 | e.emitter.open_ended = false 37 | e.must(yaml_stream_end_event_initialize(&e.event)) 38 | e.emit() 39 | } 40 | 41 | func (e *encoder) destroy() { 42 | yaml_emitter_delete(&e.emitter) 43 | } 44 | 45 | func (e *encoder) emit() { 46 | // This will internally delete the e.event value. 47 | if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { 48 | e.must(false) 49 | } 50 | } 51 | 52 | func (e *encoder) must(ok bool) { 53 | if !ok { 54 | msg := e.emitter.problem 55 | if msg == "" { 56 | msg = "unknown problem generating YAML content" 57 | } 58 | failf("%s", msg) 59 | } 60 | } 61 | 62 | func (e *encoder) marshal(tag string, in reflect.Value) { 63 | if !in.IsValid() { 64 | e.nilv() 65 | return 66 | } 67 | iface := in.Interface() 68 | if m, ok := iface.(Marshaler); ok { 69 | v, err := m.MarshalYAML() 70 | if err != nil { 71 | fail(err) 72 | } 73 | if v == nil { 74 | e.nilv() 75 | return 76 | } 77 | in = reflect.ValueOf(v) 78 | } else if m, ok := iface.(encoding.TextMarshaler); ok { 79 | text, err := m.MarshalText() 80 | if err != nil { 81 | fail(err) 82 | } 83 | in = reflect.ValueOf(string(text)) 84 | } 85 | switch in.Kind() { 86 | case reflect.Interface: 87 | if in.IsNil() { 88 | e.nilv() 89 | } else { 90 | e.marshal(tag, in.Elem()) 91 | } 92 | case reflect.Map: 93 | e.mapv(tag, in) 94 | case reflect.Ptr: 95 | if in.IsNil() { 96 | e.nilv() 97 | } else { 98 | e.marshal(tag, in.Elem()) 99 | } 100 | case reflect.Struct: 101 | e.structv(tag, in) 102 | case reflect.Slice: 103 | if in.Type().Elem() == mapItemType { 104 | e.itemsv(tag, in) 105 | } else { 106 | e.slicev(tag, in) 107 | } 108 | case reflect.String: 109 | e.stringv(tag, in) 110 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 111 | if in.Type() == durationType { 112 | e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) 113 | } else { 114 | e.intv(tag, in) 115 | } 116 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 117 | e.uintv(tag, in) 118 | case reflect.Float32, reflect.Float64: 119 | e.floatv(tag, in) 120 | case reflect.Bool: 121 | e.boolv(tag, in) 122 | default: 123 | panic("cannot marshal type: " + in.Type().String()) 124 | } 125 | } 126 | 127 | func (e *encoder) mapv(tag string, in reflect.Value) { 128 | e.mappingv(tag, func() { 129 | keys := keyList(in.MapKeys()) 130 | sort.Sort(keys) 131 | for _, k := range keys { 132 | e.marshal("", k) 133 | e.marshal("", in.MapIndex(k)) 134 | } 135 | }) 136 | } 137 | 138 | func (e *encoder) itemsv(tag string, in reflect.Value) { 139 | e.mappingv(tag, func() { 140 | slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) 141 | for _, item := range slice { 142 | e.marshal("", reflect.ValueOf(item.Key)) 143 | e.marshal("", reflect.ValueOf(item.Value)) 144 | } 145 | }) 146 | } 147 | 148 | func (e *encoder) structv(tag string, in reflect.Value) { 149 | sinfo, err := getStructInfo(in.Type()) 150 | if err != nil { 151 | panic(err) 152 | } 153 | e.mappingv(tag, func() { 154 | for _, info := range sinfo.FieldsList { 155 | var value reflect.Value 156 | if info.Inline == nil { 157 | value = in.Field(info.Num) 158 | } else { 159 | value = in.FieldByIndex(info.Inline) 160 | } 161 | if info.OmitEmpty && isZero(value) { 162 | continue 163 | } 164 | e.marshal("", reflect.ValueOf(info.Key)) 165 | e.flow = info.Flow 166 | e.marshal("", value) 167 | } 168 | if sinfo.InlineMap >= 0 { 169 | m := in.Field(sinfo.InlineMap) 170 | if m.Len() > 0 { 171 | e.flow = false 172 | keys := keyList(m.MapKeys()) 173 | sort.Sort(keys) 174 | for _, k := range keys { 175 | if _, found := sinfo.FieldsMap[k.String()]; found { 176 | panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) 177 | } 178 | e.marshal("", k) 179 | e.flow = false 180 | e.marshal("", m.MapIndex(k)) 181 | } 182 | } 183 | } 184 | }) 185 | } 186 | 187 | func (e *encoder) mappingv(tag string, f func()) { 188 | implicit := tag == "" 189 | style := yaml_BLOCK_MAPPING_STYLE 190 | if e.flow { 191 | e.flow = false 192 | style = yaml_FLOW_MAPPING_STYLE 193 | } 194 | e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 195 | e.emit() 196 | f() 197 | e.must(yaml_mapping_end_event_initialize(&e.event)) 198 | e.emit() 199 | } 200 | 201 | func (e *encoder) slicev(tag string, in reflect.Value) { 202 | implicit := tag == "" 203 | style := yaml_BLOCK_SEQUENCE_STYLE 204 | if e.flow { 205 | e.flow = false 206 | style = yaml_FLOW_SEQUENCE_STYLE 207 | } 208 | e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) 209 | e.emit() 210 | n := in.Len() 211 | for i := 0; i < n; i++ { 212 | e.marshal("", in.Index(i)) 213 | } 214 | e.must(yaml_sequence_end_event_initialize(&e.event)) 215 | e.emit() 216 | } 217 | 218 | // isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. 219 | // 220 | // The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported 221 | // in YAML 1.2 and by this package, but these should be marshalled quoted for 222 | // the time being for compatibility with other parsers. 223 | func isBase60Float(s string) (result bool) { 224 | // Fast path. 225 | if s == "" { 226 | return false 227 | } 228 | c := s[0] 229 | if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { 230 | return false 231 | } 232 | // Do the full match. 233 | return base60float.MatchString(s) 234 | } 235 | 236 | // From http://yaml.org/type/float.html, except the regular expression there 237 | // is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. 238 | var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) 239 | 240 | func (e *encoder) stringv(tag string, in reflect.Value) { 241 | var style yaml_scalar_style_t 242 | s := in.String() 243 | rtag, rs := resolve("", s) 244 | if rtag == yaml_BINARY_TAG { 245 | if tag == "" || tag == yaml_STR_TAG { 246 | tag = rtag 247 | s = rs.(string) 248 | } else if tag == yaml_BINARY_TAG { 249 | failf("explicitly tagged !!binary data must be base64-encoded") 250 | } else { 251 | failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) 252 | } 253 | } 254 | if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { 255 | style = yaml_DOUBLE_QUOTED_SCALAR_STYLE 256 | } else if strings.Contains(s, "\n") { 257 | style = yaml_LITERAL_SCALAR_STYLE 258 | } else { 259 | style = yaml_PLAIN_SCALAR_STYLE 260 | } 261 | e.emitScalar(s, "", tag, style) 262 | } 263 | 264 | func (e *encoder) boolv(tag string, in reflect.Value) { 265 | var s string 266 | if in.Bool() { 267 | s = "true" 268 | } else { 269 | s = "false" 270 | } 271 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 272 | } 273 | 274 | func (e *encoder) intv(tag string, in reflect.Value) { 275 | s := strconv.FormatInt(in.Int(), 10) 276 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 277 | } 278 | 279 | func (e *encoder) uintv(tag string, in reflect.Value) { 280 | s := strconv.FormatUint(in.Uint(), 10) 281 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 282 | } 283 | 284 | func (e *encoder) floatv(tag string, in reflect.Value) { 285 | // FIXME: Handle 64 bits here. 286 | s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) 287 | switch s { 288 | case "+Inf": 289 | s = ".inf" 290 | case "-Inf": 291 | s = "-.inf" 292 | case "NaN": 293 | s = ".nan" 294 | } 295 | e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 296 | } 297 | 298 | func (e *encoder) nilv() { 299 | e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) 300 | } 301 | 302 | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { 303 | implicit := tag == "" 304 | e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) 305 | e.emit() 306 | } 307 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/parserc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | // The parser implements the following grammar: 8 | // 9 | // stream ::= STREAM-START implicit_document? explicit_document* STREAM-END 10 | // implicit_document ::= block_node DOCUMENT-END* 11 | // explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* 12 | // block_node_or_indentless_sequence ::= 13 | // ALIAS 14 | // | properties (block_content | indentless_block_sequence)? 15 | // | block_content 16 | // | indentless_block_sequence 17 | // block_node ::= ALIAS 18 | // | properties block_content? 19 | // | block_content 20 | // flow_node ::= ALIAS 21 | // | properties flow_content? 22 | // | flow_content 23 | // properties ::= TAG ANCHOR? | ANCHOR TAG? 24 | // block_content ::= block_collection | flow_collection | SCALAR 25 | // flow_content ::= flow_collection | SCALAR 26 | // block_collection ::= block_sequence | block_mapping 27 | // flow_collection ::= flow_sequence | flow_mapping 28 | // block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END 29 | // indentless_sequence ::= (BLOCK-ENTRY block_node?)+ 30 | // block_mapping ::= BLOCK-MAPPING_START 31 | // ((KEY block_node_or_indentless_sequence?)? 32 | // (VALUE block_node_or_indentless_sequence?)?)* 33 | // BLOCK-END 34 | // flow_sequence ::= FLOW-SEQUENCE-START 35 | // (flow_sequence_entry FLOW-ENTRY)* 36 | // flow_sequence_entry? 37 | // FLOW-SEQUENCE-END 38 | // flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 39 | // flow_mapping ::= FLOW-MAPPING-START 40 | // (flow_mapping_entry FLOW-ENTRY)* 41 | // flow_mapping_entry? 42 | // FLOW-MAPPING-END 43 | // flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 44 | 45 | // Peek the next token in the token queue. 46 | func peek_token(parser *yaml_parser_t) *yaml_token_t { 47 | if parser.token_available || yaml_parser_fetch_more_tokens(parser) { 48 | return &parser.tokens[parser.tokens_head] 49 | } 50 | return nil 51 | } 52 | 53 | // Remove the next token from the queue (must be called after peek_token). 54 | func skip_token(parser *yaml_parser_t) { 55 | parser.token_available = false 56 | parser.tokens_parsed++ 57 | parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN 58 | parser.tokens_head++ 59 | } 60 | 61 | // Get the next event. 62 | func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { 63 | // Erase the event object. 64 | *event = yaml_event_t{} 65 | 66 | // No events after the end of the stream or error. 67 | if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { 68 | return true 69 | } 70 | 71 | // Generate the next event. 72 | return yaml_parser_state_machine(parser, event) 73 | } 74 | 75 | // Set parser error. 76 | func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { 77 | parser.error = yaml_PARSER_ERROR 78 | parser.problem = problem 79 | parser.problem_mark = problem_mark 80 | return false 81 | } 82 | 83 | func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { 84 | parser.error = yaml_PARSER_ERROR 85 | parser.context = context 86 | parser.context_mark = context_mark 87 | parser.problem = problem 88 | parser.problem_mark = problem_mark 89 | return false 90 | } 91 | 92 | // State dispatcher. 93 | func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { 94 | //trace("yaml_parser_state_machine", "state:", parser.state.String()) 95 | 96 | switch parser.state { 97 | case yaml_PARSE_STREAM_START_STATE: 98 | return yaml_parser_parse_stream_start(parser, event) 99 | 100 | case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: 101 | return yaml_parser_parse_document_start(parser, event, true) 102 | 103 | case yaml_PARSE_DOCUMENT_START_STATE: 104 | return yaml_parser_parse_document_start(parser, event, false) 105 | 106 | case yaml_PARSE_DOCUMENT_CONTENT_STATE: 107 | return yaml_parser_parse_document_content(parser, event) 108 | 109 | case yaml_PARSE_DOCUMENT_END_STATE: 110 | return yaml_parser_parse_document_end(parser, event) 111 | 112 | case yaml_PARSE_BLOCK_NODE_STATE: 113 | return yaml_parser_parse_node(parser, event, true, false) 114 | 115 | case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: 116 | return yaml_parser_parse_node(parser, event, true, true) 117 | 118 | case yaml_PARSE_FLOW_NODE_STATE: 119 | return yaml_parser_parse_node(parser, event, false, false) 120 | 121 | case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: 122 | return yaml_parser_parse_block_sequence_entry(parser, event, true) 123 | 124 | case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: 125 | return yaml_parser_parse_block_sequence_entry(parser, event, false) 126 | 127 | case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: 128 | return yaml_parser_parse_indentless_sequence_entry(parser, event) 129 | 130 | case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: 131 | return yaml_parser_parse_block_mapping_key(parser, event, true) 132 | 133 | case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: 134 | return yaml_parser_parse_block_mapping_key(parser, event, false) 135 | 136 | case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: 137 | return yaml_parser_parse_block_mapping_value(parser, event) 138 | 139 | case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: 140 | return yaml_parser_parse_flow_sequence_entry(parser, event, true) 141 | 142 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: 143 | return yaml_parser_parse_flow_sequence_entry(parser, event, false) 144 | 145 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: 146 | return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) 147 | 148 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: 149 | return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) 150 | 151 | case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: 152 | return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) 153 | 154 | case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: 155 | return yaml_parser_parse_flow_mapping_key(parser, event, true) 156 | 157 | case yaml_PARSE_FLOW_MAPPING_KEY_STATE: 158 | return yaml_parser_parse_flow_mapping_key(parser, event, false) 159 | 160 | case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: 161 | return yaml_parser_parse_flow_mapping_value(parser, event, false) 162 | 163 | case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: 164 | return yaml_parser_parse_flow_mapping_value(parser, event, true) 165 | 166 | default: 167 | panic("invalid parser state") 168 | } 169 | } 170 | 171 | // Parse the production: 172 | // stream ::= STREAM-START implicit_document? explicit_document* STREAM-END 173 | // ************ 174 | func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { 175 | token := peek_token(parser) 176 | if token == nil { 177 | return false 178 | } 179 | if token.typ != yaml_STREAM_START_TOKEN { 180 | return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) 181 | } 182 | parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE 183 | *event = yaml_event_t{ 184 | typ: yaml_STREAM_START_EVENT, 185 | start_mark: token.start_mark, 186 | end_mark: token.end_mark, 187 | encoding: token.encoding, 188 | } 189 | skip_token(parser) 190 | return true 191 | } 192 | 193 | // Parse the productions: 194 | // implicit_document ::= block_node DOCUMENT-END* 195 | // * 196 | // explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* 197 | // ************************* 198 | func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { 199 | 200 | token := peek_token(parser) 201 | if token == nil { 202 | return false 203 | } 204 | 205 | // Parse extra document end indicators. 206 | if !implicit { 207 | for token.typ == yaml_DOCUMENT_END_TOKEN { 208 | skip_token(parser) 209 | token = peek_token(parser) 210 | if token == nil { 211 | return false 212 | } 213 | } 214 | } 215 | 216 | if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && 217 | token.typ != yaml_TAG_DIRECTIVE_TOKEN && 218 | token.typ != yaml_DOCUMENT_START_TOKEN && 219 | token.typ != yaml_STREAM_END_TOKEN { 220 | // Parse an implicit document. 221 | if !yaml_parser_process_directives(parser, nil, nil) { 222 | return false 223 | } 224 | parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) 225 | parser.state = yaml_PARSE_BLOCK_NODE_STATE 226 | 227 | *event = yaml_event_t{ 228 | typ: yaml_DOCUMENT_START_EVENT, 229 | start_mark: token.start_mark, 230 | end_mark: token.end_mark, 231 | } 232 | 233 | } else if token.typ != yaml_STREAM_END_TOKEN { 234 | // Parse an explicit document. 235 | var version_directive *yaml_version_directive_t 236 | var tag_directives []yaml_tag_directive_t 237 | start_mark := token.start_mark 238 | if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { 239 | return false 240 | } 241 | token = peek_token(parser) 242 | if token == nil { 243 | return false 244 | } 245 | if token.typ != yaml_DOCUMENT_START_TOKEN { 246 | yaml_parser_set_parser_error(parser, 247 | "did not find expected ", token.start_mark) 248 | return false 249 | } 250 | parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) 251 | parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE 252 | end_mark := token.end_mark 253 | 254 | *event = yaml_event_t{ 255 | typ: yaml_DOCUMENT_START_EVENT, 256 | start_mark: start_mark, 257 | end_mark: end_mark, 258 | version_directive: version_directive, 259 | tag_directives: tag_directives, 260 | implicit: false, 261 | } 262 | skip_token(parser) 263 | 264 | } else { 265 | // Parse the stream end. 266 | parser.state = yaml_PARSE_END_STATE 267 | *event = yaml_event_t{ 268 | typ: yaml_STREAM_END_EVENT, 269 | start_mark: token.start_mark, 270 | end_mark: token.end_mark, 271 | } 272 | skip_token(parser) 273 | } 274 | 275 | return true 276 | } 277 | 278 | // Parse the productions: 279 | // explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* 280 | // *********** 281 | // 282 | func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { 283 | token := peek_token(parser) 284 | if token == nil { 285 | return false 286 | } 287 | if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || 288 | token.typ == yaml_TAG_DIRECTIVE_TOKEN || 289 | token.typ == yaml_DOCUMENT_START_TOKEN || 290 | token.typ == yaml_DOCUMENT_END_TOKEN || 291 | token.typ == yaml_STREAM_END_TOKEN { 292 | parser.state = parser.states[len(parser.states)-1] 293 | parser.states = parser.states[:len(parser.states)-1] 294 | return yaml_parser_process_empty_scalar(parser, event, 295 | token.start_mark) 296 | } 297 | return yaml_parser_parse_node(parser, event, true, false) 298 | } 299 | 300 | // Parse the productions: 301 | // implicit_document ::= block_node DOCUMENT-END* 302 | // ************* 303 | // explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* 304 | // 305 | func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { 306 | token := peek_token(parser) 307 | if token == nil { 308 | return false 309 | } 310 | 311 | start_mark := token.start_mark 312 | end_mark := token.start_mark 313 | 314 | implicit := true 315 | if token.typ == yaml_DOCUMENT_END_TOKEN { 316 | end_mark = token.end_mark 317 | skip_token(parser) 318 | implicit = false 319 | } 320 | 321 | parser.tag_directives = parser.tag_directives[:0] 322 | 323 | parser.state = yaml_PARSE_DOCUMENT_START_STATE 324 | *event = yaml_event_t{ 325 | typ: yaml_DOCUMENT_END_EVENT, 326 | start_mark: start_mark, 327 | end_mark: end_mark, 328 | implicit: implicit, 329 | } 330 | return true 331 | } 332 | 333 | // Parse the productions: 334 | // block_node_or_indentless_sequence ::= 335 | // ALIAS 336 | // ***** 337 | // | properties (block_content | indentless_block_sequence)? 338 | // ********** * 339 | // | block_content | indentless_block_sequence 340 | // * 341 | // block_node ::= ALIAS 342 | // ***** 343 | // | properties block_content? 344 | // ********** * 345 | // | block_content 346 | // * 347 | // flow_node ::= ALIAS 348 | // ***** 349 | // | properties flow_content? 350 | // ********** * 351 | // | flow_content 352 | // * 353 | // properties ::= TAG ANCHOR? | ANCHOR TAG? 354 | // ************************* 355 | // block_content ::= block_collection | flow_collection | SCALAR 356 | // ****** 357 | // flow_content ::= flow_collection | SCALAR 358 | // ****** 359 | func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { 360 | //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() 361 | 362 | token := peek_token(parser) 363 | if token == nil { 364 | return false 365 | } 366 | 367 | if token.typ == yaml_ALIAS_TOKEN { 368 | parser.state = parser.states[len(parser.states)-1] 369 | parser.states = parser.states[:len(parser.states)-1] 370 | *event = yaml_event_t{ 371 | typ: yaml_ALIAS_EVENT, 372 | start_mark: token.start_mark, 373 | end_mark: token.end_mark, 374 | anchor: token.value, 375 | } 376 | skip_token(parser) 377 | return true 378 | } 379 | 380 | start_mark := token.start_mark 381 | end_mark := token.start_mark 382 | 383 | var tag_token bool 384 | var tag_handle, tag_suffix, anchor []byte 385 | var tag_mark yaml_mark_t 386 | if token.typ == yaml_ANCHOR_TOKEN { 387 | anchor = token.value 388 | start_mark = token.start_mark 389 | end_mark = token.end_mark 390 | skip_token(parser) 391 | token = peek_token(parser) 392 | if token == nil { 393 | return false 394 | } 395 | if token.typ == yaml_TAG_TOKEN { 396 | tag_token = true 397 | tag_handle = token.value 398 | tag_suffix = token.suffix 399 | tag_mark = token.start_mark 400 | end_mark = token.end_mark 401 | skip_token(parser) 402 | token = peek_token(parser) 403 | if token == nil { 404 | return false 405 | } 406 | } 407 | } else if token.typ == yaml_TAG_TOKEN { 408 | tag_token = true 409 | tag_handle = token.value 410 | tag_suffix = token.suffix 411 | start_mark = token.start_mark 412 | tag_mark = token.start_mark 413 | end_mark = token.end_mark 414 | skip_token(parser) 415 | token = peek_token(parser) 416 | if token == nil { 417 | return false 418 | } 419 | if token.typ == yaml_ANCHOR_TOKEN { 420 | anchor = token.value 421 | end_mark = token.end_mark 422 | skip_token(parser) 423 | token = peek_token(parser) 424 | if token == nil { 425 | return false 426 | } 427 | } 428 | } 429 | 430 | var tag []byte 431 | if tag_token { 432 | if len(tag_handle) == 0 { 433 | tag = tag_suffix 434 | tag_suffix = nil 435 | } else { 436 | for i := range parser.tag_directives { 437 | if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { 438 | tag = append([]byte(nil), parser.tag_directives[i].prefix...) 439 | tag = append(tag, tag_suffix...) 440 | break 441 | } 442 | } 443 | if len(tag) == 0 { 444 | yaml_parser_set_parser_error_context(parser, 445 | "while parsing a node", start_mark, 446 | "found undefined tag handle", tag_mark) 447 | return false 448 | } 449 | } 450 | } 451 | 452 | implicit := len(tag) == 0 453 | if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { 454 | end_mark = token.end_mark 455 | parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE 456 | *event = yaml_event_t{ 457 | typ: yaml_SEQUENCE_START_EVENT, 458 | start_mark: start_mark, 459 | end_mark: end_mark, 460 | anchor: anchor, 461 | tag: tag, 462 | implicit: implicit, 463 | style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), 464 | } 465 | return true 466 | } 467 | if token.typ == yaml_SCALAR_TOKEN { 468 | var plain_implicit, quoted_implicit bool 469 | end_mark = token.end_mark 470 | if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { 471 | plain_implicit = true 472 | } else if len(tag) == 0 { 473 | quoted_implicit = true 474 | } 475 | parser.state = parser.states[len(parser.states)-1] 476 | parser.states = parser.states[:len(parser.states)-1] 477 | 478 | *event = yaml_event_t{ 479 | typ: yaml_SCALAR_EVENT, 480 | start_mark: start_mark, 481 | end_mark: end_mark, 482 | anchor: anchor, 483 | tag: tag, 484 | value: token.value, 485 | implicit: plain_implicit, 486 | quoted_implicit: quoted_implicit, 487 | style: yaml_style_t(token.style), 488 | } 489 | skip_token(parser) 490 | return true 491 | } 492 | if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { 493 | // [Go] Some of the events below can be merged as they differ only on style. 494 | end_mark = token.end_mark 495 | parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE 496 | *event = yaml_event_t{ 497 | typ: yaml_SEQUENCE_START_EVENT, 498 | start_mark: start_mark, 499 | end_mark: end_mark, 500 | anchor: anchor, 501 | tag: tag, 502 | implicit: implicit, 503 | style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), 504 | } 505 | return true 506 | } 507 | if token.typ == yaml_FLOW_MAPPING_START_TOKEN { 508 | end_mark = token.end_mark 509 | parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE 510 | *event = yaml_event_t{ 511 | typ: yaml_MAPPING_START_EVENT, 512 | start_mark: start_mark, 513 | end_mark: end_mark, 514 | anchor: anchor, 515 | tag: tag, 516 | implicit: implicit, 517 | style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), 518 | } 519 | return true 520 | } 521 | if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { 522 | end_mark = token.end_mark 523 | parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE 524 | *event = yaml_event_t{ 525 | typ: yaml_SEQUENCE_START_EVENT, 526 | start_mark: start_mark, 527 | end_mark: end_mark, 528 | anchor: anchor, 529 | tag: tag, 530 | implicit: implicit, 531 | style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), 532 | } 533 | return true 534 | } 535 | if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { 536 | end_mark = token.end_mark 537 | parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE 538 | *event = yaml_event_t{ 539 | typ: yaml_MAPPING_START_EVENT, 540 | start_mark: start_mark, 541 | end_mark: end_mark, 542 | anchor: anchor, 543 | tag: tag, 544 | implicit: implicit, 545 | style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), 546 | } 547 | return true 548 | } 549 | if len(anchor) > 0 || len(tag) > 0 { 550 | parser.state = parser.states[len(parser.states)-1] 551 | parser.states = parser.states[:len(parser.states)-1] 552 | 553 | *event = yaml_event_t{ 554 | typ: yaml_SCALAR_EVENT, 555 | start_mark: start_mark, 556 | end_mark: end_mark, 557 | anchor: anchor, 558 | tag: tag, 559 | implicit: implicit, 560 | quoted_implicit: false, 561 | style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), 562 | } 563 | return true 564 | } 565 | 566 | context := "while parsing a flow node" 567 | if block { 568 | context = "while parsing a block node" 569 | } 570 | yaml_parser_set_parser_error_context(parser, context, start_mark, 571 | "did not find expected node content", token.start_mark) 572 | return false 573 | } 574 | 575 | // Parse the productions: 576 | // block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END 577 | // ******************** *********** * ********* 578 | // 579 | func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { 580 | if first { 581 | token := peek_token(parser) 582 | parser.marks = append(parser.marks, token.start_mark) 583 | skip_token(parser) 584 | } 585 | 586 | token := peek_token(parser) 587 | if token == nil { 588 | return false 589 | } 590 | 591 | if token.typ == yaml_BLOCK_ENTRY_TOKEN { 592 | mark := token.end_mark 593 | skip_token(parser) 594 | token = peek_token(parser) 595 | if token == nil { 596 | return false 597 | } 598 | if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { 599 | parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) 600 | return yaml_parser_parse_node(parser, event, true, false) 601 | } else { 602 | parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE 603 | return yaml_parser_process_empty_scalar(parser, event, mark) 604 | } 605 | } 606 | if token.typ == yaml_BLOCK_END_TOKEN { 607 | parser.state = parser.states[len(parser.states)-1] 608 | parser.states = parser.states[:len(parser.states)-1] 609 | parser.marks = parser.marks[:len(parser.marks)-1] 610 | 611 | *event = yaml_event_t{ 612 | typ: yaml_SEQUENCE_END_EVENT, 613 | start_mark: token.start_mark, 614 | end_mark: token.end_mark, 615 | } 616 | 617 | skip_token(parser) 618 | return true 619 | } 620 | 621 | context_mark := parser.marks[len(parser.marks)-1] 622 | parser.marks = parser.marks[:len(parser.marks)-1] 623 | return yaml_parser_set_parser_error_context(parser, 624 | "while parsing a block collection", context_mark, 625 | "did not find expected '-' indicator", token.start_mark) 626 | } 627 | 628 | // Parse the productions: 629 | // indentless_sequence ::= (BLOCK-ENTRY block_node?)+ 630 | // *********** * 631 | func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { 632 | token := peek_token(parser) 633 | if token == nil { 634 | return false 635 | } 636 | 637 | if token.typ == yaml_BLOCK_ENTRY_TOKEN { 638 | mark := token.end_mark 639 | skip_token(parser) 640 | token = peek_token(parser) 641 | if token == nil { 642 | return false 643 | } 644 | if token.typ != yaml_BLOCK_ENTRY_TOKEN && 645 | token.typ != yaml_KEY_TOKEN && 646 | token.typ != yaml_VALUE_TOKEN && 647 | token.typ != yaml_BLOCK_END_TOKEN { 648 | parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) 649 | return yaml_parser_parse_node(parser, event, true, false) 650 | } 651 | parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE 652 | return yaml_parser_process_empty_scalar(parser, event, mark) 653 | } 654 | parser.state = parser.states[len(parser.states)-1] 655 | parser.states = parser.states[:len(parser.states)-1] 656 | 657 | *event = yaml_event_t{ 658 | typ: yaml_SEQUENCE_END_EVENT, 659 | start_mark: token.start_mark, 660 | end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? 661 | } 662 | return true 663 | } 664 | 665 | // Parse the productions: 666 | // block_mapping ::= BLOCK-MAPPING_START 667 | // ******************* 668 | // ((KEY block_node_or_indentless_sequence?)? 669 | // *** * 670 | // (VALUE block_node_or_indentless_sequence?)?)* 671 | // 672 | // BLOCK-END 673 | // ********* 674 | // 675 | func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { 676 | if first { 677 | token := peek_token(parser) 678 | parser.marks = append(parser.marks, token.start_mark) 679 | skip_token(parser) 680 | } 681 | 682 | token := peek_token(parser) 683 | if token == nil { 684 | return false 685 | } 686 | 687 | if token.typ == yaml_KEY_TOKEN { 688 | mark := token.end_mark 689 | skip_token(parser) 690 | token = peek_token(parser) 691 | if token == nil { 692 | return false 693 | } 694 | if token.typ != yaml_KEY_TOKEN && 695 | token.typ != yaml_VALUE_TOKEN && 696 | token.typ != yaml_BLOCK_END_TOKEN { 697 | parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) 698 | return yaml_parser_parse_node(parser, event, true, true) 699 | } else { 700 | parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE 701 | return yaml_parser_process_empty_scalar(parser, event, mark) 702 | } 703 | } else if token.typ == yaml_BLOCK_END_TOKEN { 704 | parser.state = parser.states[len(parser.states)-1] 705 | parser.states = parser.states[:len(parser.states)-1] 706 | parser.marks = parser.marks[:len(parser.marks)-1] 707 | *event = yaml_event_t{ 708 | typ: yaml_MAPPING_END_EVENT, 709 | start_mark: token.start_mark, 710 | end_mark: token.end_mark, 711 | } 712 | skip_token(parser) 713 | return true 714 | } 715 | 716 | context_mark := parser.marks[len(parser.marks)-1] 717 | parser.marks = parser.marks[:len(parser.marks)-1] 718 | return yaml_parser_set_parser_error_context(parser, 719 | "while parsing a block mapping", context_mark, 720 | "did not find expected key", token.start_mark) 721 | } 722 | 723 | // Parse the productions: 724 | // block_mapping ::= BLOCK-MAPPING_START 725 | // 726 | // ((KEY block_node_or_indentless_sequence?)? 727 | // 728 | // (VALUE block_node_or_indentless_sequence?)?)* 729 | // ***** * 730 | // BLOCK-END 731 | // 732 | // 733 | func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { 734 | token := peek_token(parser) 735 | if token == nil { 736 | return false 737 | } 738 | if token.typ == yaml_VALUE_TOKEN { 739 | mark := token.end_mark 740 | skip_token(parser) 741 | token = peek_token(parser) 742 | if token == nil { 743 | return false 744 | } 745 | if token.typ != yaml_KEY_TOKEN && 746 | token.typ != yaml_VALUE_TOKEN && 747 | token.typ != yaml_BLOCK_END_TOKEN { 748 | parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) 749 | return yaml_parser_parse_node(parser, event, true, true) 750 | } 751 | parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE 752 | return yaml_parser_process_empty_scalar(parser, event, mark) 753 | } 754 | parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE 755 | return yaml_parser_process_empty_scalar(parser, event, token.start_mark) 756 | } 757 | 758 | // Parse the productions: 759 | // flow_sequence ::= FLOW-SEQUENCE-START 760 | // ******************* 761 | // (flow_sequence_entry FLOW-ENTRY)* 762 | // * ********** 763 | // flow_sequence_entry? 764 | // * 765 | // FLOW-SEQUENCE-END 766 | // ***************** 767 | // flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 768 | // * 769 | // 770 | func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { 771 | if first { 772 | token := peek_token(parser) 773 | parser.marks = append(parser.marks, token.start_mark) 774 | skip_token(parser) 775 | } 776 | token := peek_token(parser) 777 | if token == nil { 778 | return false 779 | } 780 | if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { 781 | if !first { 782 | if token.typ == yaml_FLOW_ENTRY_TOKEN { 783 | skip_token(parser) 784 | token = peek_token(parser) 785 | if token == nil { 786 | return false 787 | } 788 | } else { 789 | context_mark := parser.marks[len(parser.marks)-1] 790 | parser.marks = parser.marks[:len(parser.marks)-1] 791 | return yaml_parser_set_parser_error_context(parser, 792 | "while parsing a flow sequence", context_mark, 793 | "did not find expected ',' or ']'", token.start_mark) 794 | } 795 | } 796 | 797 | if token.typ == yaml_KEY_TOKEN { 798 | parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE 799 | *event = yaml_event_t{ 800 | typ: yaml_MAPPING_START_EVENT, 801 | start_mark: token.start_mark, 802 | end_mark: token.end_mark, 803 | implicit: true, 804 | style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), 805 | } 806 | skip_token(parser) 807 | return true 808 | } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { 809 | parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) 810 | return yaml_parser_parse_node(parser, event, false, false) 811 | } 812 | } 813 | 814 | parser.state = parser.states[len(parser.states)-1] 815 | parser.states = parser.states[:len(parser.states)-1] 816 | parser.marks = parser.marks[:len(parser.marks)-1] 817 | 818 | *event = yaml_event_t{ 819 | typ: yaml_SEQUENCE_END_EVENT, 820 | start_mark: token.start_mark, 821 | end_mark: token.end_mark, 822 | } 823 | 824 | skip_token(parser) 825 | return true 826 | } 827 | 828 | // 829 | // Parse the productions: 830 | // flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 831 | // *** * 832 | // 833 | func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { 834 | token := peek_token(parser) 835 | if token == nil { 836 | return false 837 | } 838 | if token.typ != yaml_VALUE_TOKEN && 839 | token.typ != yaml_FLOW_ENTRY_TOKEN && 840 | token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { 841 | parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) 842 | return yaml_parser_parse_node(parser, event, false, false) 843 | } 844 | mark := token.end_mark 845 | skip_token(parser) 846 | parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE 847 | return yaml_parser_process_empty_scalar(parser, event, mark) 848 | } 849 | 850 | // Parse the productions: 851 | // flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 852 | // ***** * 853 | // 854 | func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { 855 | token := peek_token(parser) 856 | if token == nil { 857 | return false 858 | } 859 | if token.typ == yaml_VALUE_TOKEN { 860 | skip_token(parser) 861 | token := peek_token(parser) 862 | if token == nil { 863 | return false 864 | } 865 | if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { 866 | parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) 867 | return yaml_parser_parse_node(parser, event, false, false) 868 | } 869 | } 870 | parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE 871 | return yaml_parser_process_empty_scalar(parser, event, token.start_mark) 872 | } 873 | 874 | // Parse the productions: 875 | // flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 876 | // * 877 | // 878 | func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { 879 | token := peek_token(parser) 880 | if token == nil { 881 | return false 882 | } 883 | parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE 884 | *event = yaml_event_t{ 885 | typ: yaml_MAPPING_END_EVENT, 886 | start_mark: token.start_mark, 887 | end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? 888 | } 889 | return true 890 | } 891 | 892 | // Parse the productions: 893 | // flow_mapping ::= FLOW-MAPPING-START 894 | // ****************** 895 | // (flow_mapping_entry FLOW-ENTRY)* 896 | // * ********** 897 | // flow_mapping_entry? 898 | // ****************** 899 | // FLOW-MAPPING-END 900 | // **************** 901 | // flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 902 | // * *** * 903 | // 904 | func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { 905 | if first { 906 | token := peek_token(parser) 907 | parser.marks = append(parser.marks, token.start_mark) 908 | skip_token(parser) 909 | } 910 | 911 | token := peek_token(parser) 912 | if token == nil { 913 | return false 914 | } 915 | 916 | if token.typ != yaml_FLOW_MAPPING_END_TOKEN { 917 | if !first { 918 | if token.typ == yaml_FLOW_ENTRY_TOKEN { 919 | skip_token(parser) 920 | token = peek_token(parser) 921 | if token == nil { 922 | return false 923 | } 924 | } else { 925 | context_mark := parser.marks[len(parser.marks)-1] 926 | parser.marks = parser.marks[:len(parser.marks)-1] 927 | return yaml_parser_set_parser_error_context(parser, 928 | "while parsing a flow mapping", context_mark, 929 | "did not find expected ',' or '}'", token.start_mark) 930 | } 931 | } 932 | 933 | if token.typ == yaml_KEY_TOKEN { 934 | skip_token(parser) 935 | token = peek_token(parser) 936 | if token == nil { 937 | return false 938 | } 939 | if token.typ != yaml_VALUE_TOKEN && 940 | token.typ != yaml_FLOW_ENTRY_TOKEN && 941 | token.typ != yaml_FLOW_MAPPING_END_TOKEN { 942 | parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) 943 | return yaml_parser_parse_node(parser, event, false, false) 944 | } else { 945 | parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE 946 | return yaml_parser_process_empty_scalar(parser, event, token.start_mark) 947 | } 948 | } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { 949 | parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) 950 | return yaml_parser_parse_node(parser, event, false, false) 951 | } 952 | } 953 | 954 | parser.state = parser.states[len(parser.states)-1] 955 | parser.states = parser.states[:len(parser.states)-1] 956 | parser.marks = parser.marks[:len(parser.marks)-1] 957 | *event = yaml_event_t{ 958 | typ: yaml_MAPPING_END_EVENT, 959 | start_mark: token.start_mark, 960 | end_mark: token.end_mark, 961 | } 962 | skip_token(parser) 963 | return true 964 | } 965 | 966 | // Parse the productions: 967 | // flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? 968 | // * ***** * 969 | // 970 | func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { 971 | token := peek_token(parser) 972 | if token == nil { 973 | return false 974 | } 975 | if empty { 976 | parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE 977 | return yaml_parser_process_empty_scalar(parser, event, token.start_mark) 978 | } 979 | if token.typ == yaml_VALUE_TOKEN { 980 | skip_token(parser) 981 | token = peek_token(parser) 982 | if token == nil { 983 | return false 984 | } 985 | if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { 986 | parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) 987 | return yaml_parser_parse_node(parser, event, false, false) 988 | } 989 | } 990 | parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE 991 | return yaml_parser_process_empty_scalar(parser, event, token.start_mark) 992 | } 993 | 994 | // Generate an empty scalar event. 995 | func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { 996 | *event = yaml_event_t{ 997 | typ: yaml_SCALAR_EVENT, 998 | start_mark: mark, 999 | end_mark: mark, 1000 | value: nil, // Empty 1001 | implicit: true, 1002 | style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), 1003 | } 1004 | return true 1005 | } 1006 | 1007 | var default_tag_directives = []yaml_tag_directive_t{ 1008 | {[]byte("!"), []byte("!")}, 1009 | {[]byte("!!"), []byte("tag:yaml.org,2002:")}, 1010 | } 1011 | 1012 | // Parse directives. 1013 | func yaml_parser_process_directives(parser *yaml_parser_t, 1014 | version_directive_ref **yaml_version_directive_t, 1015 | tag_directives_ref *[]yaml_tag_directive_t) bool { 1016 | 1017 | var version_directive *yaml_version_directive_t 1018 | var tag_directives []yaml_tag_directive_t 1019 | 1020 | token := peek_token(parser) 1021 | if token == nil { 1022 | return false 1023 | } 1024 | 1025 | for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { 1026 | if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { 1027 | if version_directive != nil { 1028 | yaml_parser_set_parser_error(parser, 1029 | "found duplicate %YAML directive", token.start_mark) 1030 | return false 1031 | } 1032 | if token.major != 1 || token.minor != 1 { 1033 | yaml_parser_set_parser_error(parser, 1034 | "found incompatible YAML document", token.start_mark) 1035 | return false 1036 | } 1037 | version_directive = &yaml_version_directive_t{ 1038 | major: token.major, 1039 | minor: token.minor, 1040 | } 1041 | } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { 1042 | value := yaml_tag_directive_t{ 1043 | handle: token.value, 1044 | prefix: token.prefix, 1045 | } 1046 | if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { 1047 | return false 1048 | } 1049 | tag_directives = append(tag_directives, value) 1050 | } 1051 | 1052 | skip_token(parser) 1053 | token = peek_token(parser) 1054 | if token == nil { 1055 | return false 1056 | } 1057 | } 1058 | 1059 | for i := range default_tag_directives { 1060 | if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { 1061 | return false 1062 | } 1063 | } 1064 | 1065 | if version_directive_ref != nil { 1066 | *version_directive_ref = version_directive 1067 | } 1068 | if tag_directives_ref != nil { 1069 | *tag_directives_ref = tag_directives 1070 | } 1071 | return true 1072 | } 1073 | 1074 | // Append a tag directive to the directives stack. 1075 | func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { 1076 | for i := range parser.tag_directives { 1077 | if bytes.Equal(value.handle, parser.tag_directives[i].handle) { 1078 | if allow_duplicates { 1079 | return true 1080 | } 1081 | return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) 1082 | } 1083 | } 1084 | 1085 | // [Go] I suspect the copy is unnecessary. This was likely done 1086 | // because there was no way to track ownership of the data. 1087 | value_copy := yaml_tag_directive_t{ 1088 | handle: make([]byte, len(value.handle)), 1089 | prefix: make([]byte, len(value.prefix)), 1090 | } 1091 | copy(value_copy.handle, value.handle) 1092 | copy(value_copy.prefix, value.prefix) 1093 | parser.tag_directives = append(parser.tag_directives, value_copy) 1094 | return true 1095 | } 1096 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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 | low, high = 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 | buffer_len += 1 361 | } else if value <= 0x7FF { 362 | // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx 363 | parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) 364 | parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) 365 | buffer_len += 2 366 | } else if value <= 0xFFFF { 367 | // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx 368 | parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) 369 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) 370 | parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) 371 | buffer_len += 3 372 | } else { 373 | // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 374 | parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) 375 | parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) 376 | parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) 377 | parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) 378 | buffer_len += 4 379 | } 380 | 381 | parser.unread++ 382 | } 383 | 384 | // On EOF, put NUL into the buffer and return. 385 | if parser.eof { 386 | parser.buffer[buffer_len] = 0 387 | buffer_len++ 388 | parser.unread++ 389 | break 390 | } 391 | } 392 | parser.buffer = parser.buffer[:buffer_len] 393 | return true 394 | } 395 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "math" 6 | "regexp" 7 | "strconv" 8 | "strings" 9 | "unicode/utf8" 10 | ) 11 | 12 | type resolveMapItem struct { 13 | value interface{} 14 | tag string 15 | } 16 | 17 | var resolveTable = make([]byte, 256) 18 | var resolveMap = make(map[string]resolveMapItem) 19 | 20 | func init() { 21 | t := resolveTable 22 | t[int('+')] = 'S' // Sign 23 | t[int('-')] = 'S' 24 | for _, c := range "0123456789" { 25 | t[int(c)] = 'D' // Digit 26 | } 27 | for _, c := range "yYnNtTfFoO~" { 28 | t[int(c)] = 'M' // In map 29 | } 30 | t[int('.')] = '.' // Float (potentially in map) 31 | 32 | var resolveMapList = []struct { 33 | v interface{} 34 | tag string 35 | l []string 36 | }{ 37 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 38 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 39 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 40 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 41 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 42 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 43 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 44 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 45 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 46 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 47 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 48 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 49 | } 50 | 51 | m := resolveMap 52 | for _, item := range resolveMapList { 53 | for _, s := range item.l { 54 | m[s] = resolveMapItem{item.v, item.tag} 55 | } 56 | } 57 | } 58 | 59 | const longTagPrefix = "tag:yaml.org,2002:" 60 | 61 | func shortTag(tag string) string { 62 | // TODO This can easily be made faster and produce less garbage. 63 | if strings.HasPrefix(tag, longTagPrefix) { 64 | return "!!" + tag[len(longTagPrefix):] 65 | } 66 | return tag 67 | } 68 | 69 | func longTag(tag string) string { 70 | if strings.HasPrefix(tag, "!!") { 71 | return longTagPrefix + tag[2:] 72 | } 73 | return tag 74 | } 75 | 76 | func resolvableTag(tag string) bool { 77 | switch tag { 78 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: 79 | return true 80 | } 81 | return false 82 | } 83 | 84 | var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`) 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 | failf("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 | uintv, err := strconv.ParseUint(plain, 0, 64) 138 | if err == nil { 139 | return yaml_INT_TAG, uintv 140 | } 141 | if yamlStyleFloat.MatchString(plain) { 142 | floatv, err := strconv.ParseFloat(plain, 64) 143 | if err == nil { 144 | return yaml_FLOAT_TAG, floatv 145 | } 146 | } 147 | if strings.HasPrefix(plain, "0b") { 148 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 149 | if err == nil { 150 | if intv == int64(int(intv)) { 151 | return yaml_INT_TAG, int(intv) 152 | } else { 153 | return yaml_INT_TAG, intv 154 | } 155 | } 156 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 157 | if err == nil { 158 | return yaml_INT_TAG, uintv 159 | } 160 | } else if strings.HasPrefix(plain, "-0b") { 161 | intv, err := strconv.ParseInt(plain[3:], 2, 64) 162 | if err == nil { 163 | if intv == int64(int(intv)) { 164 | return yaml_INT_TAG, -int(intv) 165 | } else { 166 | return yaml_INT_TAG, -intv 167 | } 168 | } 169 | } 170 | // XXX Handle timestamps here. 171 | 172 | default: 173 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 174 | } 175 | } 176 | if tag == yaml_BINARY_TAG { 177 | return yaml_BINARY_TAG, in 178 | } 179 | if utf8.ValidString(in) { 180 | return yaml_STR_TAG, in 181 | } 182 | return yaml_BINARY_TAG, encodeBase64(in) 183 | } 184 | 185 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 186 | // as appropriate for the resulting length. 187 | func encodeBase64(s string) string { 188 | const lineLen = 70 189 | encLen := base64.StdEncoding.EncodedLen(len(s)) 190 | lines := encLen/lineLen + 1 191 | buf := make([]byte, encLen*2+lines) 192 | in := buf[0:encLen] 193 | out := buf[encLen:] 194 | base64.StdEncoding.Encode(in, []byte(s)) 195 | k := 0 196 | for i := 0; i < len(in); i += lineLen { 197 | j := i + lineLen 198 | if j > len(in) { 199 | j = len(in) 200 | } 201 | k += copy(out[k:], in[i:j]) 202 | if lines > 1 { 203 | out[k] = '\n' 204 | k++ 205 | } 206 | } 207 | return string(out[:k]) 208 | } 209 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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.v2/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 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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 | // MapSlice encodes and decodes as a YAML map. 18 | // The order of keys is preserved when encoding and decoding. 19 | type MapSlice []MapItem 20 | 21 | // MapItem is an item in a MapSlice. 22 | type MapItem struct { 23 | Key, Value interface{} 24 | } 25 | 26 | // The Unmarshaler interface may be implemented by types to customize their 27 | // behavior when being unmarshaled from a YAML document. The UnmarshalYAML 28 | // method receives a function that may be called to unmarshal the original 29 | // YAML value into a field or variable. It is safe to call the unmarshal 30 | // function parameter more than once if necessary. 31 | type Unmarshaler interface { 32 | UnmarshalYAML(unmarshal func(interface{}) error) error 33 | } 34 | 35 | // The Marshaler interface may be implemented by types to customize their 36 | // behavior when being marshaled into a YAML document. The returned value 37 | // is marshaled in place of the original value implementing Marshaler. 38 | // 39 | // If an error is returned by MarshalYAML, the marshaling procedure stops 40 | // and returns with the provided error. 41 | type Marshaler interface { 42 | MarshalYAML() (interface{}, error) 43 | } 44 | 45 | // Unmarshal decodes the first document found within the in byte slice 46 | // and assigns decoded values into the out value. 47 | // 48 | // Maps and pointers (to a struct, string, int, etc) are accepted as out 49 | // values. If an internal pointer within a struct is not initialized, 50 | // the yaml package will initialize it if necessary for unmarshalling 51 | // the provided data. The out parameter must not be nil. 52 | // 53 | // The type of the decoded values should be compatible with the respective 54 | // values in out. If one or more values cannot be decoded due to a type 55 | // mismatches, decoding continues partially until the end of the YAML 56 | // content, and a *yaml.TypeError is returned with details for all 57 | // missed values. 58 | // 59 | // Struct fields are only unmarshalled if they are exported (have an 60 | // upper case first letter), and are unmarshalled using the field name 61 | // lowercased as the default key. Custom keys may be defined via the 62 | // "yaml" name in the field tag: the content preceding the first comma 63 | // is used as the key, and the following comma-separated options are 64 | // used to tweak the marshalling process (see Marshal). 65 | // Conflicting names result in a runtime error. 66 | // 67 | // For example: 68 | // 69 | // type T struct { 70 | // F int `yaml:"a,omitempty"` 71 | // B int 72 | // } 73 | // var t T 74 | // yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) 75 | // 76 | // See the documentation of Marshal for the format of tags and a list of 77 | // supported tag options. 78 | // 79 | func Unmarshal(in []byte, out interface{}) (err error) { 80 | defer handleErr(&err) 81 | d := newDecoder() 82 | p := newParser(in) 83 | defer p.destroy() 84 | node := p.parse() 85 | if node != nil { 86 | v := reflect.ValueOf(out) 87 | if v.Kind() == reflect.Ptr && !v.IsNil() { 88 | v = v.Elem() 89 | } 90 | d.unmarshal(node, v) 91 | } 92 | if len(d.terrors) > 0 { 93 | return &TypeError{d.terrors} 94 | } 95 | return nil 96 | } 97 | 98 | // Marshal serializes the value provided into a YAML document. The structure 99 | // of the generated document will reflect the structure of the value itself. 100 | // Maps and pointers (to struct, string, int, etc) are accepted as the in value. 101 | // 102 | // Struct fields are only unmarshalled if they are exported (have an upper case 103 | // first letter), and are unmarshalled using the field name lowercased as the 104 | // default key. Custom keys may be defined via the "yaml" name in the field 105 | // tag: the content preceding the first comma is used as the key, and the 106 | // following comma-separated options are used to tweak the marshalling process. 107 | // Conflicting names result in a runtime error. 108 | // 109 | // The field tag format accepted is: 110 | // 111 | // `(...) yaml:"[][,[,]]" (...)` 112 | // 113 | // The following flags are currently supported: 114 | // 115 | // omitempty Only include the field if it's not set to the zero 116 | // value for the type or to empty slices or maps. 117 | // Does not apply to zero valued structs. 118 | // 119 | // flow Marshal using a flow style (useful for structs, 120 | // sequences and maps). 121 | // 122 | // inline Inline the field, which must be a struct or a map, 123 | // causing all of its fields or keys to be processed as if 124 | // they were part of the outer struct. For maps, keys must 125 | // not conflict with the yaml keys of other struct fields. 126 | // 127 | // In addition, if the key is "-", the field is ignored. 128 | // 129 | // For example: 130 | // 131 | // type T struct { 132 | // F int "a,omitempty" 133 | // B int 134 | // } 135 | // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" 136 | // yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" 137 | // 138 | func Marshal(in interface{}) (out []byte, err error) { 139 | defer handleErr(&err) 140 | e := newEncoder() 141 | defer e.destroy() 142 | e.marshal("", reflect.ValueOf(in)) 143 | e.finish() 144 | out = e.out 145 | return 146 | } 147 | 148 | func handleErr(err *error) { 149 | if v := recover(); v != nil { 150 | if e, ok := v.(yamlError); ok { 151 | *err = e.err 152 | } else { 153 | panic(v) 154 | } 155 | } 156 | } 157 | 158 | type yamlError struct { 159 | err error 160 | } 161 | 162 | func fail(err error) { 163 | panic(yamlError{err}) 164 | } 165 | 166 | func failf(format string, args ...interface{}) { 167 | panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) 168 | } 169 | 170 | // A TypeError is returned by Unmarshal when one or more fields in 171 | // the YAML document cannot be properly decoded into the requested 172 | // types. When this error is returned, the value is still 173 | // unmarshaled partially. 174 | type TypeError struct { 175 | Errors []string 176 | } 177 | 178 | func (e *TypeError) Error() string { 179 | return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) 180 | } 181 | 182 | // -------------------------------------------------------------------------- 183 | // Maintain a mapping of keys to structure field indexes 184 | 185 | // The code in this section was copied from mgo/bson. 186 | 187 | // structInfo holds details for the serialization of fields of 188 | // a given struct. 189 | type structInfo struct { 190 | FieldsMap map[string]fieldInfo 191 | FieldsList []fieldInfo 192 | 193 | // InlineMap is the number of the field in the struct that 194 | // contains an ,inline map, or -1 if there's none. 195 | InlineMap int 196 | } 197 | 198 | type fieldInfo struct { 199 | Key string 200 | Num int 201 | OmitEmpty bool 202 | Flow bool 203 | 204 | // Inline holds the field index if the field is part of an inlined struct. 205 | Inline []int 206 | } 207 | 208 | var structMap = make(map[reflect.Type]*structInfo) 209 | var fieldMapMutex sync.RWMutex 210 | 211 | func getStructInfo(st reflect.Type) (*structInfo, error) { 212 | fieldMapMutex.RLock() 213 | sinfo, found := structMap[st] 214 | fieldMapMutex.RUnlock() 215 | if found { 216 | return sinfo, nil 217 | } 218 | 219 | n := st.NumField() 220 | fieldsMap := make(map[string]fieldInfo) 221 | fieldsList := make([]fieldInfo, 0, n) 222 | inlineMap := -1 223 | for i := 0; i != n; i++ { 224 | field := st.Field(i) 225 | if field.PkgPath != "" && !field.Anonymous { 226 | continue // Private field 227 | } 228 | 229 | info := fieldInfo{Num: i} 230 | 231 | tag := field.Tag.Get("yaml") 232 | if tag == "" && strings.Index(string(field.Tag), ":") < 0 { 233 | tag = string(field.Tag) 234 | } 235 | if tag == "-" { 236 | continue 237 | } 238 | 239 | inline := false 240 | fields := strings.Split(tag, ",") 241 | if len(fields) > 1 { 242 | for _, flag := range fields[1:] { 243 | switch flag { 244 | case "omitempty": 245 | info.OmitEmpty = true 246 | case "flow": 247 | info.Flow = true 248 | case "inline": 249 | inline = true 250 | default: 251 | return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) 252 | } 253 | } 254 | tag = fields[0] 255 | } 256 | 257 | if inline { 258 | switch field.Type.Kind() { 259 | case reflect.Map: 260 | if inlineMap >= 0 { 261 | return nil, errors.New("Multiple ,inline maps in struct " + st.String()) 262 | } 263 | if field.Type.Key() != reflect.TypeOf("") { 264 | return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) 265 | } 266 | inlineMap = info.Num 267 | case reflect.Struct: 268 | sinfo, err := getStructInfo(field.Type) 269 | if err != nil { 270 | return nil, err 271 | } 272 | for _, finfo := range sinfo.FieldsList { 273 | if _, found := fieldsMap[finfo.Key]; found { 274 | msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() 275 | return nil, errors.New(msg) 276 | } 277 | if finfo.Inline == nil { 278 | finfo.Inline = []int{i, finfo.Num} 279 | } else { 280 | finfo.Inline = append([]int{i}, finfo.Inline...) 281 | } 282 | fieldsMap[finfo.Key] = finfo 283 | fieldsList = append(fieldsList, finfo) 284 | } 285 | default: 286 | //return nil, errors.New("Option ,inline needs a struct value or map field") 287 | return nil, errors.New("Option ,inline needs a struct value field") 288 | } 289 | continue 290 | } 291 | 292 | if tag != "" { 293 | info.Key = tag 294 | } else { 295 | info.Key = strings.ToLower(field.Name) 296 | } 297 | 298 | if _, found = fieldsMap[info.Key]; found { 299 | msg := "Duplicated key '" + info.Key + "' in struct " + st.String() 300 | return nil, errors.New(msg) 301 | } 302 | 303 | fieldsList = append(fieldsList, info) 304 | fieldsMap[info.Key] = info 305 | } 306 | 307 | sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} 308 | 309 | fieldMapMutex.Lock() 310 | structMap[st] = sinfo 311 | fieldMapMutex.Unlock() 312 | return sinfo, nil 313 | } 314 | 315 | func isZero(v reflect.Value) bool { 316 | switch v.Kind() { 317 | case reflect.String: 318 | return len(v.String()) == 0 319 | case reflect.Interface, reflect.Ptr: 320 | return v.IsNil() 321 | case reflect.Slice: 322 | return v.Len() == 0 323 | case reflect.Map: 324 | return v.Len() == 0 325 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 326 | return v.Int() == 0 327 | case reflect.Float32, reflect.Float64: 328 | return v.Float() == 0 329 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 330 | return v.Uint() == 0 331 | case reflect.Bool: 332 | return !v.Bool() 333 | case reflect.Struct: 334 | vt := v.Type() 335 | for i := v.NumField() - 1; i >= 0; i-- { 336 | if vt.Field(i).PkgPath != "" { 337 | continue // Private field 338 | } 339 | if !isZero(v.Field(i)) { 340 | return false 341 | } 342 | } 343 | return true 344 | } 345 | return false 346 | } 347 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/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/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "AANTVr9CVVyzsgviODY6Wi2thuM=", 7 | "path": "github.com/fatih/color", 8 | "revision": "62e9147c64a1ed519147b62a56a14e83e2be02c1", 9 | "revisionTime": "2017-05-23T20:24:04Z" 10 | }, 11 | { 12 | "checksumSHA1": "fALlQNY1fM99NesfLJ50KguWsio=", 13 | "path": "gopkg.in/yaml.v2", 14 | "revision": "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b", 15 | "revisionTime": "2017-04-07T17:21:22Z" 16 | } 17 | ], 18 | "rootPath": "github.com/oshalygin/k8s-config" 19 | } 20 | --------------------------------------------------------------------------------