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); |
+} |