|
|
@@ -25,7 +25,8 @@ const (
|
|
|
type Style uint32
|
|
|
|
|
|
const (
|
|
|
- DoubleQuotedStyle Style = 1 << iota
|
|
|
+ TaggedStyle Style = 1 << iota
|
|
|
+ DoubleQuotedStyle
|
|
|
SingleQuotedStyle
|
|
|
LiteralStyle
|
|
|
FoldedStyle
|
|
|
@@ -47,44 +48,37 @@ type Node struct {
|
|
|
Footer string
|
|
|
}
|
|
|
|
|
|
-func (n *Node) implicit() bool {
|
|
|
- return n.Style&(SingleQuotedStyle|DoubleQuotedStyle) == 0 && (n.Tag == "" || n.Tag == "!")
|
|
|
+func (n *Node) LongTag() string {
|
|
|
+ return longTag(n.ShortTag())
|
|
|
}
|
|
|
|
|
|
-// TODO Quite some garbage being generated by these common functions.
|
|
|
-
|
|
|
func (n *Node) ShortTag() string {
|
|
|
- tag := n.LongTag()
|
|
|
- if strings.HasPrefix(tag, longTagPrefix) {
|
|
|
- return "!!" + tag[len(longTagPrefix):]
|
|
|
+ if n.indicatedString() {
|
|
|
+ return strTag
|
|
|
}
|
|
|
- return tag
|
|
|
-}
|
|
|
-
|
|
|
-func (n *Node) LongTag() string {
|
|
|
if n.Tag == "" || n.Tag == "!" {
|
|
|
switch n.Kind {
|
|
|
case MappingNode:
|
|
|
- return yaml_MAP_TAG
|
|
|
+ return mapTag
|
|
|
case SequenceNode:
|
|
|
- return yaml_SEQ_TAG
|
|
|
+ return seqTag
|
|
|
case AliasNode:
|
|
|
if n.Alias != nil {
|
|
|
- return n.Alias.LongTag()
|
|
|
+ return n.Alias.ShortTag()
|
|
|
}
|
|
|
case ScalarNode:
|
|
|
- if n.Style&(SingleQuotedStyle|DoubleQuotedStyle) != 0 {
|
|
|
- return yaml_STR_TAG
|
|
|
- }
|
|
|
tag, _ := resolve("", n.Value)
|
|
|
return tag
|
|
|
}
|
|
|
return ""
|
|
|
-
|
|
|
- } else if strings.HasPrefix(n.Tag, "!!") {
|
|
|
- return longTagPrefix + n.Tag[2:]
|
|
|
}
|
|
|
- return n.Tag
|
|
|
+ return shortTag(n.Tag)
|
|
|
+}
|
|
|
+
|
|
|
+func (n *Node) indicatedString() bool {
|
|
|
+ return n.Kind == ScalarNode &&
|
|
|
+ (shortTag(n.Tag) == strTag ||
|
|
|
+ (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0)
|
|
|
}
|
|
|
|
|
|
func (n *Node) SetString(s string) {
|
|
|
@@ -92,7 +86,7 @@ func (n *Node) SetString(s string) {
|
|
|
n.Value = s
|
|
|
if strings.Contains(s, "\n") {
|
|
|
n.Style = LiteralStyle
|
|
|
- } else if n.LongTag() != "tag:yaml.org,2002:str" {
|
|
|
+ } else if n.ShortTag() != strTag {
|
|
|
n.Style = DoubleQuotedStyle
|
|
|
}
|
|
|
}
|
|
|
@@ -228,9 +222,21 @@ func (p *parser) parse() *Node {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func (p *parser) node(kind NodeKind) *Node {
|
|
|
+func (p *parser) node(kind NodeKind, defaultTag, tag, value string) *Node {
|
|
|
+ var style Style
|
|
|
+ if tag != "" && tag != "!" {
|
|
|
+ tag = shortTag(tag)
|
|
|
+ style = TaggedStyle
|
|
|
+ } else if defaultTag != "" {
|
|
|
+ tag = defaultTag
|
|
|
+ } else if kind == ScalarNode {
|
|
|
+ tag, _ = resolve("", value)
|
|
|
+ }
|
|
|
return &Node{
|
|
|
Kind: kind,
|
|
|
+ Tag: tag,
|
|
|
+ Value: value,
|
|
|
+ Style: style,
|
|
|
Line: p.event.start_mark.line + 1,
|
|
|
Column: p.event.start_mark.column + 1,
|
|
|
Header: string(p.event.header_comment),
|
|
|
@@ -246,7 +252,7 @@ func (p *parser) parseChild(parent *Node) *Node {
|
|
|
}
|
|
|
|
|
|
func (p *parser) document() *Node {
|
|
|
- n := p.node(DocumentNode)
|
|
|
+ n := p.node(DocumentNode, "", "", "")
|
|
|
p.doc = n
|
|
|
p.expect(yaml_DOCUMENT_START_EVENT)
|
|
|
p.parseChild(n)
|
|
|
@@ -258,8 +264,7 @@ func (p *parser) document() *Node {
|
|
|
}
|
|
|
|
|
|
func (p *parser) alias() *Node {
|
|
|
- n := p.node(AliasNode)
|
|
|
- n.Value = string(p.event.anchor)
|
|
|
+ n := p.node(AliasNode, "", "", string(p.event.anchor))
|
|
|
n.Alias = p.anchors[n.Value]
|
|
|
if n.Alias == nil {
|
|
|
failf("unknown anchor '%s' referenced", n.Value)
|
|
|
@@ -269,30 +274,39 @@ func (p *parser) alias() *Node {
|
|
|
}
|
|
|
|
|
|
func (p *parser) scalar() *Node {
|
|
|
- n := p.node(ScalarNode)
|
|
|
- n.Value = string(p.event.value)
|
|
|
- n.Tag = string(p.event.tag)
|
|
|
- style := p.event.scalar_style()
|
|
|
+ var parsedStyle = p.event.scalar_style()
|
|
|
+ var nodeStyle Style
|
|
|
switch {
|
|
|
- case style&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
|
|
|
- n.Style = DoubleQuotedStyle
|
|
|
- case style&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
|
|
|
- n.Style = SingleQuotedStyle
|
|
|
- case style&yaml_LITERAL_SCALAR_STYLE != 0:
|
|
|
- n.Style = LiteralStyle
|
|
|
- case style&yaml_FOLDED_SCALAR_STYLE != 0:
|
|
|
- n.Style = FoldedStyle
|
|
|
+ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
|
|
|
+ nodeStyle = DoubleQuotedStyle
|
|
|
+ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
|
|
|
+ nodeStyle = SingleQuotedStyle
|
|
|
+ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
|
|
|
+ nodeStyle = LiteralStyle
|
|
|
+ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
|
|
|
+ nodeStyle = FoldedStyle
|
|
|
+ }
|
|
|
+ var nodeValue = string(p.event.value)
|
|
|
+ var nodeTag = string(p.event.tag)
|
|
|
+ var defaultTag string
|
|
|
+ if nodeStyle == 0 {
|
|
|
+ if nodeValue == "<<" {
|
|
|
+ defaultTag = mergeTag
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ defaultTag = strTag
|
|
|
}
|
|
|
+ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
|
|
|
+ n.Style |= nodeStyle
|
|
|
p.anchor(n, p.event.anchor)
|
|
|
p.expect(yaml_SCALAR_EVENT)
|
|
|
return n
|
|
|
}
|
|
|
|
|
|
func (p *parser) sequence() *Node {
|
|
|
- n := p.node(SequenceNode)
|
|
|
- n.Tag = string(p.event.tag)
|
|
|
+ n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
|
|
|
if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
|
|
|
- n.Style = FlowStyle
|
|
|
+ n.Style |= FlowStyle
|
|
|
}
|
|
|
p.anchor(n, p.event.anchor)
|
|
|
p.expect(yaml_SEQUENCE_START_EVENT)
|
|
|
@@ -306,8 +320,7 @@ func (p *parser) sequence() *Node {
|
|
|
}
|
|
|
|
|
|
func (p *parser) mapping() *Node {
|
|
|
- n := p.node(MappingNode)
|
|
|
- n.Tag = string(p.event.tag)
|
|
|
+ n := p.node(MappingNode, mapTag, string(p.event.tag), "")
|
|
|
if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
|
|
|
n.Style |= FlowStyle
|
|
|
}
|
|
|
@@ -367,7 +380,7 @@ func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
|
|
|
tag = n.Tag
|
|
|
}
|
|
|
value := n.Value
|
|
|
- if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
|
|
|
+ if tag != seqTag && tag != mapTag {
|
|
|
if len(value) > 10 {
|
|
|
value = " `" + value[:7] + "...`"
|
|
|
} else {
|
|
|
@@ -414,7 +427,7 @@ func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good
|
|
|
//
|
|
|
// If n holds a null value, prepare returns before doing anything.
|
|
|
func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
|
|
|
- if n.Tag == yaml_NULL_TAG || n.Kind == ScalarNode && n.Tag == "" && (n.Value == "null" || n.Value == "~" || n.Value == "" && n.implicit()) {
|
|
|
+ if n.ShortTag() == nullTag {
|
|
|
return out, false, false
|
|
|
}
|
|
|
again := true
|
|
|
@@ -501,12 +514,12 @@ func resetMap(out reflect.Value) {
|
|
|
func (d *decoder) scalar(n *Node, out reflect.Value) bool {
|
|
|
var tag string
|
|
|
var resolved interface{}
|
|
|
- if n.Tag == "" && !n.implicit() {
|
|
|
- tag = yaml_STR_TAG
|
|
|
+ if n.indicatedString() {
|
|
|
+ tag = strTag
|
|
|
resolved = n.Value
|
|
|
} else {
|
|
|
tag, resolved = resolve(n.Tag, n.Value)
|
|
|
- if tag == yaml_BINARY_TAG {
|
|
|
+ if tag == binaryTag {
|
|
|
data, err := base64.StdEncoding.DecodeString(resolved.(string))
|
|
|
if err != nil {
|
|
|
failf("!!binary value contains invalid base64 data")
|
|
|
@@ -533,7 +546,7 @@ func (d *decoder) scalar(n *Node, out reflect.Value) bool {
|
|
|
u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
|
|
|
if ok {
|
|
|
var text []byte
|
|
|
- if tag == yaml_BINARY_TAG {
|
|
|
+ if tag == binaryTag {
|
|
|
text = []byte(resolved.(string))
|
|
|
} else {
|
|
|
// We let any value be unmarshaled into TextUnmarshaler.
|
|
|
@@ -550,7 +563,7 @@ func (d *decoder) scalar(n *Node, out reflect.Value) bool {
|
|
|
}
|
|
|
switch out.Kind() {
|
|
|
case reflect.String:
|
|
|
- if tag == yaml_BINARY_TAG {
|
|
|
+ if tag == binaryTag {
|
|
|
out.SetString(resolved.(string))
|
|
|
return true
|
|
|
}
|
|
|
@@ -695,7 +708,7 @@ func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
|
|
|
iface = out
|
|
|
out = settableValueOf(make([]interface{}, l))
|
|
|
default:
|
|
|
- d.terror(n, yaml_SEQ_TAG, out)
|
|
|
+ d.terror(n, seqTag, out)
|
|
|
return false
|
|
|
}
|
|
|
et := out.Type().Elem()
|
|
|
@@ -748,7 +761,7 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
|
|
|
}
|
|
|
iface.Set(out)
|
|
|
default:
|
|
|
- d.terror(n, yaml_MAP_TAG, out)
|
|
|
+ d.terror(n, mapTag, out)
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
@@ -800,7 +813,7 @@ func isStringMap(n *Node) bool {
|
|
|
}
|
|
|
l := len(n.Children)
|
|
|
for i := 0; i < l; i++ {
|
|
|
- if n.Children[i].LongTag() != yaml_STR_TAG {
|
|
|
+ if n.Children[i].ShortTag() != strTag {
|
|
|
return false
|
|
|
}
|
|
|
}
|
|
|
@@ -897,5 +910,5 @@ func (d *decoder) merge(n *Node, out reflect.Value) {
|
|
|
}
|
|
|
|
|
|
func isMerge(n *Node) bool {
|
|
|
- return n.Kind == ScalarNode && n.Value == "<<" && (n.implicit() || n.Tag == yaml_MERGE_TAG)
|
|
|
+ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
|
|
|
}
|