internal static object Convert(InternalObject obj, Type type) { if (type == typeof(IEnumerable)) { return(ConvertToIEnumerable(obj)); } return(ConvertToObject(obj, type)); }
internal void Add(InternalObject obj) { if (Count == _array.Length) { Array.Resize(ref _array, _array.Length * 2); } _array[Count++] = obj; }
internal static object Convert(InternalObject obj, Type type) { if (type == typeof(IEnumerable) || type == typeof(Dictionary <string, object>)) { return(ConvertToIEnumerable(obj)); } return(new ConvertTo().ConvertToObject(obj, type)); }
public bool TryNext(ref InternalObject obj) { if (!_enumerator.MoveNext()) { return(false); } obj = _enumerator.Current; return(true); }
public bool MoveNext() { Position++; if (Position == _count) { return(false); } _current = _array[Position]; return(true); }
public bool TryNext(ref object value, ref InternalObject result) { while (true) { _position++; if (_position == _getters.Length) { return(false); } result.Type = JsonType.Null; value = _getters[_position].Invoke(_target, ref result); _name = _getters[_position].Name; if (result.Type == JsonType.Null) { return(true); } DstDictionary[_name] = result; } }
public bool TryNext(ref Type type, ref InternalObject value) { while (true) { _position++; if (_position == _setters.Length) { return(false); } _current = _setters[_position]; type = _current.Type; if (!_dict.TryGetValue(_current.Name, out value)) { continue; } if (_current.DirectInvoke == null) { return(true); } _current.DirectInvoke(DstObject, value); } }
internal static object ToValue(InternalObject obj) { switch (obj.Type) { case JsonType.Null: return(null); case JsonType.True: return(true); case JsonType.False: return(false); case JsonType.String: return(obj.String); case JsonType.Array: case JsonType.Object: return(new JsonObject(obj)); default: return(obj.Number); } }
private static object ConvertToObject(InternalObject obj, Type type) { var stack = new Stack <Context>(); var context = new Context(); object result; Convert: if (type == typeof(object)) { result = ToValue(obj); goto Return; } switch (obj.Type) { case JsonType.Null: result = ChangeType(ToValue(obj), type, InvariantCulture); break; case JsonType.True: case JsonType.False: result = type == typeof(bool) ? obj.Type == JsonType.True : ChangeType(ToValue(obj), type, InvariantCulture); break; case JsonType.String: result = type == typeof(string) ? obj.String : ChangeType(ToValue(obj), type, InvariantCulture); break; case JsonType.Array: stack.Push(context); if (!type.IsArray && !IsGenericList(type)) { throw InvalidCastException(obj, type); } if (type.IsArray) { var element = type.GetElementType(); context = new Context { Mode = ConvertMode.Array, Type = element, DstArray = Array.CreateInstance(element, obj.Array.Count) }; } else { context = new Context { Mode = ConvertMode.List, Type = type.GetGenericArguments()[0], DstArray = ReflectiveOperation.GetObjectCreator(type)() }; } context.JsonArrayEnumerator = obj.Array.GetEnumerator(); goto ArrayNext; case JsonType.Object: if (type.IsArray) { throw InvalidCastException(obj, type); } stack.Push(context); context = new Context { Mode = ConvertMode.Object, DstObject = ReflectiveOperation.GetObjectCreator(type)(), SetterEnumerator = new SetterEnumerator(type, obj.Dictionary) }; goto ObjectNext; default: result = type == typeof(double) ? obj.Number : type == typeof(int) ? (int)obj.Number : type == typeof(float) ? (float)obj.Number : ChangeType(ToValue(obj), type, InvariantCulture); break; } Return: if (stack.Count == 0) { return(result); } switch (context.Mode) { case ConvertMode.Array: // ReSharper disable once RedundantCast context.DstArray[context.JsonArrayEnumerator.Position] = (dynamic)result; break; case ConvertMode.List: context.DstArray.Add((dynamic)result); break; case ConvertMode.Object: context.SetterEnumerator.Current.Invoke(context.DstObject, result); goto ObjectNext; } ArrayNext: if (!context.JsonArrayEnumerator.MoveNext()) { result = context.DstArray; context = stack.Pop(); goto Return; } type = context.Type; obj = context.JsonArrayEnumerator.Current; goto Convert; ObjectNext: if (!context.SetterEnumerator.MoveNext()) { result = context.DstObject; context = stack.Pop(); goto Return; } var current = context.SetterEnumerator.Current; type = current.Type; obj = current.Value; goto Convert; }
internal JsonObject(InternalObject obj) { _data = obj; }
private static object ConvertToIEnumerable(InternalObject obj) { return(obj.IsArray ? (object)obj.Array.GetEnumerator().GetEnumerable().Select(ToValue) : obj.Dictionary.GetEnumerator().GetEnumerable().ToDictionary(x => x.Key, x => ToValue(x.Value))); }
private static InvalidCastException InvalidCastException(InternalObject obj, Type type) { return(new InvalidCastException($"Unable to cast value of type {obj.Type} to type '{type.Name}'")); }
private void SerializeInternal(InternalObject obj, TextWriter writer, int maxDepth) { _buffer = BufferPool.Rent() ?? new Buffer(); _writeBuffer = _buffer.Write; _stack = _buffer.Stack; var context = new Context(); _writer = writer; fixed(char *bufferStart = _writeBuffer) { _bufferStart = bufferStart; _bufferEnd = bufferStart + _writeBuffer.Length; _pointer = bufferStart; Convert: switch (obj.Type) { case JsonType.Null: EnsureBuffer(4); *_pointer++ = 'n'; *_pointer++ = 'u'; *_pointer++ = 'l'; *_pointer++ = 'l'; break; case JsonType.True: EnsureBuffer(4); *_pointer++ = 't'; *_pointer++ = 'r'; *_pointer++ = 'u'; *_pointer++ = 'e'; break; case JsonType.False: EnsureBuffer(5); *_pointer++ = 'f'; *_pointer++ = 'a'; *_pointer++ = 'l'; *_pointer++ = 's'; *_pointer++ = 'e'; break; case JsonType.String: WriteString(obj.String); break; case JsonType.Array: if (obj.Array.Count == 0) { EnsureBuffer(2); *_pointer++ = '['; *_pointer++ = ']'; break; } EnsureBuffer(1); *_pointer++ = '['; _stack.Push(context); context = new Context { Mode = Mode.Array, ArrayEnumerator = obj.Array.GetEnumerator() }; break; case JsonType.Object: if (obj.Dictionary.Count == 0) { EnsureBuffer(2); *_pointer++ = '{'; *_pointer++ = '}'; break; } EnsureBuffer(1); *_pointer++ = '{'; if (_stack.Count == maxDepth) { throw new JsonSerializerException("Too deep nesting"); } _stack.Push(context); context = new Context { DictionaryEnumerator = obj.Dictionary.GetEnumerator() }; break; default: EnsureBuffer(24); _pointer += FastDtoa.Convert(obj.Number, _pointer); break; } Return: if (_stack.Count == 0) { var len = (int)(_pointer - _bufferStart); if (len > 0) { _writer.Write(_writeBuffer, 0, len); } BufferPool.Return(_buffer); return; } if ((context.Mode & Mode.Array) != 0) { if (context.ArrayEnumerator.MoveNext()) { if ((context.Mode & Mode.Delimiter) != 0) { EnsureBuffer(1); *_pointer++ = ','; } context.Mode |= Mode.Delimiter; obj = context.ArrayEnumerator.Current; goto Convert; } EnsureBuffer(1); *_pointer++ = ']'; } else { if (context.DictionaryEnumerator.MoveNext()) { var current = context.DictionaryEnumerator.Current; if ((context.Mode & Mode.Delimiter) != 0) { EnsureBuffer(1); *_pointer++ = ','; } WriteString(current.Key); EnsureBuffer(1); *_pointer++ = ':'; context.Mode |= Mode.Delimiter; obj = current.Value; goto Convert; } EnsureBuffer(1); *_pointer++ = '}'; } context = _stack.Pop(); goto Return; } }
public static void Serialize(InternalObject obj, TextWriter writer, int maxDepth) { new Serializer().SerializeInternal(obj, writer, maxDepth); }
private object ConvertToObject(InternalObject obj, Type type) { _stack.Count = 0; var context = new Context(); object result; Convert: if (type == typeof(object)) { result = ToValue(obj); goto Return; } switch (obj.Type) { case JsonType.Null: result = ChangeType(ToValue(obj), type, InvariantCulture); break; case JsonType.True: case JsonType.False: result = type == typeof(bool) ? obj.Type == JsonType.True : ChangeType(ToValue(obj), type, InvariantCulture); break; case JsonType.String: result = type == typeof(string) ? obj.String : ChangeType(ToValue(obj), type, InvariantCulture); break; case JsonType.Array: _stack.Push(context); if (!type.IsArray && !IsGenericList(type)) { throw InvalidCastException(obj, type); } if (type.IsArray) { context = new Context { Mode = ConvertMode.Array, ArrayEnumerator = new ArrayEnumerator(type, obj.Array) }; goto ArrayNext; } else { context = new Context { Mode = ConvertMode.List, ListEnumerator = new ListEnumerator(type, obj.Array) }; goto ListNext; } case JsonType.Object: if (type.IsArray) { throw InvalidCastException(obj, type); } _stack.Push(context); context = new Context { Mode = ConvertMode.Object, SetterEnumerator = new SetterEnumerator(type, obj.Dictionary) }; goto ObjectNext; default: result = type == typeof(double) ? obj.Number : type == typeof(int) ? (int)obj.Number : type == typeof(float) ? (float)obj.Number : ChangeType(ToValue(obj), type, InvariantCulture); break; } Return: if (_stack.Count == 0) { return(result); } switch (context.Mode) { case ConvertMode.Array: context.ArrayEnumerator.SetResult(result); break; case ConvertMode.List: context.ListEnumerator.SetResult(result); goto ListNext; case ConvertMode.Object: context.SetterEnumerator.SetResult(result); goto ObjectNext; } ArrayNext: if (!context.ArrayEnumerator.TryNext(ref obj)) { result = context.ArrayEnumerator.DstObject; context = _stack.Pop(); goto Return; } type = context.ArrayEnumerator.Element; goto Convert; ListNext: if (!context.ListEnumerator.TryNext(ref obj)) { result = context.ListEnumerator.DstObject; context = _stack.Pop(); goto Return; } type = context.ListEnumerator.Element; goto Convert; ObjectNext: if (!context.SetterEnumerator.TryNext(ref type, ref obj)) { result = context.SetterEnumerator.DstObject; context = _stack.Pop(); goto Return; } goto Convert; }
private object ParseInternal(TextReader reader, int maxDepth) { Setup(reader); var stack = new Context[maxDepth]; var depth = 0; var context = new Context(); SkipWhiteSpaces(); while (true) { var value = new InternalObject(); switch (_nextChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': value.Number = GetNumber(); break; case 'n': CheckToken("ull"); value.Type = JsonType.Null; break; case 't': CheckToken("rue"); value.Type = JsonType.True; break; case 'f': // ReSharper disable once StringLiteralTypo CheckToken("alse"); value.Type = JsonType.False; break; case '"': value.Type = JsonType.String; value.String = GetString(); break; case '[': if (depth == maxDepth) { throw JsonParserException.TooDeepNesting(depth, _position); } Consume(); stack[depth++] = context; context = new Context { Array = new JsonArray() }; SkipWhiteSpaces(); continue; case ']': if (context.Array == null) { throw JsonParserException.UnexpectedError(_nextChar, _position); } Consume(); value.Type = JsonType.Array; value.Array = context.Array; context = stack[--depth]; break; case '{': if (depth == maxDepth) { throw JsonParserException.TooDeepNesting(depth, _position); } Consume(); stack[depth++] = context; context = new Context { Dictionary = new JsonDictionary() }; goto GetKey; case '}': if (context.Dictionary == null) { throw JsonParserException.UnexpectedError(_nextChar, _position); } Consume(); value.Type = JsonType.Object; value.Dictionary = context.Dictionary; context = stack[--depth]; break; default: if (_isEnd) { throw JsonParserException.UnexpectedEnd(_position); } throw JsonParserException.UnexpectedError(_nextChar, _position); } SkipWhiteSpaces(); // Start if (depth == 0) { if (_isEnd) { return(JsonObject.ToValue(value)); } throw JsonParserException.UnexpectedError(_nextChar, _position); } // Array if (context.Key == null) { context.Array.Add(value); if (_nextChar == ']') { continue; } if (_nextChar != ',') { throw JsonParserException.ExpectingError("',' or ']'", _position); } Consume(); SkipWhiteSpaces(); continue; } // Object context.Dictionary.Add(context.Key, value); if (_nextChar == '}') { continue; } if (_nextChar != ',') { throw JsonParserException.ExpectingError("',' or '}'", _position); } Consume(); GetKey: SkipWhiteSpaces(); if (_nextChar == '}') { continue; } if (_nextChar != '"') { throw JsonParserException.ExpectingError("string", _position); } context.Key = GetString(); SkipWhiteSpaces(); if (_nextChar != ':') { throw JsonParserException.ExpectingError("':'", _position); } Consume(); SkipWhiteSpaces(); } }
public JsonObject(object obj) { _data = ConvertFrom.Convert(obj); }
private InternalObject ConvertInternal(object value) { var context = new Context(); var result = new InternalObject(); Convert: if (value == null) { result.Type = JsonType.Null; goto Return; } var type = value.GetType(); switch (Type.GetTypeCode(type)) { case TypeCode.Empty: case TypeCode.DBNull: result.Type = JsonType.Null; break; case TypeCode.Boolean: result.Type = (bool)value ? JsonType.True : JsonType.False; break; case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Decimal: result.Number = ConvertToDouble(value); break; case TypeCode.Int32: result.Number = (int)value; break; case TypeCode.Single: result.Number = (float)value; break; case TypeCode.Double: result.Number = (double)value; break; case TypeCode.Char: case TypeCode.DateTime: result.Type = JsonType.String; result.String = ConvertToString(value); break; case TypeCode.String: result.Type = JsonType.String; result.String = (string)value; break; case TypeCode.Object: if (typeof(IDictionary).IsAssignableFrom(type)) { _stack.Push(context); context = new Context { Mode = ConvertMode.Dictionary, DictionaryEnumerator = new DictionaryEnumerator(value) }; goto DictionaryNext; } if (typeof(IEnumerable).IsAssignableFrom(type)) // Can convert to array { _stack.Push(context); context = new Context { Mode = ConvertMode.Array, ArrayEnumerator = new ArrayEnumerator(value) }; goto ArrayNext; } if (value is JsonObject obj) { result = obj._data; goto Return; } _stack.Push(context); var v1 = value; context = new Context { Mode = ConvertMode.Object, GetterEnumerator = new GetterEnumerator(v1), }; goto ObjectNext; } Return: if (_stack.Count == 0) { return(result); } if (context.Mode == ConvertMode.Array) { context.ArrayEnumerator.SetResult(result); goto ArrayNext; } if (context.Mode == ConvertMode.Dictionary) { context.DictionaryEnumerator.SetResult(result); goto DictionaryNext; } context.GetterEnumerator.SetResult(result); ObjectNext: if (context.GetterEnumerator.TryNext(ref value, ref result)) { goto Convert; } result.Type = JsonType.Object; result.Dictionary = context.GetterEnumerator.DstDictionary; context = _stack.Pop(); goto Return; ArrayNext: if (context.ArrayEnumerator.TryNext(ref value)) { goto Convert; } result.Type = JsonType.Array; result.Array = context.ArrayEnumerator.DstArray; context = _stack.Pop(); goto Return; DictionaryNext: if (context.DictionaryEnumerator.TryNext(ref value)) { goto Convert; } result.Type = JsonType.Object; result.Dictionary = context.DictionaryEnumerator.DstDictionary; context = _stack.Pop(); goto Return; }
public void SetResult(InternalObject result) { DstDictionary[_key] = result; }
private unsafe object ParseInternal(TextReader reader, int maxDepth) { Setup(reader); var context = new Context(); var charBuffer = stackalloc char[StringInitialCapacity]; SkipWhiteSpaces(); while (true) { var value = new InternalObject(); switch (_nextChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': value.Number = GetNumber(); break; case 'n': CheckToken("ull"); value.Type = JsonType.Null; break; case 't': CheckToken("rue"); value.Type = JsonType.True; break; case 'f': // ReSharper disable once StringLiteralTypo CheckToken("alse"); value.Type = JsonType.False; break; case '"': value.Type = JsonType.String; value.String = GetString(charBuffer); break; case '[': if (_stack.Count == maxDepth) { throw JsonParserException.TooDeepNesting(_stack.Count, _position); } Consume(); _stack.Push(context); context = new Context { Array = new JsonArray() }; SkipWhiteSpaces(); continue; case ']': if (context.Array == null) { throw JsonParserException.UnexpectedError(_nextChar, _position); } Consume(); value.Type = JsonType.Array; value.Array = context.Array; context = _stack.Pop(); break; case '{': if (_stack.Count == maxDepth) { throw JsonParserException.TooDeepNesting(_stack.Count, _position); } Consume(); _stack.Push(context); context = new Context { Dictionary = new JsonDictionary() }; goto GetKey; case '}': if (context.Dictionary == null) { throw JsonParserException.UnexpectedError(_nextChar, _position); } Consume(); value.Type = JsonType.Object; value.Dictionary = context.Dictionary; context = _stack.Pop(); break; default: if (_isEnd) { throw JsonParserException.UnexpectedEnd(_position); } throw JsonParserException.UnexpectedError(_nextChar, _position); } SkipWhiteSpaces(); // Start if (_stack.Count == 0) { // The buffer intentionally leaks in exceptional cases to simplify the code for exceptions. BufferPool.Return(_buffer); if (_isEnd) { return(JsonObject.ToValue(value)); } throw JsonParserException.UnexpectedError(_nextChar, _position); } // Array if (context.Key == null) { context.Array.Add(value); if (_nextChar == ']') { continue; } if (_nextChar != ',') { throw JsonParserException.ExpectingError("',' or ']'", _position); } Consume(); SkipWhiteSpaces(); continue; } // Object context.Dictionary.Add(context.Key, value); if (_nextChar == '}') { continue; } if (_nextChar != ',') { throw JsonParserException.ExpectingError("',' or '}'", _position); } Consume(); GetKey: SkipWhiteSpaces(); if (_nextChar == '}') { continue; } if (_nextChar != '"') { throw JsonParserException.ExpectingError("string", _position); } context.Key = GetString(charBuffer); SkipWhiteSpaces(); if (_nextChar != ':') { throw JsonParserException.ExpectingError("':'", _position); } Consume(); SkipWhiteSpaces(); } }
public static InternalObject Convert(object value) { var stack = new Stack <Context>(); var context = new Context(); var result = new InternalObject(); Convert: if (value == null) { result.Type = JsonType.Null; goto Return; } var type = value.GetType(); switch (Type.GetTypeCode(type)) { case TypeCode.Empty: case TypeCode.DBNull: result.Type = JsonType.Null; break; case TypeCode.Boolean: result.Type = (bool)value ? JsonType.True : JsonType.False; break; case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Decimal: result.Number = ConvertToDouble(value); break; case TypeCode.Int32: result.Number = (int)value; break; case TypeCode.Single: result.Number = (float)value; break; case TypeCode.Double: result.Number = (double)value; break; case TypeCode.Char: case TypeCode.DateTime: result.Type = JsonType.String; result.String = ConvertToString(value); break; case TypeCode.String: result.Type = JsonType.String; result.String = (string)value; break; case TypeCode.Object: if (typeof(IEnumerable).IsAssignableFrom(type)) // Can convert to array { stack.Push(context); context = new Context { Mode = ConvertMode.Array, ArrayEnumerator = ((IEnumerable)value).GetEnumerator(), DstArray = new JsonArray() }; goto ArrayNext; } if (value is JsonObject obj) { result = obj._data; break; } stack.Push(context); var v1 = value; context = new Context { Mode = ConvertMode.Object, GetterEnumerator = new GetterEnumerator(v1), DstDictionary = new JsonDictionary() }; goto ObjectNext; } Return: if (stack.Count == 0) { return(result); } if (context.Mode == ConvertMode.Array) { context.DstArray.Add(result); goto ArrayNext; } context.DstDictionary[context.GetterEnumerator.Current.Name] = result; ObjectNext: if (context.GetterEnumerator.MoveNext()) { value = context.GetterEnumerator.Current.Value; goto Convert; } result.Type = JsonType.Object; result.Dictionary = context.DstDictionary; context = stack.Pop(); goto Return; ArrayNext: if (context.ArrayEnumerator.MoveNext()) { value = context.ArrayEnumerator.Current; goto Convert; } result.Type = JsonType.Array; result.Array = context.DstArray; context = stack.Pop(); goto Return; }
public void SetResult(InternalObject result) { DstArray.Add(result); }