Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
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 :
34 : #include <string.h>
35 : #include <stdlib.h>
36 :
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 : */
55 : typedef struct {
56 : grpc_json *top;
57 : grpc_json *current_container;
58 : grpc_json *current_value;
59 : gpr_uint8 *input;
60 : gpr_uint8 *key;
61 : gpr_uint8 *string;
62 : gpr_uint8 *string_ptr;
63 : size_t remaining_input;
64 : } json_reader_userdata;
65 :
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 : */
69 : typedef struct {
70 : char *output;
71 : size_t free_space;
72 : size_t string_len;
73 : size_t allocated;
74 : } json_writer_userdata;
75 :
76 : /* 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 : */
80 1903 : static void json_writer_output_check(void *userdata, size_t needed) {
81 1903 : json_writer_userdata *state = userdata;
82 3806 : if (state->free_space >= needed) return;
83 32 : needed -= state->free_space;
84 : /* Round up by 256 bytes. */
85 32 : needed = (needed + 0xff) & ~0xffU;
86 32 : state->output = gpr_realloc(state->output, state->allocated + needed);
87 32 : state->free_space += needed;
88 32 : state->allocated += needed;
89 : }
90 :
91 : /* These are needed by the writer's implementation. */
92 1851 : static void json_writer_output_char(void *userdata, char c) {
93 1851 : json_writer_userdata *state = userdata;
94 1851 : json_writer_output_check(userdata, 1);
95 1851 : state->output[state->string_len++] = c;
96 1851 : state->free_space--;
97 1851 : }
98 :
99 52 : static void json_writer_output_string_with_len(void *userdata, const char *str,
100 : size_t len) {
101 52 : json_writer_userdata *state = userdata;
102 52 : json_writer_output_check(userdata, len);
103 52 : memcpy(state->output + state->string_len, str, len);
104 52 : state->string_len += len;
105 52 : state->free_space -= len;
106 52 : }
107 :
108 27 : static void json_writer_output_string(void *userdata, const char *str) {
109 27 : size_t len = strlen(str);
110 27 : json_writer_output_string_with_len(userdata, str, len);
111 27 : }
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 : */
116 649 : static void json_reader_string_clear(void *userdata) {
117 649 : json_reader_userdata *state = userdata;
118 649 : if (state->string) {
119 537 : GPR_ASSERT(state->string_ptr < state->input);
120 537 : *state->string_ptr++ = 0;
121 : }
122 649 : state->string = state->string_ptr;
123 649 : }
124 :
125 24968 : static void json_reader_string_add_char(void *userdata, gpr_uint32 c) {
126 24968 : json_reader_userdata *state = userdata;
127 24968 : GPR_ASSERT(state->string_ptr < state->input);
128 24968 : GPR_ASSERT(c <= 0xff);
129 24968 : *state->string_ptr++ = (gpr_uint8)c;
130 24968 : }
131 :
132 : /* We are converting a UTF-32 character into UTF-8 here,
133 : * as described by RFC3629.
134 : */
135 11 : static void json_reader_string_add_utf32(void *userdata, gpr_uint32 c) {
136 11 : if (c <= 0x7f) {
137 4 : json_reader_string_add_char(userdata, c);
138 7 : } else if (c <= 0x7ff) {
139 4 : gpr_uint32 b1 = 0xc0 | ((c >> 6) & 0x1f);
140 4 : gpr_uint32 b2 = 0x80 | (c & 0x3f);
141 4 : json_reader_string_add_char(userdata, b1);
142 4 : json_reader_string_add_char(userdata, b2);
143 3 : } else if (c <= 0xffff) {
144 2 : gpr_uint32 b1 = 0xe0 | ((c >> 12) & 0x0f);
145 2 : gpr_uint32 b2 = 0x80 | ((c >> 6) & 0x3f);
146 2 : gpr_uint32 b3 = 0x80 | (c & 0x3f);
147 2 : json_reader_string_add_char(userdata, b1);
148 2 : json_reader_string_add_char(userdata, b2);
149 2 : json_reader_string_add_char(userdata, b3);
150 1 : } else if (c <= 0x1fffff) {
151 1 : gpr_uint32 b1 = 0xf0 | ((c >> 18) & 0x07);
152 1 : gpr_uint32 b2 = 0x80 | ((c >> 12) & 0x3f);
153 1 : gpr_uint32 b3 = 0x80 | ((c >> 6) & 0x3f);
154 1 : gpr_uint32 b4 = 0x80 | (c & 0x3f);
155 1 : json_reader_string_add_char(userdata, b1);
156 1 : json_reader_string_add_char(userdata, b2);
157 1 : json_reader_string_add_char(userdata, b3);
158 1 : json_reader_string_add_char(userdata, b4);
159 : }
160 11 : }
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 : */
165 27623 : static gpr_uint32 json_reader_read_char(void *userdata) {
166 : gpr_uint32 r;
167 27623 : json_reader_userdata *state = userdata;
168 :
169 27623 : if (state->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF;
170 :
171 27597 : r = *state->input++;
172 27597 : state->remaining_input--;
173 :
174 27597 : if (r == 0) {
175 59 : state->remaining_input = 0;
176 59 : return GRPC_JSON_READ_CHAR_EOF;
177 : }
178 :
179 27538 : 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 : */
185 372 : static grpc_json *json_create_and_link(void *userdata, grpc_json_type type) {
186 372 : json_reader_userdata *state = userdata;
187 372 : grpc_json *json = grpc_json_create(type);
188 :
189 372 : json->parent = state->current_container;
190 372 : json->prev = state->current_value;
191 372 : state->current_value = json;
192 :
193 372 : if (json->prev) {
194 206 : json->prev->next = json;
195 : }
196 372 : if (json->parent) {
197 283 : if (!json->parent->child) {
198 77 : json->parent->child = json;
199 : }
200 283 : if (json->parent->type == GRPC_JSON_OBJECT) {
201 259 : json->key = (char *)state->key;
202 : }
203 : }
204 372 : if (!state->top) {
205 89 : state->top = json;
206 : }
207 :
208 372 : return json;
209 : }
210 :
211 90 : static void json_reader_container_begins(void *userdata, grpc_json_type type) {
212 90 : json_reader_userdata *state = userdata;
213 : grpc_json *container;
214 :
215 90 : GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
216 :
217 90 : container = json_create_and_link(userdata, type);
218 90 : state->current_container = container;
219 90 : state->current_value = NULL;
220 90 : }
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 : */
231 80 : static grpc_json_type json_reader_container_ends(void *userdata) {
232 80 : grpc_json_type container_type = GRPC_JSON_TOP_LEVEL;
233 80 : json_reader_userdata *state = userdata;
234 :
235 80 : GPR_ASSERT(state->current_container);
236 :
237 80 : state->current_value = state->current_container;
238 80 : state->current_container = state->current_container->parent;
239 :
240 80 : if (state->current_container) {
241 12 : container_type = state->current_container->type;
242 : }
243 :
244 80 : 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 : */
253 259 : static void json_reader_set_key(void *userdata) {
254 259 : json_reader_userdata *state = userdata;
255 259 : state->key = state->string;
256 259 : }
257 :
258 236 : static void json_reader_set_string(void *userdata) {
259 236 : json_reader_userdata *state = userdata;
260 236 : grpc_json *json = json_create_and_link(userdata, GRPC_JSON_STRING);
261 236 : json->value = (char *)state->string;
262 236 : }
263 :
264 42 : static int json_reader_set_number(void *userdata) {
265 42 : json_reader_userdata *state = userdata;
266 42 : grpc_json *json = json_create_and_link(userdata, GRPC_JSON_NUMBER);
267 42 : json->value = (char *)state->string;
268 42 : 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 : */
274 2 : static void json_reader_set_true(void *userdata) {
275 2 : json_create_and_link(userdata, GRPC_JSON_TRUE);
276 2 : }
277 :
278 1 : static void json_reader_set_false(void *userdata) {
279 1 : json_create_and_link(userdata, GRPC_JSON_FALSE);
280 1 : }
281 :
282 1 : static void json_reader_set_null(void *userdata) {
283 1 : json_create_and_link(userdata, GRPC_JSON_NULL);
284 1 : }
285 :
286 : static grpc_json_reader_vtable reader_vtable = {
287 : 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};
293 :
294 : /* And finally, let's define our public API. */
295 113 : grpc_json *grpc_json_parse_string_with_len(char *input, size_t size) {
296 : grpc_json_reader reader;
297 : json_reader_userdata state;
298 113 : grpc_json *json = NULL;
299 : grpc_json_reader_status status;
300 :
301 113 : if (!input) return NULL;
302 :
303 112 : state.top = state.current_container = state.current_value = NULL;
304 112 : state.string = state.key = NULL;
305 112 : state.string_ptr = state.input = (gpr_uint8 *)input;
306 112 : state.remaining_input = size;
307 112 : grpc_json_reader_init(&reader, &reader_vtable, &state);
308 :
309 112 : status = grpc_json_reader_run(&reader);
310 112 : json = state.top;
311 :
312 112 : if ((status != GRPC_JSON_DONE) && json) {
313 13 : grpc_json_destroy(json);
314 13 : json = NULL;
315 : }
316 :
317 112 : return json;
318 : }
319 :
320 : #define UNBOUND_JSON_STRING_LENGTH 0x7fffffff
321 :
322 87 : grpc_json *grpc_json_parse_string(char *input) {
323 87 : return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
324 : }
325 :
326 53 : static void json_dump_recursive(grpc_json_writer *writer, grpc_json *json,
327 : int in_object) {
328 217 : while (json) {
329 111 : if (in_object) grpc_json_writer_object_key(writer, json->key);
330 :
331 111 : switch (json->type) {
332 : case GRPC_JSON_OBJECT:
333 : case GRPC_JSON_ARRAY:
334 24 : grpc_json_writer_container_begins(writer, json->type);
335 24 : if (json->child)
336 21 : json_dump_recursive(writer, json->child,
337 21 : json->type == GRPC_JSON_OBJECT);
338 24 : grpc_json_writer_container_ends(writer, json->type);
339 24 : break;
340 : case GRPC_JSON_STRING:
341 56 : grpc_json_writer_value_string(writer, json->value);
342 56 : break;
343 : case GRPC_JSON_NUMBER:
344 27 : grpc_json_writer_value_raw(writer, json->value);
345 27 : break;
346 : case GRPC_JSON_TRUE:
347 2 : grpc_json_writer_value_raw_with_len(writer, "true", 4);
348 2 : break;
349 : case GRPC_JSON_FALSE:
350 1 : grpc_json_writer_value_raw_with_len(writer, "false", 5);
351 1 : break;
352 : case GRPC_JSON_NULL:
353 1 : grpc_json_writer_value_raw_with_len(writer, "null", 4);
354 1 : break;
355 : default:
356 0 : abort();
357 : }
358 111 : json = json->next;
359 : }
360 53 : }
361 :
362 : static grpc_json_writer_vtable writer_vtable = {
363 : json_writer_output_char, json_writer_output_string,
364 : json_writer_output_string_with_len};
365 :
366 32 : char *grpc_json_dump_to_string(grpc_json *json, int indent) {
367 : grpc_json_writer writer;
368 : json_writer_userdata state;
369 :
370 32 : state.output = NULL;
371 32 : state.free_space = state.string_len = state.allocated = 0;
372 32 : grpc_json_writer_init(&writer, indent, &writer_vtable, &state);
373 :
374 32 : json_dump_recursive(&writer, json, 0);
375 :
376 32 : json_writer_output_char(&state, 0);
377 :
378 32 : return state.output;
379 : }
|