Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
Craig Tiller | 8a9fd52 | 2016-03-25 17:09:29 -0700 | [diff] [blame] | 3 | * Copyright 2015-2016, Google Inc. |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 4 | * All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions are |
| 8 | * met: |
| 9 | * |
| 10 | * * Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * * Redistributions in binary form must reproduce the above |
| 13 | * copyright notice, this list of conditions and the following disclaimer |
| 14 | * in the documentation and/or other materials provided with the |
| 15 | * distribution. |
| 16 | * * Neither the name of Google Inc. nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived from |
| 18 | * this software without specific prior written permission. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | * |
| 32 | */ |
| 33 | |
Nicolas Noble | 8c2be9b | 2015-01-27 14:21:18 -0800 | [diff] [blame] | 34 | #include <string.h> |
| 35 | |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 36 | #include <grpc/support/port_platform.h> |
Nicolas Noble | 8c2be9b | 2015-01-27 14:21:18 -0800 | [diff] [blame] | 37 | |
Nicolas "Pixel" Noble | 11c320d | 2015-12-12 01:47:36 +0100 | [diff] [blame] | 38 | #include <grpc/support/log.h> |
| 39 | |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame^] | 40 | #include "src/core/lib/json/json_reader.h" |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 41 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 42 | static void json_reader_string_clear(grpc_json_reader *reader) { |
| 43 | reader->vtable->string_clear(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 44 | } |
| 45 | |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 46 | static void json_reader_string_add_char(grpc_json_reader *reader, uint32_t c) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 47 | reader->vtable->string_add_char(reader->userdata, c); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 48 | } |
| 49 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 50 | static void json_reader_string_add_utf32(grpc_json_reader *reader, |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 51 | uint32_t utf32) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 52 | reader->vtable->string_add_utf32(reader->userdata, utf32); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 53 | } |
| 54 | |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 55 | static uint32_t grpc_json_reader_read_char(grpc_json_reader *reader) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 56 | return reader->vtable->read_char(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 57 | } |
| 58 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 59 | static void json_reader_container_begins(grpc_json_reader *reader, |
| 60 | grpc_json_type type) { |
| 61 | reader->vtable->container_begins(reader->userdata, type); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 62 | } |
| 63 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 64 | static grpc_json_type grpc_json_reader_container_ends( |
| 65 | grpc_json_reader *reader) { |
| 66 | return reader->vtable->container_ends(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 67 | } |
| 68 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 69 | static void json_reader_set_key(grpc_json_reader *reader) { |
| 70 | reader->vtable->set_key(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 71 | } |
| 72 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 73 | static void json_reader_set_string(grpc_json_reader *reader) { |
| 74 | reader->vtable->set_string(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 75 | } |
| 76 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 77 | static int json_reader_set_number(grpc_json_reader *reader) { |
| 78 | return reader->vtable->set_number(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 79 | } |
| 80 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 81 | static void json_reader_set_true(grpc_json_reader *reader) { |
| 82 | reader->vtable->set_true(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 83 | } |
| 84 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 85 | static void json_reader_set_false(grpc_json_reader *reader) { |
| 86 | reader->vtable->set_false(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 87 | } |
| 88 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 89 | static void json_reader_set_null(grpc_json_reader *reader) { |
| 90 | reader->vtable->set_null(reader->userdata); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 91 | } |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 92 | |
| 93 | /* Call this function to initialize the reader structure. */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 94 | void grpc_json_reader_init(grpc_json_reader *reader, |
| 95 | grpc_json_reader_vtable *vtable, void *userdata) { |
| 96 | memset(reader, 0, sizeof(*reader)); |
Nicolas Noble | 8c2be9b | 2015-01-27 14:21:18 -0800 | [diff] [blame] | 97 | reader->vtable = vtable; |
| 98 | reader->userdata = userdata; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 99 | json_reader_string_clear(reader); |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 100 | reader->state = GRPC_JSON_STATE_VALUE_BEGIN; |
| 101 | } |
| 102 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 103 | int grpc_json_reader_is_complete(grpc_json_reader *reader) { |
| 104 | return ((reader->depth == 0) && |
| 105 | ((reader->state == GRPC_JSON_STATE_END) || |
| 106 | (reader->state == GRPC_JSON_STATE_VALUE_END))); |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 107 | } |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 108 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 109 | grpc_json_reader_status grpc_json_reader_run(grpc_json_reader *reader) { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 110 | uint32_t c, success; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 111 | |
Nicolas Noble | e04455a | 2015-01-26 17:01:29 -0800 | [diff] [blame] | 112 | /* This state-machine is a strict implementation of ECMA-404 */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 113 | for (;;) { |
| 114 | c = grpc_json_reader_read_char(reader); |
| 115 | switch (c) { |
| 116 | /* Let's process the error cases first. */ |
| 117 | case GRPC_JSON_READ_CHAR_ERROR: |
| 118 | return GRPC_JSON_READ_ERROR; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 119 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 120 | case GRPC_JSON_READ_CHAR_EAGAIN: |
| 121 | return GRPC_JSON_EAGAIN; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 122 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 123 | case GRPC_JSON_READ_CHAR_EOF: |
| 124 | if (grpc_json_reader_is_complete(reader)) { |
| 125 | return GRPC_JSON_DONE; |
| 126 | } else { |
| 127 | return GRPC_JSON_PARSE_ERROR; |
| 128 | } |
| 129 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 130 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 131 | /* Processing whitespaces. */ |
| 132 | case ' ': |
| 133 | case '\t': |
| 134 | case '\n': |
| 135 | case '\r': |
| 136 | switch (reader->state) { |
| 137 | case GRPC_JSON_STATE_OBJECT_KEY_BEGIN: |
| 138 | case GRPC_JSON_STATE_OBJECT_KEY_END: |
| 139 | case GRPC_JSON_STATE_VALUE_BEGIN: |
| 140 | case GRPC_JSON_STATE_VALUE_END: |
| 141 | case GRPC_JSON_STATE_END: |
| 142 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 143 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 144 | case GRPC_JSON_STATE_OBJECT_KEY_STRING: |
| 145 | case GRPC_JSON_STATE_VALUE_STRING: |
| 146 | if (c != ' ') return GRPC_JSON_PARSE_ERROR; |
| 147 | if (reader->unicode_high_surrogate != 0) |
| 148 | return GRPC_JSON_PARSE_ERROR; |
| 149 | json_reader_string_add_char(reader, c); |
| 150 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 151 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 152 | case GRPC_JSON_STATE_VALUE_NUMBER: |
| 153 | case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL: |
| 154 | case GRPC_JSON_STATE_VALUE_NUMBER_ZERO: |
| 155 | case GRPC_JSON_STATE_VALUE_NUMBER_EPM: |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 156 | success = (uint32_t)json_reader_set_number(reader); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 157 | if (!success) return GRPC_JSON_PARSE_ERROR; |
| 158 | json_reader_string_clear(reader); |
| 159 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 160 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 161 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 162 | default: |
| 163 | return GRPC_JSON_PARSE_ERROR; |
| 164 | } |
| 165 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 166 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 167 | /* Value, object or array terminations. */ |
| 168 | case ',': |
| 169 | case '}': |
| 170 | case ']': |
| 171 | switch (reader->state) { |
| 172 | case GRPC_JSON_STATE_OBJECT_KEY_STRING: |
| 173 | case GRPC_JSON_STATE_VALUE_STRING: |
| 174 | if (reader->unicode_high_surrogate != 0) |
| 175 | return GRPC_JSON_PARSE_ERROR; |
| 176 | json_reader_string_add_char(reader, c); |
| 177 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 178 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 179 | case GRPC_JSON_STATE_VALUE_NUMBER: |
| 180 | case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL: |
| 181 | case GRPC_JSON_STATE_VALUE_NUMBER_ZERO: |
| 182 | case GRPC_JSON_STATE_VALUE_NUMBER_EPM: |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 183 | success = (uint32_t)json_reader_set_number(reader); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 184 | if (!success) return GRPC_JSON_PARSE_ERROR; |
| 185 | json_reader_string_clear(reader); |
| 186 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 187 | /* The missing break here is intentional. */ |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 188 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 189 | case GRPC_JSON_STATE_VALUE_END: |
| 190 | case GRPC_JSON_STATE_OBJECT_KEY_BEGIN: |
| 191 | case GRPC_JSON_STATE_VALUE_BEGIN: |
| 192 | if (c == ',') { |
| 193 | if (reader->state != GRPC_JSON_STATE_VALUE_END) { |
| 194 | return GRPC_JSON_PARSE_ERROR; |
| 195 | } |
| 196 | if (reader->in_object) { |
| 197 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN; |
| 198 | } else { |
| 199 | reader->state = GRPC_JSON_STATE_VALUE_BEGIN; |
| 200 | } |
| 201 | } else { |
| 202 | if (reader->depth-- == 0) return GRPC_JSON_PARSE_ERROR; |
| 203 | if ((c == '}') && !reader->in_object) { |
| 204 | return GRPC_JSON_PARSE_ERROR; |
| 205 | } |
| 206 | if ((c == '}') && |
| 207 | (reader->state == GRPC_JSON_STATE_OBJECT_KEY_BEGIN) && |
| 208 | !reader->container_just_begun) { |
| 209 | return GRPC_JSON_PARSE_ERROR; |
| 210 | } |
| 211 | if ((c == ']') && !reader->in_array) return GRPC_JSON_PARSE_ERROR; |
| 212 | if ((c == ']') && |
| 213 | (reader->state == GRPC_JSON_STATE_VALUE_BEGIN) && |
| 214 | !reader->container_just_begun) { |
| 215 | return GRPC_JSON_PARSE_ERROR; |
| 216 | } |
| 217 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 218 | switch (grpc_json_reader_container_ends(reader)) { |
| 219 | case GRPC_JSON_OBJECT: |
| 220 | reader->in_object = 1; |
| 221 | reader->in_array = 0; |
| 222 | break; |
| 223 | case GRPC_JSON_ARRAY: |
| 224 | reader->in_object = 0; |
| 225 | reader->in_array = 1; |
| 226 | break; |
| 227 | case GRPC_JSON_TOP_LEVEL: |
Nicolas "Pixel" Noble | 11c320d | 2015-12-12 01:47:36 +0100 | [diff] [blame] | 228 | GPR_ASSERT(reader->depth == 0); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 229 | reader->in_object = 0; |
| 230 | reader->in_array = 0; |
| 231 | reader->state = GRPC_JSON_STATE_END; |
| 232 | break; |
| 233 | default: |
Craig Tiller | 620e965 | 2015-12-14 12:02:50 -0800 | [diff] [blame] | 234 | GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 235 | } |
| 236 | } |
| 237 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 238 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 239 | default: |
| 240 | return GRPC_JSON_PARSE_ERROR; |
| 241 | } |
| 242 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 243 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 244 | /* In-string escaping. */ |
| 245 | case '\\': |
| 246 | switch (reader->state) { |
| 247 | case GRPC_JSON_STATE_OBJECT_KEY_STRING: |
| 248 | reader->escaped_string_was_key = 1; |
| 249 | reader->state = GRPC_JSON_STATE_STRING_ESCAPE; |
| 250 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 251 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 252 | case GRPC_JSON_STATE_VALUE_STRING: |
| 253 | reader->escaped_string_was_key = 0; |
| 254 | reader->state = GRPC_JSON_STATE_STRING_ESCAPE; |
| 255 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 256 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 257 | /* This is the \\ case. */ |
| 258 | case GRPC_JSON_STATE_STRING_ESCAPE: |
| 259 | if (reader->unicode_high_surrogate != 0) |
| 260 | return GRPC_JSON_PARSE_ERROR; |
| 261 | json_reader_string_add_char(reader, '\\'); |
| 262 | if (reader->escaped_string_was_key) { |
| 263 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; |
| 264 | } else { |
| 265 | reader->state = GRPC_JSON_STATE_VALUE_STRING; |
| 266 | } |
| 267 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 268 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 269 | default: |
| 270 | return GRPC_JSON_PARSE_ERROR; |
| 271 | } |
| 272 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 273 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 274 | default: |
| 275 | reader->container_just_begun = 0; |
| 276 | switch (reader->state) { |
| 277 | case GRPC_JSON_STATE_OBJECT_KEY_BEGIN: |
| 278 | if (c != '"') return GRPC_JSON_PARSE_ERROR; |
| 279 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; |
| 280 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 281 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 282 | case GRPC_JSON_STATE_OBJECT_KEY_STRING: |
Nicolas "Pixel" Noble | 11c320d | 2015-12-12 01:47:36 +0100 | [diff] [blame] | 283 | GPR_ASSERT(reader->unicode_high_surrogate == 0); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 284 | if (c == '"') { |
| 285 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_END; |
| 286 | json_reader_set_key(reader); |
| 287 | json_reader_string_clear(reader); |
| 288 | } else { |
| 289 | if (c <= 0x001f) return GRPC_JSON_PARSE_ERROR; |
| 290 | json_reader_string_add_char(reader, c); |
| 291 | } |
| 292 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 293 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 294 | case GRPC_JSON_STATE_VALUE_STRING: |
| 295 | if (reader->unicode_high_surrogate != 0) |
| 296 | return GRPC_JSON_PARSE_ERROR; |
| 297 | if (c == '"') { |
| 298 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 299 | json_reader_set_string(reader); |
| 300 | json_reader_string_clear(reader); |
| 301 | } else { |
| 302 | if (c < 32) return GRPC_JSON_PARSE_ERROR; |
| 303 | json_reader_string_add_char(reader, c); |
| 304 | } |
| 305 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 306 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 307 | case GRPC_JSON_STATE_OBJECT_KEY_END: |
| 308 | if (c != ':') return GRPC_JSON_PARSE_ERROR; |
| 309 | reader->state = GRPC_JSON_STATE_VALUE_BEGIN; |
| 310 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 311 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 312 | case GRPC_JSON_STATE_VALUE_BEGIN: |
| 313 | switch (c) { |
| 314 | case 't': |
| 315 | reader->state = GRPC_JSON_STATE_VALUE_TRUE_R; |
| 316 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 317 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 318 | case 'f': |
| 319 | reader->state = GRPC_JSON_STATE_VALUE_FALSE_A; |
| 320 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 321 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 322 | case 'n': |
| 323 | reader->state = GRPC_JSON_STATE_VALUE_NULL_U; |
| 324 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 325 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 326 | case '"': |
| 327 | reader->state = GRPC_JSON_STATE_VALUE_STRING; |
| 328 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 329 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 330 | case '0': |
| 331 | json_reader_string_add_char(reader, c); |
| 332 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_ZERO; |
| 333 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 334 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 335 | case '1': |
| 336 | case '2': |
| 337 | case '3': |
| 338 | case '4': |
| 339 | case '5': |
| 340 | case '6': |
| 341 | case '7': |
| 342 | case '8': |
| 343 | case '9': |
| 344 | case '-': |
| 345 | json_reader_string_add_char(reader, c); |
| 346 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER; |
| 347 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 348 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 349 | case '{': |
| 350 | reader->container_just_begun = 1; |
| 351 | json_reader_container_begins(reader, GRPC_JSON_OBJECT); |
| 352 | reader->depth++; |
| 353 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_BEGIN; |
| 354 | reader->in_object = 1; |
| 355 | reader->in_array = 0; |
| 356 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 357 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 358 | case '[': |
| 359 | reader->container_just_begun = 1; |
| 360 | json_reader_container_begins(reader, GRPC_JSON_ARRAY); |
| 361 | reader->depth++; |
| 362 | reader->in_object = 0; |
| 363 | reader->in_array = 1; |
| 364 | break; |
| 365 | } |
| 366 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 367 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 368 | case GRPC_JSON_STATE_STRING_ESCAPE: |
| 369 | if (reader->escaped_string_was_key) { |
| 370 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; |
| 371 | } else { |
| 372 | reader->state = GRPC_JSON_STATE_VALUE_STRING; |
| 373 | } |
| 374 | if (reader->unicode_high_surrogate && c != 'u') |
| 375 | return GRPC_JSON_PARSE_ERROR; |
| 376 | switch (c) { |
| 377 | case '"': |
| 378 | case '/': |
| 379 | json_reader_string_add_char(reader, c); |
| 380 | break; |
| 381 | case 'b': |
| 382 | json_reader_string_add_char(reader, '\b'); |
| 383 | break; |
| 384 | case 'f': |
| 385 | json_reader_string_add_char(reader, '\f'); |
| 386 | break; |
| 387 | case 'n': |
| 388 | json_reader_string_add_char(reader, '\n'); |
| 389 | break; |
| 390 | case 'r': |
| 391 | json_reader_string_add_char(reader, '\r'); |
| 392 | break; |
| 393 | case 't': |
| 394 | json_reader_string_add_char(reader, '\t'); |
| 395 | break; |
| 396 | case 'u': |
| 397 | reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1; |
| 398 | reader->unicode_char = 0; |
| 399 | break; |
| 400 | default: |
| 401 | return GRPC_JSON_PARSE_ERROR; |
| 402 | } |
| 403 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 404 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 405 | case GRPC_JSON_STATE_STRING_ESCAPE_U1: |
| 406 | case GRPC_JSON_STATE_STRING_ESCAPE_U2: |
| 407 | case GRPC_JSON_STATE_STRING_ESCAPE_U3: |
| 408 | case GRPC_JSON_STATE_STRING_ESCAPE_U4: |
| 409 | if ((c >= '0') && (c <= '9')) { |
| 410 | c -= '0'; |
| 411 | } else if ((c >= 'A') && (c <= 'F')) { |
| 412 | c -= 'A' - 10; |
| 413 | } else if ((c >= 'a') && (c <= 'f')) { |
| 414 | c -= 'a' - 10; |
| 415 | } else { |
| 416 | return GRPC_JSON_PARSE_ERROR; |
| 417 | } |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 418 | reader->unicode_char = (uint16_t)(reader->unicode_char << 4); |
| 419 | reader->unicode_char = (uint16_t)(reader->unicode_char | c); |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 420 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 421 | switch (reader->state) { |
| 422 | case GRPC_JSON_STATE_STRING_ESCAPE_U1: |
| 423 | reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U2; |
| 424 | break; |
| 425 | case GRPC_JSON_STATE_STRING_ESCAPE_U2: |
| 426 | reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U3; |
| 427 | break; |
| 428 | case GRPC_JSON_STATE_STRING_ESCAPE_U3: |
| 429 | reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4; |
| 430 | break; |
| 431 | case GRPC_JSON_STATE_STRING_ESCAPE_U4: |
| 432 | /* See grpc_json_writer_escape_string to have a description |
| 433 | * of what's going on here. |
| 434 | */ |
| 435 | if ((reader->unicode_char & 0xfc00) == 0xd800) { |
| 436 | /* high surrogate utf-16 */ |
| 437 | if (reader->unicode_high_surrogate != 0) |
| 438 | return GRPC_JSON_PARSE_ERROR; |
| 439 | reader->unicode_high_surrogate = reader->unicode_char; |
| 440 | } else if ((reader->unicode_char & 0xfc00) == 0xdc00) { |
| 441 | /* low surrogate utf-16 */ |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 442 | uint32_t utf32; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 443 | if (reader->unicode_high_surrogate == 0) |
| 444 | return GRPC_JSON_PARSE_ERROR; |
| 445 | utf32 = 0x10000; |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 446 | utf32 += (uint32_t)( |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 447 | (reader->unicode_high_surrogate - 0xd800) * 0x400); |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 448 | utf32 += (uint32_t)(reader->unicode_char - 0xdc00); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 449 | json_reader_string_add_utf32(reader, utf32); |
| 450 | reader->unicode_high_surrogate = 0; |
| 451 | } else { |
| 452 | /* anything else */ |
| 453 | if (reader->unicode_high_surrogate != 0) |
| 454 | return GRPC_JSON_PARSE_ERROR; |
| 455 | json_reader_string_add_utf32(reader, reader->unicode_char); |
| 456 | } |
| 457 | if (reader->escaped_string_was_key) { |
| 458 | reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING; |
| 459 | } else { |
| 460 | reader->state = GRPC_JSON_STATE_VALUE_STRING; |
| 461 | } |
| 462 | break; |
| 463 | default: |
Nicolas "Pixel" Noble | 11c320d | 2015-12-12 01:47:36 +0100 | [diff] [blame] | 464 | GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 465 | } |
| 466 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 467 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 468 | case GRPC_JSON_STATE_VALUE_NUMBER: |
| 469 | json_reader_string_add_char(reader, c); |
| 470 | switch (c) { |
| 471 | case '0': |
| 472 | case '1': |
| 473 | case '2': |
| 474 | case '3': |
| 475 | case '4': |
| 476 | case '5': |
| 477 | case '6': |
| 478 | case '7': |
| 479 | case '8': |
| 480 | case '9': |
| 481 | break; |
| 482 | case 'e': |
| 483 | case 'E': |
| 484 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E; |
| 485 | break; |
| 486 | case '.': |
| 487 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT; |
| 488 | break; |
| 489 | default: |
| 490 | return GRPC_JSON_PARSE_ERROR; |
| 491 | } |
| 492 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 493 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 494 | case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL: |
| 495 | json_reader_string_add_char(reader, c); |
| 496 | switch (c) { |
| 497 | case '0': |
| 498 | case '1': |
| 499 | case '2': |
| 500 | case '3': |
| 501 | case '4': |
| 502 | case '5': |
| 503 | case '6': |
| 504 | case '7': |
| 505 | case '8': |
| 506 | case '9': |
| 507 | break; |
| 508 | case 'e': |
| 509 | case 'E': |
| 510 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_E; |
| 511 | break; |
| 512 | default: |
| 513 | return GRPC_JSON_PARSE_ERROR; |
| 514 | } |
| 515 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 516 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 517 | case GRPC_JSON_STATE_VALUE_NUMBER_ZERO: |
| 518 | if (c != '.') return GRPC_JSON_PARSE_ERROR; |
| 519 | json_reader_string_add_char(reader, c); |
| 520 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_DOT; |
| 521 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 522 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 523 | case GRPC_JSON_STATE_VALUE_NUMBER_DOT: |
| 524 | json_reader_string_add_char(reader, c); |
| 525 | switch (c) { |
| 526 | case '0': |
| 527 | case '1': |
| 528 | case '2': |
| 529 | case '3': |
| 530 | case '4': |
| 531 | case '5': |
| 532 | case '6': |
| 533 | case '7': |
| 534 | case '8': |
| 535 | case '9': |
| 536 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL; |
| 537 | break; |
| 538 | default: |
| 539 | return GRPC_JSON_PARSE_ERROR; |
| 540 | } |
| 541 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 542 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 543 | case GRPC_JSON_STATE_VALUE_NUMBER_E: |
| 544 | json_reader_string_add_char(reader, c); |
| 545 | switch (c) { |
| 546 | case '0': |
| 547 | case '1': |
| 548 | case '2': |
| 549 | case '3': |
| 550 | case '4': |
| 551 | case '5': |
| 552 | case '6': |
| 553 | case '7': |
| 554 | case '8': |
| 555 | case '9': |
| 556 | case '+': |
| 557 | case '-': |
| 558 | reader->state = GRPC_JSON_STATE_VALUE_NUMBER_EPM; |
| 559 | break; |
| 560 | default: |
| 561 | return GRPC_JSON_PARSE_ERROR; |
| 562 | } |
| 563 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 564 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 565 | case GRPC_JSON_STATE_VALUE_NUMBER_EPM: |
| 566 | json_reader_string_add_char(reader, c); |
| 567 | switch (c) { |
| 568 | case '0': |
| 569 | case '1': |
| 570 | case '2': |
| 571 | case '3': |
| 572 | case '4': |
| 573 | case '5': |
| 574 | case '6': |
| 575 | case '7': |
| 576 | case '8': |
| 577 | case '9': |
| 578 | break; |
| 579 | default: |
| 580 | return GRPC_JSON_PARSE_ERROR; |
| 581 | } |
| 582 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 583 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 584 | case GRPC_JSON_STATE_VALUE_TRUE_R: |
| 585 | if (c != 'r') return GRPC_JSON_PARSE_ERROR; |
| 586 | reader->state = GRPC_JSON_STATE_VALUE_TRUE_U; |
| 587 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 588 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 589 | case GRPC_JSON_STATE_VALUE_TRUE_U: |
| 590 | if (c != 'u') return GRPC_JSON_PARSE_ERROR; |
| 591 | reader->state = GRPC_JSON_STATE_VALUE_TRUE_E; |
| 592 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 593 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 594 | case GRPC_JSON_STATE_VALUE_TRUE_E: |
| 595 | if (c != 'e') return GRPC_JSON_PARSE_ERROR; |
| 596 | json_reader_set_true(reader); |
| 597 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 598 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 599 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 600 | case GRPC_JSON_STATE_VALUE_FALSE_A: |
| 601 | if (c != 'a') return GRPC_JSON_PARSE_ERROR; |
| 602 | reader->state = GRPC_JSON_STATE_VALUE_FALSE_L; |
| 603 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 604 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 605 | case GRPC_JSON_STATE_VALUE_FALSE_L: |
| 606 | if (c != 'l') return GRPC_JSON_PARSE_ERROR; |
| 607 | reader->state = GRPC_JSON_STATE_VALUE_FALSE_S; |
| 608 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 609 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 610 | case GRPC_JSON_STATE_VALUE_FALSE_S: |
| 611 | if (c != 's') return GRPC_JSON_PARSE_ERROR; |
| 612 | reader->state = GRPC_JSON_STATE_VALUE_FALSE_E; |
| 613 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 614 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 615 | case GRPC_JSON_STATE_VALUE_FALSE_E: |
| 616 | if (c != 'e') return GRPC_JSON_PARSE_ERROR; |
| 617 | json_reader_set_false(reader); |
| 618 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 619 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 620 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 621 | case GRPC_JSON_STATE_VALUE_NULL_U: |
| 622 | if (c != 'u') return GRPC_JSON_PARSE_ERROR; |
| 623 | reader->state = GRPC_JSON_STATE_VALUE_NULL_L1; |
| 624 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 625 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 626 | case GRPC_JSON_STATE_VALUE_NULL_L1: |
| 627 | if (c != 'l') return GRPC_JSON_PARSE_ERROR; |
| 628 | reader->state = GRPC_JSON_STATE_VALUE_NULL_L2; |
| 629 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 630 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 631 | case GRPC_JSON_STATE_VALUE_NULL_L2: |
| 632 | if (c != 'l') return GRPC_JSON_PARSE_ERROR; |
| 633 | json_reader_set_null(reader); |
| 634 | reader->state = GRPC_JSON_STATE_VALUE_END; |
| 635 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 636 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 637 | /* All of the VALUE_END cases are handled in the specialized case |
| 638 | * above. */ |
| 639 | case GRPC_JSON_STATE_VALUE_END: |
| 640 | switch (c) { |
| 641 | case ',': |
| 642 | case '}': |
| 643 | case ']': |
Nicolas "Pixel" Noble | 11c320d | 2015-12-12 01:47:36 +0100 | [diff] [blame] | 644 | GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 645 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 646 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 647 | default: |
| 648 | return GRPC_JSON_PARSE_ERROR; |
| 649 | } |
| 650 | break; |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 651 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 652 | case GRPC_JSON_STATE_END: |
| 653 | return GRPC_JSON_PARSE_ERROR; |
| 654 | } |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 655 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 656 | } |
Nicolas Noble | 614c2bf | 2015-01-21 15:48:36 -0800 | [diff] [blame] | 657 | |
Nicolas "Pixel" Noble | 11c320d | 2015-12-12 01:47:36 +0100 | [diff] [blame] | 658 | GPR_UNREACHABLE_CODE(return GRPC_JSON_INTERNAL_ERROR); |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 659 | } |