Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: third_party/grpc/src/core/json/json_writer.c

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
36 #include <grpc/support/port_platform.h>
37
38 #include "src/core/json/json_writer.h"
39
40 static void json_writer_output_char(grpc_json_writer *writer, char c) {
41 writer->vtable->output_char(writer->userdata, c);
42 }
43
44 static void json_writer_output_string(grpc_json_writer *writer,
45 const char *str) {
46 writer->vtable->output_string(writer->userdata, str);
47 }
48
49 static void json_writer_output_string_with_len(grpc_json_writer *writer,
50 const char *str, size_t len) {
51 writer->vtable->output_string_with_len(writer->userdata, str, len);
52 }
53
54 void grpc_json_writer_init(grpc_json_writer *writer, int indent,
55 grpc_json_writer_vtable *vtable, void *userdata) {
56 memset(writer, 0, sizeof(*writer));
57 writer->container_empty = 1;
58 writer->indent = indent;
59 writer->vtable = vtable;
60 writer->userdata = userdata;
61 }
62
63 static void json_writer_output_indent(grpc_json_writer *writer) {
64 static const char spacesstr[] =
65 " "
66 " "
67 " "
68 " ";
69
70 unsigned spaces = (unsigned)(writer->depth * writer->indent);
71
72 if (writer->indent == 0) return;
73
74 if (writer->got_key) {
75 json_writer_output_char(writer, ' ');
76 return;
77 }
78
79 while (spaces >= (sizeof(spacesstr) - 1)) {
80 json_writer_output_string_with_len(writer, spacesstr,
81 sizeof(spacesstr) - 1);
82 spaces -= (unsigned)(sizeof(spacesstr) - 1);
83 }
84
85 if (spaces == 0) return;
86
87 json_writer_output_string_with_len(
88 writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces);
89 }
90
91 static void json_writer_value_end(grpc_json_writer *writer) {
92 if (writer->container_empty) {
93 writer->container_empty = 0;
94 if ((writer->indent == 0) || (writer->depth == 0)) return;
95 json_writer_output_char(writer, '\n');
96 } else {
97 json_writer_output_char(writer, ',');
98 if (writer->indent == 0) return;
99 json_writer_output_char(writer, '\n');
100 }
101 }
102
103 static void json_writer_escape_utf16(grpc_json_writer *writer, uint16_t utf16) {
104 static const char hex[] = "0123456789abcdef";
105
106 json_writer_output_string_with_len(writer, "\\u", 2);
107 json_writer_output_char(writer, hex[(utf16 >> 12) & 0x0f]);
108 json_writer_output_char(writer, hex[(utf16 >> 8) & 0x0f]);
109 json_writer_output_char(writer, hex[(utf16 >> 4) & 0x0f]);
110 json_writer_output_char(writer, hex[(utf16)&0x0f]);
111 }
112
113 static void json_writer_escape_string(grpc_json_writer *writer,
114 const char *string) {
115 json_writer_output_char(writer, '"');
116
117 for (;;) {
118 uint8_t c = (uint8_t)*string++;
119 if (c == 0) {
120 break;
121 } else if ((c >= 32) && (c <= 126)) {
122 if ((c == '\\') || (c == '"')) json_writer_output_char(writer, '\\');
123 json_writer_output_char(writer, (char)c);
124 } else if ((c < 32) || (c == 127)) {
125 switch (c) {
126 case '\b':
127 json_writer_output_string_with_len(writer, "\\b", 2);
128 break;
129 case '\f':
130 json_writer_output_string_with_len(writer, "\\f", 2);
131 break;
132 case '\n':
133 json_writer_output_string_with_len(writer, "\\n", 2);
134 break;
135 case '\r':
136 json_writer_output_string_with_len(writer, "\\r", 2);
137 break;
138 case '\t':
139 json_writer_output_string_with_len(writer, "\\t", 2);
140 break;
141 default:
142 json_writer_escape_utf16(writer, c);
143 break;
144 }
145 } else {
146 uint32_t utf32 = 0;
147 int extra = 0;
148 int i;
149 int valid = 1;
150 if ((c & 0xe0) == 0xc0) {
151 utf32 = c & 0x1f;
152 extra = 1;
153 } else if ((c & 0xf0) == 0xe0) {
154 utf32 = c & 0x0f;
155 extra = 2;
156 } else if ((c & 0xf8) == 0xf0) {
157 utf32 = c & 0x07;
158 extra = 3;
159 } else {
160 break;
161 }
162 for (i = 0; i < extra; i++) {
163 utf32 <<= 6;
164 c = (uint8_t)(*string++);
165 /* Breaks out and bail on any invalid UTF-8 sequence, including \0. */
166 if ((c & 0xc0) != 0x80) {
167 valid = 0;
168 break;
169 }
170 utf32 |= c & 0x3f;
171 }
172 if (!valid) break;
173 /* The range 0xd800 - 0xdfff is reserved by the surrogates ad vitam.
174 * Any other range is technically reserved for future usage, so if we
175 * don't want the software to break in the future, we have to allow
176 * anything else. The first non-unicode character is 0x110000. */
177 if (((utf32 >= 0xd800) && (utf32 <= 0xdfff)) || (utf32 >= 0x110000))
178 break;
179 if (utf32 >= 0x10000) {
180 /* If utf32 contains a character that is above 0xffff, it needs to be
181 * broken down into a utf-16 surrogate pair. A surrogate pair is first
182 * a high surrogate, followed by a low surrogate. Each surrogate holds
183 * 10 bits of usable data, thus allowing a total of 20 bits of data.
184 * The high surrogate marker is 0xd800, while the low surrogate marker
185 * is 0xdc00. The low 10 bits of each will be the usable data.
186 *
187 * After re-combining the 20 bits of data, one has to add 0x10000 to
188 * the resulting value, in order to obtain the original character.
189 * This is obviously because the range 0x0000 - 0xffff can be written
190 * without any special trick.
191 *
192 * Since 0x10ffff is the highest allowed character, we're working in
193 * the range 0x00000 - 0xfffff after we decrement it by 0x10000.
194 * That range is exactly 20 bits.
195 */
196 utf32 -= 0x10000;
197 json_writer_escape_utf16(writer, (uint16_t)(0xd800 | (utf32 >> 10)));
198 json_writer_escape_utf16(writer, (uint16_t)(0xdc00 | (utf32 & 0x3ff)));
199 } else {
200 json_writer_escape_utf16(writer, (uint16_t)utf32);
201 }
202 }
203 }
204
205 json_writer_output_char(writer, '"');
206 }
207
208 void grpc_json_writer_container_begins(grpc_json_writer *writer,
209 grpc_json_type type) {
210 if (!writer->got_key) json_writer_value_end(writer);
211 json_writer_output_indent(writer);
212 json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
213 writer->container_empty = 1;
214 writer->got_key = 0;
215 writer->depth++;
216 }
217
218 void grpc_json_writer_container_ends(grpc_json_writer *writer,
219 grpc_json_type type) {
220 if (writer->indent && !writer->container_empty)
221 json_writer_output_char(writer, '\n');
222 writer->depth--;
223 if (!writer->container_empty) json_writer_output_indent(writer);
224 json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']');
225 writer->container_empty = 0;
226 writer->got_key = 0;
227 }
228
229 void grpc_json_writer_object_key(grpc_json_writer *writer, const char *string) {
230 json_writer_value_end(writer);
231 json_writer_output_indent(writer);
232 json_writer_escape_string(writer, string);
233 json_writer_output_char(writer, ':');
234 writer->got_key = 1;
235 }
236
237 void grpc_json_writer_value_raw(grpc_json_writer *writer, const char *string) {
238 if (!writer->got_key) json_writer_value_end(writer);
239 json_writer_output_indent(writer);
240 json_writer_output_string(writer, string);
241 writer->got_key = 0;
242 }
243
244 void grpc_json_writer_value_raw_with_len(grpc_json_writer *writer,
245 const char *string, size_t len) {
246 if (!writer->got_key) json_writer_value_end(writer);
247 json_writer_output_indent(writer);
248 json_writer_output_string_with_len(writer, string, len);
249 writer->got_key = 0;
250 }
251
252 void grpc_json_writer_value_string(grpc_json_writer *writer,
253 const char *string) {
254 if (!writer->got_key) json_writer_value_end(writer);
255 json_writer_output_indent(writer);
256 json_writer_escape_string(writer, string);
257 writer->got_key = 0;
258 }
OLDNEW
« no previous file with comments | « third_party/grpc/src/core/json/json_writer.h ('k') | third_party/grpc/src/core/profiling/basic_timers.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698