github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/encoding/kmgYaml/decode.go (about)

     1  package kmgYaml
     2  
     3  import (
     4  	"encoding"
     5  	"reflect"
     6  	"strconv"
     7  )
     8  
     9  const (
    10  	documentNode = 1 << iota
    11  	mappingNode
    12  	sequenceNode
    13  	scalarNode
    14  	aliasNode
    15  )
    16  
    17  type node struct {
    18  	kind         int
    19  	line, column int
    20  	tag          string
    21  	value        string
    22  	implicit     bool
    23  	children     []*node
    24  	anchors      map[string]*node
    25  }
    26  
    27  // ----------------------------------------------------------------------------
    28  // Parser, produces a node tree out of a libyaml event stream.
    29  
    30  type parser struct {
    31  	parser yaml_parser_t
    32  	event  yaml_event_t
    33  	doc    *node
    34  }
    35  
    36  func newParser(b []byte) *parser {
    37  	p := parser{}
    38  	if !yaml_parser_initialize(&p.parser) {
    39  		panic("Failed to initialize YAML emitter")
    40  	}
    41  
    42  	if len(b) == 0 {
    43  		b = []byte{'\n'}
    44  	}
    45  
    46  	yaml_parser_set_input_string(&p.parser, b)
    47  
    48  	p.skip()
    49  	if p.event.typ != yaml_STREAM_START_EVENT {
    50  		panic("Expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
    51  	}
    52  	p.skip()
    53  	return &p
    54  }
    55  
    56  func (p *parser) destroy() {
    57  	if p.event.typ != yaml_NO_EVENT {
    58  		yaml_event_delete(&p.event)
    59  	}
    60  	yaml_parser_delete(&p.parser)
    61  }
    62  
    63  func (p *parser) skip() {
    64  	if p.event.typ != yaml_NO_EVENT {
    65  		if p.event.typ == yaml_STREAM_END_EVENT {
    66  			panic("Attempted to go past the end of stream. Corrupted value?")
    67  		}
    68  		yaml_event_delete(&p.event)
    69  	}
    70  	if !yaml_parser_parse(&p.parser, &p.event) {
    71  		p.fail()
    72  	}
    73  }
    74  
    75  func (p *parser) fail() {
    76  	var where string
    77  	var line int
    78  	if p.parser.problem_mark.line != 0 {
    79  		line = p.parser.problem_mark.line
    80  	} else if p.parser.context_mark.line != 0 {
    81  		line = p.parser.context_mark.line
    82  	}
    83  	if line != 0 {
    84  		where = "line " + strconv.Itoa(line) + ": "
    85  	}
    86  	var msg string
    87  	if len(p.parser.problem) > 0 {
    88  		msg = p.parser.problem
    89  	} else {
    90  		msg = "Unknown problem parsing YAML content"
    91  	}
    92  	panic(where + msg)
    93  }
    94  
    95  func (p *parser) anchor(n *node, anchor []byte) {
    96  	if anchor != nil {
    97  		p.doc.anchors[string(anchor)] = n
    98  	}
    99  }
   100  
   101  func (p *parser) parse() *node {
   102  	switch p.event.typ {
   103  	case yaml_SCALAR_EVENT:
   104  		return p.scalar()
   105  	case yaml_ALIAS_EVENT:
   106  		return p.alias()
   107  	case yaml_MAPPING_START_EVENT:
   108  		return p.mapping()
   109  	case yaml_SEQUENCE_START_EVENT:
   110  		return p.sequence()
   111  	case yaml_DOCUMENT_START_EVENT:
   112  		return p.document()
   113  	case yaml_STREAM_END_EVENT:
   114  		// Happens when attempting to decode an empty buffer.
   115  		return nil
   116  	default:
   117  		panic("Attempted to parse unknown event: " +
   118  			strconv.Itoa(int(p.event.typ)))
   119  	}
   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  	if out.CanAddr() {
   294  		marhsaler, ok := (out).Addr().Interface().(encoding.TextUnmarshaler)
   295  		if ok {
   296  			err := marhsaler.UnmarshalText([]byte(n.value))
   297  			if err != nil {
   298  				panic(err)
   299  			}
   300  			return true
   301  		}
   302  	}
   303  	switch out.Kind() {
   304  	case reflect.String:
   305  		if resolved != nil {
   306  			out.SetString(n.value)
   307  			good = true
   308  		}
   309  	case reflect.Interface:
   310  		if resolved == nil {
   311  			out.Set(reflect.Zero(out.Type()))
   312  		} else {
   313  			out.Set(reflect.ValueOf(resolved))
   314  		}
   315  		good = true
   316  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   317  		switch resolved := resolved.(type) {
   318  		case int:
   319  			if !out.OverflowInt(int64(resolved)) {
   320  				out.SetInt(int64(resolved))
   321  				good = true
   322  			}
   323  		case int64:
   324  			if !out.OverflowInt(resolved) {
   325  				out.SetInt(resolved)
   326  				good = true
   327  			}
   328  		}
   329  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   330  		switch resolved := resolved.(type) {
   331  		case int:
   332  			if resolved >= 0 {
   333  				out.SetUint(uint64(resolved))
   334  				good = true
   335  			}
   336  		case int64:
   337  			if resolved >= 0 {
   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 float64:
   351  			out.SetFloat(resolved)
   352  			good = true
   353  		case int:
   354  			out.SetFloat(float64(resolved))
   355  			good = true
   356  		case int64:
   357  			out.SetFloat(float64(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  		et := out.Type().Elem()
   397  
   398  		l := len(n.children)
   399  		for i := 0; i < l; i++ {
   400  			e := reflect.New(et).Elem()
   401  			if ok := d.unmarshal(n.children[i], e); ok {
   402  				out.Set(reflect.Append(out, e))
   403  			}
   404  		}
   405  		if iface.IsValid() {
   406  			iface.Set(out)
   407  		}
   408  		return true
   409  	} else if out.Kind() == reflect.Array {
   410  		et := out.Type().Elem()
   411  
   412  		l := len(n.children)
   413  		// cut elements more than type allowed
   414  		if l > out.Type().Len() {
   415  			l = out.Type().Len()
   416  		}
   417  		for i := 0; i < l; i++ {
   418  			e := reflect.New(et).Elem()
   419  			if ok := d.unmarshal(n.children[i], e); ok {
   420  				out.Index(i).Set(e)
   421  			}
   422  		}
   423  		if iface.IsValid() {
   424  			iface.Set(out)
   425  		}
   426  		return true
   427  	}
   428  	panic("Type not match, can not set slice to " + out.Kind().String())
   429  	return false
   430  }
   431  
   432  func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
   433  	if set := d.setter("!!map", &out, &good); set != nil {
   434  		defer set()
   435  	}
   436  	if out.Kind() == reflect.Struct {
   437  		return d.mappingStruct(n, out)
   438  	}
   439  
   440  	if out.Kind() == reflect.Interface {
   441  		// No type hints. Will have to use a generic map.
   442  		iface := out
   443  		out = settableValueOf(make(map[interface{}]interface{}))
   444  		iface.Set(out)
   445  	}
   446  
   447  	if out.Kind() != reflect.Map {
   448  		panic("Type not match, can not set map to " + out.Kind().String())
   449  		return false
   450  	}
   451  	outt := out.Type()
   452  	kt := outt.Key()
   453  	et := outt.Elem()
   454  
   455  	if out.IsNil() {
   456  		out.Set(reflect.MakeMap(outt))
   457  	}
   458  	l := len(n.children)
   459  	for i := 0; i < l; i += 2 {
   460  		k := reflect.New(kt).Elem()
   461  		if d.unmarshal(n.children[i], k) {
   462  			e := reflect.New(et).Elem()
   463  			if d.unmarshal(n.children[i+1], e) {
   464  				out.SetMapIndex(k, e)
   465  			}
   466  		}
   467  	}
   468  	return true
   469  }
   470  
   471  func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
   472  	sinfo, err := getStructInfo(out.Type())
   473  	if err != nil {
   474  		panic(err)
   475  	}
   476  	name := settableValueOf("")
   477  	l := len(n.children)
   478  	for i := 0; i < l; i += 2 {
   479  		if !d.unmarshal(n.children[i], name) {
   480  			continue
   481  		}
   482  		if info, ok := sinfo.FieldsMap[name.String()]; ok {
   483  			var field reflect.Value
   484  			if info.Inline == nil {
   485  				field = out.Field(info.Num)
   486  			} else {
   487  				field = out.FieldByIndex(info.Inline)
   488  			}
   489  			d.unmarshal(n.children[i+1], field)
   490  		}
   491  	}
   492  	return true
   493  }