Gustavo Niemeyer 7 лет назад
Родитель
Сommit
d8c328eb99
4 измененных файлов с 116 добавлено и 79 удалено
  1. 8 23
      apic.go
  2. 15 16
      decode.go
  3. 13 10
      encode.go
  4. 80 30
      node_test.go

+ 8 - 23
apic.go

@@ -288,29 +288,14 @@ func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
 	}
 }
 
-///*
-// * Create ALIAS.
-// */
-//
-//YAML_DECLARE(int)
-//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
-//{
-//    mark yaml_mark_t = { 0, 0, 0 }
-//    anchor_copy *yaml_char_t = NULL
-//
-//    assert(event) // Non-NULL event object is expected.
-//    assert(anchor) // Non-NULL anchor is expected.
-//
-//    if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
-//
-//    anchor_copy = yaml_strdup(anchor)
-//    if (!anchor_copy)
-//        return 0
-//
-//    ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
-//
-//    return 1
-//}
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+	*event = yaml_event_t{
+		typ: yaml_ALIAS_EVENT,
+		anchor: anchor,
+	}
+	return true
+}
 
 // Create SCALAR.
 func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {

+ 15 - 16
decode.go

@@ -33,15 +33,14 @@ const (
 )
 
 type Node struct {
-	Kind   NodeKind
-	Style  Style
-	Line   int
-	Column int
-	Tag    string
-	Value  string
-	// TODO Alias should probably be the string, and then perhaps have a hidden cache?
-	Alias    *Node // Resolved alias for alias nodes.
-	Anchors  map[string]*Node
+	Kind     NodeKind
+	Style    Style
+	Line     int
+	Column   int
+	Tag      string
+	Value    string
+	Anchor   string
+	Alias    *Node
 	Children []*Node
 	Header   string
 	Inline   string
@@ -103,6 +102,7 @@ type parser struct {
 	parser   yaml_parser_t
 	event    yaml_event_t
 	doc      *Node
+	anchors  map[string]*Node
 	doneInit bool
 }
 
@@ -131,6 +131,7 @@ func (p *parser) init() {
 	if p.doneInit {
 		return
 	}
+	p.anchors = make(map[string]*Node)
 	p.expect(yaml_STREAM_START_EVENT)
 	p.doneInit = true
 }
@@ -199,7 +200,8 @@ func (p *parser) fail() {
 
 func (p *parser) anchor(n *Node, anchor []byte) {
 	if anchor != nil {
-		p.doc.Anchors[string(anchor)] = n
+		n.Anchor = string(anchor)
+		p.anchors[n.Anchor] = n
 	}
 }
 
@@ -243,7 +245,6 @@ func (p *parser) parseChild(parent *Node) *Node {
 
 func (p *parser) document() *Node {
 	n := p.node(DocumentNode)
-	n.Anchors = make(map[string]*Node)
 	p.doc = n
 	p.expect(yaml_DOCUMENT_START_EVENT)
 	p.parseChild(n)
@@ -257,7 +258,7 @@ func (p *parser) document() *Node {
 func (p *parser) alias() *Node {
 	n := p.node(AliasNode)
 	n.Value = string(p.event.anchor)
-	n.Alias = p.doc.Anchors[n.Value]
+	n.Alias = p.anchors[n.Value]
 	if n.Alias == nil {
 		failf("unknown anchor '%s' referenced", n.Value)
 	}
@@ -848,8 +849,7 @@ func (d *decoder) merge(n *Node, out reflect.Value) {
 	case MappingNode:
 		d.unmarshal(n, out)
 	case AliasNode:
-		an, ok := d.doc.Anchors[n.Value]
-		if ok && an.Kind != MappingNode {
+		if n.Alias != nil && n.Alias.Kind != MappingNode {
 			failWantMap()
 		}
 		d.unmarshal(n, out)
@@ -858,8 +858,7 @@ func (d *decoder) merge(n *Node, out reflect.Value) {
 		for i := len(n.Children) - 1; i >= 0; i-- {
 			ni := n.Children[i]
 			if ni.Kind == AliasNode {
-				an, ok := d.doc.Anchors[ni.Value]
-				if ok && an.Kind != MappingNode {
+				if ni.Alias != nil && ni.Alias.Kind != MappingNode {
 					failWantMap()
 				}
 			} else if ni.Kind != MappingNode {

+ 13 - 10
encode.go

@@ -14,12 +14,10 @@ import (
 )
 
 type encoder struct {
-	emitter yaml_emitter_t
-	event   yaml_event_t
-	out     []byte
-	flow    bool
-	// doneInit holds whether the initial stream_start_event has been
-	// emitted.
+	emitter  yaml_emitter_t
+	event    yaml_event_t
+	out      []byte
+	flow     bool
 	doneInit bool
 }
 
@@ -382,7 +380,7 @@ func (e *encoder) node(node *Node) {
 		if node.Style&FlowStyle != 0 {
 			style = yaml_FLOW_SEQUENCE_STYLE
 		}
-		e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(node.Tag), node.implicit(), style))
+		e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(node.Tag), node.implicit(), style))
 		e.event.header_comment = []byte(node.Header)
 		e.emit()
 		for _, node := range node.Children {
@@ -398,7 +396,7 @@ func (e *encoder) node(node *Node) {
 		if node.Style&FlowStyle != 0 {
 			style = yaml_FLOW_MAPPING_STYLE
 		}
-		yaml_mapping_start_event_initialize(&e.event, nil, []byte(node.Tag), node.implicit(), style)
+		yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(node.Tag), node.implicit(), style)
 		e.event.header_comment = []byte(node.Header)
 		e.emit()
 
@@ -412,7 +410,12 @@ func (e *encoder) node(node *Node) {
 		e.event.footer_comment = []byte(node.Footer)
 		e.emit()
 
-	case ScalarNode, AliasNode:
+	case AliasNode:
+		// TODO This is lacking comment handling. Test and fix.
+		yaml_alias_event_initialize(&e.event, []byte(node.Value))
+		e.emit()
+
+	case ScalarNode:
 		style := yaml_PLAIN_SCALAR_STYLE
 		switch {
 		case node.Style&DoubleQuotedStyle != 0:
@@ -428,7 +431,7 @@ func (e *encoder) node(node *Node) {
 		if style == yaml_PLAIN_SCALAR_STYLE && strings.Contains(node.Value, "\n") {
 			style = yaml_LITERAL_SCALAR_STYLE
 		}
-		e.emitScalar(node.Value, "", node.Tag, style, []byte(node.Header), []byte(node.Inline), []byte(node.Footer))
+		e.emitScalar(node.Value, node.Anchor, node.Tag, style, []byte(node.Header), []byte(node.Inline), []byte(node.Footer))
 
 		// TODO Check if binaries are being decoded into node.Value or not.
 		//switch {

+ 80 - 30
node_test.go

@@ -19,7 +19,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "null",
@@ -35,7 +34,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "foo",
@@ -50,7 +48,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Style:  yaml.DoubleQuotedStyle,
@@ -66,7 +63,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Style:  yaml.SingleQuotedStyle,
@@ -82,7 +78,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Style:  yaml.SingleQuotedStyle,
@@ -98,7 +93,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Style:  yaml.LiteralStyle,
@@ -114,7 +108,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "true",
@@ -129,7 +122,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "-10",
@@ -144,7 +136,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "4294967296",
@@ -159,7 +150,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "0.1000",
@@ -174,7 +164,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "-.inf",
@@ -189,7 +178,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  ".nan",
@@ -204,7 +192,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.MappingNode,
 				Style:  yaml.FlowStyle,
@@ -221,7 +208,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.MappingNode,
 				Value:  "",
@@ -248,7 +234,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.MappingNode,
 				Line:   1,
@@ -293,7 +278,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.SequenceNode,
 				Value:  "",
@@ -320,7 +304,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.SequenceNode,
 				Line:   1,
@@ -355,7 +338,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.SequenceNode,
 				Style:  yaml.FlowStyle,
@@ -383,7 +365,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    1,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.SequenceNode,
 				Line:   1,
@@ -413,13 +394,75 @@ var nodeTests = []struct {
 			}},
 		},
 	}, {
+		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
+		"!!map",
+		yaml.Node{
+			Kind:   yaml.DocumentNode,
+			Line:   1,
+			Column: 1,
+			Children: []*yaml.Node{{
+				Kind: yaml.MappingNode,
+				Line: 1,
+				Column: 1,
+				Children: []*yaml.Node{{
+					Kind: yaml.ScalarNode,
+					Line: 1,
+					Column: 1,
+					Value: "a",
+				},
+				saveNode("x", &yaml.Node{
+					Kind:   yaml.ScalarNode,
+					Line:   1,
+					Column: 4,
+					Value:  "1",
+					Anchor: "x",
+				}),
+				{
+					Kind: yaml.ScalarNode,
+					Line: 2,
+					Column: 1,
+					Value: "b",
+				},
+				saveNode("y", &yaml.Node{
+					Kind:   yaml.ScalarNode,
+					Line:   2,
+					Column: 4,
+					Value:  "2",
+					Anchor: "y",
+				}),
+				{
+					Kind: yaml.ScalarNode,
+					Line: 3,
+					Column: 1,
+					Value: "c",
+				}, {
+					Kind: yaml.AliasNode,
+					Line: 3,
+					Column: 4,
+					Value: "x",
+					Alias: dropNode("x"),
+				}, {
+					Kind: yaml.ScalarNode,
+					Line: 4,
+					Column: 1,
+					Value: "d",
+				}, {
+					Kind: yaml.AliasNode,
+					Line: 4,
+					Column: 4,
+					Value: "y",
+					Alias: dropNode("y"),
+				}},
+			}},
+		},
+	}, {
+
 		"# One\n# Two\ntrue # Three\n# Four\n# Five\n",
 		"!!bool",
 		yaml.Node{
 			Kind:    yaml.DocumentNode,
 			Line:    3,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.ScalarNode,
 				Value:  "true",
@@ -437,7 +480,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    7,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1\n\n# DH2",
 			Footer:  "# DF1\n\n# DF2",
 			Children: []*yaml.Node{{
@@ -457,7 +499,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    7,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1\n\n# DH2",
 			Footer:  "# DF1\n\n# DF2",
 			Children: []*yaml.Node{{
@@ -500,7 +541,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    7,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1\n\n# DH2",
 			Footer:  "# DF1\n\n# DF2",
 			Children: []*yaml.Node{{
@@ -533,7 +573,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    3,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1",
 			Children: []*yaml.Node{{
 				Kind:   yaml.SequenceNode,
@@ -561,7 +600,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    4,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1",
 			Footer:  "# DF1",
 			Children: []*yaml.Node{{
@@ -617,7 +655,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    2,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Children: []*yaml.Node{{
 				Kind:   yaml.SequenceNode,
 				Style:  yaml.FlowStyle,
@@ -646,7 +683,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    4,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1",
 			Footer:  "# DF1",
 			Children: []*yaml.Node{{
@@ -682,7 +718,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    4,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1",
 			Footer:  "# DF1",
 			Children: []*yaml.Node{{
@@ -716,7 +751,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    4,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1",
 			Footer:  "# DF1",
 			Children: []*yaml.Node{{
@@ -762,7 +796,6 @@ var nodeTests = []struct {
 			Kind:    yaml.DocumentNode,
 			Line:    4,
 			Column:  1,
-			Anchors: map[string]*yaml.Node{},
 			Header:  "# DH1",
 			Footer:  "# DF1",
 			Children: []*yaml.Node{{
@@ -819,3 +852,20 @@ func (s *S) TestNodeRoundtrip(c *C) {
 		}
 	}
 }
+
+var savedNodes = make(map[string]*yaml.Node)
+
+func saveNode(name string, node *yaml.Node) *yaml.Node {
+	savedNodes[name] = node
+	return node
+}
+
+func peekNode(name string) *yaml.Node {
+	return savedNodes[name]
+}
+
+func dropNode(name string) *yaml.Node {
+	node := savedNodes[name]
+	delete(savedNodes, name)
+	return node
+}