Append() private method

private Append ( JsonValue value ) : void
value JsonValue
return void
コード例 #1
0
ファイル: Json.cs プロジェクト: MingLu8/Nemo
        public static JsonValue Parse(string json)
        {
            JsonValue root = null;
            JsonValue top  = null;
            string    name = null;

            var escapedNewlines = 0;

            char[] jsonArray = null;
            var    i         = 0;

            for (; i < json.Length; i++)
            {
                var ch = json[i];

                // skip white space
                if (ch == '\x20' || ch == '\x9' || ch == '\xD' || ch == '\xA')
                {
                    continue;
                }

                switch (ch)
                {
                case '{':
                case '[':
                {
                    // create new value
                    var value = new JsonValue {
                        Name = name
                    };

                    // name
                    name = null;

                    // type
                    value.Type = ch == '{' ? JsonType.Object : JsonType.Array;

                    // set top and root
                    if (top != null)
                    {
                        top.Append(value);
                    }
                    else if (root == null)
                    {
                        root = value;
                    }
                    else
                    {
                        throw new JsonParserException(i, "Second root. Only one root allowed");
                    }
                    top = value;
                }
                break;

                case '}':
                case ']':
                {
                    if (top == null || top.Type != ((ch == '}') ? JsonType.Object : JsonType.Array))
                    {
                        throw new JsonParserException(i, "Mismatch closing brace/bracket");
                    }

                    // set top
                    top = top.Parent;
                }
                break;

                case ':':
                    if (top == null || top.Type != JsonType.Object)
                    {
                        throw new JsonParserException(i, "Unexpected character");
                    }
                    break;

                case ',':
                    CheckTop(top, i);
                    break;

                case '"':
                {
                    CheckTop(top, i);

                    // skip '"' character
                    i++;
                    ch = json[i];

                    var first  = i;
                    var last   = i;
                    var chLast = ch;
                    while (i < json.Length)
                    {
                        if (ch < '\x20')
                        {
                            throw new JsonParserException(first, "Control characters not allowed in strings");
                        }
                        if (ch == '\\')
                        {
                            switch (json[i + 1])
                            {
                            case '"':
                                chLast = '"';
                                break;

                            case '\\':
                                chLast = '\\';
                                break;

                            case '/':
                                chLast = '/';
                                break;

                            case 'b':
                                chLast = '\b';
                                break;

                            case 'f':
                                chLast = '\f';
                                break;

                            case 'n':
                                chLast = '\n';
                                ++escapedNewlines;
                                break;

                            case 'r':
                                chLast = '\r';
                                break;

                            case 't':
                                chLast = '\t';
                                break;

                            case 'u':
                            {
                                if (jsonArray == null)
                                {
                                    jsonArray = json.ToCharArray();
                                }

                                uint codepoint;
                                if (HexToInteger(json.Substring(i + 2, 4), out codepoint) != 4)
                                {
                                    throw new JsonParserException(i, "Bad unicode codepoint");
                                }

                                if (codepoint <= 0x7F)
                                {
                                    chLast = (char)codepoint;
                                }
                                else if (codepoint <= 0x7FF)
                                {
                                    last++;
                                    jsonArray[last] = (char)(0xC0 | (codepoint >> 6));
                                    last++;
                                    jsonArray[last] = (char)(0x80 | (codepoint & 0x3F));
                                }
                                else if (codepoint <= 0xFFFF)
                                {
                                    last++;
                                    jsonArray[last] = (char)(0xE0 | (codepoint >> 12));
                                    last++;
                                    jsonArray[last] = (char)(0x80 | ((codepoint >> 6) & 0x3F));
                                    last++;
                                    jsonArray[last] = (char)(0x80 | (codepoint & 0x3F));
                                }
                            }
                                i += 4;
                                break;

                            default:
                                throw new JsonParserException(first, "Unrecognized escape sequence");
                            }

                            last++;
                            i++;
                        }
                        else if (ch == '"')
                        {
                            break;
                        }
                        else
                        {
                            last++;
                            i++;
                            ch = json[i];
                        }
                    }

                    if (top != null && (name == null && top.Type == JsonType.Object))
                    {
                        // field name in object
                        name = json.Substring(first, i - first);
                    }
                    else
                    {
                        // new string value
                        var value = new JsonValue {
                            Name = name
                        };

                        name = null;

                        value.Type = JsonType.String;

                        string s;
                        if (jsonArray != null)
                        {
                            var slice = new char[i - first];
                            Array.Copy(jsonArray, first, slice, 0, i - first);
                            s = new string(slice);
                        }
                        else
                        {
                            s = json.Substring(first, i - first);
                        }
                        value.Value = s;

                        if (top != null)
                        {
                            top.Append(value);
                        }
                    }
                }
                break;

                case 'n':
                case 't':
                case 'f':
                {
                    CheckTop(top, i);

                    // new null/bool value
                    var value = new JsonValue {
                        Name = name
                    };

                    name = null;

                    // null
                    if (ch == 'n' && json[i + 1] == 'u' && json[i + 2] == 'l' && json[i + 3] == 'l')
                    {
                        value.Type = JsonType.Null;
                        i         += 3;
                    }
                    // true
                    else if (ch == 't' && json[i + 1] == 'r' && json[i + 2] == 'u' && json[i + 3] == 'e')
                    {
                        value.Type  = JsonType.Boolean;
                        value.Value = true;
                        i          += 3;
                    }
                    // false
                    else if (ch == 'f' && json[i + 1] == 'a' && json[i + 2] == 'l' && json[i + 3] == 's' && json[i + 4] == 'e')
                    {
                        value.Type  = JsonType.Boolean;
                        value.Value = false;
                        i          += 4;
                    }
                    else
                    {
                        throw new JsonParserException(i, "Unknown identifier");
                    }

                    if (top != null)
                    {
                        top.Append(value);
                    }
                }
                break;

                case '-':
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                {
                    CheckTop(top, i);

                    // new number value
                    var value = new JsonValue {
                        Name = name
                    };

                    name = null;

                    value.Type = JsonType.Integer;

                    int first = i;
                    while (ch != '\x20' && ch != '\x9' && ch != '\xD' && ch != '\xA' && ch != ',' && ch != ']' && ch != '}')
                    {
                        if (ch == '.' || ch == 'e' || ch == 'E')
                        {
                            value.Type = JsonType.Decimal;
                        }
                        i++;
                        ch = json[i];
                    }

                    if (value.Type == JsonType.Integer)
                    {
                        if (TextToInteger(json.Substring(first, i - first), out var n) != i - first)
                        {
                            throw new JsonParserException(first, "Bad integer number");
                        }
                        else
                        {
                            value.Value = n;
                        }
                        i--;
                    }

                    if (value.Type == JsonType.Decimal)
                    {
                        if (TextToDecimal(json.Substring(first, i - first), out var d) != i - first)
                        {
                            throw new JsonParserException(first, "Bad decimal number");
                        }
                        value.Value = d;
                        i--;
                    }

                    if (top != null)
                    {
                        top.Append(value);
                    }
                }
                break;

                default:
                    throw new JsonParserException(i, "Unexpected character");
                }
            }

            if (top != null)
            {
                throw new JsonParserException(i, "Not all objects/arrays have been properly closed");
            }

            return(root);
        }