blob: d4ebce18e161d7befcb92a77b6ea8504e608fdc5 [file] [log] [blame]
Nicolas Noblee04455a2015-01-26 17:01:29 -08001/*
2 *
Craig Tiller2e190362016-03-25 14:33:26 -07003 * Copyright 2015-2016, Google Inc.
Nicolas Noblee04455a2015-01-26 17:01:29 -08004 * 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 Noblee04455a2015-01-26 17:01:29 -080034#include <stdlib.h>
Craig Tillerf40df232016-03-25 13:38:14 -070035#include <string.h>
Nicolas Noblee04455a2015-01-26 17:01:29 -080036
37#include <grpc/support/alloc.h>
38#include <grpc/support/log.h>
39
40#include "src/core/json/json.h"
41#include "src/core/json/json_reader.h"
42#include "src/core/json/json_writer.h"
43
44/* The json reader will construct a bunch of grpc_json objects and
45 * link them all up together in a tree-like structure that will represent
46 * the json data in memory.
47 *
48 * It also uses its own input as a scratchpad to store all of the decoded,
49 * unescaped strings. So we need to keep track of all these pointers in
50 * that opaque structure the reader will carry for us.
51 *
52 * Note that this works because the act of parsing json always reduces its
53 * input size, and never expands it.
54 */
Craig Tillera82950e2015-09-22 12:33:20 -070055typedef struct {
Craig Tiller45724b32015-09-22 10:42:19 -070056 grpc_json *top;
57 grpc_json *current_container;
58 grpc_json *current_value;
Craig Tiller7536af02015-12-22 13:49:30 -080059 uint8_t *input;
60 uint8_t *key;
61 uint8_t *string;
62 uint8_t *string_ptr;
Nicolas Noblee04455a2015-01-26 17:01:29 -080063 size_t remaining_input;
Nicolas Noble8c2be9b2015-01-27 14:21:18 -080064} json_reader_userdata;
Nicolas Noblee04455a2015-01-26 17:01:29 -080065
66/* This json writer will put everything in a big string.
67 * The point is that we allocate that string in chunks of 256 bytes.
68 */
Craig Tillera82950e2015-09-22 12:33:20 -070069typedef struct {
Craig Tiller45724b32015-09-22 10:42:19 -070070 char *output;
Nicolas Noble8c2be9b2015-01-27 14:21:18 -080071 size_t free_space;
72 size_t string_len;
73 size_t allocated;
74} json_writer_userdata;
Nicolas Noblee04455a2015-01-26 17:01:29 -080075
Nicolas Noblee04455a2015-01-26 17:01:29 -080076/* This function checks if there's enough space left in the output buffer,
77 * and will enlarge it if necessary. We're only allocating chunks of 256
78 * bytes at a time (or multiples thereof).
79 */
Craig Tillera82950e2015-09-22 12:33:20 -070080static void json_writer_output_check(void *userdata, size_t needed) {
Craig Tiller45724b32015-09-22 10:42:19 -070081 json_writer_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -070082 if (state->free_space >= needed) return;
Nicolas Noblee04455a2015-01-26 17:01:29 -080083 needed -= state->free_space;
84 /* Round up by 256 bytes. */
murgatroid99482a44c2015-06-19 16:12:22 -070085 needed = (needed + 0xff) & ~0xffU;
Craig Tillera82950e2015-09-22 12:33:20 -070086 state->output = gpr_realloc(state->output, state->allocated + needed);
Nicolas Noblee04455a2015-01-26 17:01:29 -080087 state->free_space += needed;
88 state->allocated += needed;
89}
90
91/* These are needed by the writer's implementation. */
Craig Tillera82950e2015-09-22 12:33:20 -070092static void json_writer_output_char(void *userdata, char c) {
Craig Tiller45724b32015-09-22 10:42:19 -070093 json_writer_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -070094 json_writer_output_check(userdata, 1);
Nicolas Noblee04455a2015-01-26 17:01:29 -080095 state->output[state->string_len++] = c;
96 state->free_space--;
97}
98
Craig Tillera82950e2015-09-22 12:33:20 -070099static void json_writer_output_string_with_len(void *userdata, const char *str,
100 size_t len) {
Craig Tiller45724b32015-09-22 10:42:19 -0700101 json_writer_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -0700102 json_writer_output_check(userdata, len);
103 memcpy(state->output + state->string_len, str, len);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800104 state->string_len += len;
105 state->free_space -= len;
106}
107
Craig Tillera82950e2015-09-22 12:33:20 -0700108static void json_writer_output_string(void *userdata, const char *str) {
109 size_t len = strlen(str);
110 json_writer_output_string_with_len(userdata, str, len);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800111}
112
113/* The reader asks us to clear our scratchpad. In our case, we'll simply mark
114 * the end of the current string, and advance our output pointer.
115 */
Craig Tillera82950e2015-09-22 12:33:20 -0700116static void json_reader_string_clear(void *userdata) {
Craig Tiller45724b32015-09-22 10:42:19 -0700117 json_reader_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -0700118 if (state->string) {
119 GPR_ASSERT(state->string_ptr < state->input);
120 *state->string_ptr++ = 0;
121 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800122 state->string = state->string_ptr;
123}
124
Craig Tiller7536af02015-12-22 13:49:30 -0800125static void json_reader_string_add_char(void *userdata, uint32_t c) {
Craig Tiller45724b32015-09-22 10:42:19 -0700126 json_reader_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -0700127 GPR_ASSERT(state->string_ptr < state->input);
128 GPR_ASSERT(c <= 0xff);
Craig Tiller7536af02015-12-22 13:49:30 -0800129 *state->string_ptr++ = (uint8_t)c;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800130}
131
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800132/* We are converting a UTF-32 character into UTF-8 here,
133 * as described by RFC3629.
134 */
Craig Tiller7536af02015-12-22 13:49:30 -0800135static void json_reader_string_add_utf32(void *userdata, uint32_t c) {
Craig Tillera82950e2015-09-22 12:33:20 -0700136 if (c <= 0x7f) {
137 json_reader_string_add_char(userdata, c);
138 } else if (c <= 0x7ff) {
Craig Tiller7536af02015-12-22 13:49:30 -0800139 uint32_t b1 = 0xc0 | ((c >> 6) & 0x1f);
140 uint32_t b2 = 0x80 | (c & 0x3f);
Craig Tillera82950e2015-09-22 12:33:20 -0700141 json_reader_string_add_char(userdata, b1);
142 json_reader_string_add_char(userdata, b2);
143 } else if (c <= 0xffff) {
Craig Tiller7536af02015-12-22 13:49:30 -0800144 uint32_t b1 = 0xe0 | ((c >> 12) & 0x0f);
145 uint32_t b2 = 0x80 | ((c >> 6) & 0x3f);
146 uint32_t b3 = 0x80 | (c & 0x3f);
Craig Tillera82950e2015-09-22 12:33:20 -0700147 json_reader_string_add_char(userdata, b1);
148 json_reader_string_add_char(userdata, b2);
149 json_reader_string_add_char(userdata, b3);
150 } else if (c <= 0x1fffff) {
Craig Tiller7536af02015-12-22 13:49:30 -0800151 uint32_t b1 = 0xf0 | ((c >> 18) & 0x07);
152 uint32_t b2 = 0x80 | ((c >> 12) & 0x3f);
153 uint32_t b3 = 0x80 | ((c >> 6) & 0x3f);
154 uint32_t b4 = 0x80 | (c & 0x3f);
Craig Tillera82950e2015-09-22 12:33:20 -0700155 json_reader_string_add_char(userdata, b1);
156 json_reader_string_add_char(userdata, b2);
157 json_reader_string_add_char(userdata, b3);
158 json_reader_string_add_char(userdata, b4);
159 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800160}
161
162/* We consider that the input may be a zero-terminated string. So we
163 * can end up hitting eof before the end of the alleged string length.
164 */
Craig Tiller7536af02015-12-22 13:49:30 -0800165static uint32_t json_reader_read_char(void *userdata) {
166 uint32_t r;
Craig Tiller45724b32015-09-22 10:42:19 -0700167 json_reader_userdata *state = userdata;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800168
Craig Tillera82950e2015-09-22 12:33:20 -0700169 if (state->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800170
171 r = *state->input++;
172 state->remaining_input--;
173
Craig Tillera82950e2015-09-22 12:33:20 -0700174 if (r == 0) {
175 state->remaining_input = 0;
176 return GRPC_JSON_READ_CHAR_EOF;
177 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800178
179 return r;
180}
181
182/* Helper function to create a new grpc_json object and link it into
183 * our tree-in-progress inside our opaque structure.
184 */
Craig Tillera82950e2015-09-22 12:33:20 -0700185static grpc_json *json_create_and_link(void *userdata, grpc_json_type type) {
Craig Tiller45724b32015-09-22 10:42:19 -0700186 json_reader_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -0700187 grpc_json *json = grpc_json_create(type);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800188
189 json->parent = state->current_container;
190 json->prev = state->current_value;
191 state->current_value = json;
192
Craig Tillera82950e2015-09-22 12:33:20 -0700193 if (json->prev) {
194 json->prev->next = json;
195 }
196 if (json->parent) {
197 if (!json->parent->child) {
198 json->parent->child = json;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800199 }
Craig Tillera82950e2015-09-22 12:33:20 -0700200 if (json->parent->type == GRPC_JSON_OBJECT) {
201 json->key = (char *)state->key;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800202 }
Craig Tillera82950e2015-09-22 12:33:20 -0700203 }
204 if (!state->top) {
205 state->top = json;
206 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800207
208 return json;
209}
210
Craig Tillera82950e2015-09-22 12:33:20 -0700211static void json_reader_container_begins(void *userdata, grpc_json_type type) {
Craig Tiller45724b32015-09-22 10:42:19 -0700212 json_reader_userdata *state = userdata;
213 grpc_json *container;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800214
Craig Tillera82950e2015-09-22 12:33:20 -0700215 GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800216
Craig Tillera82950e2015-09-22 12:33:20 -0700217 container = json_create_and_link(userdata, type);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800218 state->current_container = container;
219 state->current_value = NULL;
220}
221
222/* It's important to remember that the reader is mostly stateless, so it
223 * isn't trying to remember what the container was prior the one that just
224 * ends. Since we're keeping track of these for our own purpose, we are
225 * able to return that information back, which is useful for it to validate
226 * the input json stream.
227 *
228 * Also note that if we're at the top of the tree, and the last container
229 * ends, we have to return GRPC_JSON_TOP_LEVEL.
230 */
Craig Tillera82950e2015-09-22 12:33:20 -0700231static grpc_json_type json_reader_container_ends(void *userdata) {
Nicolas Noblee04455a2015-01-26 17:01:29 -0800232 grpc_json_type container_type = GRPC_JSON_TOP_LEVEL;
Craig Tiller45724b32015-09-22 10:42:19 -0700233 json_reader_userdata *state = userdata;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800234
Craig Tillera82950e2015-09-22 12:33:20 -0700235 GPR_ASSERT(state->current_container);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800236
237 state->current_value = state->current_container;
238 state->current_container = state->current_container->parent;
239
Craig Tillera82950e2015-09-22 12:33:20 -0700240 if (state->current_container) {
241 container_type = state->current_container->type;
242 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800243
244 return container_type;
245}
246
247/* The next 3 functions basically are the reader asking us to use our string
248 * scratchpad for one of these 3 purposes.
249 *
250 * Note that in the set_number case, we're not going to try interpreting it.
251 * We'll keep it as a string, and leave it to the caller to evaluate it.
252 */
Craig Tillera82950e2015-09-22 12:33:20 -0700253static void json_reader_set_key(void *userdata) {
Craig Tiller45724b32015-09-22 10:42:19 -0700254 json_reader_userdata *state = userdata;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800255 state->key = state->string;
256}
257
Craig Tillera82950e2015-09-22 12:33:20 -0700258static void json_reader_set_string(void *userdata) {
Craig Tiller45724b32015-09-22 10:42:19 -0700259 json_reader_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -0700260 grpc_json *json = json_create_and_link(userdata, GRPC_JSON_STRING);
261 json->value = (char *)state->string;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800262}
263
Craig Tillera82950e2015-09-22 12:33:20 -0700264static int json_reader_set_number(void *userdata) {
Craig Tiller45724b32015-09-22 10:42:19 -0700265 json_reader_userdata *state = userdata;
Craig Tillera82950e2015-09-22 12:33:20 -0700266 grpc_json *json = json_create_and_link(userdata, GRPC_JSON_NUMBER);
267 json->value = (char *)state->string;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800268 return 1;
269}
270
271/* The object types true, false and null are self-sufficient, and don't need
272 * any more information beside their type.
273 */
Craig Tillera82950e2015-09-22 12:33:20 -0700274static void json_reader_set_true(void *userdata) {
275 json_create_and_link(userdata, GRPC_JSON_TRUE);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800276}
277
Craig Tillera82950e2015-09-22 12:33:20 -0700278static void json_reader_set_false(void *userdata) {
279 json_create_and_link(userdata, GRPC_JSON_FALSE);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800280}
281
Craig Tillera82950e2015-09-22 12:33:20 -0700282static void json_reader_set_null(void *userdata) {
283 json_create_and_link(userdata, GRPC_JSON_NULL);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800284}
285
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800286static grpc_json_reader_vtable reader_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700287 json_reader_string_clear, json_reader_string_add_char,
288 json_reader_string_add_utf32, json_reader_read_char,
289 json_reader_container_begins, json_reader_container_ends,
290 json_reader_set_key, json_reader_set_string,
291 json_reader_set_number, json_reader_set_true,
292 json_reader_set_false, json_reader_set_null};
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800293
Nicolas Noblee04455a2015-01-26 17:01:29 -0800294/* And finally, let's define our public API. */
Craig Tillera82950e2015-09-22 12:33:20 -0700295grpc_json *grpc_json_parse_string_with_len(char *input, size_t size) {
Nicolas Noblee04455a2015-01-26 17:01:29 -0800296 grpc_json_reader reader;
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800297 json_reader_userdata state;
Craig Tiller45724b32015-09-22 10:42:19 -0700298 grpc_json *json = NULL;
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800299 grpc_json_reader_status status;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800300
Craig Tillera82950e2015-09-22 12:33:20 -0700301 if (!input) return NULL;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800302
303 state.top = state.current_container = state.current_value = NULL;
304 state.string = state.key = NULL;
Craig Tiller7536af02015-12-22 13:49:30 -0800305 state.string_ptr = state.input = (uint8_t *)input;
Nicolas Noblee04455a2015-01-26 17:01:29 -0800306 state.remaining_input = size;
Craig Tillera82950e2015-09-22 12:33:20 -0700307 grpc_json_reader_init(&reader, &reader_vtable, &state);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800308
Craig Tillera82950e2015-09-22 12:33:20 -0700309 status = grpc_json_reader_run(&reader);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800310 json = state.top;
311
Craig Tillera82950e2015-09-22 12:33:20 -0700312 if ((status != GRPC_JSON_DONE) && json) {
313 grpc_json_destroy(json);
314 json = NULL;
315 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800316
317 return json;
318}
319
320#define UNBOUND_JSON_STRING_LENGTH 0x7fffffff
321
Craig Tillera82950e2015-09-22 12:33:20 -0700322grpc_json *grpc_json_parse_string(char *input) {
323 return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800324}
325
Craig Tillera82950e2015-09-22 12:33:20 -0700326static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json,
327 int in_object) {
328 while (json) {
329 if (in_object) grpc_json_writer_object_key(writer, json->key);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800330
Craig Tillera82950e2015-09-22 12:33:20 -0700331 switch (json->type) {
332 case GRPC_JSON_OBJECT:
333 case GRPC_JSON_ARRAY:
334 grpc_json_writer_container_begins(writer, json->type);
335 if (json->child)
336 json_dump_recursive(writer, json->child,
337 json->type == GRPC_JSON_OBJECT);
338 grpc_json_writer_container_ends(writer, json->type);
339 break;
340 case GRPC_JSON_STRING:
341 grpc_json_writer_value_string(writer, json->value);
342 break;
343 case GRPC_JSON_NUMBER:
344 grpc_json_writer_value_raw(writer, json->value);
345 break;
346 case GRPC_JSON_TRUE:
347 grpc_json_writer_value_raw_with_len(writer, "true", 4);
348 break;
349 case GRPC_JSON_FALSE:
350 grpc_json_writer_value_raw_with_len(writer, "false", 5);
351 break;
352 case GRPC_JSON_NULL:
353 grpc_json_writer_value_raw_with_len(writer, "null", 4);
354 break;
355 default:
Nicolas "Pixel" Noble11c320d2015-12-12 01:47:36 +0100356 GPR_UNREACHABLE_CODE(abort());
Nicolas Noblee04455a2015-01-26 17:01:29 -0800357 }
Craig Tillera82950e2015-09-22 12:33:20 -0700358 json = json->next;
359 }
Nicolas Noblee04455a2015-01-26 17:01:29 -0800360}
361
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800362static grpc_json_writer_vtable writer_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700363 json_writer_output_char, json_writer_output_string,
364 json_writer_output_string_with_len};
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800365
Craig Tillera82950e2015-09-22 12:33:20 -0700366char *grpc_json_dump_to_string(grpc_json *json, int indent) {
Nicolas Noblee04455a2015-01-26 17:01:29 -0800367 grpc_json_writer writer;
Nicolas Noble8c2be9b2015-01-27 14:21:18 -0800368 json_writer_userdata state;
369
Nicolas Noblee04455a2015-01-26 17:01:29 -0800370 state.output = NULL;
371 state.free_space = state.string_len = state.allocated = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700372 grpc_json_writer_init(&writer, indent, &writer_vtable, &state);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800373
Craig Tillera82950e2015-09-22 12:33:20 -0700374 json_dump_recursive(&writer, json, 0);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800375
Craig Tillera82950e2015-09-22 12:33:20 -0700376 json_writer_output_char(&state, 0);
Nicolas Noblee04455a2015-01-26 17:01:29 -0800377
378 return state.output;
Craig Tiller190d3602015-02-18 09:23:38 -0800379}