You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
8.8 KiB

  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.Collections;
  27. using System.Collections.Generic;
  28. using Newtonsoft.Json.Utilities;
  29. using System.Globalization;
  30. namespace Newtonsoft.Json.Linq
  31. {
  32. /// <summary>
  33. /// Represents a JSON constructor.
  34. /// </summary>
  35. internal partial class JConstructor : JContainer
  36. {
  37. private string _name;
  38. private readonly List<JToken> _values = new List<JToken>();
  39. /// <summary>
  40. /// Gets the container's children tokens.
  41. /// </summary>
  42. /// <value>The container's children tokens.</value>
  43. protected override IList<JToken> ChildrenTokens => _values;
  44. internal override int IndexOfItem(JToken item)
  45. {
  46. return _values.IndexOfReference(item);
  47. }
  48. internal override void MergeItem(object content, JsonMergeSettings settings)
  49. {
  50. if (!(content is JConstructor c))
  51. {
  52. return;
  53. }
  54. if (c.Name != null)
  55. {
  56. Name = c.Name;
  57. }
  58. MergeEnumerableContent(this, c, settings);
  59. }
  60. /// <summary>
  61. /// Gets or sets the name of this constructor.
  62. /// </summary>
  63. /// <value>The constructor name.</value>
  64. public string Name
  65. {
  66. get => _name;
  67. set => _name = value;
  68. }
  69. /// <summary>
  70. /// Gets the node type for this <see cref="JToken"/>.
  71. /// </summary>
  72. /// <value>The type.</value>
  73. public override JTokenType Type => JTokenType.Constructor;
  74. /// <summary>
  75. /// Initializes a new instance of the <see cref="JConstructor"/> class.
  76. /// </summary>
  77. public JConstructor()
  78. {
  79. }
  80. /// <summary>
  81. /// Initializes a new instance of the <see cref="JConstructor"/> class from another <see cref="JConstructor"/> object.
  82. /// </summary>
  83. /// <param name="other">A <see cref="JConstructor"/> object to copy from.</param>
  84. public JConstructor(JConstructor other)
  85. : base(other)
  86. {
  87. _name = other.Name;
  88. }
  89. /// <summary>
  90. /// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name and content.
  91. /// </summary>
  92. /// <param name="name">The constructor name.</param>
  93. /// <param name="content">The contents of the constructor.</param>
  94. public JConstructor(string name, params object[] content)
  95. : this(name, (object)content)
  96. {
  97. }
  98. /// <summary>
  99. /// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name and content.
  100. /// </summary>
  101. /// <param name="name">The constructor name.</param>
  102. /// <param name="content">The contents of the constructor.</param>
  103. public JConstructor(string name, object content)
  104. : this(name)
  105. {
  106. Add(content);
  107. }
  108. /// <summary>
  109. /// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name.
  110. /// </summary>
  111. /// <param name="name">The constructor name.</param>
  112. public JConstructor(string name)
  113. {
  114. if (name == null)
  115. {
  116. throw new ArgumentNullException(nameof(name));
  117. }
  118. if (name.Length == 0)
  119. {
  120. throw new ArgumentException("Constructor name cannot be empty.", nameof(name));
  121. }
  122. _name = name;
  123. }
  124. internal override bool DeepEquals(JToken node)
  125. {
  126. return (node is JConstructor c && _name == c.Name && ContentsEqual(c));
  127. }
  128. internal override JToken CloneToken()
  129. {
  130. return new JConstructor(this);
  131. }
  132. /// <summary>
  133. /// Writes this token to a <see cref="JsonWriter"/>.
  134. /// </summary>
  135. /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
  136. /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
  137. public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
  138. {
  139. writer.WriteStartConstructor(_name);
  140. int count = _values.Count;
  141. for (int i = 0; i < count; i++)
  142. {
  143. _values[i].WriteTo(writer, converters);
  144. }
  145. writer.WriteEndConstructor();
  146. }
  147. /// <summary>
  148. /// Gets the <see cref="JToken"/> with the specified key.
  149. /// </summary>
  150. /// <value>The <see cref="JToken"/> with the specified key.</value>
  151. public override JToken this[object key]
  152. {
  153. get
  154. {
  155. ValidationUtils.ArgumentNotNull(key, nameof(key));
  156. if (!(key is int))
  157. {
  158. throw new ArgumentException("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
  159. }
  160. return GetItem((int)key);
  161. }
  162. set
  163. {
  164. ValidationUtils.ArgumentNotNull(key, nameof(key));
  165. if (!(key is int))
  166. {
  167. throw new ArgumentException("Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
  168. }
  169. SetItem((int)key, value);
  170. }
  171. }
  172. internal override int GetDeepHashCode()
  173. {
  174. return _name.GetHashCode() ^ ContentsHashCode();
  175. }
  176. /// <summary>
  177. /// Loads a <see cref="JConstructor"/> from a <see cref="JsonReader"/>.
  178. /// </summary>
  179. /// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JConstructor"/>.</param>
  180. /// <returns>A <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
  181. public new static JConstructor Load(JsonReader reader)
  182. {
  183. return Load(reader, null);
  184. }
  185. /// <summary>
  186. /// Loads a <see cref="JConstructor"/> from a <see cref="JsonReader"/>.
  187. /// </summary>
  188. /// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JConstructor"/>.</param>
  189. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
  190. /// If this is <c>null</c>, default load settings will be used.</param>
  191. /// <returns>A <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
  192. public new static JConstructor Load(JsonReader reader, JsonLoadSettings settings)
  193. {
  194. if (reader.TokenType == JsonToken.None)
  195. {
  196. if (!reader.Read())
  197. {
  198. throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader.");
  199. }
  200. }
  201. reader.MoveToContent();
  202. if (reader.TokenType != JsonToken.StartConstructor)
  203. {
  204. throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
  205. }
  206. JConstructor c = new JConstructor((string)reader.Value);
  207. c.SetLineInfo(reader as IJsonLineInfo, settings);
  208. c.ReadTokenFrom(reader, settings);
  209. return c;
  210. }
  211. }
  212. }