Browse Source

Added support for most escape chars

voice-allocs
RogueException 7 years ago
parent
commit
d2c4d81317
2 changed files with 134 additions and 34 deletions
  1. +74
    -28
      src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs
  2. +60
    -6
      src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs

+ 74
- 28
src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonReader.cs View File

@@ -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<byte>.Shared.Rent(newSize);
var oldArray = _working.Resize(newArray);
ArrayPool<byte>.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<byte>.Shared.Rent(newSize);
var oldArray = _working.Resize(newArray);
ArrayPool<byte>.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<byte>.Shared.Rent(newSize);
var oldArray = _working.Resize(newArray);
ArrayPool<byte>.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++;


+ 60
- 6
src/Discord.Net.Serialization/_corefxlab/System.Text.Json/System/Text/Json/JsonWriter.cs View File

@@ -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;
}
}
}
}


Loading…
Cancel
Save