summaryrefslogtreecommitdiff
path: root/upb/json/printer.c
diff options
context:
space:
mode:
Diffstat (limited to 'upb/json/printer.c')
-rw-r--r--upb/json/printer.c105
1 files changed, 99 insertions, 6 deletions
diff --git a/upb/json/printer.c b/upb/json/printer.c
index 9c8949e..a3803a1 100644
--- a/upb/json/printer.c
+++ b/upb/json/printer.c
@@ -692,22 +692,91 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
upb_handlerattr_uninit(&empty_attr);
}
-static bool puttimestamp_seconds(void *closure, const void *handler_data,
- int64_t seconds) {
+static bool putseconds(void *closure, const void *handler_data,
+ int64_t seconds) {
upb_json_printer *p = closure;
p->seconds = seconds;
UPB_UNUSED(handler_data);
return true;
}
-static bool puttimestamp_nanos(void *closure, const void *handler_data,
- int32_t nanos) {
+static bool putnanos(void *closure, const void *handler_data,
+ int32_t nanos) {
upb_json_printer *p = closure;
p->nanos = nanos;
UPB_UNUSED(handler_data);
return true;
}
+static bool printer_startdurationmsg(void *closure, const void *handler_data) {
+ upb_json_printer *p = closure;
+ UPB_UNUSED(handler_data);
+ if (p->depth_ == 0) {
+ upb_bytessink_start(p->output_, 0, &p->subc_);
+ }
+ return true;
+}
+
+#define UPB_DURATION_MAX_JSON_LEN 23
+#define UPB_DURATION_MAX_NANO_LEN 9
+
+static bool printer_enddurationmsg(void *closure, const void *handler_data,
+ upb_status *s) {
+ upb_json_printer *p = closure;
+ char buffer[UPB_DURATION_MAX_JSON_LEN];
+ size_t base_len;
+ size_t curr;
+ size_t i;
+
+ memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN);
+
+ if (p->seconds < -315576000000) {
+ upb_status_seterrf(s, "error parsing duration: "
+ "minimum acceptable value is "
+ "-315576000000");
+ return false;
+ }
+
+ if (p->seconds > 315576000000) {
+ upb_status_seterrf(s, "error serializing duration: "
+ "maximum acceptable value is "
+ "315576000000");
+ return false;
+ }
+
+ _upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds);
+ base_len = strlen(buffer);
+
+ if (p->nanos != 0) {
+ char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3];
+ _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
+ p->nanos / 1000000000.0);
+ /* Remove trailing 0. */
+ for (i = UPB_DURATION_MAX_NANO_LEN + 2;
+ nanos_buffer[i] == '0'; i--) {
+ nanos_buffer[i] = 0;
+ }
+ strcpy(buffer + base_len, nanos_buffer + 1);
+ }
+
+ curr = strlen(buffer);
+ strcpy(buffer + curr, "s");
+
+ p->seconds = 0;
+ p->nanos = 0;
+
+ print_data(p, "\"", 1);
+ print_data(p, buffer, strlen(buffer));
+ print_data(p, "\"", 1);
+
+ if (p->depth_ == 0) {
+ upb_bytessink_end(p->output_);
+ }
+
+ UPB_UNUSED(handler_data);
+ return true;
+}
+
static bool printer_starttimestampmsg(void *closure, const void *handler_data) {
upb_json_printer *p = closure;
UPB_UNUSED(handler_data);
@@ -783,6 +852,25 @@ static bool printer_endtimestampmsg(void *closure, const void *handler_data,
return true;
}
+/* Set up handlers for a duration submessage. */
+void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
+ const upb_msgdef *md = upb_handlers_msgdef(h);
+
+ const upb_fielddef* seconds_field =
+ upb_msgdef_itof(md, UPB_DURATION_SECONDS);
+ const upb_fielddef* nanos_field =
+ upb_msgdef_itof(md, UPB_DURATION_NANOS);
+
+ upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
+
+ upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
+ upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
+ upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
+ upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr);
+
+ UPB_UNUSED(closure);
+}
+
/* Set up handlers for a timestamp submessage. Instead of printing fields
* separately, the json representation of timestamp follows RFC 3339 */
void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
@@ -796,8 +884,8 @@ void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
- upb_handlers_setint64(h, seconds_field, puttimestamp_seconds, &empty_attr);
- upb_handlers_setint32(h, nanos_field, puttimestamp_nanos, &empty_attr);
+ upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
+ upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr);
UPB_UNUSED(closure);
@@ -818,6 +906,11 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
return;
}
+ if (upb_msgdef_duration(md)) {
+ printer_sethandlers_duration(closure, h);
+ return;
+ }
+
if (upb_msgdef_timestamp(md)) {
printer_sethandlers_timestamp(closure, h);
return;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback