Skip to content

Commit f2aedbd

Browse files
authored
ref: Optimize JSON formatting (ISSUE-1379) (#674)
1 parent 0c5dd44 commit f2aedbd

File tree

4 files changed

+101
-79
lines changed

4 files changed

+101
-79
lines changed

src/sentry_json.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,49 @@ write_str(sentry_jsonwriter_t *jw, const char *str)
101101
sentry__stringbuilder_append(jw->sb, str);
102102
}
103103

104+
// The Lookup table and algorithm below are adapted from:
105+
// https://github.com/serde-rs/json/blob/977975ee650829a1f3c232cd5f641a7011bdce1d/src/ser.rs#L2079-L2145
106+
107+
// Lookup table of escape sequences. `0` means no need to escape, and `1` means
108+
// that escaping is needed.
109+
static unsigned char needs_escaping[256] = {
110+
// 1 2 3 4 5 6 7 8 9 A B C D E F
111+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
112+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
113+
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
114+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
115+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
116+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // 5
117+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
118+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
119+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
120+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
121+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
122+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
123+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
124+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
125+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
126+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F
127+
};
128+
104129
static void
105130
write_json_str(sentry_jsonwriter_t *jw, const char *str)
106131
{
107132
// using unsigned here because utf-8 is > 127 :-)
108133
const unsigned char *ptr = (const unsigned char *)str;
109134
write_char(jw, '"');
135+
136+
const unsigned char *start = ptr;
110137
for (; *ptr; ptr++) {
138+
if (!needs_escaping[*ptr]) {
139+
continue;
140+
}
141+
142+
size_t len = ptr - start;
143+
if (len) {
144+
sentry__stringbuilder_append_buf(jw->sb, (const char *)start, len);
145+
}
146+
111147
switch (*ptr) {
112148
case '\\':
113149
write_str(jw, "\\\\");
@@ -142,7 +178,15 @@ write_json_str(sentry_jsonwriter_t *jw, const char *str)
142178
write_char(jw, *ptr);
143179
}
144180
}
181+
182+
start = ptr + 1;
145183
}
184+
185+
size_t len = ptr - start;
186+
if (len) {
187+
sentry__stringbuilder_append_buf(jw->sb, (const char *)start, len);
188+
}
189+
146190
write_char(jw, '"');
147191
}
148192

src/sentry_string.c

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -39,49 +39,6 @@ sentry__stringbuilder_reserve(sentry_stringbuilder_t *sb, size_t len)
3939
return &sb->buf[sb->len];
4040
}
4141

42-
static int
43-
append(sentry_stringbuilder_t *sb, const char *s, size_t len)
44-
{
45-
char *buf = sentry__stringbuilder_reserve(sb, len + 1);
46-
if (!buf) {
47-
return 1;
48-
}
49-
memcpy(buf, s, len);
50-
sb->len += len;
51-
52-
// make sure we're always zero terminated
53-
sb->buf[sb->len] = '\0';
54-
55-
return 0;
56-
}
57-
58-
int
59-
sentry__stringbuilder_append(sentry_stringbuilder_t *sb, const char *s)
60-
{
61-
return append(sb, s, strlen(s));
62-
}
63-
64-
int
65-
sentry__stringbuilder_append_buf(
66-
sentry_stringbuilder_t *sb, const char *s, size_t len)
67-
{
68-
return append(sb, s, len);
69-
}
70-
71-
int
72-
sentry__stringbuilder_append_char(sentry_stringbuilder_t *sb, char c)
73-
{
74-
return append(sb, &c, 1);
75-
}
76-
77-
int
78-
sentry__stringbuilder_append_char32(sentry_stringbuilder_t *sb, uint32_t c)
79-
{
80-
char buf[4];
81-
size_t len = sentry__unichar_to_utf8(c, buf);
82-
return sentry__stringbuilder_append_buf(sb, buf, len);
83-
}
84-
8542
char *
8643
sentry_stringbuilder_take_string(sentry_stringbuilder_t *sb)
8744
{
@@ -121,24 +78,6 @@ sentry__stringbuilder_set_len(sentry_stringbuilder_t *sb, size_t len)
12178
sb->len = len;
12279
}
12380

124-
char *
125-
sentry__string_clone(const char *str)
126-
{
127-
return str ? sentry__string_clonen(str, strlen(str)) : NULL;
128-
}
129-
130-
char *
131-
sentry__string_clonen(const char *str, size_t n)
132-
{
133-
size_t len = n + 1;
134-
char *rv = sentry_malloc(len);
135-
if (rv) {
136-
memcpy(rv, str, n);
137-
rv[n] = 0;
138-
}
139-
return rv;
140-
}
141-
14281
#ifdef SENTRY_PLATFORM_WINDOWS
14382
char *
14483
sentry__string_from_wstr(const wchar_t *s)

src/sentry_string.h

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,55 @@ typedef struct sentry_stringbuilder_s {
2222
void sentry__stringbuilder_init(sentry_stringbuilder_t *sb);
2323

2424
/**
25-
* Appends a zero terminated string to the builder.
25+
* Resizes the stringbuilder buffer to make sure there is at least `len` bytes
26+
* available at the end, and returns a pointer *to the reservation*.
2627
*/
27-
int sentry__stringbuilder_append(sentry_stringbuilder_t *sb, const char *s);
28+
char *sentry__stringbuilder_reserve(sentry_stringbuilder_t *sb, size_t len);
2829

2930
/**
3031
* Appends a sized buffer.
3132
*/
32-
int sentry__stringbuilder_append_buf(
33-
sentry_stringbuilder_t *sb, const char *s, size_t len);
33+
static inline int
34+
sentry__stringbuilder_append_buf(
35+
sentry_stringbuilder_t *sb, const char *s, size_t len)
36+
{
37+
size_t needed = sb->len + len + 1;
38+
char *buf = sb->buf;
39+
if (!sb->buf || needed > sb->allocated) {
40+
buf = sentry__stringbuilder_reserve(sb, len + 1);
41+
if (!buf) {
42+
return 1;
43+
}
44+
} else {
45+
buf = buf + sb->len;
46+
}
47+
48+
memcpy(buf, s, len);
49+
sb->len += len;
50+
51+
// make sure we're always zero terminated
52+
sb->buf[sb->len] = '\0';
53+
54+
return 0;
55+
}
3456

3557
/**
36-
* Appends a single character.
58+
* Appends a zero terminated string to the builder.
3759
*/
38-
int sentry__stringbuilder_append_char(sentry_stringbuilder_t *sb, char c);
60+
static inline int
61+
sentry__stringbuilder_append(sentry_stringbuilder_t *sb, const char *s)
62+
{
63+
return sentry__stringbuilder_append_buf(sb, s, strlen(s));
64+
}
3965

4066
/**
41-
* Appends a utf-32 character.
67+
* Appends a single character.
4268
*/
43-
int sentry__stringbuilder_append_char32(sentry_stringbuilder_t *sb, uint32_t c);
69+
static inline int
70+
sentry__stringbuilder_append_char(sentry_stringbuilder_t *sb, char c)
71+
{
72+
return sentry__stringbuilder_append_buf(sb, &c, 1);
73+
}
4474

4575
/**
4676
* Appends an int64 value.
@@ -73,27 +103,35 @@ void sentry__stringbuilder_cleanup(sentry_stringbuilder_t *sb);
73103
*/
74104
size_t sentry__stringbuilder_len(const sentry_stringbuilder_t *sb);
75105

76-
/**
77-
* Resizes the stringbuilder buffer to make sure there is at least `len` bytes
78-
* available at the end, and returns a pointer *to the reservation*.
79-
*/
80-
char *sentry__stringbuilder_reserve(sentry_stringbuilder_t *sb, size_t len);
81-
82106
/**
83107
* Sets the number of used bytes in the string builder, to be used together with
84108
* `sentry__stringbuilder_reserve` to avoid copying from an intermediate buffer.
85109
*/
86110
void sentry__stringbuilder_set_len(sentry_stringbuilder_t *sb, size_t len);
87111

88112
/**
89-
* Duplicates a zero terminated string.
113+
* Duplicates a zero terminated string with a length limit.
90114
*/
91-
char *sentry__string_clone(const char *str);
115+
static inline char *
116+
sentry__string_clonen(const char *str, size_t n)
117+
{
118+
size_t len = n + 1;
119+
char *rv = (char *)sentry_malloc(len);
120+
if (rv) {
121+
memcpy(rv, str, n);
122+
rv[n] = 0;
123+
}
124+
return rv;
125+
}
92126

93127
/**
94-
* Duplicates a zero terminated string with a length limit.
128+
* Duplicates a zero terminated string.
95129
*/
96-
char *sentry__string_clonen(const char *str, size_t n);
130+
static inline char *
131+
sentry__string_clone(const char *str)
132+
{
133+
return str ? sentry__string_clonen(str, strlen(str)) : NULL;
134+
}
97135

98136
/**
99137
* Converts a string to lowercase.

src/sentry_transport.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "sentry_envelope.h"
44
#include "sentry_options.h"
55
#include "sentry_ratelimiter.h"
6+
#include "sentry_string.h"
67

78
#define ENVELOPE_MIME "application/x-sentry-envelope"
89
// The headers we use are: `x-sentry-auth`, `content-type`, `content-length`

0 commit comments

Comments
 (0)