public bool TryGetValue(string propertyName, out JsonObject value) { var record = Record; if (record.Length == 0) { throw new KeyNotFoundException(); } if (record.Type != JsonValueType.Object) { throw new NullReferenceException(); } for (int i = DbRow.Size; i <= _db.Length; i += DbRow.Size) { record = _db.Slice(i).Read<DbRow>(); if (!record.IsSimpleValue) { i += record.Length * DbRow.Size; continue; } if (new Utf8String(_values.Slice(record.Location, record.Length)) == propertyName) { int newStart = i + DbRow.Size; int newEnd = newStart + DbRow.Size; record = _db.Slice(newStart).Read<DbRow>(); if (!record.IsSimpleValue) { newEnd = newEnd + DbRow.Size * record.Length; } value = new JsonObject(_values, _db.Slice(newStart, newEnd - newStart)); return true; } var valueType = _db.Slice(i + DbRow.Size + 8).Read<JsonValueType>(); if (valueType != JsonValueType.Object && valueType != JsonValueType.Array) { i += DbRow.Size; } } value = default(JsonObject); return false; }
private bool AppendDbRow(JsonObject.JsonValueType type, int valueIndex, int LengthOrNumberOfRows = DbRow.UnknownNumberOfRows) { var newIndex = _dbIndex + DbRow.Size; if (newIndex >= _db.Length) { ResizeDb(); } var dbRow = new DbRow(type, valueIndex, LengthOrNumberOfRows); _db.Span.Slice(_dbIndex).Write(dbRow); _dbIndex = newIndex; return true; }
public DbRow(JsonObject.JsonValueType type, int valueIndex, int lengthOrNumberOfRows = UnknownNumberOfRows) { Location = valueIndex; Length = lengthOrNumberOfRows; Type = type; }
private void ParseLiteral(JsonObject.JsonValueType literal, ReadOnlySpan<byte> expected) { if (!_values.Slice(_valuesIndex).StartsWith(expected)) { throw new FormatException("Invalid json, tried to read " + literal.ToString()); } AppendDbRow(literal, _valuesIndex, expected.Length); _valuesIndex += expected.Length; SkipWhitespace(); }
public JsonObject Parse(ReadOnlySpan<byte> utf8Json, BufferPool pool = null) { _pool = pool; if (_pool == null) _pool = ManagedBufferPool.Shared; _scratchManager = _pool.Rent(utf8Json.Length * 4); _scratchMemory = _scratchManager.Memory; int dbLength = _scratchMemory.Length / 2; _db = _scratchMemory.Slice(0, dbLength); _stack = new TwoStacks(_scratchMemory.Slice(dbLength)); _values = utf8Json; _insideObject = 0; _insideArray = 0; _tokenType = 0; _valuesIndex = 0; _dbIndex = 0; _jsonStartIsObject = false; SkipWhitespace(); _jsonStartIsObject = _values[_valuesIndex] == '{'; int arrayItemsCount = 0; int numberOfRowsForMembers = 0; while (Read()) { var tokenType = _tokenType; switch (tokenType) { case JsonTokenType.ObjectStart: AppendDbRow(JsonObject.JsonValueType.Object, _valuesIndex); while(!_stack.TryPushObject(numberOfRowsForMembers)) { ResizeDb(); } numberOfRowsForMembers = 0; break; case JsonTokenType.ObjectEnd: _db.Span.Slice(FindLocation(_stack.ObjectStackCount - 1, true)).Write<int>(numberOfRowsForMembers); numberOfRowsForMembers += _stack.PopObject(); break; case JsonTokenType.ArrayStart: AppendDbRow(JsonObject.JsonValueType.Array, _valuesIndex); while (!_stack.TryPushArray(arrayItemsCount)) { ResizeDb(); } arrayItemsCount = 0; break; case JsonTokenType.ArrayEnd: _db.Span.Slice(FindLocation(_stack.ArrayStackCount - 1, false)).Write<int>(arrayItemsCount); arrayItemsCount += _stack.PopArray(); break; case JsonTokenType.Property: ParsePropertyName(); ParseValue(); numberOfRowsForMembers++; numberOfRowsForMembers++; break; case JsonTokenType.Value: ParseValue(); arrayItemsCount++; numberOfRowsForMembers++; break; default: throw new ArgumentOutOfRangeException(); } } var result = new JsonObject(_values, _db.Slice(0, _dbIndex).Span, _pool, _scratchManager); _scratchManager = null; return result; }