コード例 #1
0
        public static void ConsumeWhiteSpaceThunkReader(ref ThunkReader reader)
        {
            int c;
            while ((c = reader.Peek()) != -1)
            {
                if (!IsWhiteSpace(c)) return;

                reader.Read();
            }
        }
コード例 #2
0
        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();
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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();
        }
コード例 #5
0
        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;
        }
コード例 #6
0
        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;
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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;
        }