diff options
author | JamesNK <james@newtonking.com> | 2010-12-28 00:25:06 +0300 |
---|---|---|
committer | JamesNK <james@newtonking.com> | 2010-12-28 00:25:06 +0300 |
commit | 3ad33f73299e6a8f05405d5b49a30ad1702a756a (patch) | |
tree | 9c5b4c80bbbe3c00e7ab94c829c8823ec1e1b4ed /Src | |
parent | f32e1f53c58a8023fb647531ccafdbacc11cf4e4 (diff) |
-Added ICloneable and DeepClone to JToken
-Changed DeepEquals to take into account possible floating point errors
Diffstat (limited to 'Src')
-rw-r--r-- | Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs | 76 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Linq/JToken.cs | 23 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Linq/JValue.cs | 8 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Utilities/MathUtils.cs | 6 |
4 files changed, 110 insertions, 3 deletions
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs index b33bd86..1114d28 100644 --- a/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs +++ b/Src/Newtonsoft.Json.Tests/Linq/JTokenTests.cs @@ -646,5 +646,81 @@ namespace Newtonsoft.Json.Tests.Linq Assert.AreEqual("secondlastpie", (string)a[5]);
Assert.AreEqual(7, a.Count());
}
+
+ [Test]
+ public void DeepClone()
+ {
+ JArray a =
+ new JArray(
+ 5,
+ new JArray(1),
+ new JArray(1, 2),
+ new JArray(1, 2, 3),
+ new JObject(
+ new JProperty("First", new JValue(Encoding.UTF8.GetBytes("Hi"))),
+ new JProperty("Second", 1),
+ new JProperty("Third", null),
+ new JProperty("Fourth", new JConstructor("Date", 12345)),
+ new JProperty("Fifth", double.PositiveInfinity),
+ new JProperty("Sixth", double.NaN)
+ )
+ );
+
+ JArray a2 = (JArray)a.DeepClone();
+
+ Console.WriteLine(a2.ToString(Formatting.Indented));
+
+ Assert.IsTrue(a.DeepEquals(a2));
+ }
+
+#if !SILVERLIGHT
+ [Test]
+ public void Clone()
+ {
+ JArray a =
+ new JArray(
+ 5,
+ new JArray(1),
+ new JArray(1, 2),
+ new JArray(1, 2, 3),
+ new JObject(
+ new JProperty("First", new JValue(Encoding.UTF8.GetBytes("Hi"))),
+ new JProperty("Second", 1),
+ new JProperty("Third", null),
+ new JProperty("Fourth", new JConstructor("Date", 12345)),
+ new JProperty("Fifth", double.PositiveInfinity),
+ new JProperty("Sixth", double.NaN)
+ )
+ );
+
+ ICloneable c = a;
+
+ JArray a2 = (JArray) c.Clone();
+
+ Assert.IsTrue(a.DeepEquals(a2));
+ }
+#endif
+
+ [Test]
+ public void DoubleDeepEquals()
+ {
+ JArray a =
+ new JArray(
+ double.NaN,
+ double.PositiveInfinity,
+ double.NegativeInfinity
+ );
+
+ JArray a2 = (JArray)a.DeepClone();
+
+ Assert.IsTrue(a.DeepEquals(a2));
+
+ double d = 1 + 0.1 + 0.1 + 0.1;
+
+ JValue v1 = new JValue(d);
+ JValue v2 = new JValue(1.3);
+
+ Assert.IsTrue(v1.DeepEquals(v2));
+ }
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index 3d32300..d48e969 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -43,10 +43,13 @@ namespace Newtonsoft.Json.Linq /// Represents an abstract JSON token.
/// </summary>
public abstract class JToken : IJEnumerable<JToken>, IJsonLineInfo
+#if !SILVERLIGHT
+, ICloneable
+#endif
#if !(NET35 || NET20 || SILVERLIGHT)
- , IDynamicMetaObjectProvider
+, IDynamicMetaObjectProvider
#endif
- {
+ {
private JContainer _parent;
internal JToken _next;
private static JTokenEqualityComparer _equalityComparer;
@@ -1298,5 +1301,21 @@ namespace Newtonsoft.Json.Linq return GetMetaObject(parameter);
}
#endif
+
+#if !SILVERLIGHT
+ object ICloneable.Clone()
+ {
+ return DeepClone();
+ }
+#endif
+
+ /// <summary>
+ /// Creates a new instance of the <see cref="JToken"/>. All child tokens are recursively cloned.
+ /// </summary>
+ /// <returns>A new instance of the <see cref="JToken"/>.</returns>
+ public JToken DeepClone()
+ {
+ return CloneToken();
+ }
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 68ec283..e8ad67d 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -159,7 +159,13 @@ namespace Newtonsoft.Json.Linq else
return Convert.ToInt64(objA, CultureInfo.InvariantCulture).Equals(Convert.ToInt64(objB, CultureInfo.InvariantCulture));
case JTokenType.Float:
- return Convert.ToDouble(objA, CultureInfo.InvariantCulture).Equals(Convert.ToDouble(objB, CultureInfo.InvariantCulture));
+ double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture);
+ double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture);
+ if (d1.Equals(d2))
+ return true;
+
+ // take into account possible floating point errors
+ return MathUtils.ApproxEquals(d1, d2);
case JTokenType.Comment:
case JTokenType.String:
case JTokenType.Boolean:
diff --git a/Src/Newtonsoft.Json/Utilities/MathUtils.cs b/Src/Newtonsoft.Json/Utilities/MathUtils.cs index db489eb..e60ed05 100644 --- a/Src/Newtonsoft.Json/Utilities/MathUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/MathUtils.cs @@ -124,5 +124,11 @@ namespace Newtonsoft.Json.Utilities return Math.Max(val1.Value, val2.Value);
}
+
+ public static bool ApproxEquals(double d1, double d2)
+ {
+ // are values equal to within 12 (or so) digits of precision?
+ return Math.Abs(d1 - d2) < (Math.Abs(d1) * 1e-12);
+ }
}
}
\ No newline at end of file |