diff --git a/Src/Newtonsoft.Json.Tests/Benchmarks/JsonTextWriterBenchmarks.cs b/Src/Newtonsoft.Json.Tests/Benchmarks/JsonTextWriterBenchmarks.cs index 68db23eb..774a3db3 100644 --- a/Src/Newtonsoft.Json.Tests/Benchmarks/JsonTextWriterBenchmarks.cs +++ b/Src/Newtonsoft.Json.Tests/Benchmarks/JsonTextWriterBenchmarks.cs @@ -45,6 +45,20 @@ namespace Newtonsoft.Json.Tests.Benchmarks return sw.ToString(); } + + [Benchmark] + public string SerializeIntegers() + { + StringWriter sw = new StringWriter(); + JsonTextWriter jsonTextWriter = new JsonTextWriter(sw); + for (int i = 0; i < 10000; i++) + { + jsonTextWriter.WriteValue(i); + } + jsonTextWriter.Flush(); + + return sw.ToString(); + } } } diff --git a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs index 11598977..d2ca20b8 100644 --- a/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs +++ b/Src/Newtonsoft.Json.Tests/JsonTextWriterTest.cs @@ -902,6 +902,9 @@ namespace Newtonsoft.Json.Tests jsonWriter.WriteValue(long.MinValue); jsonWriter.WriteValue(ulong.MaxValue); jsonWriter.WriteValue(ulong.MinValue); + jsonWriter.WriteValue((ulong)uint.MaxValue - 1); + jsonWriter.WriteValue((ulong)uint.MaxValue); + jsonWriter.WriteValue((ulong)uint.MaxValue + 1); jsonWriter.WriteEndArray(); } @@ -918,7 +921,10 @@ namespace Newtonsoft.Json.Tests 9223372036854775807, -9223372036854775808, 18446744073709551615, - 0 + 0, + 4294967294, + 4294967295, + 4294967296 ]", sb.ToString()); } diff --git a/Src/Newtonsoft.Json/JsonTextWriter.cs b/Src/Newtonsoft.Json/JsonTextWriter.cs index d70cafcd..67ee038e 100644 --- a/Src/Newtonsoft.Json/JsonTextWriter.cs +++ b/Src/Newtonsoft.Json/JsonTextWriter.cs @@ -817,20 +817,77 @@ namespace Newtonsoft.Json } } - private void WriteIntegerValue(ulong uvalue, bool negative) + private void WriteIntegerValue(ulong value, bool negative) { - if (!negative & uvalue <= 9) + if (!negative & value <= 9) { - _writer.Write((char)('0' + uvalue)); + _writer.Write((char)('0' + value)); } else { - int length = WriteNumberToBuffer(uvalue, negative); + int length = WriteNumberToBuffer(value, negative); _writer.Write(_writeBuffer, 0, length); } } private int WriteNumberToBuffer(ulong value, bool negative) + { + if (value <= uint.MaxValue) + { + // avoid the 64 bit division if possible + return WriteNumberToBuffer((uint)value, negative); + } + + EnsureWriteBuffer(); + + int totalLength = MathUtils.IntLength(value); + + if (negative) + { + totalLength++; + _writeBuffer[0] = '-'; + } + + int index = totalLength; + + do + { + ulong quotient = value / 10; + ulong digit = value - (quotient * 10); + _writeBuffer[--index] = (char)('0' + digit); + value = quotient; + } while (value != 0); + + return totalLength; + } + + private void WriteIntegerValue(int value) + { + if (value >= 0 && value <= 9) + { + _writer.Write((char)('0' + value)); + } + else + { + bool negative = value < 0; + WriteIntegerValue(negative ? (uint)-value : (uint)value, negative); + } + } + + private void WriteIntegerValue(uint value, bool negative) + { + if (!negative & value <= 9) + { + _writer.Write((char)('0' + value)); + } + else + { + int length = WriteNumberToBuffer(value, negative); + _writer.Write(_writeBuffer, 0, length); + } + } + + private int WriteNumberToBuffer(uint value, bool negative) { EnsureWriteBuffer(); @@ -846,8 +903,10 @@ namespace Newtonsoft.Json do { - _writeBuffer[--index] = (char)('0' + value % 10); - value /= 10; + uint quotient = value / 10; + uint digit = value - (quotient * 10); + _writeBuffer[--index] = (char)('0' + digit); + value = quotient; } while (value != 0); return totalLength;