Beispiel #1
0
    private static async ValueTask <Int32> PerformWriteJSONTTokenAsync(
        StreamWriterWithResizableBuffer stream,
        IEncodingInfo encoding,
        JToken jsonValue
        )
    {
        ArgumentValidator.ValidateNotNull(nameof(jsonValue), jsonValue);
        Int32 bytesWritten;
        var   asciiSize = encoding.BytesPerASCIICharacter;
        Int32 max;

        (Int32 Offset, Int32 Count)range;
        switch (jsonValue)
        {
        case JArray array:
            range = stream.ReserveBufferSegment(asciiSize);
            encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)ARRAY_START);
            bytesWritten = range.Count;
            max          = array.Count;
            if (max > 0)
            {
                for (var i = 0; i < max; ++i)
                {
                    bytesWritten += await PerformWriteJSONTTokenAsync(stream, encoding, array[i]);

                    if (i < max - 1)
                    {
                        range = stream.ReserveBufferSegment(asciiSize);
                        encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)ARRAY_VALUE_DELIM);
                        bytesWritten += range.Count;
                    }
                }
            }
            range = stream.ReserveBufferSegment(asciiSize);
            encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)ARRAY_END);
            bytesWritten += await stream.FlushAsync();

            break;

        case JObject obj:
            range = stream.ReserveBufferSegment(asciiSize);
            encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)OBJ_START);
            bytesWritten = range.Count;
            max          = obj.Count;
            if (max > 0)
            {
                var j = 0;
                foreach (var kvp in obj)
                {
                    bytesWritten += WriteJSONString(stream, encoding, kvp.Key);
                    range         = stream.ReserveBufferSegment(asciiSize);
                    encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)OBJ_KEY_VALUE_DELIM);
                    bytesWritten += range.Count;
                    await stream.FlushAsync();

                    bytesWritten += await PerformWriteJSONTTokenAsync(stream, encoding, kvp.Value);

                    if (++j < max)
                    {
                        range = stream.ReserveBufferSegment(asciiSize);
                        encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)OBJ_VALUE_DELIM);
                        bytesWritten += range.Count;
                    }
                }
            }
            range = stream.ReserveBufferSegment(asciiSize);
            encoding.WriteASCIIByte(stream.Buffer, ref range.Offset, (Byte)OBJ_END);
            bytesWritten += await stream.FlushAsync();

            break;

        case JValue value:
            var val = value.Value;
            switch (val)
            {
            case String str:
                bytesWritten = WriteJSONString(stream, encoding, str);
                break;

            case Boolean boolean:
                // Write 'true' or 'false'
                range = stream.ReserveBufferSegment(boolean ? 4 : 5);
                encoding.WriteString(stream.Buffer, ref range.Offset, boolean ? "true" : "false");
                bytesWritten = range.Count;
                break;

            case Int64 i64:
                range = stream.ReserveBufferSegment(encoding.GetTextualIntegerRepresentationSize(i64));
                encoding.WriteIntegerTextual(stream.Buffer, ref range.Offset, i64);
                bytesWritten = range.Count;
                break;

            case Double dbl:
                // Have to allocate string :/
                var dblStr = dbl.ToString(System.Globalization.CultureInfo.InvariantCulture);
                range = stream.ReserveBufferSegment(encoding.Encoding.GetByteCount(dblStr));
                encoding.WriteString(stream.Buffer, ref range.Offset, dblStr);
                bytesWritten = range.Count;
                break;

            case null:
                // Write 'null'
                range = stream.ReserveBufferSegment(asciiSize * 4);
                encoding.WriteString(stream.Buffer, ref range.Offset, "null");
                bytesWritten = range.Count;
                break;

            default:
                throw new NotSupportedException($"Unsupported primitive value {val}.");
            }
            // Remember to flush stream
            await stream.FlushAsync();

            break;

        default:
            throw new NotSupportedException($"Unrecognized JToken type: {jsonValue?.GetType()}.");
        }

        return(bytesWritten);
    }
Beispiel #2
0
    private static Int32 PerformCalculateJTokenTextSize(IEncodingInfo encoding, JToken jsonValue)
    {
        ArgumentValidator.ValidateNotNull(nameof(jsonValue), jsonValue);

        var   asciiSize = encoding.BytesPerASCIICharacter;
        Int32 retVal;

        switch (jsonValue)
        {
        case JArray array:
            // '['followed by items with ',' in between them followed by ']'
            retVal = (2 + Math.Max(array.Count - 1, 0)) * asciiSize + array.Aggregate(0, (cur, curToken) => cur + PerformCalculateJTokenTextSize(encoding, curToken));
            break;

        case JObject obj:
            // '{' followed by items with ',' in between them followed by '}'
            // Each item has ':' between key and value
            retVal = (2 + Math.Max(obj.Count - 1, 0)) * asciiSize + Enumerable.Aggregate <KeyValuePair <String, JToken>, Int32>(obj, 0, (cur, curKvp) => cur + asciiSize + CalculateJSONStringValueSize(curKvp.Key, encoding) + PerformCalculateJTokenTextSize(encoding, curKvp.Value));
            break;

        case JValue simple:
            var val = simple.Value;
            switch (val)
            {
            case String str:
                retVal = CalculateJSONStringValueSize(str, encoding);
                break;

            case Boolean bol:
                retVal = (bol ? 4 : 5) * asciiSize;
                break;

            case Byte b:
            case SByte sb:
            case Int16 i16:
            case UInt16 u16:
            case Int32 i32:
            case UInt32 u32:
            case Int64 i64:
                retVal = encoding.GetTextualIntegerRepresentationSize((Int64)Convert.ChangeType(val, typeof(Int64)));
                break;

            // TODO UInt64
            case Single s:
            case Double d:
            case Decimal dec:
                retVal = encoding.Encoding.GetByteCount(((IFormattable)val).ToString(null, System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
                break;

            case null:
                // Word 'null' has 4 ascii characters
                retVal = 4 * asciiSize;
                break;

            default:
                throw new NotSupportedException($"Unsupported primitive value {val}.");
            }
            break;

        default:
            throw new NotSupportedException($"Unrecognized JToken type: {jsonValue?.GetType()}.");
        }

        return(retVal);
    }