implement box avoidance (#2639)
Co-authored-by: Marc Gravell <marcgravell@microsoft.com> Co-authored-by: James Newton-King <james@newtonking.com>
This commit is contained in:
co-authored by
Marc Gravell
James Newton-King
parent
197c6db94a
commit
13717cfc45
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if (NET45 || NET50)
|
||||
#if (NET45 || NET5_0_OR_GREATER)
|
||||
#if DNXCORE50
|
||||
using Xunit;
|
||||
using Test = Xunit.FactAttribute;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if (NET45 || NET50)
|
||||
#if (NET45 || NET5_0_OR_GREATER)
|
||||
#if DNXCORE50
|
||||
using Xunit;
|
||||
using Test = Xunit.FactAttribute;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if (NET45 || NET50)
|
||||
#if (NET45 || NET5_0_OR_GREATER)
|
||||
#if DNXCORE50
|
||||
using Xunit;
|
||||
using Test = Xunit.FactAttribute;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if (NET45 || NET50)
|
||||
#if (NET45 || NET5_0_OR_GREATER)
|
||||
#if DNXCORE50
|
||||
using Xunit;
|
||||
using Test = Xunit.FactAttribute;
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
#region License
|
||||
// Copyright (c) 2022 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 Newtonsoft.Json.Linq;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Tests.Documentation.Samples.Linq;
|
||||
|
||||
#if DNXCORE50
|
||||
using Xunit;
|
||||
using Test = Xunit.FactAttribute;
|
||||
using Assert = Newtonsoft.Json.Tests.XUnitAssert;
|
||||
#else
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Tests.Issues
|
||||
{
|
||||
[TestFixture]
|
||||
public class Issue2638
|
||||
{
|
||||
[Test]
|
||||
public void DeserilizeUsesSharedBooleans()
|
||||
{
|
||||
Test(true);
|
||||
Test(false);
|
||||
|
||||
static void Test(bool value)
|
||||
{
|
||||
var obj = (JObject)JToken.Parse(@"{""x"": XXX, ""y"": XXX}".Replace("XXX", value ? "true" : "false"));
|
||||
var x = ((JValue)obj["x"]).Value;
|
||||
var y = ((JValue)obj["y"]).Value;
|
||||
|
||||
Assert.AreEqual(value, (bool)x);
|
||||
Assert.AreEqual(value, (bool)y);
|
||||
Assert.AreSame(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserilizeUsesSharedDoubleZeros()
|
||||
{
|
||||
Test(0, true);
|
||||
Test(double.NaN, true);
|
||||
Test(double.NegativeInfinity, true);
|
||||
Test(double.PositiveInfinity, true);
|
||||
Test(1, false);
|
||||
Test(42.42, false);
|
||||
|
||||
static void Test(double value, bool expectSame)
|
||||
{
|
||||
var obj = (JObject)JToken.Parse(@"{""x"": XXX, ""y"": XXX}".Replace("XXX", value.ToString("0.0###", CultureInfo.InvariantCulture)));
|
||||
var x = ((JValue)obj["x"]).Value;
|
||||
var y = ((JValue)obj["y"]).Value;
|
||||
|
||||
Assert.AreEqual(value, (double)x);
|
||||
Assert.AreEqual(value, (double)y);
|
||||
if (expectSame)
|
||||
{
|
||||
Assert.AreSame(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreNotSame(x, y);
|
||||
}
|
||||
var unboxed = (double)x;
|
||||
Assert.AreEqual(double.IsNaN(value), double.IsNaN(unboxed));
|
||||
Assert.AreEqual(double.IsPositiveInfinity(value), double.IsPositiveInfinity(unboxed));
|
||||
Assert.AreEqual(double.IsNegativeInfinity(value), double.IsNegativeInfinity(unboxed));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserilizeUsesSharedSmallInt64()
|
||||
{
|
||||
Test(-2, false);
|
||||
Test(-1, true);
|
||||
Test(0, true);
|
||||
Test(1, true);
|
||||
Test(2, true);
|
||||
Test(3, true);
|
||||
Test(4, true);
|
||||
Test(5, true);
|
||||
Test(6, true);
|
||||
Test(7, true);
|
||||
Test(8, true);
|
||||
Test(9, false);
|
||||
|
||||
static void Test(long value, bool expectSame)
|
||||
{
|
||||
var obj = (JObject)JToken.Parse(@"{""x"": XXX, ""y"": XXX}".Replace("XXX", value.ToString(CultureInfo.InvariantCulture)));
|
||||
var x = ((JValue)obj["x"]).Value;
|
||||
var y = ((JValue)obj["y"]).Value;
|
||||
|
||||
Assert.AreEqual(value, (long)x);
|
||||
Assert.AreEqual(value, (long)y);
|
||||
if (expectSame)
|
||||
{
|
||||
Assert.AreSame(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreNotSame(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
<RootNamespace>Newtonsoft.Json.Tests</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
<!-- Workaround for https://github.com/nunit/nunit3-vs-adapter/issues/296 -->
|
||||
<DebugType Condition="'$(TargetFramework)' != '' AND '$(TargetFramework)' != 'netcoreapp2.1' AND '$(TargetFramework)' != 'netcoreapp3.1' AND '$(TargetFramework)' != 'net5.0'">Full</DebugType>
|
||||
<DebugType Condition="'$(TargetFramework)' != '' AND '$(TargetFramework)' != 'netcoreapp2.1' AND '$(TargetFramework)' != 'netcoreapp3.1' AND '$(TargetFramework)' != 'net6.0'">Full</DebugType>
|
||||
<!-- Disabled because SourceLink isn't referenced to calculate paths -->
|
||||
<DeterministicSourcePaths>false</DeterministicSourcePaths>
|
||||
<!-- It's ok if a test target has exited support. Disable NETSSDK1138 warning -->
|
||||
|
||||
@@ -841,7 +841,7 @@ namespace Newtonsoft.Json
|
||||
{
|
||||
throw CreateUnexpectedCharacterException(_chars[_charPos]);
|
||||
}
|
||||
SetToken(JsonToken.Boolean, isTrue);
|
||||
SetToken(JsonToken.Boolean, BoxedPrimitives.Get(isTrue));
|
||||
return isTrue;
|
||||
case '/':
|
||||
ParseComment(false);
|
||||
@@ -2030,7 +2030,7 @@ namespace Newtonsoft.Json
|
||||
if (singleDigit)
|
||||
{
|
||||
// digit char values start at 48
|
||||
numberValue = firstChar - 48;
|
||||
numberValue = BoxedPrimitives.Get(firstChar - 48);
|
||||
}
|
||||
else if (nonBase10)
|
||||
{
|
||||
@@ -2040,7 +2040,7 @@ namespace Newtonsoft.Json
|
||||
{
|
||||
int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(number, 16) : Convert.ToInt32(number, 8);
|
||||
|
||||
numberValue = integer;
|
||||
numberValue = BoxedPrimitives.Get(integer);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -2052,7 +2052,7 @@ namespace Newtonsoft.Json
|
||||
ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out int value);
|
||||
if (parseResult == ParseResult.Success)
|
||||
{
|
||||
numberValue = value;
|
||||
numberValue = BoxedPrimitives.Get(value);
|
||||
}
|
||||
else if (parseResult == ParseResult.Overflow)
|
||||
{
|
||||
@@ -2072,7 +2072,7 @@ namespace Newtonsoft.Json
|
||||
if (singleDigit)
|
||||
{
|
||||
// digit char values start at 48
|
||||
numberValue = (decimal)firstChar - 48;
|
||||
numberValue = BoxedPrimitives.Get((decimal)firstChar - 48);
|
||||
}
|
||||
else if (nonBase10)
|
||||
{
|
||||
@@ -2083,7 +2083,7 @@ namespace Newtonsoft.Json
|
||||
// decimal.Parse doesn't support parsing hexadecimal values
|
||||
long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8);
|
||||
|
||||
numberValue = Convert.ToDecimal(integer);
|
||||
numberValue = BoxedPrimitives.Get(Convert.ToDecimal(integer));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -2095,7 +2095,7 @@ namespace Newtonsoft.Json
|
||||
ParseResult parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out decimal value);
|
||||
if (parseResult == ParseResult.Success)
|
||||
{
|
||||
numberValue = value;
|
||||
numberValue = BoxedPrimitives.Get(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2111,7 +2111,7 @@ namespace Newtonsoft.Json
|
||||
if (singleDigit)
|
||||
{
|
||||
// digit char values start at 48
|
||||
numberValue = (double)firstChar - 48;
|
||||
numberValue = BoxedPrimitives.Get((double)firstChar - 48);
|
||||
}
|
||||
else if (nonBase10)
|
||||
{
|
||||
@@ -2122,7 +2122,7 @@ namespace Newtonsoft.Json
|
||||
// double.Parse doesn't support parsing hexadecimal values
|
||||
long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8);
|
||||
|
||||
numberValue = Convert.ToDouble(integer);
|
||||
numberValue = BoxedPrimitives.Get(Convert.ToDouble(integer));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -2135,7 +2135,7 @@ namespace Newtonsoft.Json
|
||||
|
||||
if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double value))
|
||||
{
|
||||
numberValue = value;
|
||||
numberValue = BoxedPrimitives.Get(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2152,7 +2152,7 @@ namespace Newtonsoft.Json
|
||||
if (singleDigit)
|
||||
{
|
||||
// digit char values start at 48
|
||||
numberValue = (long)firstChar - 48;
|
||||
numberValue = BoxedPrimitives.Get((long)firstChar - 48);
|
||||
numberType = JsonToken.Integer;
|
||||
}
|
||||
else if (nonBase10)
|
||||
@@ -2161,7 +2161,7 @@ namespace Newtonsoft.Json
|
||||
|
||||
try
|
||||
{
|
||||
numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8);
|
||||
numberValue = BoxedPrimitives.Get(number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -2175,7 +2175,7 @@ namespace Newtonsoft.Json
|
||||
ParseResult parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out long value);
|
||||
if (parseResult == ParseResult.Success)
|
||||
{
|
||||
numberValue = value;
|
||||
numberValue = BoxedPrimitives.Get(value);
|
||||
numberType = JsonToken.Integer;
|
||||
}
|
||||
else if (parseResult == ParseResult.Overflow)
|
||||
@@ -2201,7 +2201,7 @@ namespace Newtonsoft.Json
|
||||
parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out decimal d);
|
||||
if (parseResult == ParseResult.Success)
|
||||
{
|
||||
numberValue = d;
|
||||
numberValue = BoxedPrimitives.Get(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2214,7 +2214,7 @@ namespace Newtonsoft.Json
|
||||
|
||||
if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double d))
|
||||
{
|
||||
numberValue = d;
|
||||
numberValue = BoxedPrimitives.Get(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2455,7 +2455,7 @@ namespace Newtonsoft.Json
|
||||
// or the text ends
|
||||
if (MatchValueWithTrailingSeparator(JsonConvert.True))
|
||||
{
|
||||
SetToken(JsonToken.Boolean, true);
|
||||
SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanTrue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2491,7 +2491,7 @@ namespace Newtonsoft.Json
|
||||
{
|
||||
if (MatchValueWithTrailingSeparator(JsonConvert.False))
|
||||
{
|
||||
SetToken(JsonToken.Boolean, false);
|
||||
SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanFalse);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2514,7 +2514,7 @@ namespace Newtonsoft.Json
|
||||
case ReadType.ReadAsDouble:
|
||||
if (_floatParseHandling == FloatParseHandling.Double)
|
||||
{
|
||||
SetToken(JsonToken.Float, double.NegativeInfinity);
|
||||
SetToken(JsonToken.Float, BoxedPrimitives.DoubleNegativeInfinity);
|
||||
return double.NegativeInfinity;
|
||||
}
|
||||
break;
|
||||
@@ -2543,7 +2543,7 @@ namespace Newtonsoft.Json
|
||||
case ReadType.ReadAsDouble:
|
||||
if (_floatParseHandling == FloatParseHandling.Double)
|
||||
{
|
||||
SetToken(JsonToken.Float, double.PositiveInfinity);
|
||||
SetToken(JsonToken.Float, BoxedPrimitives.DoublePositiveInfinity);
|
||||
return double.PositiveInfinity;
|
||||
}
|
||||
break;
|
||||
@@ -2573,7 +2573,7 @@ namespace Newtonsoft.Json
|
||||
case ReadType.ReadAsDouble:
|
||||
if (_floatParseHandling == FloatParseHandling.Double)
|
||||
{
|
||||
SetToken(JsonToken.Float, double.NaN);
|
||||
SetToken(JsonToken.Float, BoxedPrimitives.DoubleNaN);
|
||||
return double.NaN;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -187,12 +187,12 @@ namespace Newtonsoft.Json.Linq
|
||||
base.WritePropertyName(name);
|
||||
}
|
||||
|
||||
private void AddValue(object? value, JsonToken token)
|
||||
private void AddRawValue(object? value, JTokenType type, JsonToken token)
|
||||
{
|
||||
AddValue(new JValue(value), token);
|
||||
AddJValue(new JValue(value, type), token);
|
||||
}
|
||||
|
||||
internal void AddValue(JValue? value, JsonToken token)
|
||||
internal void AddJValue(JValue? value, JsonToken token)
|
||||
{
|
||||
if (_parent != null)
|
||||
{
|
||||
@@ -228,7 +228,7 @@ namespace Newtonsoft.Json.Linq
|
||||
if (value is BigInteger)
|
||||
{
|
||||
InternalWriteValue(JsonToken.Integer);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -243,7 +243,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteNull()
|
||||
{
|
||||
base.WriteNull();
|
||||
AddValue(null, JsonToken.Null);
|
||||
AddJValue(JValue.CreateNull(), JsonToken.Null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -252,7 +252,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteUndefined()
|
||||
{
|
||||
base.WriteUndefined();
|
||||
AddValue(null, JsonToken.Undefined);
|
||||
AddJValue(JValue.CreateUndefined(), JsonToken.Undefined);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -262,7 +262,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteRaw(string? json)
|
||||
{
|
||||
base.WriteRaw(json);
|
||||
AddValue(new JRaw(json), JsonToken.Raw);
|
||||
AddJValue(new JRaw(json), JsonToken.Raw);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -272,7 +272,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteComment(string? text)
|
||||
{
|
||||
base.WriteComment(text);
|
||||
AddValue(JValue.CreateComment(text), JsonToken.Comment);
|
||||
AddJValue(JValue.CreateComment(text), JsonToken.Comment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -282,7 +282,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(string? value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.String);
|
||||
AddJValue(new JValue(value), JsonToken.String);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -292,7 +292,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(int value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -303,7 +303,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(uint value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -313,7 +313,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(long value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddJValue(new JValue(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -324,7 +324,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(ulong value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddJValue(new JValue(value), JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -334,7 +334,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(float value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Float);
|
||||
AddJValue(new JValue(value), JsonToken.Float);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -344,7 +344,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(double value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Float);
|
||||
AddJValue(new JValue(value), JsonToken.Float);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -354,7 +354,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(bool value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Boolean);
|
||||
AddJValue(new JValue(value), JsonToken.Boolean);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -364,7 +364,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(short value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -375,7 +375,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(ushort value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -391,7 +391,7 @@ namespace Newtonsoft.Json.Linq
|
||||
#else
|
||||
s = value.ToString();
|
||||
#endif
|
||||
AddValue(s, JsonToken.String);
|
||||
AddJValue(new JValue(s), JsonToken.String);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -401,7 +401,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(byte value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -412,7 +412,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(sbyte value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Integer);
|
||||
AddRawValue(value, JTokenType.Integer, JsonToken.Integer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -422,7 +422,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(decimal value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Float);
|
||||
AddJValue(new JValue(value), JsonToken.Float);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -433,7 +433,7 @@ namespace Newtonsoft.Json.Linq
|
||||
{
|
||||
base.WriteValue(value);
|
||||
value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
|
||||
AddValue(value, JsonToken.Date);
|
||||
AddJValue(new JValue(value), JsonToken.Date);
|
||||
}
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
@@ -444,7 +444,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(DateTimeOffset value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Date);
|
||||
AddJValue(new JValue(value), JsonToken.Date);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -455,7 +455,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(byte[]? value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.Bytes);
|
||||
AddJValue(new JValue(value, JTokenType.Bytes), JsonToken.Bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -465,7 +465,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(TimeSpan value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.String);
|
||||
AddJValue(new JValue(value), JsonToken.String);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -475,7 +475,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(Guid value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.String);
|
||||
AddJValue(new JValue(value), JsonToken.String);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -485,7 +485,7 @@ namespace Newtonsoft.Json.Linq
|
||||
public override void WriteValue(Uri? value)
|
||||
{
|
||||
base.WriteValue(value);
|
||||
AddValue(value, JsonToken.String);
|
||||
AddJValue(new JValue(value), JsonToken.String);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Newtonsoft.Json.Linq
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public JValue(long value)
|
||||
: this(value, JTokenType.Integer)
|
||||
: this(BoxedPrimitives.Get(value), JTokenType.Integer)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Newtonsoft.Json.Linq
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public JValue(decimal value)
|
||||
: this(value, JTokenType.Float)
|
||||
: this(BoxedPrimitives.Get(value), JTokenType.Float)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Newtonsoft.Json.Linq
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public JValue(double value)
|
||||
: this(value, JTokenType.Float)
|
||||
: this(BoxedPrimitives.Get(value), JTokenType.Float)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace Newtonsoft.Json.Linq
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
public JValue(bool value)
|
||||
: this(value, JTokenType.Boolean)
|
||||
: this(BoxedPrimitives.Get(value), JTokenType.Boolean)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#region License
|
||||
// Copyright (c) 2022 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
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class BoxedPrimitives
|
||||
{
|
||||
internal static object Get(bool value) => value ? BooleanTrue : BooleanFalse;
|
||||
|
||||
internal static readonly object BooleanTrue = true;
|
||||
internal static readonly object BooleanFalse = false;
|
||||
|
||||
internal static object Get(int value) => value switch
|
||||
{
|
||||
-1 => Int32_M1,
|
||||
0 => Int32_0,
|
||||
1 => Int32_1,
|
||||
2 => Int32_2,
|
||||
3 => Int32_3,
|
||||
4 => Int32_4,
|
||||
5 => Int32_5,
|
||||
6 => Int32_6,
|
||||
7 => Int32_7,
|
||||
8 => Int32_8,
|
||||
_ => value,
|
||||
};
|
||||
|
||||
// integers tend to be weighted towards a handful of low numbers; we could argue
|
||||
// for days over the "correct" range to have special handling, but I'm arbitrarily
|
||||
// mirroring the same decision as the IL opcodes, which has M1 thru 8
|
||||
internal static readonly object Int32_M1 = -1;
|
||||
internal static readonly object Int32_0 = 0;
|
||||
internal static readonly object Int32_1 = 1;
|
||||
internal static readonly object Int32_2 = 2;
|
||||
internal static readonly object Int32_3 = 3;
|
||||
internal static readonly object Int32_4 = 4;
|
||||
internal static readonly object Int32_5 = 5;
|
||||
internal static readonly object Int32_6 = 6;
|
||||
internal static readonly object Int32_7 = 7;
|
||||
internal static readonly object Int32_8 = 8;
|
||||
|
||||
internal static object Get(long value) => value switch
|
||||
{
|
||||
-1 => Int64_M1,
|
||||
0 => Int64_0,
|
||||
1 => Int64_1,
|
||||
2 => Int64_2,
|
||||
3 => Int64_3,
|
||||
4 => Int64_4,
|
||||
5 => Int64_5,
|
||||
6 => Int64_6,
|
||||
7 => Int64_7,
|
||||
8 => Int64_8,
|
||||
_ => value,
|
||||
};
|
||||
|
||||
internal static readonly object Int64_M1 = -1L;
|
||||
internal static readonly object Int64_0 = 0L;
|
||||
internal static readonly object Int64_1 = 1L;
|
||||
internal static readonly object Int64_2 = 2L;
|
||||
internal static readonly object Int64_3 = 3L;
|
||||
internal static readonly object Int64_4 = 4L;
|
||||
internal static readonly object Int64_5 = 5L;
|
||||
internal static readonly object Int64_6 = 6L;
|
||||
internal static readonly object Int64_7 = 7L;
|
||||
internal static readonly object Int64_8 = 8L;
|
||||
|
||||
internal static object Get(decimal value) => value == decimal.Zero ? DecimalZero : value;
|
||||
|
||||
private static readonly object DecimalZero = decimal.Zero;
|
||||
|
||||
internal static object Get(double value)
|
||||
{
|
||||
if (value == 0.0d)
|
||||
{
|
||||
return DoubleZero;
|
||||
}
|
||||
if (double.IsInfinity(value))
|
||||
{
|
||||
return double.IsPositiveInfinity(value) ? DoublePositiveInfinity : DoubleNegativeInfinity;
|
||||
}
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return DoubleNaN;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
internal static readonly object DoubleNaN = double.NaN;
|
||||
internal static readonly object DoublePositiveInfinity = double.PositiveInfinity;
|
||||
internal static readonly object DoubleNegativeInfinity = double.NegativeInfinity;
|
||||
internal static readonly object DoubleZero = (double)0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user