diff options
author | JamesNK <james@newtonking.com> | 2011-01-17 10:19:20 +0300 |
---|---|---|
committer | JamesNK <james@newtonking.com> | 2011-01-17 10:19:20 +0300 |
commit | 868d6d394840d54ea5c61c94ffb1fc50b248d427 (patch) | |
tree | 0e10eb01662ac450ec100915c9ab723d1e6479e3 /Src/Newtonsoft.Json | |
parent | 35351737167c27eca08de2e0114edb641e33930c (diff) |
-Added Equals, NotEquals, GreaterThan, GreaterThanEquals, LesserThan, LesserThanEquals support to dynamic JValue
-Added IComparable to JValue
Diffstat (limited to 'Src/Newtonsoft.Json')
-rw-r--r-- | Src/Newtonsoft.Json/Linq/JValue.cs | 152 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Utilities/MathUtils.cs | 4 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs | 14 |
3 files changed, 119 insertions, 51 deletions
diff --git a/Src/Newtonsoft.Json/Linq/JValue.cs b/Src/Newtonsoft.Json/Linq/JValue.cs index 8bbb321..7da7678 100644 --- a/Src/Newtonsoft.Json/Linq/JValue.cs +++ b/Src/Newtonsoft.Json/Linq/JValue.cs @@ -40,7 +40,7 @@ namespace Newtonsoft.Json.Linq /// <summary>
/// Represents a value in JSON (string, integer, date, etc).
/// </summary>
- public class JValue : JToken, IEquatable<JValue>, IFormattable
+ public class JValue : JToken, IEquatable<JValue>, IFormattable, IComparable, IComparable<JValue>
{
private JTokenType _valueType;
private object _value;
@@ -144,47 +144,85 @@ namespace Newtonsoft.Json.Linq get { return false; }
}
- private static bool Compare(JTokenType valueType, object objA, object objB)
+ private static int Compare(JTokenType valueType, object objA, object objB)
{
if (objA == null && objB == null)
- return true;
- if (objA == null || objB == null)
- return false;
+ return 0;
+ if (objA != null && objB == null)
+ return 1;
+ if (objA == null && objB != null)
+ return -1;
switch (valueType)
{
case JTokenType.Integer:
- if (objA is ulong || objB is ulong)
- return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).Equals(Convert.ToDecimal(objB, CultureInfo.InvariantCulture));
+ if (objA is ulong || objB is ulong || objA is decimal || objB is decimal)
+ return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture));
+ else if (objA is float || objB is float || objA is double || objB is double)
+ return CompareFloat(objA, objB);
else
- return Convert.ToInt64(objA, CultureInfo.InvariantCulture).Equals(Convert.ToInt64(objB, CultureInfo.InvariantCulture));
+ return Convert.ToInt64(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToInt64(objB, CultureInfo.InvariantCulture));
case JTokenType.Float:
- 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);
+ return CompareFloat(objA, objB);
case JTokenType.Comment:
case JTokenType.String:
- case JTokenType.Boolean:
case JTokenType.Raw:
- return objA.Equals(objB);
+ string s1 = Convert.ToString(objA);
+ string s2 = Convert.ToString(objB);
+
+ return s1.CompareTo(s2);
+ case JTokenType.Boolean:
+ bool b1 = Convert.ToBoolean(objA);
+ bool b2 = Convert.ToBoolean(objB);
+
+ return b1.CompareTo(b2);
case JTokenType.Date:
- return objA.Equals(objB);
+ if (objA is DateTime)
+ {
+ DateTime date1 = Convert.ToDateTime(objA);
+ DateTime date2 = Convert.ToDateTime(objB);
+
+ return date1.CompareTo(date2);
+ }
+ else
+ {
+ if (!(objB is DateTimeOffset))
+ throw new ArgumentException("Object must be of type DateTimeOffset.");
+
+ DateTimeOffset date1 = (DateTimeOffset)objA;
+ DateTimeOffset date2 = (DateTimeOffset)objB;
+
+ return date1.CompareTo(date2);
+ }
case JTokenType.Bytes:
- byte[] b1 = objA as byte[];
- byte[] b2 = objB as byte[];
- if (b1 == null || b2 == null)
- return false;
+ if (!(objB is byte[]))
+ throw new ArgumentException("Object must be of type byte[].");
+
+ byte[] bytes1 = objA as byte[];
+ byte[] bytes2 = objB as byte[];
+ if (bytes1 == null)
+ return -1;
+ if (bytes2 == null)
+ return 1;
- return MiscellaneousUtils.ByteArrayCompare(b1, b2);
+ return MiscellaneousUtils.ByteArrayCompare(bytes1, bytes2);
default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("valueType", valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType));
}
}
+ private static int CompareFloat(object objA, object objB)
+ {
+ double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture);
+ double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture);
+
+ // take into account possible floating point errors
+ if (MathUtils.ApproxEquals(d1, d2))
+ return 0;
+
+ return d1.CompareTo(d2);
+ }
+
internal override JToken CloneToken()
{
return new JValue(this);
@@ -352,7 +390,7 @@ namespace Newtonsoft.Json.Linq private static bool ValuesEquals(JValue v1, JValue v2)
{
- return (v1 == v2 || (v1._valueType == v2._valueType && Compare(v1._valueType, v1._value, v2._value)));
+ return (v1 == v2 || (v1._valueType == v2._valueType && Compare(v1._valueType, v1._value, v2._value) == 0));
}
/// <summary>
@@ -475,26 +513,54 @@ namespace Newtonsoft.Json.Linq return true;
}
- //public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result)
- //{
- // dynamic d1 = arg;
- // dynamic d2 = instance._value;
- // //// use built in JValue equals
- // //if (arg is JValue)
- // //{
- // // result = null;
- // // return false;
- // //}
-
- // //if (binder.Operation == ExpressionType.Equal)
- // //{
- // // result = Compare(instance.Type, instance.Value, arg);
- // // return true;
- // //}
-
- // //return base.TryBinaryOperation(instance, binder, arg, out result);
- //}
+ public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result)
+ {
+ object compareValue = (arg is JValue) ? ((JValue) arg).Value : arg;
+
+ switch (binder.Operation)
+ {
+ case ExpressionType.Equal:
+ result = (Compare(instance.Type, instance.Value, compareValue) == 0);
+ return true;
+ case ExpressionType.NotEqual:
+ result = (Compare(instance.Type, instance.Value, compareValue) != 0);
+ return true;
+ case ExpressionType.GreaterThan:
+ result = (Compare(instance.Type, instance.Value, compareValue) > 0);
+ return true;
+ case ExpressionType.GreaterThanOrEqual:
+ result = (Compare(instance.Type, instance.Value, compareValue) >= 0);
+ return true;
+ case ExpressionType.LessThan:
+ result = (Compare(instance.Type, instance.Value, compareValue) < 0);
+ return true;
+ case ExpressionType.LessThanOrEqual:
+ result = (Compare(instance.Type, instance.Value, compareValue) <= 0);
+ return true;
+ }
+
+ result = null;
+ return false;
+ }
}
#endif
+
+ int IComparable.CompareTo(object obj)
+ {
+ if (obj == null)
+ return 1;
+
+ object otherValue = (obj is JValue) ? ((JValue) obj).Value : obj;
+
+ return Compare(_valueType, _value, otherValue);
+ }
+
+ public int CompareTo(JValue other)
+ {
+ if (other == null)
+ return 1;
+
+ return Compare(_valueType, _value, other._value);
+ }
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/MathUtils.cs b/Src/Newtonsoft.Json/Utilities/MathUtils.cs index e60ed05..1059686 100644 --- a/Src/Newtonsoft.Json/Utilities/MathUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/MathUtils.cs @@ -127,8 +127,8 @@ namespace Newtonsoft.Json.Utilities 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);
+ // are values equal to within 6 (or so) digits of precision?
+ return Math.Abs(d1 - d2) < (Math.Abs(d1) * 1e-6);
}
}
}
\ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs b/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs index b6665c9..f0fa2dd 100644 --- a/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs @@ -85,18 +85,20 @@ namespace Newtonsoft.Json.Utilities return hex;
}
- public static bool ByteArrayCompare(byte[] a1, byte[] a2)
+ public static int ByteArrayCompare(byte[] a1, byte[] a2)
{
- if (a1.Length != a2.Length)
- return false;
+ int lengthCompare = a1.Length.CompareTo(a2.Length);
+ if (lengthCompare != 0)
+ return lengthCompare;
for (int i = 0; i < a1.Length; i++)
{
- if (a1[i] != a2[i])
- return false;
+ int valueCompare = a1[i].CompareTo(a2[i]);
+ if (valueCompare != 0)
+ return valueCompare;
}
- return true;
+ return 0;
}
public static string GetPrefix(string qualifiedName)
|