PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/Ruby/Libraries.Yaml/Engine/Representer.cs

http://github.com/IronLanguages/main
C# | 240 lines | 187 code | 36 blank | 17 comment | 41 complexity | 8f2dc8a4fcd0fc66ad34bd5dbbf82163 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. // Version: CPL 1.0
  2. //
  3. // The contents of this file are subject to the Common Public
  4. // License Version 1.0 (the "License"); you may not use this file
  5. // except in compliance with the License. You may obtain a copy of
  6. // the License at http://www.eclipse.org/legal/cpl-v10.html
  7. //
  8. // Software distributed under the License is distributed on an "AS
  9. // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10. // implied. See the License for the specific language governing
  11. // rights and limitations under the License.
  12. //
  13. // Copyright (C) 2007 Ola Bini <ola@ologix.com>
  14. // Copyright (c) Microsoft Corporation.
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Reflection;
  19. using Microsoft.Scripting.Runtime;
  20. using Microsoft.Scripting.Utils;
  21. using System.Globalization;
  22. namespace IronRuby.StandardLibrary.Yaml {
  23. public class Representer {
  24. private readonly Dictionary<object, Node>/*!*/ _representedObjects = new Dictionary<object, Node>(ReferenceEqualityComparer<object>.Instance);
  25. private readonly Dictionary<object, List<LinkNode>>/*!*/ _links = new Dictionary<object, List<LinkNode>>(ReferenceEqualityComparer<object>.Instance);
  26. private readonly static object _NullKey = new object();
  27. // recursion level as we build YAML representation of an object graph:
  28. private int _level;
  29. public Representer() {
  30. }
  31. public int Level {
  32. get { return _level; }
  33. set { _level = value; }
  34. }
  35. public void ForgetObjects() {
  36. _representedObjects.Clear();
  37. }
  38. public Node/*!*/ RepresentItem(object item) {
  39. int oldLevel = _level++;
  40. try {
  41. return Represent(item);
  42. } finally {
  43. _level = oldLevel;
  44. }
  45. }
  46. public Node/*!*/ Represent(object data) {
  47. Node node;
  48. bool ignoreAlias = HasIdentity(data);
  49. object dataKey = data ?? _NullKey;
  50. if (!ignoreAlias) {
  51. if (_representedObjects.TryGetValue(dataKey, out node)) {
  52. if (node == null) {
  53. LinkNode link = new LinkNode();
  54. List<LinkNode> list;
  55. if (!_links.TryGetValue(dataKey, out list)) {
  56. _links.Add(dataKey, list = new List<LinkNode>());
  57. }
  58. list.Add(link);
  59. return link;
  60. }
  61. return node;
  62. }
  63. _representedObjects.Add(dataKey, null);
  64. }
  65. node = CreateNode(data);
  66. if (!ignoreAlias) {
  67. _representedObjects[dataKey] = node;
  68. List<LinkNode> list;
  69. if (_links.TryGetValue(dataKey, out list)) {
  70. _links.Remove(dataKey);
  71. foreach (LinkNode n in list) {
  72. n.Linked = node;
  73. }
  74. }
  75. }
  76. return node;
  77. }
  78. public ScalarNode/*!*/ Scalar(string tag, string value, ScalarQuotingStyle style) {
  79. return new ScalarNode(tag, value, style);
  80. }
  81. public ScalarNode/*!*/ Scalar(bool value) {
  82. return Scalar(value ? Tags.True : Tags.False, value ? "true" : "false", ScalarQuotingStyle.None);
  83. }
  84. public SequenceNode/*!*/ Sequence(string tag, IList/*!*/ sequence, FlowStyle flowStyle) {
  85. List<Node> value = new List<Node>(sequence.Count);
  86. foreach (object x in sequence) {
  87. value.Add(RepresentItem(x));
  88. }
  89. return new SequenceNode(tag, value, flowStyle);
  90. }
  91. public MappingNode/*!*/ Map(string tag, IDictionary/*!*/ mapping, FlowStyle flowStyle) {
  92. return Map(new Dictionary<Node, Node>(mapping.Count), tag, mapping, flowStyle);
  93. }
  94. public MappingNode/*!*/ Map(Dictionary<Node, Node> value, string tag, IDictionary/*!*/ mapping, FlowStyle flowStyle) {
  95. foreach (DictionaryEntry entry in mapping) {
  96. value.Add(RepresentItem(entry.Key), RepresentItem(entry.Value));
  97. }
  98. return new MappingNode(tag, value, flowStyle);
  99. }
  100. protected virtual bool HasIdentity(object data) {
  101. return data == null || data is string || data is bool || data is int || data is float || data is double || data is decimal;
  102. }
  103. protected virtual Node CreateNode(object data) {
  104. return BaseCreateNode(data);
  105. }
  106. protected internal Node BaseCreateNode(object data) {
  107. if (data == null) {
  108. return Scalar(Tags.Null, null, ScalarQuotingStyle.None);
  109. }
  110. IDictionary map = data as IDictionary;
  111. if (map != null) {
  112. string taguri = map is Dictionary<object, object> ? Tags.Map : Tags.Map + ":" + map.GetType().Name;
  113. return Map(taguri, map, FlowStyle.Block);
  114. }
  115. byte[] bytes = data as byte[];
  116. if (bytes != null) {
  117. return Scalar(Tags.Binary, Convert.ToBase64String(bytes) + "\n", ScalarQuotingStyle.None);
  118. }
  119. IList seq = data as IList;
  120. if (seq != null) {
  121. string taguri = seq is List<object> ? Tags.Seq : Tags.Seq + ":" + seq.GetType().Name;
  122. return Sequence(taguri, seq, FlowStyle.Block);
  123. }
  124. ICollection set = data as ICollection;
  125. if (set != null) {
  126. Dictionary<object, object> entries = new Dictionary<object, object>(set.Count);
  127. foreach (object x in set) {
  128. entries.Add(x, null);
  129. }
  130. return Map("tag:yaml.org,2002:set", entries, FlowStyle.Block);
  131. }
  132. PrivateType pt = data as PrivateType;
  133. if (pt != null) {
  134. Node n = Represent(pt.Value);
  135. n.Tag = pt.Tag;
  136. return n;
  137. }
  138. string tag, value;
  139. switch (data.GetType().GetTypeCode()) {
  140. case TypeCode.Boolean:
  141. tag = "tag:yaml.org,2002:bool";
  142. value = data.ToString();
  143. break;
  144. case TypeCode.Byte:
  145. case TypeCode.SByte:
  146. case TypeCode.Int16:
  147. case TypeCode.UInt16:
  148. case TypeCode.Int32:
  149. case TypeCode.UInt32:
  150. case TypeCode.Int64:
  151. case TypeCode.UInt64:
  152. case TypeCode.Char:
  153. tag = Tags.Int;
  154. value = data.ToString();
  155. break;
  156. case TypeCode.Single:
  157. case TypeCode.Double:
  158. case TypeCode.Decimal:
  159. tag = Tags.Float;
  160. value = data.ToString();
  161. if (value == "Infinity") {
  162. value = ".inf";
  163. } else if (value == "-Infinity") {
  164. value = "-.inf";
  165. } else if (value == "NaN") {
  166. value = ".nan";
  167. }
  168. break;
  169. case TypeCode.String:
  170. tag = Tags.Str;
  171. value = data.ToString();
  172. break;
  173. case TypeCode.DateTime:
  174. DateTime date = (DateTime)data;
  175. string format = (date.Millisecond != 0) ? "yyyy-MM-dd HH:mm:ss.SSS Z" : "yyyy-MM-dd HH:mm:ss Z";
  176. value = date.ToString(format, CultureInfo.InvariantCulture);
  177. // TODO: what is this code for?
  178. if (value.Length >= 23) {
  179. value = value.Substring(0, 23) + ":" + value.Substring(23);
  180. }
  181. tag = Tags.Timestamp;
  182. break;
  183. default:
  184. return CreateNodeForObject(data);
  185. }
  186. return Scalar(tag, value, ScalarQuotingStyle.None);
  187. }
  188. // TODO: use some type of standard .NET serialization
  189. private Node CreateNodeForObject(object data) {
  190. Dictionary<object, object> values = new Dictionary<object, object>();
  191. foreach (PropertyInfo prop in data.GetType().GetInheritedProperties()) {
  192. MethodInfo getter = prop.GetGetMethod();
  193. if (getter != null && getter.GetParameters().Length == 0) {
  194. try {
  195. values.Add(prop.Name, prop.GetValue(data, null));
  196. } catch (Exception) {
  197. values.Add(prop.Name, null);
  198. }
  199. }
  200. }
  201. return Map("!cli/object:" + data.GetType().Name, values, FlowStyle.Block);
  202. }
  203. }
  204. }