diff --git a/src/sentry_database.c b/src/sentry_database.c index 778bd639b..c1d823179 100644 --- a/src/sentry_database.c +++ b/src/sentry_database.c @@ -108,7 +108,7 @@ bool sentry__run_write_session( const sentry_run_t *run, const sentry_session_t *session) { - sentry_jsonwriter_t *jw = sentry__jsonwriter_new_in_memory(); + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL); if (!jw) { return false; } diff --git a/src/sentry_envelope.c b/src/sentry_envelope.c index f9ba5ff2a..7bd621c0d 100644 --- a/src/sentry_envelope.c +++ b/src/sentry_envelope.c @@ -212,11 +212,17 @@ sentry__envelope_add_event(sentry_envelope_t *envelope, sentry_value_t event) return NULL; } + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL); + if (!jw) { + return NULL; + } + sentry_value_t event_id = sentry__ensure_event_id(event, NULL); item->event = event; - item->payload = sentry_value_to_json(event); - item->payload_len = strlen(item->payload); + sentry__jsonwriter_write_value(jw, event); + item->payload = sentry__jsonwriter_into_string(jw, &item->payload_len); + sentry__envelope_item_set_header( item, "type", sentry_value_new_string("event")); sentry_value_t length = sentry_value_new_int32((int32_t)item->payload_len); @@ -235,7 +241,7 @@ sentry__envelope_add_session( if (!envelope || !session) { return NULL; } - sentry_jsonwriter_t *jw = sentry__jsonwriter_new_in_memory(); + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL); if (!jw) { return NULL; } @@ -281,20 +287,27 @@ static void sentry__envelope_serialize_headers_into_stringbuilder( const sentry_envelope_t *envelope, sentry_stringbuilder_t *sb) { - char *buf = sentry_value_to_json(envelope->contents.items.headers); - sentry__stringbuilder_append(sb, buf); - sentry_free(buf); + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(sb); + if (jw) { + sentry__jsonwriter_write_value(jw, envelope->contents.items.headers); + sentry__jsonwriter_free(jw); + } } static void sentry__envelope_serialize_item_into_stringbuilder( const sentry_envelope_item_t *item, sentry_stringbuilder_t *sb) { + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(sb); + if (!jw) { + return; + } sentry__stringbuilder_append_char(sb, '\n'); - char *buf = sentry_value_to_json(item->headers); - sentry__stringbuilder_append(sb, buf); + + sentry__jsonwriter_write_value(jw, item->headers); + sentry__jsonwriter_free(jw); + sentry__stringbuilder_append_char(sb, '\n'); - sentry_free(buf); sentry__stringbuilder_append_buf(sb, item->payload, item->payload_len); } diff --git a/src/sentry_json.c b/src/sentry_json.c index 549a4af94..df5e85de7 100644 --- a/src/sentry_json.c +++ b/src/sentry_json.c @@ -11,35 +11,36 @@ #include "sentry_utils.h" #include "sentry_value.h" -#define DST_MODE_SB 1 - struct sentry_jsonwriter_s { - union { - sentry_stringbuilder_t *sb; - } dst; + sentry_stringbuilder_t *sb; uint64_t want_comma; uint32_t depth; bool last_was_key; - char dst_mode; + bool owns_sb; }; sentry_jsonwriter_t * -sentry__jsonwriter_new_in_memory(void) +sentry__jsonwriter_new(sentry_stringbuilder_t *sb) { - sentry_jsonwriter_t *rv = SENTRY_MAKE(sentry_jsonwriter_t); - if (!rv) { + bool owns_sb = false; + if (!sb) { + sb = SENTRY_MAKE(sentry_stringbuilder_t); + owns_sb = true; + sentry__stringbuilder_init(sb); + } + if (!sb) { return NULL; } - rv->dst.sb = SENTRY_MAKE(sentry_stringbuilder_t); - if (!rv->dst.sb) { - sentry_free(rv); + sentry_jsonwriter_t *rv = SENTRY_MAKE(sentry_jsonwriter_t); + if (!rv) { return NULL; } - sentry__stringbuilder_init(rv->dst.sb); - rv->dst_mode = DST_MODE_SB; + + rv->sb = sb; rv->want_comma = 0; rv->depth = 0; rv->last_was_key = 0; + rv->owns_sb = owns_sb; return rv; } @@ -49,42 +50,22 @@ sentry__jsonwriter_free(sentry_jsonwriter_t *jw) if (!jw) { return; } - switch (jw->dst_mode) { - case DST_MODE_SB: - sentry__stringbuilder_cleanup(jw->dst.sb); - sentry_free(jw->dst.sb); - break; + if (jw->owns_sb) { + sentry__stringbuilder_cleanup(jw->sb); + sentry_free(jw->sb); } sentry_free(jw); } -size_t -sentry__jsonwriter_get_length(const sentry_jsonwriter_t *jw) -{ - switch (jw->dst_mode) { - case DST_MODE_SB: { - const sentry_stringbuilder_t *sb = jw->dst.sb; - return sb->len; - } - default: - return 0; - } -} - char * sentry__jsonwriter_into_string(sentry_jsonwriter_t *jw, size_t *len_out) { char *rv = NULL; - switch (jw->dst_mode) { - case DST_MODE_SB: { - sentry_stringbuilder_t *sb = jw->dst.sb; - if (len_out) { - *len_out = sb->len; - } - rv = sentry__stringbuilder_into_string(sb); - break; - } + sentry_stringbuilder_t *sb = jw->sb; + if (len_out) { + *len_out = sb->len; } + rv = sentry__stringbuilder_into_string(sb); sentry__jsonwriter_free(jw); return rv; } @@ -111,19 +92,13 @@ set_comma(sentry_jsonwriter_t *jw, bool val) static void write_char(sentry_jsonwriter_t *jw, char c) { - switch (jw->dst_mode) { - case DST_MODE_SB: - sentry__stringbuilder_append_char(jw->dst.sb, c); - } + sentry__stringbuilder_append_char(jw->sb, c); } static void write_str(sentry_jsonwriter_t *jw, const char *str) { - switch (jw->dst_mode) { - case DST_MODE_SB: - sentry__stringbuilder_append(jw->dst.sb, str); - } + sentry__stringbuilder_append(jw->sb, str); } static void diff --git a/src/sentry_json.h b/src/sentry_json.h index d3e533278..1ff9a11c7 100644 --- a/src/sentry_json.h +++ b/src/sentry_json.h @@ -3,13 +3,16 @@ #include "sentry_boot.h" -struct sentry_jsonwriter_s; +typedef struct sentry_stringbuilder_s sentry_stringbuilder_t; typedef struct sentry_jsonwriter_s sentry_jsonwriter_t; /** - * This creates a new in-memory JSON writer, based on `sentry_stringbuilder_s`. + * This creates a new JSON writer. + * + * It will use an existing `sentry_stringbuilder_t` as its output if one is + * provided, otherwise it will allocate a new one. */ -sentry_jsonwriter_t *sentry__jsonwriter_new_in_memory(void); +sentry_jsonwriter_t *sentry__jsonwriter_new(sentry_stringbuilder_t *sb); /** * Deallocates a JSON writer. diff --git a/src/sentry_value.c b/src/sentry_value.c index 233e39b70..95158c9c5 100644 --- a/src/sentry_value.c +++ b/src/sentry_value.c @@ -794,8 +794,8 @@ sentry_value_is_null(sentry_value_t value) return value._bits == CONST_NULL; } -static void -value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value) +void +sentry__jsonwriter_write_value(sentry_jsonwriter_t *jw, sentry_value_t value) { switch (sentry_value_get_type(value)) { case SENTRY_VALUE_TYPE_NULL: @@ -817,7 +817,7 @@ value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value) const list_t *l = value_as_thing(value)->payload._ptr; sentry__jsonwriter_write_list_start(jw); for (size_t i = 0; i < l->len; i++) { - value_to_json(jw, l->items[i]); + sentry__jsonwriter_write_value(jw, l->items[i]); } sentry__jsonwriter_write_list_end(jw); break; @@ -827,7 +827,7 @@ value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value) sentry__jsonwriter_write_object_start(jw); for (size_t i = 0; i < o->len; i++) { sentry__jsonwriter_write_key(jw, o->pairs[i].k); - value_to_json(jw, o->pairs[i].v); + sentry__jsonwriter_write_value(jw, o->pairs[i].v); } sentry__jsonwriter_write_object_end(jw); break; @@ -838,8 +838,11 @@ value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value) char * sentry_value_to_json(sentry_value_t value) { - sentry_jsonwriter_t *jw = sentry__jsonwriter_new_in_memory(); - value_to_json(jw, value); + sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL); + if (!jw) { + return NULL; + } + sentry__jsonwriter_write_value(jw, value); return sentry__jsonwriter_into_string(jw, NULL); } diff --git a/src/sentry_value.h b/src/sentry_value.h index d591b9369..375cb70ca 100644 --- a/src/sentry_value.h +++ b/src/sentry_value.h @@ -80,4 +80,12 @@ int sentry__value_append_bounded( */ sentry_value_t sentry__value_from_json(const char *buf, size_t buflen); +typedef struct sentry_jsonwriter_s sentry_jsonwriter_t; + +/** + * Writes the given `value` into the `jsonwriter`. + */ +void sentry__jsonwriter_write_value( + sentry_jsonwriter_t *jw, sentry_value_t value); + #endif