public async Task <(string errorMessage, JsonValue value)> TryParseAsync(TextReader stream, CancellationToken token) { System.Diagnostics.Debug.Assert(stream.Peek() == '['); var scratch = SmallBufferCache.Acquire(1); var array = new JsonArray(); bool complete = false; char c; string errorMessage = null; while (stream.Peek() != -1) { if (token.IsCancellationRequested) { errorMessage = "Parsing incomplete. The task was cancelled."; break; } await stream.TryRead(scratch, 0, 1, token); // waste the '[' or ',' (errorMessage, c) = await stream.SkipWhiteSpaceAsync(scratch); if (errorMessage != null) { break; } // check for empty array if (c == ']') { if (array.Count == 0) { complete = true; await stream.TryRead(scratch, 0, 1, token); // waste the ']' break; } else { errorMessage = "Expected value."; break; } } // get value JsonValue item; (errorMessage, item) = await JsonParser.TryParseAsync(stream, token); array.Add(item); if (errorMessage != null) { break; } (errorMessage, c) = await stream.SkipWhiteSpaceAsync(scratch); if (errorMessage != null) { break; } // check for end or separator if (c == ']') { complete = true; await stream.TryRead(scratch, 0, 1, token); // waste the ']' break; } if (c != ',') { errorMessage = "Expected ','."; break; } } if (!complete) { errorMessage = "Unterminated array (missing ']')"; } SmallBufferCache.Release(scratch); return(errorMessage, array); }
public async Task <(string?errorMessage, JsonValue?value)> TryParseAsync(TextReader stream, CancellationToken token) { bool complete = false; var obj = new JsonObject(); var scratch = SmallBufferCache.Acquire(1); string?errorMessage = null; while (stream.Peek() != -1) { if (token.IsCancellationRequested) { errorMessage = "Parsing incomplete. The task was cancelled."; break; } await stream.TryRead(scratch, 0, 1, token); // waste the '{' or ',' char c; (errorMessage, c) = await stream.SkipWhiteSpaceAsync(scratch); if (errorMessage != null) { break; } // check for empty object if (c == '}') { if (obj.Count == 0) { complete = true; await stream.TryRead(scratch, 0, 1, token); // waste the '}' break; } else { errorMessage = "Expected key."; break; } } // get key (errorMessage, c) = await stream.SkipWhiteSpaceAsync(scratch); if (errorMessage != null) { break; } if (c != '\"') { errorMessage = "Expected key."; break; } JsonValue?item; (errorMessage, item) = await JsonParser.TryParseAsync(stream, token); if (errorMessage != null) { break; } var key = item !.String; // check for colon (errorMessage, c) = await stream.SkipWhiteSpaceAsync(scratch); if (errorMessage != null) { break; } if (c != ':') { obj.Add(key, null !); errorMessage = "Expected ':'."; break; } await stream.TryRead(scratch, 0, 1, token); // waste the ':' // get value (whitespace is removed in Parse) (errorMessage, item) = await JsonParser.TryParseAsync(stream, token); obj.Add(key, item !); if (errorMessage != null) { break; } (errorMessage, c) = await stream.SkipWhiteSpaceAsync(scratch); if (errorMessage != null) { break; } // check for end or separator if (c == '}') { complete = true; await stream.TryRead(scratch, 0, 1, token); // waste the '}' break; } if (c != ',') { errorMessage = "Expected ','."; break; } } if (!complete && errorMessage == null) { errorMessage = "Unterminated object (missing '}')."; } SmallBufferCache.Release(scratch); return(errorMessage, obj); }