| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 part of yaml; | 5 part of yaml; | 
| 6 | 6 | 
| 7 // This file contains the node classes for the internal representations of YAML | 7 // This file contains the node classes for the internal representations of YAML | 
| 8 // documents. These nodes are used for both the serialization tree and the | 8 // documents. These nodes are used for both the serialization tree and the | 
| 9 // representation graph. | 9 // representation graph. | 
| 10 | 10 | 
| 11 /** A tag that indicates the type of a YAML node. */ | 11 /// A tag that indicates the type of a YAML node. | 
| 12 class _Tag { | 12 class _Tag { | 
| 13   // TODO(nweiz): it would better match the semantics of the spec if there were | 13   // TODO(nweiz): it would better match the semantics of the spec if there were | 
| 14   // a singleton instance of this class for each tag. | 14   // a singleton instance of this class for each tag. | 
| 15 | 15 | 
| 16   static const SCALAR_KIND = 0; | 16   static const SCALAR_KIND = 0; | 
| 17   static const SEQUENCE_KIND = 1; | 17   static const SEQUENCE_KIND = 1; | 
| 18   static const MAPPING_KIND = 2; | 18   static const MAPPING_KIND = 2; | 
| 19 | 19 | 
| 20   static const String YAML_URI_PREFIX = 'tag:yaml.org,2002:'; | 20   static const String YAML_URI_PREFIX = 'tag:yaml.org,2002:'; | 
| 21 | 21 | 
| 22   /** The name of the tag, either a URI or a local tag beginning with "!". */ | 22   /// The name of the tag, either a URI or a local tag beginning with "!". | 
| 23   final String name; | 23   final String name; | 
| 24 | 24 | 
| 25   /** The kind of the tag: SCALAR_KIND, SEQUENCE_KIND, or MAPPING_KIND. */ | 25   /// The kind of the tag: SCALAR_KIND, SEQUENCE_KIND, or MAPPING_KIND. | 
| 26   final int kind; | 26   final int kind; | 
| 27 | 27 | 
| 28   _Tag(this.name, this.kind); | 28   _Tag(this.name, this.kind); | 
| 29 | 29 | 
| 30   _Tag.scalar(String name) : this(name, SCALAR_KIND); | 30   _Tag.scalar(String name) : this(name, SCALAR_KIND); | 
| 31   _Tag.sequence(String name) : this(name, SEQUENCE_KIND); | 31   _Tag.sequence(String name) : this(name, SEQUENCE_KIND); | 
| 32   _Tag.mapping(String name) : this(name, MAPPING_KIND); | 32   _Tag.mapping(String name) : this(name, MAPPING_KIND); | 
| 33 | 33 | 
| 34   /** Returns the standard YAML tag URI for [type]. */ | 34   /// Returns the standard YAML tag URI for [type]. | 
| 35   static String yaml(String type) => "tag:yaml.org,2002:$type"; | 35   static String yaml(String type) => "tag:yaml.org,2002:$type"; | 
| 36 | 36 | 
| 37   /** Two tags are equal if their URIs are equal. */ | 37   /// Two tags are equal if their URIs are equal. | 
| 38   operator ==(other) { | 38   operator ==(other) { | 
| 39     if (other is! _Tag) return false; | 39     if (other is! _Tag) return false; | 
| 40     return name == other.name; | 40     return name == other.name; | 
| 41   } | 41   } | 
| 42 | 42 | 
| 43   String toString() { | 43   String toString() { | 
| 44     if (name.startsWith(YAML_URI_PREFIX)) { | 44     if (name.startsWith(YAML_URI_PREFIX)) { | 
| 45       return '!!${name.substring(YAML_URI_PREFIX.length)}'; | 45       return '!!${name.substring(YAML_URI_PREFIX.length)}'; | 
| 46     } else { | 46     } else { | 
| 47       return '!<$name>'; | 47       return '!<$name>'; | 
| 48     } | 48     } | 
| 49   } | 49   } | 
| 50 | 50 | 
| 51   int get hashCode => name.hashCode; | 51   int get hashCode => name.hashCode; | 
| 52 } | 52 } | 
| 53 | 53 | 
| 54 /** The abstract class for YAML nodes. */ | 54 /// The abstract class for YAML nodes. | 
| 55 abstract class _Node { | 55 abstract class _Node { | 
| 56   /** Every YAML node has a tag that describes its type. */ | 56   /// Every YAML node has a tag that describes its type. | 
| 57   _Tag tag; | 57   _Tag tag; | 
| 58 | 58 | 
| 59   /** Any YAML node can have an anchor associated with it. */ | 59   /// Any YAML node can have an anchor associated with it. | 
| 60   String anchor; | 60   String anchor; | 
| 61 | 61 | 
| 62   _Node(this.tag, [this.anchor]); | 62   _Node(this.tag, [this.anchor]); | 
| 63 | 63 | 
| 64   bool operator ==(other) { | 64   bool operator ==(other) { | 
| 65     if (other is! _Node) return false; | 65     if (other is! _Node) return false; | 
| 66     return tag == other.tag; | 66     return tag == other.tag; | 
| 67   } | 67   } | 
| 68 | 68 | 
| 69   int get hashCode => _hashCode([tag, anchor]); | 69   int get hashCode => _hashCode([tag, anchor]); | 
| 70 | 70 | 
| 71   visit(_Visitor v); | 71   visit(_Visitor v); | 
| 72 } | 72 } | 
| 73 | 73 | 
| 74 /** A sequence node represents an ordered list of nodes. */ | 74 /// A sequence node represents an ordered list of nodes. | 
| 75 class _SequenceNode extends _Node { | 75 class _SequenceNode extends _Node { | 
| 76   /** The nodes in the sequence. */ | 76   /// The nodes in the sequence. | 
| 77   List<_Node> content; | 77   List<_Node> content; | 
| 78 | 78 | 
| 79   _SequenceNode(String tagName, this.content) | 79   _SequenceNode(String tagName, this.content) | 
| 80     : super(new _Tag.sequence(tagName)); | 80     : super(new _Tag.sequence(tagName)); | 
| 81 | 81 | 
| 82   /** Two sequences are equal if their tags and contents are equal. */ | 82   /// Two sequences are equal if their tags and contents are equal. | 
| 83   bool operator ==(other) { | 83   bool operator ==(other) { | 
| 84     // Should be super != other; bug 2554 | 84     // Should be super != other; bug 2554 | 
| 85     if (!(super == other) || other is! _SequenceNode) return false; | 85     if (!(super == other) || other is! _SequenceNode) return false; | 
| 86     if (content.length != other.content.length) return false; | 86     if (content.length != other.content.length) return false; | 
| 87     for (var i = 0; i < content.length; i++) { | 87     for (var i = 0; i < content.length; i++) { | 
| 88       if (content[i] != other.content[i]) return false; | 88       if (content[i] != other.content[i]) return false; | 
| 89     } | 89     } | 
| 90     return true; | 90     return true; | 
| 91   } | 91   } | 
| 92 | 92 | 
| 93   String toString() => '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]'; | 93   String toString() => '$tag [${Strings.join(content.map((e) => '$e'), ', ')}]'; | 
| 94 | 94 | 
| 95   int get hashCode => super.hashCode ^ _hashCode(content); | 95   int get hashCode => super.hashCode ^ _hashCode(content); | 
| 96 | 96 | 
| 97   visit(_Visitor v) => v.visitSequence(this); | 97   visit(_Visitor v) => v.visitSequence(this); | 
| 98 } | 98 } | 
| 99 | 99 | 
| 100 /** An alias node is a reference to an anchor. */ | 100 /// An alias node is a reference to an anchor. | 
| 101 class _AliasNode extends _Node { | 101 class _AliasNode extends _Node { | 
| 102   _AliasNode(String anchor) : super(new _Tag.scalar(_Tag.yaml("str")), anchor); | 102   _AliasNode(String anchor) : super(new _Tag.scalar(_Tag.yaml("str")), anchor); | 
| 103 | 103 | 
| 104   visit(_Visitor v) => v.visitAlias(this); | 104   visit(_Visitor v) => v.visitAlias(this); | 
| 105 } | 105 } | 
| 106 | 106 | 
| 107 /** A scalar node represents all YAML nodes that have a single value. */ | 107 /// A scalar node represents all YAML nodes that have a single value. | 
| 108 class _ScalarNode extends _Node { | 108 class _ScalarNode extends _Node { | 
| 109   /** The string value of the scalar node, if it was created by the parser. */ | 109   /// The string value of the scalar node, if it was created by the parser. | 
| 110   final String _content; | 110   final String _content; | 
| 111 | 111 | 
| 112   /** The Dart value of the scalar node, if it was created by the composer. */ | 112   /// The Dart value of the scalar node, if it was created by the composer. | 
| 113   final value; | 113   final value; | 
| 114 | 114 | 
| 115   /** | 115   /// Creates a new Scalar node. | 
| 116    * Creates a new Scalar node. | 116   /// | 
| 117    * | 117   /// Exactly one of [content] and [value] should be specified. Content should | 
| 118    * Exactly one of [content] and [value] should be specified. Content should be | 118   /// be specified for a newly-parsed scalar that hasn't yet been composed. | 
| 119    * specified for a newly-parsed scalar that hasn't yet been composed. Value | 119   /// Value should be specified for a composed scalar, although `null` is a | 
| 120    * should be specified for a composed scalar, although `null` is a valid | 120   /// valid value. | 
| 121    * value. |  | 
| 122    */ |  | 
| 123   _ScalarNode(String tagName, {String content, this.value}) | 121   _ScalarNode(String tagName, {String content, this.value}) | 
| 124    : _content = content, | 122    : _content = content, | 
| 125      super(new _Tag.scalar(tagName)); | 123      super(new _Tag.scalar(tagName)); | 
| 126 | 124 | 
| 127   /** Two scalars are equal if their string representations are equal. */ | 125   /// Two scalars are equal if their string representations are equal. | 
| 128   bool operator ==(other) { | 126   bool operator ==(other) { | 
| 129     // Should be super != other; bug 2554 | 127     // Should be super != other; bug 2554 | 
| 130     if (!(super == other) || other is! _ScalarNode) return false; | 128     if (!(super == other) || other is! _ScalarNode) return false; | 
| 131     return content == other.content; | 129     return content == other.content; | 
| 132   } | 130   } | 
| 133 | 131 | 
| 134   /** | 132   /// Returns the string representation of the scalar. After composition, this | 
| 135    * Returns the string representation of the scalar. After composition, this is | 133   /// is equal to the canonical serialization of the value of the scalar. | 
| 136    * equal to the canonical serialization of the value of the scalar. |  | 
| 137    */ |  | 
| 138   String get content => _content != null ? _content : canonicalContent; | 134   String get content => _content != null ? _content : canonicalContent; | 
| 139 | 135 | 
| 140   /** | 136   /// Returns the canonical serialization of the value of the scalar. If the | 
| 141    * Returns the canonical serialization of the value of the scalar. If the | 137   /// value isn't given, the result of this will be "null". | 
| 142    * value isn't given, the result of this will be "null". |  | 
| 143    */ |  | 
| 144   String get canonicalContent { | 138   String get canonicalContent { | 
| 145     if (value == null || value is bool || value is int) return '$value'; | 139     if (value == null || value is bool || value is int) return '$value'; | 
| 146 | 140 | 
| 147     if (value is num) { | 141     if (value is num) { | 
| 148       // 20 is the maximum value for this argument, which we use since YAML | 142       // 20 is the maximum value for this argument, which we use since YAML | 
| 149       // doesn't specify a maximum. | 143       // doesn't specify a maximum. | 
| 150       return value.toStringAsExponential(20). | 144       return value.toStringAsExponential(20). | 
| 151         replaceFirst(new RegExp("0+e"), "e"); | 145         replaceFirst(new RegExp("0+e"), "e"); | 
| 152     } | 146     } | 
| 153 | 147 | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 185         } | 179         } | 
| 186       }); | 180       }); | 
| 187       return '"${Strings.join(escapedValue, '')}"'; | 181       return '"${Strings.join(escapedValue, '')}"'; | 
| 188     } | 182     } | 
| 189 | 183 | 
| 190     throw new YamlException("unknown scalar value: $value"); | 184     throw new YamlException("unknown scalar value: $value"); | 
| 191   } | 185   } | 
| 192 | 186 | 
| 193   String toString() => '$tag "$content"'; | 187   String toString() => '$tag "$content"'; | 
| 194 | 188 | 
| 195   /** | 189   /// Left-pads [str] with zeros so that it's at least [length] characters | 
| 196    * Left-pads [str] with zeros so that it's at least [length] characters | 190   /// long. | 
| 197    * long. |  | 
| 198    */ |  | 
| 199   String zeroPad(String str, int length) { | 191   String zeroPad(String str, int length) { | 
| 200     assert(length >= str.length); | 192     assert(length >= str.length); | 
| 201     var prefix = []; | 193     var prefix = []; | 
| 202     prefix.insertRange(0, length - str.length, '0'); | 194     prefix.insertRange(0, length - str.length, '0'); | 
| 203     return '${Strings.join(prefix, '')}$str'; | 195     return '${Strings.join(prefix, '')}$str'; | 
| 204   } | 196   } | 
| 205 | 197 | 
| 206   int get hashCode => super.hashCode ^ content.hashCode; | 198   int get hashCode => super.hashCode ^ content.hashCode; | 
| 207 | 199 | 
| 208   visit(_Visitor v) => v.visitScalar(this); | 200   visit(_Visitor v) => v.visitScalar(this); | 
| 209 } | 201 } | 
| 210 | 202 | 
| 211 /** A mapping node represents an unordered map of nodes to nodes. */ | 203 /// A mapping node represents an unordered map of nodes to nodes. | 
| 212 class _MappingNode extends _Node { | 204 class _MappingNode extends _Node { | 
| 213   /** The node map. */ | 205   /// The node map. | 
| 214   Map<_Node, _Node> content; | 206   Map<_Node, _Node> content; | 
| 215 | 207 | 
| 216   _MappingNode(String tagName, this.content) | 208   _MappingNode(String tagName, this.content) | 
| 217     : super(new _Tag.mapping(tagName)); | 209     : super(new _Tag.mapping(tagName)); | 
| 218 | 210 | 
| 219   /** Two mappings are equal if their tags and contents are equal. */ | 211   /// Two mappings are equal if their tags and contents are equal. | 
| 220   bool operator ==(other) { | 212   bool operator ==(other) { | 
| 221     // Should be super != other; bug 2554 | 213     // Should be super != other; bug 2554 | 
| 222     if (!(super == other) || other is! _MappingNode) return false; | 214     if (!(super == other) || other is! _MappingNode) return false; | 
| 223     if (content.length != other.content.length) return false; | 215     if (content.length != other.content.length) return false; | 
| 224     for (var key in content.keys) { | 216     for (var key in content.keys) { | 
| 225       if (!other.content.containsKey(key)) return false; | 217       if (!other.content.containsKey(key)) return false; | 
| 226       if (content[key] != other.content[key]) return false; | 218       if (content[key] != other.content[key]) return false; | 
| 227     } | 219     } | 
| 228     return true; | 220     return true; | 
| 229   } | 221   } | 
| 230 | 222 | 
| 231   String toString() { | 223   String toString() { | 
| 232     var strContent = Strings.join(content.keys. | 224     var strContent = Strings.join(content.keys. | 
| 233         map((k) => '${k}: ${content[k]}'), ', '); | 225         map((k) => '${k}: ${content[k]}'), ', '); | 
| 234     return '$tag {$strContent}'; | 226     return '$tag {$strContent}'; | 
| 235   } | 227   } | 
| 236 | 228 | 
| 237   int get hashCode => super.hashCode ^ _hashCode(content); | 229   int get hashCode => super.hashCode ^ _hashCode(content); | 
| 238 | 230 | 
| 239   visit(_Visitor v) => v.visitMapping(this); | 231   visit(_Visitor v) => v.visitMapping(this); | 
| 240 } | 232 } | 
| OLD | NEW | 
|---|