PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/External.LCA_RESTRICTED/Languages/IronRuby/yaml/IronRuby.Libraries.Yaml/Engine/Representer.cs

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