final class · System.Text
JsonReader
public final class JsonReader
Reads a value from UTF-8 units. Arrays and objects nest at most MaxDepth deep (a FormatError beyond).
- Tipo
- final class
- Espacio de nombres
- System.Text
- Ensamblado
- System.Core
- Acceso
- public, final
- Archivo fuente
Json.ant
Herencia
- Clases base
-
AnyJsonReader
Constructores
Propiedades
Métodos
Fail(str what)
#
SkipSpace()
#
ExpectWord(str word)
#
A number by the JSON grammar: -?, 0 or digits not starting with one, a fraction . digits, an
exponent e/E, a sign, digits (no leading zeros, no 1., no .5).
Past the digits here; how many there were.
ReadText() : str
#
ReadKey() : str
#
An object's key: the string of an earlier key with the same units when there is one.
Constantes
Miembros privados e internos (8)
Miembros heredados (5)
GetTypemétodo de AnyUndescribedmétodo de AnyToStringmétodo de AnyHashmétodo de Anydestroymétodo de Any
Código fuente
JsonReader en Antril, descompilado a partir de su Larva HIR.
// System.Text.JsonReader — System.Core (decompiled from Larva HIR)
import System;
into namespace System.Text
{
/// Reads a value from UTF-8 units. Arrays and objects nest at most MaxDepth deep (a FormatError beyond).
public final class JsonReader
{
u8[] p;
i32 at;
i32 depth;
u8[] scratch;
i32 used;
str?[] keys;
Enter()
{
depth++;
if (depth > 256)
Fail("nesting deeper than " + 256);
}
Put(u32 unit)
{
if (used == scratch.Length)
{
u8[] bigger = new u8[scratch.Length * 2];
Array.Copy(scratch, 0, bigger, 0, used);
scratch = bigger;
}
scratch[used] = (u8)unit;
used++;
}
public:
const i32 MaxDepth = 256;
new(u8[] units)
{
p = units;
scratch = new u8[64];
keys = new str?[64];
}
Fail(str what)
{
throw new FormatError("JSON: " + what + " at " + at);
}
SkipSpace()
{
loop (at < p.Length && (p[at] == 32 || p[at] == 9 || p[at] == 10 || p[at] == 13))
at++;
}
ReadValue() : JsonValue
{
SkipSpace();
if (at >= p.Length)
Fail("unexpected end");
u32 c = p[at];
if (c == 123)
return ReadObject();
if (c == 91)
return ReadArray();
if (c == 34)
return JsonValue.Of(ReadText());
if (c == 116)
{
ExpectWord("true");
return JsonValue.Of(true);
}
if (c == 102)
{
ExpectWord("false");
return JsonValue.Of(false);
}
if (c == 110)
{
ExpectWord("null");
return JsonValue.Null();
}
if (c == 45 || c >= 48 && c <= 57)
return ReadNumber();
Fail("unexpected character");
return JsonValue.Null();
}
ExpectWord(str word)
{
i32 n = word.Length;
loop (i32 i = 0..n)
{
if (at + i >= p.Length || p[at + i] != word[i])
Fail("expected " + word);
}
at += n;
}
/// A number by the JSON grammar: `-`?, `0` or digits not starting with one, a fraction `.` digits, an
/// exponent `e`/`E`, a sign, digits (no leading zeros, no `1.`, no `.5`).
ReadNumber() : JsonValue
{
i32 start = at;
bool negative = p[at] == 45;
if (negative)
at++;
if (at < p.Length && p[at] == 48)
at++;
else if (Digits() == 0)
Fail("bad number");
i32 whole = at - start - (negative ? 1 : 0);
bool integer = !(at < p.Length && (p[at] == 46 || p[at] == 101 || p[at] == 69));
if (integer && whole <= 15 && !(negative && whole == 1 && p[at - 1] == 48))
{
i64 value = 0;
loop (i32 i = at - whole..at)
value = value * 10 + ((i64)p[i] - 48);
return JsonValue.Of(negative ? -value : value);
}
if (at < p.Length && p[at] == 46)
{
at++;
if (Digits() == 0)
Fail("bad number");
}
if (at < p.Length && (p[at] == 101 || p[at] == 69))
{
at++;
if (at < p.Length && (p[at] == 43 || p[at] == 45))
at++;
if (Digits() == 0)
Fail("bad number");
}
f64? parsed = Float64.TryParse(new str(p, start, at - start));
if (parsed == null)
Fail("bad number");
return JsonValue.Of(parsed ?? 0.0);
}
/// Past the digits here; how many there were.
Digits() : i32
{
i32 start = at;
loop (at < p.Length && p[at] >= 48 && p[at] <= 57)
at++;
return at - start;
}
ReadText() : str
{
at++;
i32 start = at;
loop (at < p.Length && p[at] != 34 && p[at] != 92)
at++;
if (at >= p.Length)
Fail("unterminated string");
if (p[at] == 34)
{
at++;
return new str(p, start, at - 1 - start);
}
used = 0;
loop (i32 i = start..at)
Put(p[i]);
loop (true)
{
if (at >= p.Length)
Fail("unterminated string");
u32 c = p[at];
at++;
if (c == 34)
break;
if (c != 92)
{
Put(c);
continue;
}
if (at >= p.Length)
Fail("unterminated escape");
u32 e = p[at];
at++;
if (e == 110)
Put(10);
else if (e == 116)
Put(9);
else if (e == 114)
Put(13);
else if (e == 98)
Put(8);
else if (e == 102)
Put(12);
else if (e == 34 || e == 92 || e == 47)
Put(e);
else if (e == 117)
{
u32 code = ReadHex4();
if (code >= 55296 && code < 56320)
{
i32 before = at;
u32 low = 0;
if (at + 1 < p.Length && p[at] == 92 && p[at + 1] == 117)
{
at += 2;
low = ReadHex4();
}
if (low >= 56320 && low < 57344)
code = 65536 + (code - 55296 << 10) + (low - 56320);
else
{
at = before;
code = 65533;
}
}
else if (code >= 56320 && code < 57344)
code = 65533;
if (code < 128)
Put(code);
else if (code < 2048)
{
Put(192 | code >> 6);
Put(128 | code & 63);
}
else if (code < 65536)
{
Put(224 | code >> 12);
Put(128 | code >> 6 & 63);
Put(128 | code & 63);
}
else
{
Put(240 | code >> 18);
Put(128 | code >> 12 & 63);
Put(128 | code >> 6 & 63);
Put(128 | code & 63);
}
}
else
Fail("bad escape");
}
return new str(scratch, 0, used);
}
/// An object's key: the string of an earlier key with the same units when there is one.
ReadKey() : str
{
i32 start = at + 1;
i32 end = start;
u32 h = 0;
loop (end < p.Length && p[end] != 34 && p[end] != 92)
{
h = h * 31 + (u32)p[end];
end++;
}
if (end >= p.Length || p[end] != 34 || end - start > 32)
return ReadText();
i32 count = end - start;
i32 slot = (i32)(h & 63);
at = end + 1;
if (keys[slot] is str known && known.Length == count)
{
bool same = true;
loop (i32 i = 0..count)
{
if (known[i] != p[start + i])
{
same = false;
break;
}
}
if (same)
return known;
}
str key = new str(p, start, count);
keys[slot] = key;
return key;
}
ReadHex4() : u32
{
u32 value = 0;
loop (i32 i = 0..4)
{
if (at >= p.Length)
Fail("bad \\u escape");
u32 c = p[at];
at++;
u32 digit = c >= 48 && c <= 57 ? c - 48 : c >= 97 && c <= 102 ? c - 97 + 10 : c >= 65 && c <= 70 ? c - 65 + 10 : 16;
if (digit > 15)
Fail("bad \\u escape");
value = value * 16 + digit;
}
return value;
}
ReadArray() : JsonValue
{
at++;
Enter();
JsonValue array = JsonValue.NewArray();
SkipSpace();
if (at < p.Length && p[at] == 93)
{
at++;
depth--;
return array;
}
loop (true)
{
array.Add(ReadValue());
SkipSpace();
if (at >= p.Length)
Fail("unterminated array");
u32 c = p[at];
at++;
if (c == 93)
break;
if (c != 44)
Fail("expected , or ]");
}
depth--;
return array;
}
ReadObject() : JsonValue
{
at++;
Enter();
JsonValue obj = JsonValue.NewObject();
SkipSpace();
if (at < p.Length && p[at] == 125)
{
at++;
depth--;
return obj;
}
loop (true)
{
SkipSpace();
if (at >= p.Length || p[at] != 34)
Fail("expected a key");
str key = ReadKey();
SkipSpace();
if (at >= p.Length || p[at] != 58)
Fail("expected :");
at++;
obj.Set(key, ReadValue());
SkipSpace();
if (at >= p.Length)
Fail("unterminated obj");
u32 c = p[at];
at++;
if (c == 125)
break;
if (c != 44)
Fail("expected , or }");
}
depth--;
return obj;
}
bool AtEnd
{
get => at >= p.Length;
}
}
}