json_encode.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Google LLC nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "upb/json_encode.h"
29 
30 #include <ctype.h>
31 #include <float.h>
32 #include <inttypes.h>
33 #include <math.h>
34 #include <setjmp.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <string.h>
38 
39 #include "upb/decode.h"
40 #include "upb/reflection.h"
41 #include "upb/upb_internal.h"
42 
43 /* Must be last. */
44 #include "upb/port_def.inc"
45 
46 typedef struct {
47  char *buf, *ptr, *end;
48  size_t overflow;
49  int indent_depth;
50  int options;
52  jmp_buf err;
55 } jsonenc;
56 
57 static void jsonenc_msg(jsonenc* e, const upb_Message* msg,
58  const upb_MessageDef* m);
59 static void jsonenc_scalar(jsonenc* e, upb_MessageValue val,
60  const upb_FieldDef* f);
61 static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg,
62  const upb_MessageDef* m);
63 static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg,
64  const upb_MessageDef* m, bool first);
65 static void jsonenc_value(jsonenc* e, const upb_Message* msg,
66  const upb_MessageDef* m);
67 
68 UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) {
69  upb_Status_SetErrorMessage(e->status, msg);
70  longjmp(e->err, 1);
71 }
72 
73 UPB_PRINTF(2, 3)
74 UPB_NORETURN static void jsonenc_errf(jsonenc* e, const char* fmt, ...) {
75  va_list argp;
76  va_start(argp, fmt);
77  upb_Status_VSetErrorFormat(e->status, fmt, argp);
78  va_end(argp);
79  longjmp(e->err, 1);
80 }
81 
83  /* Create lazily, since it's only needed for Any */
84  if (!e->arena) {
85  e->arena = upb_Arena_New();
86  }
87  return e->arena;
88 }
89 
90 static void jsonenc_putbytes(jsonenc* e, const void* data, size_t len) {
91  size_t have = e->end - e->ptr;
92  if (UPB_LIKELY(have >= len)) {
93  memcpy(e->ptr, data, len);
94  e->ptr += len;
95  } else {
96  if (have) {
97  memcpy(e->ptr, data, have);
98  e->ptr += have;
99  }
100  e->overflow += (len - have);
101  }
102 }
103 
104 static void jsonenc_putstr(jsonenc* e, const char* str) {
105  jsonenc_putbytes(e, str, strlen(str));
106 }
107 
108 UPB_PRINTF(2, 3)
109 static void jsonenc_printf(jsonenc* e, const char* fmt, ...) {
110  size_t n;
111  size_t have = e->end - e->ptr;
112  va_list args;
113 
114  va_start(args, fmt);
115  n = vsnprintf(e->ptr, have, fmt, args);
116  va_end(args);
117 
118  if (UPB_LIKELY(have > n)) {
119  e->ptr += n;
120  } else {
121  e->ptr = UPB_PTRADD(e->ptr, have);
122  e->overflow += (n - have);
123  }
124 }
125 
126 static void jsonenc_nanos(jsonenc* e, int32_t nanos) {
127  int digits = 9;
128 
129  if (nanos == 0) return;
130  if (nanos < 0 || nanos >= 1000000000) {
131  jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos");
132  }
133 
134  while (nanos % 1000 == 0) {
135  nanos /= 1000;
136  digits -= 3;
137  }
138 
139  jsonenc_printf(e, ".%.*" PRId32, digits, nanos);
140 }
141 
142 static void jsonenc_timestamp(jsonenc* e, const upb_Message* msg,
143  const upb_MessageDef* m) {
144  const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1);
145  const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2);
147  int32_t nanos = upb_Message_Get(msg, nanos_f).int32_val;
148  int L, N, I, J, K, hour, min, sec;
149 
150  if (seconds < -62135596800) {
151  jsonenc_err(e,
152  "error formatting timestamp as JSON: minimum acceptable value "
153  "is 0001-01-01T00:00:00Z");
154  } else if (seconds > 253402300799) {
155  jsonenc_err(e,
156  "error formatting timestamp as JSON: maximum acceptable value "
157  "is 9999-12-31T23:59:59Z");
158  }
159 
160  /* Julian Day -> Y/M/D, Algorithm from:
161  * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
162  * Processing Calendar Dates," Communications of the Association of
163  * Computing Machines, vol. 11 (1968), p. 657. */
164  seconds += 62135596800; // Ensure seconds is positive.
165  L = (int)(seconds / 86400) - 719162 + 68569 + 2440588;
166  N = 4 * L / 146097;
167  L = L - (146097 * N + 3) / 4;
168  I = 4000 * (L + 1) / 1461001;
169  L = L - 1461 * I / 4 + 31;
170  J = 80 * L / 2447;
171  K = L - 2447 * J / 80;
172  L = J / 11;
173  J = J + 2 - 12 * L;
174  I = 100 * (N - 49) + I + L;
175 
176  sec = seconds % 60;
177  min = (seconds / 60) % 60;
178  hour = (seconds / 3600) % 24;
179 
180  jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec);
181  jsonenc_nanos(e, nanos);
182  jsonenc_putstr(e, "Z\"");
183 }
184 
185 static void jsonenc_duration(jsonenc* e, const upb_Message* msg,
186  const upb_MessageDef* m) {
187  const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1);
188  const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2);
190  int32_t nanos = upb_Message_Get(msg, nanos_f).int32_val;
191 
192  if (seconds > 315576000000 || seconds < -315576000000 ||
193  (seconds < 0) != (nanos < 0)) {
194  jsonenc_err(e, "bad duration");
195  }
196 
197  if (nanos < 0) {
198  nanos = -nanos;
199  }
200 
201  jsonenc_printf(e, "\"%" PRId64, seconds);
202  jsonenc_nanos(e, nanos);
203  jsonenc_putstr(e, "s\"");
204 }
205 
206 static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) {
207  const upb_EnumDef* e_def = upb_FieldDef_EnumSubDef(f);
208 
209  if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) {
210  jsonenc_putstr(e, "null");
211  } else {
212  const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e_def, val);
213 
214  if (ev) {
215  jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev));
216  } else {
217  jsonenc_printf(e, "%" PRId32, val);
218  }
219  }
220 }
221 
223  /* This is the regular base64, not the "web-safe" version. */
224  static const char base64[] =
225  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
226  const unsigned char* ptr = (unsigned char*)str.data;
227  const unsigned char* end = UPB_PTRADD(ptr, str.size);
228  char buf[4];
229 
230  jsonenc_putstr(e, "\"");
231 
232  while (end - ptr >= 3) {
233  buf[0] = base64[ptr[0] >> 2];
234  buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
235  buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)];
236  buf[3] = base64[ptr[2] & 0x3f];
237  jsonenc_putbytes(e, buf, 4);
238  ptr += 3;
239  }
240 
241  switch (end - ptr) {
242  case 2:
243  buf[0] = base64[ptr[0] >> 2];
244  buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
245  buf[2] = base64[(ptr[1] & 0xf) << 2];
246  buf[3] = '=';
247  jsonenc_putbytes(e, buf, 4);
248  break;
249  case 1:
250  buf[0] = base64[ptr[0] >> 2];
251  buf[1] = base64[((ptr[0] & 0x3) << 4)];
252  buf[2] = '=';
253  buf[3] = '=';
254  jsonenc_putbytes(e, buf, 4);
255  break;
256  }
257 
258  jsonenc_putstr(e, "\"");
259 }
260 
262  const char* ptr = str.data;
263  const char* end = UPB_PTRADD(ptr, str.size);
264 
265  while (ptr < end) {
266  switch (*ptr) {
267  case '\n':
268  jsonenc_putstr(e, "\\n");
269  break;
270  case '\r':
271  jsonenc_putstr(e, "\\r");
272  break;
273  case '\t':
274  jsonenc_putstr(e, "\\t");
275  break;
276  case '\"':
277  jsonenc_putstr(e, "\\\"");
278  break;
279  case '\f':
280  jsonenc_putstr(e, "\\f");
281  break;
282  case '\b':
283  jsonenc_putstr(e, "\\b");
284  break;
285  case '\\':
286  jsonenc_putstr(e, "\\\\");
287  break;
288  default:
289  if ((uint8_t)*ptr < 0x20) {
290  jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr);
291  } else {
292  /* This could be a non-ASCII byte. We rely on the string being valid
293  * UTF-8. */
294  jsonenc_putbytes(e, ptr, 1);
295  }
296  break;
297  }
298  ptr++;
299  }
300 }
301 
303  jsonenc_putstr(e, "\"");
305  jsonenc_putstr(e, "\"");
306 }
307 
308 static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) {
309  if (val == INFINITY) {
310  jsonenc_putstr(e, "\"Infinity\"");
311  } else if (val == -INFINITY) {
312  jsonenc_putstr(e, "\"-Infinity\"");
313  } else if (val != val) {
314  jsonenc_putstr(e, "\"NaN\"");
315  } else {
316  return false;
317  }
318  return true;
319 }
320 
321 static void upb_JsonEncode_Double(jsonenc* e, double val) {
322  if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return;
323  char buf[32];
324  _upb_EncodeRoundTripDouble(val, buf, sizeof(buf));
325  jsonenc_putstr(e, buf);
326 }
327 
328 static void upb_JsonEncode_Float(jsonenc* e, float val) {
329  if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return;
330  char buf[32];
331  _upb_EncodeRoundTripFloat(val, buf, sizeof(buf));
332  jsonenc_putstr(e, buf);
333 }
334 
335 static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg,
336  const upb_MessageDef* m) {
338  upb_MessageValue val = upb_Message_Get(msg, val_f);
339  jsonenc_scalar(e, val, val_f);
340 }
341 
344  /* Find last '/', if any. */
345  const char* end = type_url.data + type_url.size;
346  const char* ptr = end;
347  const upb_MessageDef* ret;
348 
349  if (!e->ext_pool) {
350  jsonenc_err(e, "Tried to encode Any, but no symtab was provided");
351  }
352 
353  if (type_url.size == 0) goto badurl;
354 
355  while (true) {
356  if (--ptr == type_url.data) {
357  /* Type URL must contain at least one '/', with host before. */
358  goto badurl;
359  }
360  if (*ptr == '/') {
361  ptr++;
362  break;
363  }
364  }
365 
367 
368  if (!ret) {
369  jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr);
370  }
371 
372  return ret;
373 
374 badurl:
375  jsonenc_errf(e, "Bad type URL: " UPB_STRINGVIEW_FORMAT,
377 }
378 
379 static void jsonenc_any(jsonenc* e, const upb_Message* msg,
380  const upb_MessageDef* m) {
381  const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1);
382  const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2);
385  const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url);
386  const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
388  upb_Message* any = upb_Message_New(any_m, arena);
389 
390  if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) !=
392  jsonenc_err(e, "Error decoding message in Any");
393  }
394 
395  jsonenc_putstr(e, "{\"@type\":");
397 
399  /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */
400  jsonenc_msgfields(e, any, any_m, false);
401  } else {
402  /* Well-known type: {"@type": "...","value": <well-known encoding>} */
403  jsonenc_putstr(e, ",\"value\":");
404  jsonenc_msgfield(e, any, any_m);
405  }
406 
407  jsonenc_putstr(e, "}");
408 }
409 
410 static void jsonenc_putsep(jsonenc* e, const char* str, bool* first) {
411  if (*first) {
412  *first = false;
413  } else {
414  jsonenc_putstr(e, str);
415  }
416 }
417 
419  const char* ptr = path.data;
420  const char* end = ptr + path.size;
421 
422  while (ptr < end) {
423  char ch = *ptr;
424 
425  if (ch >= 'A' && ch <= 'Z') {
426  jsonenc_err(e, "Field mask element may not have upper-case letter.");
427  } else if (ch == '_') {
428  if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') {
429  jsonenc_err(e, "Underscore must be followed by a lowercase letter.");
430  }
431  ch = *++ptr - 32;
432  }
433 
434  jsonenc_putbytes(e, &ch, 1);
435  ptr++;
436  }
437 }
438 
439 static void jsonenc_fieldmask(jsonenc* e, const upb_Message* msg,
440  const upb_MessageDef* m) {
441  const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1);
442  const upb_Array* paths = upb_Message_Get(msg, paths_f).array_val;
443  bool first = true;
444  size_t i, n = 0;
445 
446  if (paths) n = upb_Array_Size(paths);
447 
448  jsonenc_putstr(e, "\"");
449 
450  for (i = 0; i < n; i++) {
451  jsonenc_putsep(e, ",", &first);
452  jsonenc_fieldpath(e, upb_Array_Get(paths, i).str_val);
453  }
454 
455  jsonenc_putstr(e, "\"");
456 }
457 
458 static void jsonenc_struct(jsonenc* e, const upb_Message* msg,
459  const upb_MessageDef* m) {
460  const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
461  const upb_Map* fields = upb_Message_Get(msg, fields_f).map_val;
462  const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
463  const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
464  size_t iter = kUpb_Map_Begin;
465  bool first = true;
466 
467  jsonenc_putstr(e, "{");
468 
469  if (fields) {
470  while (upb_MapIterator_Next(fields, &iter)) {
473 
474  jsonenc_putsep(e, ",", &first);
475  jsonenc_string(e, key.str_val);
476  jsonenc_putstr(e, ":");
478  }
479  }
480 
481  jsonenc_putstr(e, "}");
482 }
483 
484 static void jsonenc_listvalue(jsonenc* e, const upb_Message* msg,
485  const upb_MessageDef* m) {
486  const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1);
487  const upb_MessageDef* values_m = upb_FieldDef_MessageSubDef(values_f);
488  const upb_Array* values = upb_Message_Get(msg, values_f).array_val;
489  size_t i;
490  bool first = true;
491 
492  jsonenc_putstr(e, "[");
493 
494  if (values) {
495  const size_t size = upb_Array_Size(values);
496  for (i = 0; i < size; i++) {
498 
499  jsonenc_putsep(e, ",", &first);
500  jsonenc_value(e, elem.msg_val, values_m);
501  }
502  }
503 
504  jsonenc_putstr(e, "]");
505 }
506 
507 static void jsonenc_value(jsonenc* e, const upb_Message* msg,
508  const upb_MessageDef* m) {
509  /* TODO(haberman): do we want a reflection method to get oneof case? */
510  size_t iter = kUpb_Message_Begin;
511  const upb_FieldDef* f;
512  upb_MessageValue val;
513 
514  if (!upb_Message_Next(msg, m, NULL, &f, &val, &iter)) {
515  jsonenc_err(e, "No value set in Value proto");
516  }
517 
518  switch (upb_FieldDef_Number(f)) {
519  case 1:
520  jsonenc_putstr(e, "null");
521  break;
522  case 2:
524  break;
525  case 3:
526  jsonenc_string(e, val.str_val);
527  break;
528  case 4:
529  jsonenc_putstr(e, val.bool_val ? "true" : "false");
530  break;
531  case 5:
533  break;
534  case 6:
536  break;
537  }
538 }
539 
540 static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg,
541  const upb_MessageDef* m) {
542  switch (upb_MessageDef_WellKnownType(m)) {
544  jsonenc_msg(e, msg, m);
545  break;
546  case kUpb_WellKnown_Any:
547  jsonenc_any(e, msg, m);
548  break;
550  jsonenc_fieldmask(e, msg, m);
551  break;
553  jsonenc_duration(e, msg, m);
554  break;
556  jsonenc_timestamp(e, msg, m);
557  break;
567  jsonenc_wrapper(e, msg, m);
568  break;
570  jsonenc_value(e, msg, m);
571  break;
573  jsonenc_listvalue(e, msg, m);
574  break;
576  jsonenc_struct(e, msg, m);
577  break;
578  }
579 }
580 
582  const upb_FieldDef* f) {
583  switch (upb_FieldDef_CType(f)) {
584  case kUpb_CType_Bool:
585  jsonenc_putstr(e, val.bool_val ? "true" : "false");
586  break;
587  case kUpb_CType_Float:
589  break;
590  case kUpb_CType_Double:
592  break;
593  case kUpb_CType_Int32:
594  jsonenc_printf(e, "%" PRId32, val.int32_val);
595  break;
596  case kUpb_CType_UInt32:
597  jsonenc_printf(e, "%" PRIu32, val.uint32_val);
598  break;
599  case kUpb_CType_Int64:
600  jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val);
601  break;
602  case kUpb_CType_UInt64:
603  jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val);
604  break;
605  case kUpb_CType_String:
606  jsonenc_string(e, val.str_val);
607  break;
608  case kUpb_CType_Bytes:
609  jsonenc_bytes(e, val.str_val);
610  break;
611  case kUpb_CType_Enum:
612  jsonenc_enum(val.int32_val, f, e);
613  break;
614  case kUpb_CType_Message:
616  break;
617  }
618 }
619 
621  const upb_FieldDef* f) {
622  jsonenc_putstr(e, "\"");
623 
624  switch (upb_FieldDef_CType(f)) {
625  case kUpb_CType_Bool:
626  jsonenc_putstr(e, val.bool_val ? "true" : "false");
627  break;
628  case kUpb_CType_Int32:
629  jsonenc_printf(e, "%" PRId32, val.int32_val);
630  break;
631  case kUpb_CType_UInt32:
632  jsonenc_printf(e, "%" PRIu32, val.uint32_val);
633  break;
634  case kUpb_CType_Int64:
635  jsonenc_printf(e, "%" PRId64, val.int64_val);
636  break;
637  case kUpb_CType_UInt64:
638  jsonenc_printf(e, "%" PRIu64, val.uint64_val);
639  break;
640  case kUpb_CType_String:
641  jsonenc_stringbody(e, val.str_val);
642  break;
643  default:
644  UPB_UNREACHABLE();
645  }
646 
647  jsonenc_putstr(e, "\":");
648 }
649 
650 static void jsonenc_array(jsonenc* e, const upb_Array* arr,
651  const upb_FieldDef* f) {
652  size_t i;
653  size_t size = arr ? upb_Array_Size(arr) : 0;
654  bool first = true;
655 
656  jsonenc_putstr(e, "[");
657 
658  for (i = 0; i < size; i++) {
659  jsonenc_putsep(e, ",", &first);
660  jsonenc_scalar(e, upb_Array_Get(arr, i), f);
661  }
662 
663  jsonenc_putstr(e, "]");
664 }
665 
666 static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) {
668  const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1);
669  const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2);
670  size_t iter = kUpb_Map_Begin;
671  bool first = true;
672 
673  jsonenc_putstr(e, "{");
674 
675  if (map) {
676  while (upb_MapIterator_Next(map, &iter)) {
677  jsonenc_putsep(e, ",", &first);
680  }
681  }
682 
683  jsonenc_putstr(e, "}");
684 }
685 
686 static void jsonenc_fieldval(jsonenc* e, const upb_FieldDef* f,
687  upb_MessageValue val, bool* first) {
688  const char* name;
689 
690  jsonenc_putsep(e, ",", first);
691 
693  // TODO: For MessageSet, I would have expected this to print the message
694  // name here, but Python doesn't appear to do this. We should do more
695  // research here about what various implementations do.
696  jsonenc_printf(e, "\"[%s]\":", upb_FieldDef_FullName(f));
697  } else {
698  if (e->options & upb_JsonEncode_UseProtoNames) {
700  } else {
702  }
703  jsonenc_printf(e, "\"%s\":", name);
704  }
705 
706  if (upb_FieldDef_IsMap(f)) {
707  jsonenc_map(e, val.map_val, f);
708  } else if (upb_FieldDef_IsRepeated(f)) {
709  jsonenc_array(e, val.array_val, f);
710  } else {
711  jsonenc_scalar(e, val, f);
712  }
713 }
714 
715 static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg,
716  const upb_MessageDef* m, bool first) {
717  upb_MessageValue val;
718  const upb_FieldDef* f;
719 
720  if (e->options & upb_JsonEncode_EmitDefaults) {
721  /* Iterate over all fields. */
722  int i = 0;
724  for (i = 0; i < n; i++) {
728  }
729  }
730  } else {
731  /* Iterate over non-empty fields. */
732  size_t iter = kUpb_Message_Begin;
733  while (upb_Message_Next(msg, m, e->ext_pool, &f, &val, &iter)) {
734  jsonenc_fieldval(e, f, val, &first);
735  }
736  }
737 }
738 
739 static void jsonenc_msg(jsonenc* e, const upb_Message* msg,
740  const upb_MessageDef* m) {
741  jsonenc_putstr(e, "{");
742  jsonenc_msgfields(e, msg, m, true);
743  jsonenc_putstr(e, "}");
744 }
745 
746 static size_t jsonenc_nullz(jsonenc* e, size_t size) {
747  size_t ret = e->ptr - e->buf + e->overflow;
748 
749  if (size > 0) {
750  if (e->ptr == e->end) e->ptr--;
751  *e->ptr = '\0';
752  }
753 
754  return ret;
755 }
756 
758  const upb_DefPool* ext_pool, int options, char* buf,
759  size_t size, upb_Status* status) {
760  jsonenc e;
761 
762  e.buf = buf;
763  e.ptr = buf;
764  e.end = UPB_PTRADD(buf, size);
765  e.overflow = 0;
766  e.options = options;
767  e.ext_pool = ext_pool;
768  e.status = status;
769  e.arena = NULL;
770 
771  if (setjmp(e.err)) return -1;
772 
773  jsonenc_msgfield(&e, msg, m);
774  if (e.arena) upb_Arena_Free(e.arena);
775  return jsonenc_nullz(&e, size);
776 }
kUpb_WellKnown_StringValue
@ kUpb_WellKnown_StringValue
Definition: upb/upb/def.h:85
xds_interop_client.str
str
Definition: xds_interop_client.py:487
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
upb_FieldDef_Number
uint32_t upb_FieldDef_Number(const upb_FieldDef *f)
Definition: upb/upb/def.c:541
absl::time_internal::cctz::seconds
std::chrono::duration< std::int_fast64_t > seconds
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h:40
upb_internal.h
upb_MessageValue::uint32_val
uint32_t uint32_val
Definition: upb/upb/reflection.h:46
jsonenc_fieldpath
static void jsonenc_fieldpath(jsonenc *e, upb_StringView path)
Definition: json_encode.c:418
kUpb_CType_String
@ kUpb_CType_String
Definition: upb/upb/upb.h:296
upb_MapIterator_Key
upb_MessageValue upb_MapIterator_Key(const upb_Map *map, size_t iter)
Definition: reflection.c:461
upb_MessageValue::int64_val
int64_t int64_val
Definition: upb/upb/reflection.h:45
kUpb_CType_UInt32
@ kUpb_CType_UInt32
Definition: upb/upb/upb.h:290
test_server.argp
argp
Definition: test_server.py:33
vsnprintf
int __cdecl vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
Definition: libc.cpp:135
jsonenc_msgfields
static void jsonenc_msgfields(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m, bool first)
Definition: json_encode.c:715
jsonenc::status
upb_Status * status
Definition: json_encode.c:53
kUpb_CType_Int32
@ kUpb_CType_Int32
Definition: upb/upb/upb.h:289
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
jsonenc_mapkey
static void jsonenc_mapkey(jsonenc *e, upb_MessageValue val, const upb_FieldDef *f)
Definition: json_encode.c:620
kUpb_Map_Begin
#define kUpb_Map_Begin
Definition: upb/upb/upb.h:329
jsonenc_any
static void jsonenc_any(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:379
upb_MessageDef_MiniTable
const upb_MiniTable * upb_MessageDef_MiniTable(const upb_MessageDef *m)
Definition: upb/upb/def.c:818
UPB_STRINGVIEW_ARGS
#define UPB_STRINGVIEW_ARGS(view)
Definition: upb/upb/upb.h:97
upb_Decode
upb_DecodeStatus upb_Decode(const char *buf, size_t size, void *msg, const upb_MiniTable *l, const upb_ExtensionRegistry *extreg, int options, upb_Arena *arena)
Definition: decode.c:1076
upb_EnumValueDef_Name
const char * upb_EnumValueDef_Name(const upb_EnumValueDef *ev)
Definition: upb/upb/def.c:454
upb_MessageDef
Definition: upb/upb/def.c:100
jsonenc_printf
static void jsonenc_printf(jsonenc *e, const char *fmt,...)
Definition: json_encode.c:109
string.h
options
double_dict options[]
Definition: capstone_test.c:55
jsonenc::ext_pool
const upb_DefPool * ext_pool
Definition: json_encode.c:51
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
kUpb_CType_Bytes
@ kUpb_CType_Bytes
Definition: upb/upb/upb.h:297
elem
Timer elem
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:109
kUpb_DecodeStatus_Ok
@ kUpb_DecodeStatus_Ok
Definition: decode.h:72
UPB_UNREACHABLE
#define UPB_UNREACHABLE()
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:145
error_ref_leak.err
err
Definition: error_ref_leak.py:35
jsonenc_fieldmask
static void jsonenc_fieldmask(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:439
upb_MessageValue::str_val
upb_StringView str_val
Definition: upb/upb/reflection.h:51
jsonenc_value
static void jsonenc_value(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:507
status
absl::Status status
Definition: rls.cc:251
upb_MiniTable
Definition: msg_internal.h:185
upb_JsonEncode
size_t upb_JsonEncode(const upb_Message *msg, const upb_MessageDef *m, const upb_DefPool *ext_pool, int options, char *buf, size_t size, upb_Status *status)
Definition: json_encode.c:757
jsonenc_nanos
static void jsonenc_nanos(jsonenc *e, int32_t nanos)
Definition: json_encode.c:126
setup.name
name
Definition: setup.py:542
check_documentation.path
path
Definition: check_documentation.py:57
upb_MessageValue::int32_val
int32_t int32_val
Definition: upb/upb/reflection.h:44
jsonenc_arena
static upb_Arena * jsonenc_arena(jsonenc *e)
Definition: json_encode.c:82
upb_Array_Get
upb_MessageValue upb_Array_Get(const upb_Array *arr, size_t i)
Definition: reflection.c:364
jsonenc
Definition: php-upb.c:8814
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
UPB_PRINTF
#define UPB_PRINTF(str, first_vararg)
Definition: php-upb.c:122
map
zval * map
Definition: php/ext/google/protobuf/encode_decode.c:480
json_encode.h
upb_Arena_New
UPB_INLINE upb_Arena * upb_Arena_New(void)
Definition: upb/upb/upb.h:267
kUpb_CType_Int64
@ kUpb_CType_Int64
Definition: upb/upb/upb.h:294
upb_MessageValue::double_val
double double_val
Definition: upb/upb/reflection.h:43
arena
grpc_core::ScopedArenaPtr arena
Definition: binder_transport_test.cc:237
upb_MessageValue::array_val
const upb_Array * array_val
Definition: upb/upb/reflection.h:50
upb_JsonEncode_Double
static void upb_JsonEncode_Double(jsonenc *e, double val)
Definition: json_encode.c:321
upb_MessageValue::bool_val
bool bool_val
Definition: upb/upb/reflection.h:41
upb_Message_New
upb_Message * upb_Message_New(const upb_MessageDef *m, upb_Arena *a)
Definition: reflection.c:95
upb_EnumDef_FindValueByNumber
const upb_EnumValueDef * upb_EnumDef_FindValueByNumber(const upb_EnumDef *def, int32_t num)
Definition: upb/upb/def.c:417
jsonenc_struct
static void jsonenc_struct(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:458
kUpb_WellKnown_FloatValue
@ kUpb_WellKnown_FloatValue
Definition: upb/upb/def.h:79
upb_MessageValue
Definition: upb/upb/reflection.h:40
jsonenc_timestamp
static void jsonenc_timestamp(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:142
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
UPB_PTRADD
#define UPB_PTRADD(ptr, ofs)
Definition: php-upb.c:168
upb_Status_SetErrorMessage
void upb_Status_SetErrorMessage(upb_Status *status, const char *msg)
Definition: upb/upb/upb.c:56
upb_MessageDef_WellKnownType
upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef *m)
Definition: upb/upb/def.c:855
upb_Status_VSetErrorFormat
void upb_Status_VSetErrorFormat(upb_Status *status, const char *fmt, va_list args)
Definition: upb/upb/upb.c:70
jsonenc_duration
static void jsonenc_duration(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:185
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
xds_interop_client.int
int
Definition: xds_interop_client.py:113
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
decode.h
kUpb_Message_Begin
#define kUpb_Message_Begin
Definition: upb/upb/reflection.h:113
upb_FieldDef_IsMap
bool upb_FieldDef_IsMap(const upb_FieldDef *f)
Definition: upb/upb/def.c:659
kUpb_CType_Double
@ kUpb_CType_Double
Definition: upb/upb/upb.h:293
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
upb_MapIterator_Next
bool upb_MapIterator_Next(const upb_Map *map, size_t *iter)
Definition: reflection.c:448
upb_FieldDef_HasPresence
bool upb_FieldDef_HasPresence(const upb_FieldDef *f)
Definition: upb/upb/def.c:671
kUpb_WellKnown_BytesValue
@ kUpb_WellKnown_BytesValue
Definition: upb/upb/def.h:86
kUpb_WellKnown_Unspecified
@ kUpb_WellKnown_Unspecified
Definition: upb/upb/def.h:72
kUpb_WellKnown_Timestamp
@ kUpb_WellKnown_Timestamp
Definition: upb/upb/def.h:76
jsonenc_fieldval
static void jsonenc_fieldval(jsonenc *e, const upb_FieldDef *f, upb_MessageValue val, bool *first)
Definition: json_encode.c:686
upb_Array
Definition: msg_internal.h:424
jsonenc::arena
upb_Arena * arena
Definition: json_encode.c:54
jsonenc_array
static void jsonenc_array(jsonenc *e, const upb_Array *arr, const upb_FieldDef *f)
Definition: json_encode.c:650
jsonenc_map
static void jsonenc_map(jsonenc *e, const upb_Map *map, const upb_FieldDef *f)
Definition: json_encode.c:666
jsonenc_wrapper
static void jsonenc_wrapper(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:335
upb_MessageValue::uint64_val
uint64_t uint64_val
Definition: upb/upb/reflection.h:47
jsonenc_string
static void jsonenc_string(jsonenc *e, upb_StringView str)
Definition: json_encode.c:302
upb_EnumValueDef
Definition: upb/upb/def.c:150
upb_EnumDef_FullName
const char * upb_EnumDef_FullName(const upb_EnumDef *e)
Definition: upb/upb/def.c:390
kUpb_WellKnown_UInt32Value
@ kUpb_WellKnown_UInt32Value
Definition: upb/upb/def.h:83
jsonenc_getanymsg
static const upb_MessageDef * jsonenc_getanymsg(jsonenc *e, upb_StringView type_url)
Definition: json_encode.c:342
jsonenc_listvalue
static void jsonenc_listvalue(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:484
upb_FieldDef_IsExtension
bool upb_FieldDef_IsExtension(const upb_FieldDef *f)
Definition: upb/upb/def.c:543
reflection.h
kUpb_WellKnown_BoolValue
@ kUpb_WellKnown_BoolValue
Definition: upb/upb/def.h:87
UPB_STRINGVIEW_FORMAT
#define UPB_STRINGVIEW_FORMAT
Definition: upb/upb/upb.h:96
upb_Message_Next
bool upb_Message_Next(const upb_Message *msg, const upb_MessageDef *m, const upb_DefPool *ext_pool, const upb_FieldDef **out_f, upb_MessageValue *out_val, size_t *iter)
Definition: reflection.c:245
jsonenc_stringbody
static void jsonenc_stringbody(jsonenc *e, upb_StringView str)
Definition: json_encode.c:261
upb_Status
Definition: upb/upb/upb.h:52
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
upb_MessageValue::msg_val
const upb_Message * msg_val
Definition: upb/upb/reflection.h:49
upb_FieldDef_CType
upb_CType upb_FieldDef_CType(const upb_FieldDef *f)
Definition: upb/upb/def.c:500
jsonenc_scalar
static void jsonenc_scalar(jsonenc *e, upb_MessageValue val, const upb_FieldDef *f)
Definition: json_encode.c:581
min
#define min(a, b)
Definition: qsort.h:83
upb_Message
void upb_Message
Definition: msg.h:49
upb_FieldDef_MessageSubDef
const upb_MessageDef * upb_FieldDef_MessageSubDef(const upb_FieldDef *f)
Definition: upb/upb/def.c:619
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
upb_JsonEncode_UseProtoNames
@ upb_JsonEncode_UseProtoNames
Definition: json_encode.h:43
upb_FieldDef_EnumSubDef
const upb_EnumDef * upb_FieldDef_EnumSubDef(const upb_FieldDef *f)
Definition: upb/upb/def.c:623
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
kUpb_WellKnown_Any
@ kUpb_WellKnown_Any
Definition: upb/upb/def.h:73
upb_FieldDef
Definition: upb/upb/def.c:56
upb_MessageValue::map_val
const upb_Map * map_val
Definition: upb/upb/reflection.h:48
upb_Array_Size
size_t upb_Array_Size(const upb_Array *arr)
Definition: reflection.c:362
kUpb_CType_Float
@ kUpb_CType_Float
Definition: upb/upb/upb.h:288
upb_Message_Has
bool upb_Message_Has(const upb_Message *msg, const upb_FieldDef *f)
Definition: reflection.c:112
value
const char * value
Definition: hpack_parser_table.cc:165
jsonenc_putbytes
static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len)
Definition: json_encode.c:90
jsonenc_enum
static void jsonenc_enum(int32_t val, const upb_FieldDef *f, jsonenc *e)
Definition: json_encode.c:206
jsonenc_errf
static UPB_NORETURN void jsonenc_errf(jsonenc *e, const char *fmt,...)
Definition: json_encode.c:74
jsonenc_nullz
static size_t jsonenc_nullz(jsonenc *e, size_t size)
Definition: json_encode.c:746
testing::internal::fmt
GTEST_API_ const char * fmt
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1808
jsonenc_msgfield
static void jsonenc_msgfield(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:540
kUpb_WellKnown_UInt64Value
@ kUpb_WellKnown_UInt64Value
Definition: upb/upb/def.h:81
kUpb_WellKnown_Duration
@ kUpb_WellKnown_Duration
Definition: upb/upb/def.h:75
kUpb_WellKnown_Struct
@ kUpb_WellKnown_Struct
Definition: upb/upb/def.h:90
key
const char * key
Definition: hpack_parser_table.cc:164
upb_FieldDef_JsonName
const char * upb_FieldDef_JsonName(const upb_FieldDef *f)
Definition: upb/upb/def.c:553
upb_StringView
Definition: upb/upb/upb.h:72
N
#define N
Definition: sync_test.cc:37
I
#define I(b, c, d)
Definition: md5.c:120
UPB_LIKELY
#define UPB_LIKELY(x)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:61
upb_Message_Get
upb_MessageValue upb_Message_Get(const upb_Message *msg, const upb_FieldDef *f)
Definition: reflection.c:146
upb_FieldDef_IsRepeated
bool upb_FieldDef_IsRepeated(const upb_FieldDef *f)
Definition: upb/upb/def.c:651
upb_DefPool_FindMessageByNameWithSize
const upb_MessageDef * upb_DefPool_FindMessageByNameWithSize(const upb_DefPool *s, const char *sym, size_t len)
Definition: upb/upb/def.c:1130
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
profile_analyzer.fields
list fields
Definition: profile_analyzer.py:266
L
lua_State * L
Definition: upb/upb/bindings/lua/main.c:35
upb_JsonEncode_EmitDefaults
@ upb_JsonEncode_EmitDefaults
Definition: json_encode.h:39
first
StrT first
Definition: cxa_demangle.cpp:4884
values
std::array< int64_t, Size > values
Definition: abseil-cpp/absl/container/btree_benchmark.cc:608
upb_MessageValue::float_val
float float_val
Definition: upb/upb/reflection.h:42
type_url
string * type_url
Definition: bloaty/third_party/protobuf/conformance/conformance_cpp.cc:72
UPB_NORETURN
#define UPB_NORETURN
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:79
kUpb_WellKnown_Value
@ kUpb_WellKnown_Value
Definition: upb/upb/def.h:88
kUpb_WellKnown_ListValue
@ kUpb_WellKnown_ListValue
Definition: upb/upb/def.h:89
kUpb_WellKnown_Int64Value
@ kUpb_WellKnown_Int64Value
Definition: upb/upb/def.h:80
kUpb_WellKnown_DoubleValue
@ kUpb_WellKnown_DoubleValue
Definition: upb/upb/def.h:78
kUpb_WellKnown_Int32Value
@ kUpb_WellKnown_Int32Value
Definition: upb/upb/def.h:82
_upb_EncodeRoundTripFloat
void _upb_EncodeRoundTripFloat(float val, char *buf, size_t size)
Definition: upb/upb/upb.c:354
kUpb_CType_Bool
@ kUpb_CType_Bool
Definition: upb/upb/upb.h:287
kUpb_CType_Enum
@ kUpb_CType_Enum
Definition: upb/upb/upb.h:291
upb_EnumDef
Definition: upb/upb/def.c:134
upb_Map
Definition: msg_internal.h:581
jsonenc_err
static UPB_NORETURN void jsonenc_err(jsonenc *e, const char *msg)
Definition: json_encode.c:68
iter
Definition: test_winkernel.cpp:47
upb_FieldDef_Name
const char * upb_FieldDef_Name(const upb_FieldDef *f)
Definition: upb/upb/def.c:549
upb_JsonEncode_Float
static void upb_JsonEncode_Float(jsonenc *e, float val)
Definition: json_encode.c:328
ch
char ch
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3621
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
upb_MessageDef_FieldCount
int upb_MessageDef_FieldCount(const upb_MessageDef *m)
Definition: upb/upb/def.c:794
kUpb_CType_UInt64
@ kUpb_CType_UInt64
Definition: upb/upb/upb.h:295
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
jsonenc_putsep
static void jsonenc_putsep(jsonenc *e, const char *str, bool *first)
Definition: json_encode.c:410
upb_JsonEncode_HandleSpecialDoubles
static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc *e, double val)
Definition: json_encode.c:308
upb_MessageDef_Field
const upb_FieldDef * upb_MessageDef_Field(const upb_MessageDef *m, int i)
Definition: upb/upb/def.c:828
regress.m
m
Definition: regress/regress.py:25
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
upb_MapIterator_Value
upb_MessageValue upb_MapIterator_Value(const upb_Map *map, size_t iter)
Definition: reflection.c:470
jsonenc_msg
static void jsonenc_msg(jsonenc *e, const upb_Message *msg, const upb_MessageDef *m)
Definition: json_encode.c:739
kUpb_WellKnown_FieldMask
@ kUpb_WellKnown_FieldMask
Definition: upb/upb/def.h:74
upb_DefPool
Definition: upb/upb/def.c:217
upb_MessageDef_FindFieldByNumber
const upb_FieldDef * upb_MessageDef_FindFieldByNumber(const upb_MessageDef *m, uint32_t i)
Definition: upb/upb/def.c:721
jsonenc_bytes
static void jsonenc_bytes(jsonenc *e, upb_StringView str)
Definition: json_encode.c:222
upb_Arena
Definition: upb_internal.h:36
_upb_EncodeRoundTripDouble
void _upb_EncodeRoundTripDouble(double val, char *buf, size_t size)
Definition: upb/upb/upb.c:344
upb_Arena_Free
void upb_Arena_Free(upb_Arena *a)
Definition: upb/upb/upb.c:273
upb_FieldDef_FullName
const char * upb_FieldDef_FullName(const upb_FieldDef *f)
Definition: upb/upb/def.c:496
kUpb_CType_Message
@ kUpb_CType_Message
Definition: upb/upb/upb.h:292
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
jsonenc_putstr
static void jsonenc_putstr(jsonenc *e, const char *str)
Definition: json_encode.c:104


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:25