github.com/ssube/gitlab-ci-multi-runner@v1.2.1-0.20160607142738-b8d1285632e6/Godeps/_workspace/src/gopkg.in/yaml.v1/decode.go (about)

     1  package yaml
     2  
     3  import (
     4  	"encoding/base64"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  	"time"
     9  )
    10  
    11  const (
    12  	documentNode = 1 << iota
    13  	mappingNode
    14  	sequenceNode
    15  	scalarNode
    16  	aliasNode
    17  )
    18  
    19  type node struct {
    20  	kind         int
    21  	line, column int
    22  	tag          string
    23  	value        string
    24  	implicit     bool
    25  	children     []*node
    26  	anchors      map[string]*node
    27  }
    28  
    29  // ----------------------------------------------------------------------------
    30  // Parser, produces a node tree out of a libyaml event stream.
    31  
    32  type parser struct {
    33  	parser yaml_parser_t
    34  	event  yaml_event_t
    35  	doc    *node
    36  }
    37  
    38  func newParser(b []byte) *parser {
    39  	p := parser{}
    40  	if !yaml_parser_initialize(&p.parser) {
    41  		panic("Failed to initialize YAML emitter")
    42  	}
    43  
    44  	if len(b) == 0 {
    45  		b = []byte{'\n'}
    46  	}
    47  
    48  	yaml_parser_set_input_string(&p.parser, b)
    49  
    50  	p.skip()
    51  	if p.event.typ != yaml_STREAM_START_EVENT {
    52  		panic("Expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
    53  	}
    54  	p.skip()
    55  	return &p
    56  }
    57  
    58  func (p *parser) destroy() {
    59  	if p.event.typ != yaml_NO_EVENT {
    60  		yaml_event_delete(&p.event)
    61  	}
    62  	yaml_parser_delete(&p.parser)
    63  }
    64  
    65  func (p *parser) skip() {
    66  	if p.event.typ != yaml_NO_EVENT {
    67  		if p.event.typ == yaml_STREAM_END_EVENT {
    68  			fail("Attempted to go past the end of stream. Corrupted value?")
    69  		}
    70  		yaml_event_delete(&p.event)
    71  	}
    72  	if !yaml_parser_parse(&p.parser, &p.event) {
    73  		p.fail()
    74  	}
    75  }
    76  
    77  func (p *parser) fail() {
    78  	var where string
    79  	var line int
    80  	if p.parser.problem_mark.line != 0 {
    81  		line = p.parser.problem_mark.line
    82  	} else if p.parser.context_mark.line != 0 {
    83  		line = p.parser.context_mark.line
    84  	}
    85  	if line != 0 {
    86  		where = "line " + strconv.Itoa(line) + ": "
    87  	}
    88  	var msg string
    89  	if len(p.parser.problem) > 0 {
    90  		msg = p.parser.problem
    91  	} else {
    92  		msg = "Unknown problem parsing YAML content"
    93  	}
    94  	fail(where + msg)
    95  }
    96  
    97  func (p *parser) anchor(n *node, anchor []byte) {
    98  	if anchor != nil {
    99  		p.doc.anchors[string(anchor)] = n
   100  	}
   101  }
   102  
   103  func (p *parser) parse() *node {
   104  	switch p.event.typ {
   105  	case yaml_SCALAR_EVENT:
   106  		return p.scalar()
   107  	case yaml_ALIAS_EVENT:
   108  		return p.alias()
   109  	case yaml_MAPPING_START_EVENT:
   110  		return p.mapping()
   111  	case yaml_SEQUENCE_START_EVENT:
   112  		return p.sequence()
   113  	case yaml_DOCUMENT_START_EVENT:
   114  		return p.document()
   115  	case yaml_STREAM_END_EVENT:
   116  		// Happens when attempting to decode an empty buffer.
   117  		return nil
   118  	default:
   119  		panic("Attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ)))
   120  	}
   121  	panic("unreachable")
   122  }
   123  
   124  func (p *parser) node(kind int) *node {
   125  	return &node{
   126  		kind:   kind,
   127  		line:   p.event.start_mark.line,
   128  		column: p.event.start_mark.column,
   129  	}
   130  }
   131  
   132  func (p *parser) document() *node {
   133  	n := p.node(documentNode)
   134  	n.anchors = make(map[string]*node)
   135  	p.doc = n
   136  	p.skip()
   137  	n.children = append(n.children, p.parse())
   138  	if p.event.typ != yaml_DOCUMENT_END_EVENT {
   139  		panic("Expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
   140  	}
   141  	p.skip()
   142  	return n
   143  }
   144  
   145  func (p *parser) alias() *node {
   146  	n := p.node(aliasNode)
   147  	n.value = string(p.event.anchor)
   148  	p.skip()
   149  	return n
   150  }
   151  
   152  func (p *parser) scalar() *node {
   153  	n := p.node(scalarNode)
   154  	n.value = string(p.event.value)
   155  	n.tag = string(p.event.tag)
   156  	n.implicit = p.event.implicit
   157  	p.anchor(n, p.event.anchor)
   158  	p.skip()
   159  	return n
   160  }
   161  
   162  func (p *parser) sequence() *node {
   163  	n := p.node(sequenceNode)
   164  	p.anchor(n, p.event.anchor)
   165  	p.skip()
   166  	for p.event.typ != yaml_SEQUENCE_END_EVENT {
   167  		n.children = append(n.children, p.parse())
   168  	}
   169  	p.skip()
   170  	return n
   171  }
   172  
   173  func (p *parser) mapping() *node {
   174  	n := p.node(mappingNode)
   175  	p.anchor(n, p.event.anchor)
   176  	p.skip()
   177  	for p.event.typ != yaml_MAPPING_END_EVENT {
   178  		n.children = append(n.children, p.parse(), p.parse())
   179  	}
   180  	p.skip()
   181  	return n
   182  }
   183  
   184  // ----------------------------------------------------------------------------
   185  // Decoder, unmarshals a node into a provided value.
   186  
   187  type decoder struct {
   188  	doc     *node
   189  	aliases map[string]bool
   190  }
   191  
   192  func newDecoder() *decoder {
   193  	d := &decoder{}
   194  	d.aliases = make(map[string]bool)
   195  	return d
   196  }
   197  
   198  // d.setter deals with setters and pointer dereferencing and initialization.
   199  //
   200  // It's a slightly convoluted case to handle properly:
   201  //
   202  // - nil pointers should be initialized, unless being set to nil
   203  // - we don't know at this point yet what's the value to SetYAML() with.
   204  // - we can't separate pointer deref/init and setter checking, because
   205  //   a setter may be found while going down a pointer chain.
   206  //
   207  // Thus, here is how it takes care of it:
   208  //
   209  // - out is provided as a pointer, so that it can be replaced.
   210  // - when looking at a non-setter ptr, *out=ptr.Elem(), unless tag=!!null
   211  // - when a setter is found, *out=interface{}, and a set() function is
   212  //   returned to call SetYAML() with the value of *out once it's defined.
   213  //
   214  func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) {
   215  	if (*out).Kind() != reflect.Ptr && (*out).CanAddr() {
   216  		setter, _ := (*out).Addr().Interface().(Setter)
   217  		if setter != nil {
   218  			var arg interface{}
   219  			*out = reflect.ValueOf(&arg).Elem()
   220  			return func() {
   221  				*good = setter.SetYAML(shortTag(tag), arg)
   222  			}
   223  		}
   224  	}
   225  	again := true
   226  	for again {
   227  		again = false
   228  		setter, _ := (*out).Interface().(Setter)
   229  		if tag != yaml_NULL_TAG || setter != nil {
   230  			if pv := (*out); pv.Kind() == reflect.Ptr {
   231  				if pv.IsNil() {
   232  					*out = reflect.New(pv.Type().Elem()).Elem()
   233  					pv.Set((*out).Addr())
   234  				} else {
   235  					*out = pv.Elem()
   236  				}
   237  				setter, _ = pv.Interface().(Setter)
   238  				again = true
   239  			}
   240  		}
   241  		if setter != nil {
   242  			var arg interface{}
   243  			*out = reflect.ValueOf(&arg).Elem()
   244  			return func() {
   245  				*good = setter.SetYAML(shortTag(tag), arg)
   246  			}
   247  		}
   248  	}
   249  	return nil
   250  }
   251  
   252  func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
   253  	switch n.kind {
   254  	case documentNode:
   255  		good = d.document(n, out)
   256  	case scalarNode:
   257  		good = d.scalar(n, out)
   258  	case aliasNode:
   259  		good = d.alias(n, out)
   260  	case mappingNode:
   261  		good = d.mapping(n, out)
   262  	case sequenceNode:
   263  		good = d.sequence(n, out)
   264  	default:
   265  		panic("Internal error: unknown node kind: " + strconv.Itoa(n.kind))
   266  	}
   267  	return
   268  }
   269  
   270  func (d *decoder) document(n *node, out reflect.Value) (good bool) {
   271  	if len(n.children) == 1 {
   272  		d.doc = n
   273  		d.unmarshal(n.children[0], out)
   274  		return true
   275  	}
   276  	return false
   277  }
   278  
   279  func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
   280  	an, ok := d.doc.anchors[n.value]
   281  	if !ok {
   282  		fail("Unknown anchor '" + n.value + "' referenced")
   283  	}
   284  	if d.aliases[n.value] {
   285  		fail("Anchor '" + n.value + "' value contains itself")
   286  	}
   287  	d.aliases[n.value] = true
   288  	good = d.unmarshal(an, out)
   289  	delete(d.aliases, n.value)
   290  	return good
   291  }
   292  
   293  var zeroValue reflect.Value
   294  
   295  func resetMap(out reflect.Value) {
   296  	for _, k := range out.MapKeys() {
   297  		out.SetMapIndex(k, zeroValue)
   298  	}
   299  }
   300  
   301  var durationType = reflect.TypeOf(time.Duration(0))
   302  
   303  func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
   304  	var tag string
   305  	var resolved interface{}
   306  	if n.tag == "" && !n.implicit {
   307  		tag = yaml_STR_TAG
   308  		resolved = n.value
   309  	} else {
   310  		tag, resolved = resolve(n.tag, n.value)
   311  		if tag == yaml_BINARY_TAG {
   312  			data, err := base64.StdEncoding.DecodeString(resolved.(string))
   313  			if err != nil {
   314  				fail("!!binary value contains invalid base64 data")
   315  			}
   316  			resolved = string(data)
   317  		}
   318  	}
   319  	if set := d.setter(tag, &out, &good); set != nil {
   320  		defer set()
   321  	}
   322  	if resolved == nil {
   323  		if out.Kind() == reflect.Map && !out.CanAddr() {
   324  			resetMap(out)
   325  		} else {
   326  			out.Set(reflect.Zero(out.Type()))
   327  		}
   328  		good = true
   329  		return
   330  	}
   331  	switch out.Kind() {
   332  	case reflect.String:
   333  		if tag == yaml_BINARY_TAG {
   334  			out.SetString(resolved.(string))
   335  			good = true
   336  		} else if resolved != nil {
   337  			out.SetString(n.value)
   338  			good = true
   339  		}
   340  	case reflect.Interface:
   341  		if resolved == nil {
   342  			out.Set(reflect.Zero(out.Type()))
   343  		} else {
   344  			out.Set(reflect.ValueOf(resolved))
   345  		}
   346  		good = true
   347  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   348  		switch resolved := resolved.(type) {
   349  		case int:
   350  			if !out.OverflowInt(int64(resolved)) {
   351  				out.SetInt(int64(resolved))
   352  				good = true
   353  			}
   354  		case int64:
   355  			if !out.OverflowInt(resolved) {
   356  				out.SetInt(resolved)
   357  				good = true
   358  			}
   359  		case float64:
   360  			if resolved < 1<<63-1 && !out.OverflowInt(int64(resolved)) {
   361  				out.SetInt(int64(resolved))
   362  				good = true
   363  			}
   364  		case string:
   365  			if out.Type() == durationType {
   366  				d, err := time.ParseDuration(resolved)
   367  				if err == nil {
   368  					out.SetInt(int64(d))
   369  					good = true
   370  				}
   371  			}
   372  		}
   373  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   374  		switch resolved := resolved.(type) {
   375  		case int:
   376  			if resolved >= 0 {
   377  				out.SetUint(uint64(resolved))
   378  				good = true
   379  			}
   380  		case int64:
   381  			if resolved >= 0 {
   382  				out.SetUint(uint64(resolved))
   383  				good = true
   384  			}
   385  		case float64:
   386  			if resolved < 1<<64-1 && !out.OverflowUint(uint64(resolved)) {
   387  				out.SetUint(uint64(resolved))
   388  				good = true
   389  			}
   390  		}
   391  	case reflect.Bool:
   392  		switch resolved := resolved.(type) {
   393  		case bool:
   394  			out.SetBool(resolved)
   395  			good = true
   396  		}
   397  	case reflect.Float32, reflect.Float64:
   398  		switch resolved := resolved.(type) {
   399  		case int:
   400  			out.SetFloat(float64(resolved))
   401  			good = true
   402  		case int64:
   403  			out.SetFloat(float64(resolved))
   404  			good = true
   405  		case float64:
   406  			out.SetFloat(resolved)
   407  			good = true
   408  		}
   409  	case reflect.Ptr:
   410  		if out.Type().Elem() == reflect.TypeOf(resolved) {
   411  			elem := reflect.New(out.Type().Elem())
   412  			elem.Elem().Set(reflect.ValueOf(resolved))
   413  			out.Set(elem)
   414  			good = true
   415  		}
   416  	}
   417  	return good
   418  }
   419  
   420  func settableValueOf(i interface{}) reflect.Value {
   421  	v := reflect.ValueOf(i)
   422  	sv := reflect.New(v.Type()).Elem()
   423  	sv.Set(v)
   424  	return sv
   425  }
   426  
   427  func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
   428  	if set := d.setter(yaml_SEQ_TAG, &out, &good); set != nil {
   429  		defer set()
   430  	}
   431  	var iface reflect.Value
   432  	if out.Kind() == reflect.Interface {
   433  		// No type hints. Will have to use a generic sequence.
   434  		iface = out
   435  		out = settableValueOf(make([]interface{}, 0))
   436  	}
   437  
   438  	if out.Kind() != reflect.Slice {
   439  		return false
   440  	}
   441  	et := out.Type().Elem()
   442  
   443  	l := len(n.children)
   444  	for i := 0; i < l; i++ {
   445  		e := reflect.New(et).Elem()
   446  		if ok := d.unmarshal(n.children[i], e); ok {
   447  			out.Set(reflect.Append(out, e))
   448  		}
   449  	}
   450  	if iface.IsValid() {
   451  		iface.Set(out)
   452  	}
   453  	return true
   454  }
   455  
   456  func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
   457  	if set := d.setter(yaml_MAP_TAG, &out, &good); set != nil {
   458  		defer set()
   459  	}
   460  	if out.Kind() == reflect.Struct {
   461  		return d.mappingStruct(n, out)
   462  	}
   463  
   464  	if out.Kind() == reflect.Interface {
   465  		// No type hints. Will have to use a generic map.
   466  		iface := out
   467  		out = settableValueOf(make(map[interface{}]interface{}))
   468  		iface.Set(out)
   469  	}
   470  
   471  	if out.Kind() != reflect.Map {
   472  		return false
   473  	}
   474  	outt := out.Type()
   475  	kt := outt.Key()
   476  	et := outt.Elem()
   477  
   478  	if out.IsNil() {
   479  		out.Set(reflect.MakeMap(outt))
   480  	}
   481  	l := len(n.children)
   482  	for i := 0; i < l; i += 2 {
   483  		if isMerge(n.children[i]) {
   484  			d.merge(n.children[i+1], out)
   485  			continue
   486  		}
   487  		k := reflect.New(kt).Elem()
   488  		if d.unmarshal(n.children[i], k) {
   489  			kkind := k.Kind()
   490  			if kkind == reflect.Interface {
   491  				kkind = k.Elem().Kind()
   492  			}
   493  			if kkind == reflect.Map || kkind == reflect.Slice {
   494  				fail(fmt.Sprintf("invalid map key: %#v", k.Interface()))
   495  			}
   496  			e := reflect.New(et).Elem()
   497  			if d.unmarshal(n.children[i+1], e) {
   498  				out.SetMapIndex(k, e)
   499  			}
   500  		}
   501  	}
   502  	return true
   503  }
   504  
   505  func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
   506  	sinfo, err := getStructInfo(out.Type())
   507  	if err != nil {
   508  		panic(err)
   509  	}
   510  	name := settableValueOf("")
   511  	l := len(n.children)
   512  	for i := 0; i < l; i += 2 {
   513  		ni := n.children[i]
   514  		if isMerge(ni) {
   515  			d.merge(n.children[i+1], out)
   516  			continue
   517  		}
   518  		if !d.unmarshal(ni, name) {
   519  			continue
   520  		}
   521  		if info, ok := sinfo.FieldsMap[name.String()]; ok {
   522  			var field reflect.Value
   523  			if info.Inline == nil {
   524  				field = out.Field(info.Num)
   525  			} else {
   526  				field = out.FieldByIndex(info.Inline)
   527  			}
   528  			d.unmarshal(n.children[i+1], field)
   529  		}
   530  	}
   531  	return true
   532  }
   533  
   534  func (d *decoder) merge(n *node, out reflect.Value) {
   535  	const wantMap = "map merge requires map or sequence of maps as the value"
   536  	switch n.kind {
   537  	case mappingNode:
   538  		d.unmarshal(n, out)
   539  	case aliasNode:
   540  		an, ok := d.doc.anchors[n.value]
   541  		if ok && an.kind != mappingNode {
   542  			fail(wantMap)
   543  		}
   544  		d.unmarshal(n, out)
   545  	case sequenceNode:
   546  		// Step backwards as earlier nodes take precedence.
   547  		for i := len(n.children) - 1; i >= 0; i-- {
   548  			ni := n.children[i]
   549  			if ni.kind == aliasNode {
   550  				an, ok := d.doc.anchors[ni.value]
   551  				if ok && an.kind != mappingNode {
   552  					fail(wantMap)
   553  				}
   554  			} else if ni.kind != mappingNode {
   555  				fail(wantMap)
   556  			}
   557  			d.unmarshal(ni, out)
   558  		}
   559  	default:
   560  		fail(wantMap)
   561  	}
   562  }
   563  
   564  func isMerge(n *node) bool {
   565  	return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
   566  }