github.com/marinho/drone@v0.2.1-0.20140504195434-d3ba962e89a7/Godeps/_workspace/src/launchpad.net/goyaml/decode.go (about)

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