1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/log.h>
24
25 #include "src/core/lib/json/json_reader.h"
26 #include "src/core/lib/json/json_writer.h"
27 #include "test/core/util/cmdline.h"
28
29 typedef struct json_writer_userdata {
30 FILE* out;
31 } json_writer_userdata;
32
33 typedef struct stacked_container {
34 grpc_json_type type;
35 struct stacked_container* next;
36 } stacked_container;
37
38 typedef struct json_reader_userdata {
39 FILE* in;
40 grpc_json_writer* writer;
41 char* scratchpad;
42 char* ptr;
43 size_t free_space;
44 size_t allocated;
45 size_t string_len;
46 stacked_container* top;
47 } json_reader_userdata;
48
json_writer_output_char(void * userdata,char c)49 static void json_writer_output_char(void* userdata, char c) {
50 json_writer_userdata* state = static_cast<json_writer_userdata*>(userdata);
51 fputc(c, state->out);
52 }
53
json_writer_output_string(void * userdata,const char * str)54 static void json_writer_output_string(void* userdata, const char* str) {
55 json_writer_userdata* state = static_cast<json_writer_userdata*>(userdata);
56 fputs(str, state->out);
57 }
58
json_writer_output_string_with_len(void * userdata,const char * str,size_t len)59 static void json_writer_output_string_with_len(void* userdata, const char* str,
60 size_t len) {
61 json_writer_userdata* state = static_cast<json_writer_userdata*>(userdata);
62 fwrite(str, len, 1, state->out);
63 }
64
65 grpc_json_writer_vtable writer_vtable = {json_writer_output_char,
66 json_writer_output_string,
67 json_writer_output_string_with_len};
68
check_string(json_reader_userdata * state,size_t needed)69 static void check_string(json_reader_userdata* state, size_t needed) {
70 if (state->free_space >= needed) return;
71 needed -= state->free_space;
72 needed = (needed + 0xffu) & ~0xffu;
73 state->scratchpad = static_cast<char*>(
74 gpr_realloc(state->scratchpad, state->allocated + needed));
75 state->free_space += needed;
76 state->allocated += needed;
77 }
78
json_reader_string_clear(void * userdata)79 static void json_reader_string_clear(void* userdata) {
80 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
81 state->free_space = state->allocated;
82 state->string_len = 0;
83 }
84
json_reader_string_add_char(void * userdata,uint32_t c)85 static void json_reader_string_add_char(void* userdata, uint32_t c) {
86 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
87 check_string(state, 1);
88 GPR_ASSERT(c < 256);
89 state->scratchpad[state->string_len++] = static_cast<char>(c);
90 }
91
json_reader_string_add_utf32(void * userdata,uint32_t c)92 static void json_reader_string_add_utf32(void* userdata, uint32_t c) {
93 if (c <= 0x7f) {
94 json_reader_string_add_char(userdata, c);
95 } else if (c <= 0x7ff) {
96 uint32_t b1 = 0xc0u | ((c >> 6u) & 0x1fu);
97 uint32_t b2 = 0x80u | (c & 0x3fu);
98 json_reader_string_add_char(userdata, b1);
99 json_reader_string_add_char(userdata, b2);
100 } else if (c <= 0xffffu) {
101 uint32_t b1 = 0xe0u | ((c >> 12u) & 0x0fu);
102 uint32_t b2 = 0x80u | ((c >> 6u) & 0x3fu);
103 uint32_t b3 = 0x80u | (c & 0x3fu);
104 json_reader_string_add_char(userdata, b1);
105 json_reader_string_add_char(userdata, b2);
106 json_reader_string_add_char(userdata, b3);
107 } else if (c <= 0x1fffffu) {
108 uint32_t b1 = 0xf0u | ((c >> 18u) & 0x07u);
109 uint32_t b2 = 0x80u | ((c >> 12u) & 0x3fu);
110 uint32_t b3 = 0x80u | ((c >> 6u) & 0x3fu);
111 uint32_t b4 = 0x80u | (c & 0x3fu);
112 json_reader_string_add_char(userdata, b1);
113 json_reader_string_add_char(userdata, b2);
114 json_reader_string_add_char(userdata, b3);
115 json_reader_string_add_char(userdata, b4);
116 }
117 }
118
json_reader_read_char(void * userdata)119 static uint32_t json_reader_read_char(void* userdata) {
120 int r;
121 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
122
123 r = fgetc(state->in);
124 if (r == EOF) r = GRPC_JSON_READ_CHAR_EOF;
125 return static_cast<uint32_t>(r);
126 }
127
json_reader_container_begins(void * userdata,grpc_json_type type)128 static void json_reader_container_begins(void* userdata, grpc_json_type type) {
129 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
130 stacked_container* container =
131 static_cast<stacked_container*>(gpr_malloc(sizeof(stacked_container)));
132
133 container->type = type;
134 container->next = state->top;
135 state->top = container;
136
137 grpc_json_writer_container_begins(state->writer, type);
138 }
139
json_reader_container_ends(void * userdata)140 static grpc_json_type json_reader_container_ends(void* userdata) {
141 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
142 stacked_container* container = state->top;
143
144 grpc_json_writer_container_ends(state->writer, container->type);
145 state->top = container->next;
146 gpr_free(container);
147 return state->top ? state->top->type : GRPC_JSON_TOP_LEVEL;
148 }
149
json_reader_set_key(void * userdata)150 static void json_reader_set_key(void* userdata) {
151 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
152 json_reader_string_add_char(userdata, 0);
153
154 grpc_json_writer_object_key(state->writer, state->scratchpad);
155 }
156
json_reader_set_string(void * userdata)157 static void json_reader_set_string(void* userdata) {
158 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
159 json_reader_string_add_char(userdata, 0);
160
161 grpc_json_writer_value_string(state->writer, state->scratchpad);
162 }
163
json_reader_set_number(void * userdata)164 static int json_reader_set_number(void* userdata) {
165 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
166
167 grpc_json_writer_value_raw_with_len(state->writer, state->scratchpad,
168 state->string_len);
169
170 return 1;
171 }
172
json_reader_set_true(void * userdata)173 static void json_reader_set_true(void* userdata) {
174 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
175
176 grpc_json_writer_value_raw_with_len(state->writer, "true", 4);
177 }
178
json_reader_set_false(void * userdata)179 static void json_reader_set_false(void* userdata) {
180 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
181
182 grpc_json_writer_value_raw_with_len(state->writer, "false", 5);
183 }
184
json_reader_set_null(void * userdata)185 static void json_reader_set_null(void* userdata) {
186 json_reader_userdata* state = static_cast<json_reader_userdata*>(userdata);
187
188 grpc_json_writer_value_raw_with_len(state->writer, "null", 4);
189 }
190
191 static grpc_json_reader_vtable reader_vtable = {
192 json_reader_string_clear, json_reader_string_add_char,
193 json_reader_string_add_utf32, json_reader_read_char,
194 json_reader_container_begins, json_reader_container_ends,
195 json_reader_set_key, json_reader_set_string,
196 json_reader_set_number, json_reader_set_true,
197 json_reader_set_false, json_reader_set_null};
198
rewrite(FILE * in,FILE * out,int indent)199 int rewrite(FILE* in, FILE* out, int indent) {
200 grpc_json_writer writer;
201 grpc_json_reader reader;
202 grpc_json_reader_status status;
203 json_writer_userdata writer_user;
204 json_reader_userdata reader_user;
205
206 reader_user.writer = &writer;
207 reader_user.in = in;
208 reader_user.top = nullptr;
209 reader_user.scratchpad = nullptr;
210 reader_user.string_len = 0;
211 reader_user.free_space = 0;
212 reader_user.allocated = 0;
213
214 writer_user.out = out;
215
216 grpc_json_writer_init(&writer, indent, &writer_vtable, &writer_user);
217 grpc_json_reader_init(&reader, &reader_vtable, &reader_user);
218
219 status = grpc_json_reader_run(&reader);
220
221 free(reader_user.scratchpad);
222 while (reader_user.top) {
223 stacked_container* container = reader_user.top;
224 reader_user.top = container->next;
225 free(container);
226 }
227
228 return status == GRPC_JSON_DONE;
229 }
230
main(int argc,char ** argv)231 int main(int argc, char** argv) {
232 int indent = 2;
233 gpr_cmdline* cl;
234
235 cl = gpr_cmdline_create(nullptr);
236 gpr_cmdline_add_int(cl, "indent", nullptr, &indent);
237 gpr_cmdline_parse(cl, argc, argv);
238 gpr_cmdline_destroy(cl);
239
240 return rewrite(stdin, stdout, indent) ? 0 : 1;
241 }
242