From d2c4d813177e2422f2a17426a4c3cf0e1abf040b Mon Sep 17 00:00:00 2001 From: RogueException Date: Tue, 15 Aug 2017 07:44:37 -0300 Subject: [PATCH] Added support for most escape chars --- .../System/Text/Json/JsonReader.cs | 102 +++++++++++++++------ .../System/Text/Json/JsonWriter.cs | 66 +++++++++++-- 2 files changed, 134 insertions(+), 34 deletions(-) diff --git a/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs index a141f7e48..66dc1232c 100644 --- a/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs +++ b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs @@ -703,41 +703,87 @@ namespace System.Text.Json bool isEscaping = false; bool success = false; - while (idx < length) + while (!success && idx < length) { byte c = Unsafe.Add(ref src, idx); if (isEscaping) - isEscaping = false; - else if (c == JsonConstants.Backslash || c == JsonConstants.Quote) { - int segmentLength = idx - start; - if (segmentLength != 0) + switch (c) { - //Ensure we have enough space in the buffer - int remaining = _working.Capacity - _working.Count; - if (segmentLength > remaining) - { - int doubleSize = _working.Free.Count * 2; - int minNewSize = _working.Capacity + segmentLength; - int newSize = minNewSize > doubleSize ? minNewSize : doubleSize; - var newArray = ArrayPool.Shared.Rent(newSize); - var oldArray = _working.Resize(newArray); - ArrayPool.Shared.Return(oldArray); - } - - //Copy all data before the backslash - var span = _working.Free.AsSpan(); - Unsafe.CopyBlock(ref span.DangerousGetPinnableReference(), ref Unsafe.Add(ref src, start), (uint)segmentLength); - _working.Count += segmentLength; + case (byte)'/': + case (byte)'b': + case (byte)'f': + case (byte)'n': + case (byte)'r': + case (byte)'t': + { + int remaining = _working.Capacity - _working.Count; + if (remaining == 0) + { + int newSize = _working.Free.Count * 2; + var newArray = ArrayPool.Shared.Rent(newSize); + var oldArray = _working.Resize(newArray); + ArrayPool.Shared.Return(oldArray); + } + + var span = _working.Free.AsSpan(); + switch (c) + { + case (byte)'/': span[0] = (byte)'/'; break; + case (byte)'b': span[0] = (byte)'\b'; break; + case (byte)'f': span[0] = (byte)'\f'; break; + case (byte)'n': span[0] = (byte)'\n'; break; + case (byte)'r': span[0] = (byte)'\r'; break; + case (byte)'t': span[0] = (byte)'\t'; break; + } + _working.Count++; + start++; //Skip this char + } + break; + //case (byte)'u': //Not Supported } - start = idx + 1; - isEscaping = true; - - if (c == JsonConstants.Quote) + isEscaping = false; + } + else + { + switch (c) { - idx++; - success = true; - break; + case JsonConstants.Backslash: + case JsonConstants.Quote: + { + int segmentLength = idx - start; + if (segmentLength != 0) + { + //Ensure we have enough space in the buffer + int remaining = _working.Capacity - _working.Count; + if (segmentLength > remaining) + { + int doubleSize = _working.Free.Count * 2; + int minNewSize = _working.Capacity + segmentLength; + int newSize = minNewSize > doubleSize ? minNewSize : doubleSize; + var newArray = ArrayPool.Shared.Rent(newSize); + var oldArray = _working.Resize(newArray); + ArrayPool.Shared.Return(oldArray); + } + + //Copy all data before the backslash + var span = _working.Free.AsSpan(); + Unsafe.CopyBlock(ref span.DangerousGetPinnableReference(), ref Unsafe.Add(ref src, start), (uint)segmentLength); + _working.Count += segmentLength; + } + + if (c == JsonConstants.Quote) + { + success = true; + break; + } + else + { + start = idx + 1; + isEscaping = true; + } + } + break; } } idx++; diff --git a/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs index 900dea56a..2af26b573 100644 --- a/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs +++ b/src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs @@ -481,14 +481,18 @@ namespace System.Text.Json byte c = i != workingWritten ? _working[i] : (byte)0; //Search for next backslash/quote or end of string - bool isEscapable = c == JsonConstants.Backslash || c == JsonConstants.Quote; + bool isEscapable = + c == (byte)'"' || + c == (byte)'\\' || + c == (byte)'/' || + c < 32; if (isEscapable || i == workingWritten) { int segmentLength = i - start; //Ensure buffer length var destination = _output.Buffer; - if (destination.Length <= segmentLength) + if (destination.Length < segmentLength + 2) { workingLength += segmentLength; _output.Enlarge(workingLength); @@ -504,12 +508,62 @@ namespace System.Text.Json _output.Advance(segmentLength); } - //Write backslash if (isEscapable) { - destination[segmentLength] = JsonConstants.Backslash; - outputWritten++; - _output.Advance(1); + switch (c) + { + case (byte)'"': + case (byte)'\\': + case (byte)'/': + //Just write backslash + destination[segmentLength] = JsonConstants.Backslash; + outputWritten++; + _output.Advance(1); + break; + case (byte)'\b': + destination[segmentLength] = JsonConstants.Backslash; + destination[segmentLength + 1] = (byte)'b'; + outputWritten += 2; + _output.Advance(2); + i++; + start++; + break; + case (byte)'\f': + destination[segmentLength] = JsonConstants.Backslash; + destination[segmentLength + 1] = (byte)'f'; + outputWritten += 2; + _output.Advance(2); + i++; + start++; + break; + case (byte)'\n': + destination[segmentLength] = JsonConstants.Backslash; + destination[segmentLength + 1] = (byte)'n'; + outputWritten += 2; + _output.Advance(2); + i++; + start++; + break; + case (byte)'\r': + destination[segmentLength] = JsonConstants.Backslash; + destination[segmentLength + 1] = (byte)'r'; + outputWritten += 2; + _output.Advance(2); + i++; + start++; + break; + case (byte)'\t': + destination[segmentLength] = JsonConstants.Backslash; + destination[segmentLength + 1] = (byte)'t'; + outputWritten += 2; + _output.Advance(2); + i++; + start++; + break; + default: //Unsupported control char, ignore + i++; + break; + } } } }