static void DeserializeNullThunkReader(ref ThunkReader reader, ObjectBuilder builder) { var c = reader.Read(); if (c != 'u') throw new DeserializationException("Expected u", ref reader, c == -1); c = reader.Read(); if (c != 'l') throw new DeserializationException("Expected l", ref reader, c == -1); c = reader.Read(); if (c != 'l') throw new DeserializationException("Expected l", ref reader, c == -1); builder.PutNull(); }
static void DeserializeTrueThunkReader(ref ThunkReader reader, ObjectBuilder builder) { var c = reader.Read(); if (c != 'r') throw new DeserializationException("Expected r", ref reader, c == -1); c = reader.Read(); if (c != 'u') throw new DeserializationException("Expected u", ref reader, c == -1); c = reader.Read(); if (c != 'e') throw new DeserializationException("Expected e", ref reader, c == -1); builder.PutTrue(); }
static void DeserializeFalseThunkReader(ref ThunkReader reader, ObjectBuilder builder) { var c = reader.Read(); if (c != 'a') throw new DeserializationException("Expected a", ref reader, c == -1); c = reader.Read(); if (c != 'l') throw new DeserializationException("Expected l", ref reader, c == -1); c = reader.Read(); if (c != 's') throw new DeserializationException("Expected s", ref reader, c == -1); c = reader.Read(); if (c != 'e') throw new DeserializationException("Expected e", ref reader, c == -1); builder.PutFalse(); }
static void _ConsumeThunkReader(ref ThunkReader tr, int ch) { while (ch != '\"' && ch != -1) { ch = tr.Read(); } }
static void _DeserializeMemberThunkReader(ref ThunkReader reader, ObjectBuilder builder) { Methods.ConsumeWhiteSpaceThunkReader(ref reader); var c = reader.Read(); switch (c) { case '"': DeserializeStringThunkReader(ref reader, builder); return; case '[': DeserializeArrayThunkReader(ref reader, builder); return; case '{': DeserializeObjectThunkReader(ref reader, builder); return; case 'n': DeserializeNullThunkReader(ref reader, builder); return; case 't': DeserializeTrueThunkReader(ref reader, builder); return; case 'f': DeserializeFalseThunkReader(ref reader, builder); return; case '-': DeserializeNumberThunkReader('-', ref reader, builder); return; } if (c >= '0' && c <= '9') { DeserializeNumberThunkReader((char)c, ref reader, builder); return; } if (c == -1) throw new DeserializationException("Unexpected end of stream", ref reader, true); throw new DeserializationException("Expected \", [, {, n, t, f, -, 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9; found " + (char)c, ref reader, false); }
public static void ConsumeWhiteSpaceThunkReader(ref ThunkReader reader) { int c; while ((c = reader.Peek()) != -1) { if (!IsWhiteSpace(c)) return; reader.Read(); } }
static int _ExpectUnicodeHexQuadThunkReader(ref ThunkReader reader) { var c = reader.Read(); if (c != 'u') { throw new DeserializationException("Escape sequence expected unicode hex quad", ref reader, c == -1); } return(Methods.ReadHexQuadThunkReader(ref reader)); }
public static string ReadEncodedStringWithBufferThunkReader(ref ThunkReader reader, char[] buffer, ref StringBuilder commonSb) { commonSb = commonSb ?? new StringBuilder(); { var ix = 0; while (ix <= CharBufferSize) { if (ix == CharBufferSize) { commonSb.Append(buffer, 0, ix); break; } var first = reader.Read(); if (first == -1) throw new DeserializationException("Expected any character", ref reader, true); // we didn't have to use anything but the buffer, make a string and return it! if (first == '"') { // avoid an allocation here if (ix == 0) return ""; return new string(buffer, 0, ix); } if (first != '\\') { buffer[ix] = (char)first; ix++; continue; } var second = reader.Read(); if (second == -1) throw new DeserializationException("Expected any character", ref reader, true); switch (second) { case '"': buffer[ix] = '"'; ix++; continue; case '\\': buffer[ix] = '\\'; ix++; continue; case '/': buffer[ix] = '/'; ix++; continue; case 'b': buffer[ix] = '\b'; ix++; continue; case 'f': buffer[ix] = '\f'; ix++; continue; case 'n': buffer[ix] = '\n'; ix++; continue; case 'r': buffer[ix] = '\r'; ix++; continue; case 't': buffer[ix] = '\t'; ix++; continue; } if (second != 'u') throw new DeserializationException("Unrecognized escape sequence", ref reader, false); commonSb.Append(buffer, 0, ix); // now we're in an escape sequence, we expect 4 hex #s; always ReadHexQuadToBuilderThunkReader(ref reader, commonSb); break; } } // fall through to using a StringBuilder while (true) { var first = reader.Read(); if (first == -1) throw new DeserializationException("Expected any character", ref reader, true); if (first == '"') { break; } if (first != '\\') { commonSb.Append((char)first); continue; } var second = reader.Read(); if (second == -1) throw new DeserializationException("Expected any character", ref reader, true); switch (second) { case '"': commonSb.Append('"'); continue; case '\\': commonSb.Append('\\'); continue; case '/': commonSb.Append('/'); continue; case 'b': commonSb.Append('\b'); continue; case 'f': commonSb.Append('\f'); continue; case 'n': commonSb.Append('\n'); continue; case 'r': commonSb.Append('\r'); continue; case 't': commonSb.Append('\t'); continue; } if (second != 'u') throw new DeserializationException("Unrecognized escape sequence", ref reader, false); // now we're in an escape sequence, we expect 4 hex #s; always ReadHexQuadToBuilderThunkReader(ref reader, commonSb); } var ret = commonSb.ToString(); // leave this clean for the next use commonSb.Clear(); return ret; }
static void DeserializeArrayThunkReader(ref ThunkReader reader, ObjectBuilder builder) { int c; builder.StartArray(); while (true) { Methods.ConsumeWhiteSpaceThunkReader(ref reader); c = reader.Peek(); if (c == -1) throw new DeserializationException("Unexpected end of stream", ref reader, true); if (c == ']') { reader.Read(); // skip the ] break; } _DeserializeMemberThunkReader(ref reader, builder); Methods.ConsumeWhiteSpaceThunkReader(ref reader); c = reader.Read(); if (c == ',') continue; if (c == ']') break; throw new DeserializationException("Expected , or ], found " + (char)c, ref reader, c == -1); } builder.EndArray(); }
void InspectReader(ref ThunkReader reader) { try { Position = reader.Position; var sb = new StringBuilder(); int c; while ((c = reader.Read()) != -1 && sb.Length < 50) { sb.Append((char)c); } SnippetAfterError = sb.ToString(); } catch (Exception) { /* best effort here, things are already jacked */ } }
public static ulong ReadULongThunkReader(char firstChar, ref ThunkReader reader, out byte overflowByPowersOfTen) { // ulong.MaxValue // ============== // 18446744073709551615 // 123456789ABCDEFGHIJK // // Length: 20 overflowByPowersOfTen = 0; ulong ret; int c; var firstDigitZero = firstChar == '0'; // char1 ret = (ulong)(firstChar - '0'); for (var i = 2; i < 20; i++) { c = reader.Peek(); if (c < '0' || c > '9') return ret; reader.Read(); if (firstDigitZero) throw new DeserializationException("Number cannot have leading zeros", ref reader, false); ret *= 10; ret += (uint)(c - '0'); } // still more number to go? c = reader.Peek(); if (c < '0' || c > '9') return ret; // now we need to see if we can pack this very last digit into the ulong // this check is only necessary *now* because, due to base 10, you can't // overflow a ulong until the 20th digit var retCanBeMultiplied = (ulong.MaxValue / ret) >= 10; if (retCanBeMultiplied) { // remaining space will only be < 9 when we're really close // to ulong.MaxValue (ie. we've read 1844674407370955161 // and are now on the last digit, which could be [0, 5]) var remainingSpace = (ulong.MaxValue - (ret * 10UL)); var asAdd = (uint)(c - '0'); if (asAdd <= remainingSpace) { // we fit the criteria, advance! reader.Read(); ret *= 10; ret += asAdd; } } // now every character is just an extra order of magnitude for the exponent for (var i = 0; i < byte.MaxValue; i++) { c = reader.Peek(); if (c < '0' || c > '9') return ret; reader.Read(); overflowByPowersOfTen++; } throw new DeserializationException("Number too large to be parsed encountered", ref reader, false); }
public static double ReadDoubleThunkReader(char firstChar, ref ThunkReader reader, ref StringBuilder commonSb) { commonSb = commonSb ?? new StringBuilder(); int c; int prev = firstChar; var afterFirstDigit = (firstChar >= '0' && firstChar <= '9'); var afterE = false; var afterDot = false; commonSb.Append(firstChar); while ((c = reader.Peek()) != -1) { var isDigit = c >= '0' && c <= '9'; if (!isDigit) { var isPlus = c == '+'; if (isPlus) { if (!(prev == 'e' || prev == 'E')) { throw new DeserializationException("Unexpected +", ref reader, false); } goto storeChar; } var isMinus = c == '-'; if (isMinus) { if (!(prev == 'e' || prev == 'E')) { throw new DeserializationException("Unexpected -", ref reader, false); } goto storeChar; } var isE = c == 'e' || c == 'E'; if (isE) { if (afterE || !afterFirstDigit) { throw new DeserializationException("Unexpected " + c, ref reader, false); } afterE = true; goto storeChar; } var isDot = c == '.'; if (isDot) { if (!afterFirstDigit || afterE || afterDot) { throw new DeserializationException("Unexpected .", ref reader, false); } afterDot = true; goto storeChar; } break; } else { afterFirstDigit = true; } storeChar: commonSb.Append((char)c); reader.Read(); prev = c; } var result = double.Parse(commonSb.ToString(), CultureInfo.InvariantCulture); commonSb.Clear(); return result; }
public static uint ReadUIntThunkReader(char firstChar, ref ThunkReader reader, out byte length) { length = 1; uint ret = (uint)(firstChar - '0'); int c; while ((c = reader.Peek()) != -1) { c -= '0'; if (c < 0 || c > 9) break; reader.Read(); // skip digit length++; ret *= 10; ret += (uint)c; } return ret; }
static void DeserializeNumberThunkReader(char leadingChar, ref ThunkReader reader, ObjectBuilder builder) { if (!UseFastNumberParsing) { var number = Methods.ReadDoubleThunkReader(leadingChar, ref reader, ref builder.CommonStringBuffer); builder.PutNumber(number); return; } bool negative; ulong beforeDot; long afterE; uint afterDot; byte afterDotLen; byte extraOrdersOfMagnitude; if (leadingChar == '-') { var next = reader.Read(); if (next != '-' && !(next >= '0' && next <= '9')) throw new DeserializationException("Expected -, or digit", ref reader, next == -1); leadingChar = (char)next; negative = true; } else { negative = false; } beforeDot = Methods.ReadULongThunkReader(leadingChar, ref reader, out extraOrdersOfMagnitude); var c = reader.Peek(); if (c == '.') { reader.Read(); c = reader.Read(); if (c < '0' || c > '9') throw new DeserializationException("Expected digit", ref reader, c == -1); afterDot = Methods.ReadUIntThunkReader((char)c, ref reader, out afterDotLen); c = reader.Peek(); } else { afterDot = afterDotLen = 0; } if (c == 'e' || c == 'E') { reader.Read(); c = reader.Read(); if (c == '+') { c = reader.Read(); } if (c != '-' && !(c >= '0' || c <= '9')) throw new DeserializationException("Expected -, +, or digit", ref reader, c == -1); afterE = Methods.ReadLongThunkReader((char)c, ref reader); } else { afterE = 0; } if (extraOrdersOfMagnitude != 0) { try { checked { afterE += extraOrdersOfMagnitude; } } catch (OverflowException) { throw new DeserializationException("Number too large to be parsed encountered", ref reader, false); } } builder.PutFastNumber(negative, beforeDot, afterDot, afterDotLen, afterE); }
static void ReadHexQuadToBuilderThunkReader(ref ThunkReader reader, StringBuilder commonSb) { var encodedChar = 0; //char1: { var c = reader.Read(); if (c == -1) throw new DeserializationException("Unexpected end of reader", ref reader, true); c -= '0'; if (c >= 0 && c <= 9) { encodedChar += c; goto char2; } c -= ('A' - '0'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto char2; } c -= ('f' - 'F'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto char2; } throw new DeserializationException("Expected hex digit, found: " + c, ref reader, false); } char2: encodedChar *= 16; { var c = reader.Read(); if (c == -1) throw new DeserializationException("Unexpected end of reader", ref reader, true); c -= '0'; if (c >= 0 && c <= 9) { encodedChar += c; goto char3; } c -= ('A' - '0'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto char3; } c -= ('f' - 'F'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto char3; } throw new DeserializationException("Expected hex digit, found: " + c, ref reader, false); } char3: encodedChar *= 16; { var c = reader.Read(); if (c == -1) throw new DeserializationException("Unexpected end of reader", ref reader, true); c -= '0'; if (c >= 0 && c <= 9) { encodedChar += c; goto char4; } c -= ('A' - '0'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto char4; } c -= ('f' - 'F'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto char4; } throw new DeserializationException("Expected hex digit, found: " + c, ref reader, false); } char4: encodedChar *= 16; { var c = reader.Read(); if (c == -1) throw new DeserializationException("Unexpected end of reader", ref reader, true); c -= '0'; if (c >= 0 && c <= 9) { encodedChar += c; goto finished; } c -= ('A' - '0'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto finished; } c -= ('f' - 'F'); if (c >= 0 && c <= 5) { encodedChar += 10 + c; goto finished; } throw new DeserializationException("Expected hex digit, found: " + c, ref reader, false); } finished: commonSb.Append(Utils.SafeConvertFromUtf32(encodedChar)); }
static void DeserializeObjectThunkReader(ref ThunkReader reader, ObjectBuilder builder) { int c; builder.StartObject(); while (true) { Methods.ConsumeWhiteSpaceThunkReader(ref reader); c = reader.Peek(); if (c == -1) throw new DeserializationException("Unexpected end of stream", ref reader, true); if (c == '}') { reader.Read(); // skip } break; } c = reader.Read(); if (c == -1) throw new DeserializationException("Unexpected end of stream", ref reader, true); if (c != '"') throw new DeserializationException("Expected \", found " + (char)c, ref reader, false); builder.StartObjectMember(); DeserializeStringThunkReader(ref reader, builder); Methods.ConsumeWhiteSpaceThunkReader(ref reader); c = reader.Read(); if (c == -1) throw new DeserializationException("Unexpected end of stream", ref reader, true); if (c != ':') throw new DeserializationException("Expected :, found " + (char)c, ref reader, false); _DeserializeMemberThunkReader(ref reader, builder); builder.EndObjectMember(); Methods.ConsumeWhiteSpaceThunkReader(ref reader); c = reader.Read(); if (c == ',') continue; if (c == '}') break; if (c == -1) throw new DeserializationException("Unexpected end of stream", ref reader, true); throw new DeserializationException("Expected , or }, found " + (char)c, ref reader, false); } builder.EndObject(); }
public static long ReadLongThunkReader(char firstChar, ref ThunkReader reader) { var negate = false; long ret = 0; if (firstChar == '-') { negate = true; } else { ret = (firstChar - '0'); } int c; while ((c = reader.Peek()) != -1) { c -= '0'; if (c < 0 || c > 9) break; reader.Read(); // skip digit ret *= 10; ret += c; } if (negate) ret = -ret; return ret; }