#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Utilities;
using System.Globalization;
namespace Newtonsoft.Json.Linq
{
///
/// Represents a value in JSON (string, integer, date, etc).
///
public class JValue : JToken, IEquatable
{
private JTokenType _valueType;
private object _value;
internal JValue(object value, JTokenType type)
{
_value = value;
_valueType = type;
}
///
/// Initializes a new instance of the class from another object.
///
/// A object to copy from.
public JValue(JValue other)
: this(other.Value, other.Type)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(long value)
: this(value, JTokenType.Integer)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(ulong value)
: this(value, JTokenType.Integer)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(double value)
: this(value, JTokenType.Float)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(DateTime value)
: this(value, JTokenType.Date)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(bool value)
: this(value, JTokenType.Boolean)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(string value)
: this(value, JTokenType.String)
{
}
///
/// Initializes a new instance of the class with the given value.
///
/// The value.
public JValue(object value)
: this(value, GetValueType(null, value))
{
}
internal override bool DeepEquals(JToken node)
{
JValue other = node as JValue;
if (other == null)
return false;
return ValuesEquals(this, other);
}
///
/// Gets a value indicating whether this token has childen tokens.
///
///
/// true if this token has child values; otherwise, false.
///
public override bool HasValues
{
get { return false; }
}
private static bool Compare(JTokenType valueType, object objA, object objB)
{
if (objA == null && objB == null)
return true;
if (objA == null || objB == null)
return false;
switch (valueType)
{
case JTokenType.Integer:
if (objA is ulong || objB is ulong)
return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).Equals(Convert.ToDecimal(objB, CultureInfo.InvariantCulture));
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));
case JTokenType.Comment:
case JTokenType.String:
case JTokenType.Boolean:
case JTokenType.Raw:
return objA.Equals(objB);
case JTokenType.Date:
return objA.Equals(objB);
case JTokenType.Bytes:
byte[] b1 = objA as byte[];
byte[] b2 = objB as byte[];
if (b1 == null || b2 == null)
return false;
return MiscellaneousUtils.ByteArrayCompare(b1, b2);
default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("valueType", valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType));
}
}
internal override JToken CloneToken()
{
return new JValue(this);
}
///
/// Creates a comment with the given value.
///
/// The value.
/// A comment with the given value.
public static JValue CreateComment(string value)
{
return new JValue(value, JTokenType.Comment);
}
///
/// Creates a string with the given value.
///
/// The value.
/// A string with the given value.
public static JValue CreateString(string value)
{
return new JValue(value, JTokenType.String);
}
private static JTokenType GetValueType(JTokenType? current, object value)
{
if (value == null)
return JTokenType.Null;
else if (value == DBNull.Value)
return JTokenType.Null;
else if (value is string)
return GetStringValueType(current);
else if (value is long || value is int || value is short || value is sbyte
|| value is ulong || value is uint || value is ushort || value is byte)
return JTokenType.Integer;
else if (value is Enum)
return JTokenType.Integer;
else if (value is double || value is float || value is decimal)
return JTokenType.Float;
else if (value is DateTime)
return JTokenType.Date;
#if !PocketPC && !NET20
else if (value is DateTimeOffset)
return JTokenType.Date;
#endif
else if (value is byte[])
return JTokenType.Bytes;
else if (value is bool)
return JTokenType.Boolean;
throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
}
private static JTokenType GetStringValueType(JTokenType? current)
{
if (current == null)
return JTokenType.String;
switch (current.Value)
{
case JTokenType.Comment:
case JTokenType.String:
case JTokenType.Raw:
return current.Value;
default:
return JTokenType.String;
}
}
///
/// Gets the node type for this .
///
/// The type.
public override JTokenType Type
{
get { return _valueType; }
}
///
/// Gets or sets the underlying token value.
///
/// The underlying token value.
public object Value
{
get { return _value; }
set
{
Type currentType = (_value != null) ? _value.GetType() : null;
Type newType = (value != null) ? value.GetType() : null;
if (currentType != newType)
_valueType = GetValueType(_valueType, value);
_value = value;
}
}
private static void WriteConvertableValue(JsonWriter writer, IList converters, Action