| Index: third_party/grpc/src/core/json/json_reader.c
|
| diff --git a/third_party/grpc/src/core/json/json_reader.c b/third_party/grpc/src/core/json/json_reader.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..30da6f28f396329538e57a793b99d48271bbb641
|
| --- /dev/null
|
| +++ b/third_party/grpc/src/core/json/json_reader.c
|
| @@ -0,0 +1,659 @@
|
| +/*
|
| + *
|
| + * Copyright 2015, Google Inc.
|
| + * All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + *
|
| + */
|
| +
|
| +#include <string.h>
|
| +
|
| +#include <grpc/support/port_platform.h>
|
| +
|
| +#include <grpc/support/log.h>
|
| +
|
| +#include "src/core/json/json_reader.h"
|
| +
|
| +static void json_reader_string_clear(grpc_json_reader *reader) {
|
| + reader->vtable->string_clear(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_string_add_char(grpc_json_reader *reader, uint32_t c) {
|
| + reader->vtable->string_add_char(reader->userdata, c);
|
| +}
|
| +
|
| +static void json_reader_string_add_utf32(grpc_json_reader *reader,
|
| + uint32_t utf32) {
|
| + reader->vtable->string_add_utf32(reader->userdata, utf32);
|
| +}
|
| +
|
| +static uint32_t grpc_json_reader_read_char(grpc_json_reader *reader) {
|
| + return reader->vtable->read_char(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_container_begins(grpc_json_reader *reader,
|
| + grpc_json_type type) {
|
| + reader->vtable->container_begins(reader->userdata, type);
|
| +}
|
| +
|
| +static grpc_json_type grpc_json_reader_container_ends(
|
| + grpc_json_reader *reader) {
|
| + return reader->vtable->container_ends(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_set_key(grpc_json_reader *reader) {
|
| + reader->vtable->set_key(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_set_string(grpc_json_reader *reader) {
|
| + reader->vtable->set_string(reader->userdata);
|
| +}
|
| +
|
| +static int json_reader_set_number(grpc_json_reader *reader) {
|
| + return reader->vtable->set_number(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_set_true(grpc_json_reader *reader) {
|
| + reader->vtable->set_true(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_set_false(grpc_json_reader *reader) {
|
| + reader->vtable->set_false(reader->userdata);
|
| +}
|
| +
|
| +static void json_reader_set_null(grpc_json_reader *reader) {
|
| + reader->vtable->set_null(reader->userdata);
|
| +}
|
| +
|
| +/* Call this function to initialize the reader structure. */
|
| +void grpc_json_reader_init(grpc_json_reader *reader,
|
| + grpc_json_reader_vtable *vtable, void *userdata) {
|
| + memset(reader, 0, sizeof(*reader));
|
| + reader->vtable = vtable;
|
| + reader->userdata = userdata;
|
| + json_reader_string_clear(reader);
|
| + reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
|
| +}
|
| +
|
| +int grpc_json_reader_is_complete(grpc_json_reader *reader) {
|
| + return ((reader->depth == 0) &&
|
| + ((reader->state == GRPC_JSON_STATE_END) ||
|
| + (reader->state == GRPC_JSON_STATE_VALUE_END)));
|
| +}
|
| +
|
| +grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) {
|
| + uint32_t c, success;
|
| +
|
| + /* This state-machine is a strict implementation of ECMA-404 */
|
| + for (;;) {
|
| + c = grpc_json_reader_read_char(reader);
|
| + switch (c) {
|
| + /* Let's process the error cases first. */
|
| + case GRPC_JSON_READ_CHAR_ERROR:
|
| + return GRPC_JSON_READ_ERROR;
|
| +
|
| + case GRPC_JSON_READ_CHAR_EAGAIN:
|
| + return GRPC_JSON_EAGAIN;
|
| +
|
| + case GRPC_JSON_READ_CHAR_EOF:
|
| + if (grpc_json_reader_is_complete(reader)) {
|
| + return GRPC_JSON_DONE;
|
| + } else {
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + /* Processing whitespaces. */
|
| + case ' ':
|
| + case '\t':
|
| + case '\n':
|
| + case '\r':
|
| + switch (reader->state) {
|
| + case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
|
| + case GRPC_JSON_STATE_OBJECT_KEY_END:
|
| + case GRPC_JSON_STATE_VALUE_BEGIN:
|
| + case GRPC_JSON_STATE_VALUE_END:
|
| + case GRPC_JSON_STATE_END:
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_OBJECT_KEY_STRING:
|
| + case GRPC_JSON_STATE_VALUE_STRING:
|
| + if (c != ' ') return GRPC_JSON_PARSE_ERROR;
|
| + if (reader->unicode_high_surrogate != 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_char(reader, c);
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER:
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
|
| + success = (uint32_t)json_reader_set_number(reader);
|
| + if (!success) return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_clear(reader);
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + break;
|
| +
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + /* Value, object or array terminations. */
|
| + case ',':
|
| + case '}':
|
| + case ']':
|
| + switch (reader->state) {
|
| + case GRPC_JSON_STATE_OBJECT_KEY_STRING:
|
| + case GRPC_JSON_STATE_VALUE_STRING:
|
| + if (reader->unicode_high_surrogate != 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_char(reader, c);
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER:
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
|
| + success = (uint32_t)json_reader_set_number(reader);
|
| + if (!success) return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_clear(reader);
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + /* The missing break here is intentional. */
|
| +
|
| + case GRPC_JSON_STATE_VALUE_END:
|
| + case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
|
| + case GRPC_JSON_STATE_VALUE_BEGIN:
|
| + if (c == ',') {
|
| + if (reader->state != GRPC_JSON_STATE_VALUE_END) {
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + if (reader->in_object) {
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
|
| + } else {
|
| + reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
|
| + }
|
| + } else {
|
| + if (reader->depth-- == 0) return GRPC_JSON_PARSE_ERROR;
|
| + if ((c == '}') && !reader->in_object) {
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + if ((c == '}') &&
|
| + (reader->state == GRPC_JSON_STATE_OBJECT_KEY_BEGIN) &&
|
| + !reader->container_just_begun) {
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + if ((c == ']') && !reader->in_array) return GRPC_JSON_PARSE_ERROR;
|
| + if ((c == ']') &&
|
| + (reader->state == GRPC_JSON_STATE_VALUE_BEGIN) &&
|
| + !reader->container_just_begun) {
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + switch (grpc_json_reader_container_ends(reader)) {
|
| + case GRPC_JSON_OBJECT:
|
| + reader->in_object = 1;
|
| + reader->in_array = 0;
|
| + break;
|
| + case GRPC_JSON_ARRAY:
|
| + reader->in_object = 0;
|
| + reader->in_array = 1;
|
| + break;
|
| + case GRPC_JSON_TOP_LEVEL:
|
| + GPR_ASSERT(reader->depth == 0);
|
| + reader->in_object = 0;
|
| + reader->in_array = 0;
|
| + reader->state = GRPC_JSON_STATE_END;
|
| + break;
|
| + default:
|
| + GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
| + }
|
| + }
|
| + break;
|
| +
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + /* In-string escaping. */
|
| + case '\\':
|
| + switch (reader->state) {
|
| + case GRPC_JSON_STATE_OBJECT_KEY_STRING:
|
| + reader->escaped_string_was_key = 1;
|
| + reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_STRING:
|
| + reader->escaped_string_was_key = 0;
|
| + reader->state = GRPC_JSON_STATE_STRING_ESCAPE;
|
| + break;
|
| +
|
| + /* This is the \\ case. */
|
| + case GRPC_JSON_STATE_STRING_ESCAPE:
|
| + if (reader->unicode_high_surrogate != 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_char(reader, '\\');
|
| + if (reader->escaped_string_was_key) {
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
|
| + } else {
|
| + reader->state = GRPC_JSON_STATE_VALUE_STRING;
|
| + }
|
| + break;
|
| +
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + default:
|
| + reader->container_just_begun = 0;
|
| + switch (reader->state) {
|
| + case GRPC_JSON_STATE_OBJECT_KEY_BEGIN:
|
| + if (c != '"') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_OBJECT_KEY_STRING:
|
| + GPR_ASSERT(reader->unicode_high_surrogate == 0);
|
| + if (c == '"') {
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
|
| + json_reader_set_key(reader);
|
| + json_reader_string_clear(reader);
|
| + } else {
|
| + if (c <= 0x001f) return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_char(reader, c);
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_STRING:
|
| + if (reader->unicode_high_surrogate != 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + if (c == '"') {
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + json_reader_set_string(reader);
|
| + json_reader_string_clear(reader);
|
| + } else {
|
| + if (c < 32) return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_char(reader, c);
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_OBJECT_KEY_END:
|
| + if (c != ':') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_BEGIN:
|
| + switch (c) {
|
| + case 't':
|
| + reader->state = GRPC_JSON_STATE_VALUE_TRUE_R;
|
| + break;
|
| +
|
| + case 'f':
|
| + reader->state = GRPC_JSON_STATE_VALUE_FALSE_A;
|
| + break;
|
| +
|
| + case 'n':
|
| + reader->state = GRPC_JSON_STATE_VALUE_NULL_U;
|
| + break;
|
| +
|
| + case '"':
|
| + reader->state = GRPC_JSON_STATE_VALUE_STRING;
|
| + break;
|
| +
|
| + case '0':
|
| + json_reader_string_add_char(reader, c);
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_ZERO;
|
| + break;
|
| +
|
| + case '1':
|
| + case '2':
|
| + case '3':
|
| + case '4':
|
| + case '5':
|
| + case '6':
|
| + case '7':
|
| + case '8':
|
| + case '9':
|
| + case '-':
|
| + json_reader_string_add_char(reader, c);
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER;
|
| + break;
|
| +
|
| + case '{':
|
| + reader->container_just_begun = 1;
|
| + json_reader_container_begins(reader, GRPC_JSON_OBJECT);
|
| + reader->depth++;
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN;
|
| + reader->in_object = 1;
|
| + reader->in_array = 0;
|
| + break;
|
| +
|
| + case '[':
|
| + reader->container_just_begun = 1;
|
| + json_reader_container_begins(reader, GRPC_JSON_ARRAY);
|
| + reader->depth++;
|
| + reader->in_object = 0;
|
| + reader->in_array = 1;
|
| + break;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_STRING_ESCAPE:
|
| + if (reader->escaped_string_was_key) {
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
|
| + } else {
|
| + reader->state = GRPC_JSON_STATE_VALUE_STRING;
|
| + }
|
| + if (reader->unicode_high_surrogate && c != 'u')
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + switch (c) {
|
| + case '"':
|
| + case '/':
|
| + json_reader_string_add_char(reader, c);
|
| + break;
|
| + case 'b':
|
| + json_reader_string_add_char(reader, '\b');
|
| + break;
|
| + case 'f':
|
| + json_reader_string_add_char(reader, '\f');
|
| + break;
|
| + case 'n':
|
| + json_reader_string_add_char(reader, '\n');
|
| + break;
|
| + case 'r':
|
| + json_reader_string_add_char(reader, '\r');
|
| + break;
|
| + case 't':
|
| + json_reader_string_add_char(reader, '\t');
|
| + break;
|
| + case 'u':
|
| + reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1;
|
| + reader->unicode_char = 0;
|
| + break;
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U1:
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U2:
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U3:
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U4:
|
| + if ((c >= '0') && (c <= '9')) {
|
| + c -= '0';
|
| + } else if ((c >= 'A') && (c <= 'F')) {
|
| + c -= 'A' - 10;
|
| + } else if ((c >= 'a') && (c <= 'f')) {
|
| + c -= 'a' - 10;
|
| + } else {
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + reader->unicode_char = (uint16_t)(reader->unicode_char << 4);
|
| + reader->unicode_char = (uint16_t)(reader->unicode_char | c);
|
| +
|
| + switch (reader->state) {
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U1:
|
| + reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U2;
|
| + break;
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U2:
|
| + reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U3;
|
| + break;
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U3:
|
| + reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4;
|
| + break;
|
| + case GRPC_JSON_STATE_STRING_ESCAPE_U4:
|
| + /* See grpc_json_writer_escape_string to have a description
|
| + * of what's going on here.
|
| + */
|
| + if ((reader->unicode_char & 0xfc00) == 0xd800) {
|
| + /* high surrogate utf-16 */
|
| + if (reader->unicode_high_surrogate != 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + reader->unicode_high_surrogate = reader->unicode_char;
|
| + } else if ((reader->unicode_char & 0xfc00) == 0xdc00) {
|
| + /* low surrogate utf-16 */
|
| + uint32_t utf32;
|
| + if (reader->unicode_high_surrogate == 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + utf32 = 0x10000;
|
| + utf32 += (uint32_t)(
|
| + (reader->unicode_high_surrogate - 0xd800) * 0x400);
|
| + utf32 += (uint32_t)(reader->unicode_char - 0xdc00);
|
| + json_reader_string_add_utf32(reader, utf32);
|
| + reader->unicode_high_surrogate = 0;
|
| + } else {
|
| + /* anything else */
|
| + if (reader->unicode_high_surrogate != 0)
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_utf32(reader, reader->unicode_char);
|
| + }
|
| + if (reader->escaped_string_was_key) {
|
| + reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
|
| + } else {
|
| + reader->state = GRPC_JSON_STATE_VALUE_STRING;
|
| + }
|
| + break;
|
| + default:
|
| + GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER:
|
| + json_reader_string_add_char(reader, c);
|
| + switch (c) {
|
| + case '0':
|
| + case '1':
|
| + case '2':
|
| + case '3':
|
| + case '4':
|
| + case '5':
|
| + case '6':
|
| + case '7':
|
| + case '8':
|
| + case '9':
|
| + break;
|
| + case 'e':
|
| + case 'E':
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
|
| + break;
|
| + case '.':
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
|
| + break;
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
|
| + json_reader_string_add_char(reader, c);
|
| + switch (c) {
|
| + case '0':
|
| + case '1':
|
| + case '2':
|
| + case '3':
|
| + case '4':
|
| + case '5':
|
| + case '6':
|
| + case '7':
|
| + case '8':
|
| + case '9':
|
| + break;
|
| + case 'e':
|
| + case 'E':
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E;
|
| + break;
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
|
| + if (c != '.') return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_string_add_char(reader, c);
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_DOT:
|
| + json_reader_string_add_char(reader, c);
|
| + switch (c) {
|
| + case '0':
|
| + case '1':
|
| + case '2':
|
| + case '3':
|
| + case '4':
|
| + case '5':
|
| + case '6':
|
| + case '7':
|
| + case '8':
|
| + case '9':
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL;
|
| + break;
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_E:
|
| + json_reader_string_add_char(reader, c);
|
| + switch (c) {
|
| + case '0':
|
| + case '1':
|
| + case '2':
|
| + case '3':
|
| + case '4':
|
| + case '5':
|
| + case '6':
|
| + case '7':
|
| + case '8':
|
| + case '9':
|
| + case '+':
|
| + case '-':
|
| + reader->state = GRPC_JSON_STATE_VALUE_NUMBER_EPM;
|
| + break;
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
|
| + json_reader_string_add_char(reader, c);
|
| + switch (c) {
|
| + case '0':
|
| + case '1':
|
| + case '2':
|
| + case '3':
|
| + case '4':
|
| + case '5':
|
| + case '6':
|
| + case '7':
|
| + case '8':
|
| + case '9':
|
| + break;
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_TRUE_R:
|
| + if (c != 'r') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_TRUE_U;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_TRUE_U:
|
| + if (c != 'u') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_TRUE_E;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_TRUE_E:
|
| + if (c != 'e') return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_set_true(reader);
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_FALSE_A:
|
| + if (c != 'a') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_FALSE_L;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_FALSE_L:
|
| + if (c != 'l') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_FALSE_S;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_FALSE_S:
|
| + if (c != 's') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_FALSE_E;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_FALSE_E:
|
| + if (c != 'e') return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_set_false(reader);
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NULL_U:
|
| + if (c != 'u') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_NULL_L1;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NULL_L1:
|
| + if (c != 'l') return GRPC_JSON_PARSE_ERROR;
|
| + reader->state = GRPC_JSON_STATE_VALUE_NULL_L2;
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_VALUE_NULL_L2:
|
| + if (c != 'l') return GRPC_JSON_PARSE_ERROR;
|
| + json_reader_set_null(reader);
|
| + reader->state = GRPC_JSON_STATE_VALUE_END;
|
| + break;
|
| +
|
| + /* All of the VALUE_END cases are handled in the specialized case
|
| + * above. */
|
| + case GRPC_JSON_STATE_VALUE_END:
|
| + switch (c) {
|
| + case ',':
|
| + case '}':
|
| + case ']':
|
| + GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
| + break;
|
| +
|
| + default:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + break;
|
| +
|
| + case GRPC_JSON_STATE_END:
|
| + return GRPC_JSON_PARSE_ERROR;
|
| + }
|
| + }
|
| + }
|
| +
|
| + GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR);
|
| +}
|
|
|