示例#1
0
        static object ReadNumber(StringView input)
        {
#if SHARE_INTERNAL_METHODS
            input.TrimStart();
#endif

            int offset = -1;
            while (++offset < input.Length)
            {
                char c = input[offset];

                if (c == '.' || c == 'e')
                {
                    return(ReadDouble(input));
                }
                if (c == '-' && offset == 0)
                {
                    continue;
                }
                //ASCII 0 - 9
                if (c >= 0x30 && c <= 0x39)
                {
                    continue;
                }

                break;
            }

            return(ReadInt(input));
        }
示例#2
0
        static (string, object) ReadObjectEntry(StringView input)
        {
#if SHARE_INTERNAL_METHODS
            input.TrimStart();
#endif

            if (input.Length < 1 || input[0] != '"')
            {
                throw new Exception($"Unexpected value at offset {input.offset}. Expected object-key string at {input.offset}");
            }


            string key = ReadString(input);
            input.TrimStart();

            if (input.Length == 0 || input[0] != ':')
            {
                throw new Exception($"Unexpected value at offset {input.offset}. Expected object key-value separator ':'");
            }

            input.Move(1);
            object value = ReadElement(input);

            return(key, value);
        }
示例#3
0
        static IEnumerable <object> ReadArray(StringView input)
        {
#if SHARE_INTERNAL_METHODS
            input.TrimStart();
            if (input.Length < 1 || input[0] != '[')
            {
                throw new Exception($"No Array at offset {input.offset}");
            }
#endif
            input.Move(1);
            input.TrimStart();

            List <object> objects     = new List <object>();
            int           startOffset = input.offset;


            if (input.Length != 0 && input[0] == ']')
            {
                input.Move(1);
                return(objects);
            }

            while (true)
            {
                input.TrimStart();

#if ALLOW_TRAILING_ARRAY_COMMAS
                if (input.Length == 0 || input[0] == ']')
                {
                    break;
                }
#endif

                object child = ReadElement(input);
                objects.Add(child);


                input.TrimStart();
                if (input.Length == 0 || input[0] == ']')
                {
                    break;
                }

                if (input[0] != ',')
                {
                    throw new Exception($"Unexpected char at offset {input.offset}. Expected array separator ','");
                }
                input.Move(1);
            }

            if (input.Length == 0)
            {
                throw new Exception($"Array at offset {startOffset} isn't closed");
            }

            input.Move(1);
            return(objects);
        }
示例#4
0
        public static object ReadJSON(string input)
        {
            var stringView = new StringView(input);

#if ALLOW_LINE_COMMENTS || ALLOW_BLOCK_COMMENTS
            stringView = new CommentableStringView(input);
#endif

            return(ReadJSON(stringView));
        }
示例#5
0
        static object ReadJSON(StringView input)
        {
            object result = ReadElement(input);

            input.TrimStart();
            if (input.Length != 0)
            {
                throw new Exception($"Forbidden second root element at offset {input.offset}");
            }

            return(result);
        }
示例#6
0
        static object ReadInt(StringView input)
        {
            int offset = -1;

            while (++offset < input.Length)
            {
                char c = input[offset];

                if (c == '-' && offset == 0)
                {
                    continue;
                }
                //ASCII 0 - 9
                if (c >= 0x30 && c <= 0x39)
                {
                    continue;
                }

                break;
            }

            var intString = input.SubString(0, offset);

            input.Move(offset);


            try
            {
                long longValue = Convert.ToInt64(intString);

                //Previous versions always returned int32,
                //and asint32 is the most common data type
                //for numbers we return an int32 if possible
                if (longValue >= int.MinValue && longValue <= int.MaxValue)
                {
                    return((int)longValue);
                }


                return(longValue);
            }
            catch (OverflowException) { }

            try
            {
                return(Convert.ToUInt64(intString));
            }
            catch (OverflowException) { }

            return(Convert.ToDouble(intString));
        }
示例#7
0
        static object ReadNull(StringView input)
        {
            if (input.Length < 4)
            {
                throw new Exception($"Unexpected value at offset {input.offset}");
            }

            string nullStr = input.SubString(0, 4);

            input.Move(4);

            if (nullStr == "null")
            {
                return(null);
            }

            throw new Exception($"Unexpected value at offset {input.offset}");
        }
示例#8
0
        static bool ReadBool(StringView input)
        {
            if (input.Length < 4)
            {
                throw new Exception($"Unexpected value at offset {input.offset}");
            }

            int offset = -1;

            while (++offset < input.Length)
            {
                char c = input[offset];
                //ASCII a - z
                if (c >= 0x61 && c <= 0x7a)
                {
                    continue;
                }

                break;
            }

            if (offset > 5)
            {
                throw new Exception($"Unexpected value at offset {input.offset}");
            }

            string boolStr = input.SubString(0, offset);

            input.Move(boolStr.Length);

            if (boolStr == "true")
            {
                return(true);
            }
            if (boolStr == "false")
            {
                return(false);
            }

            throw new Exception($"Unexpected value at offset {input.offset}");
        }
示例#9
0
        static object ReadElement(StringView input)
        {
            input.TrimStart();
            if (input.Length == 0)
            {
                throw new Exception("Unexpected EOF");
            }

            char indicator = input[0];

            //ASCII 0 - 9
            if (indicator >= 0x30 && indicator <= 0x39)
            {
                return(ReadNumber(input));
            }

            switch (input[0])
            {
            case '{':
                return(ReadObject(input));

            case '[':
                return(ReadArray(input));

            case '"':
                return(ReadString(input));

            case '-':
                return(ReadNumber(input));

            case 't':
            case 'f':
                return(ReadBool(input));

            case 'n':
                return(ReadNull(input));
            }

            throw new Exception("Unknown value at pos " + input.offset);
        }
示例#10
0
        static double ReadDouble(StringView input)
        {
            int nonNumberChars = 0;

            int doubleDotOffset = -1;
            int eOffset         = -1;
            int eSignOffset     = -1;

            int offset = -1;

            while (++offset < input.Length)
            {
                char c = input[offset];

                if (c == '-' && offset == 0)
                {
                    ++nonNumberChars;
                    continue;
                }
                if (c == '.' && doubleDotOffset == -1)
                {
                    if (offset == nonNumberChars)
                    {
                        throw new Exception($"Invalid float value at offset {input.offset}. Floats mustn't start with a dot");
                    }

                    doubleDotOffset = offset;
                    ++nonNumberChars;
                    continue;
                }
                if (c == 'e' && eOffset == -1)
                {
                    if (offset == nonNumberChars)
                    {
                        throw new Exception($"Invalid float value at offset {input.offset}. Floats mustn't start with an 'e'");
                    }

                    eOffset = offset;
                    ++nonNumberChars;
                    continue;
                }
                if ((c == '+' || c == '-') && eOffset != -1 && offset == eOffset + 1)
                {
                    eSignOffset = offset;
                    continue;
                }
                //ASCII 0 - 9
                if (c >= 0x30 && c <= 0x39)
                {
                    continue;
                }

                break;
            }

            if (doubleDotOffset == offset - 1)
            {
                throw new Exception($"Invalid float value at offset {input.offset}. Floats mustn't end with a dot");
            }
            if (eOffset == offset - 1)
            {
                throw new Exception($"Invalid float value at offset {input.offset}. Floats mustn't end with an 'e'");
            }
            if (eSignOffset == offset - 1)
            {
                throw new Exception($"Invalid float value at offset {input.offset}. Floats mustn't end with an 'e'-sign");
            }

            var doubleString = input.SubString(0, offset);

            input.Move(offset);

            return(Convert.ToDouble(doubleString, CultureInfo.InvariantCulture));
        }
示例#11
0
        static string ReadString(StringView input)
        {
#if SHARE_INTERNAL_METHODS
            input.TrimStart();
            if (input.Length < 1 || input[0] != '"')
            {
                throw new Exception($"No string at offset {input.offset}");
            }
#endif

            if (input.Length < 2)
            {
                throw new Exception($"Invalid string at offset {input.offset}");
            }

            input.Move(1);

            var  builder      = new StringBuilder();
            bool escape       = false;
            bool stringClosed = false;

            while (input.Length != 0)
            {
                char c = input[0];
                input.Move(1);

                if (escape)
                {
                    switch (c)
                    {
                    case '\\':
                        builder.Append('\\');
                        break;

                    case 'b':
                        builder.Append('\b');
                        break;

                    case 'f':
                        builder.Append('\f');
                        break;

                    case 'r':
                        builder.Append('\r');
                        break;

                    case 'n':
                        builder.Append('\n');
                        break;

                    case 't':
                        builder.Append('\t');
                        break;

                    case '"':
                        builder.Append('"');
                        break;

                    case 'u':
                        builder.Append(ReadEscapedUnicodeChar());
                        break;

                    default:
                        throw new Exception($"Invalid string escape sequence at offset {input.offset - 2}");
                    }

                    escape = false;
                    continue;
                }

                if (c == '\\')
                {
                    escape = true;
                    continue;
                }
                if (c == '"')
                {
                    stringClosed = true;
                    break;
                }

                builder.Append(c);
            }

            if (!stringClosed)
            {
                throw new Exception($"String not closed at offset {input.offset}");
            }

            return(builder.ToString());


            char ReadEscapedUnicodeChar()
            {
                if (input.Length < 4)
                {
                    throw new Exception($"Invalid Unicode escape sequence at offset {input.offset}");
                }

                string hexChars = input.SubString(0, 4);

                foreach (var c in hexChars)
                {
                    if ((c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66))
                    {
                        continue;
                    }

                    throw new Exception($"Invalid Unicode escape sequence at offset {input.offset}");
                }

                input.Move(4);

                int unicodePos = int.Parse(hexChars, NumberStyles.HexNumber);

                return((char)unicodePos);
            }
        }
示例#12
0
        static Dictionary <string, object> ReadObject(StringView input)
        {
#if SHARE_INTERNAL_METHODS
            input.TrimStart();
            if (input.Length < 1 || input[0] != '{')
            {
                throw new Exception($"No Object at offset {input.offset}");
            }
#endif
            input.Move(1);
            input.TrimStart();

            Dictionary <string, object> childs = new Dictionary <string, object>();
            int startOffset = input.offset;


            if (input.Length != 0 && input[0] == '}')
            {
                input.Move(1);
                return(childs);
            }

            while (true)
            {
                input.TrimStart();

#if ALLOW_TRAILING_OBJECT_COMMAS
                if (input.Length == 0 || input[0] == '}')
                {
                    break;
                }
#endif

                var(key, value) = ReadObjectEntry(input);
                if (childs.ContainsKey(key))
                {
                    throw new Exception($"Key '{key}' already exists in object at offset {startOffset}");
                }

                childs[key] = value;


                input.TrimStart();
                if (input.Length == 0 || input[0] == '}')
                {
                    break;
                }

                if (input[0] != ',')
                {
                    throw new Exception($"Unexpected char at offset {input.offset}. Expected object separator ','");
                }
                input.Move(1);
            }

            input.TrimStart();
            if (input.Length == 0)
            {
                throw new Exception($"Object at offset {startOffset} isn't closed");
            }

            input.Move(1);
            return(childs);
        }