public static void ConsumeWhiteSpaceThunkReader(ref ThunkReader reader) { int c; while ((c = reader.Peek()) != -1) { if (!IsWhiteSpace(c)) return; reader.Read(); } }
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(); }
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 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; }
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; }
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; }