File: | deps/jemalloc/include/jemalloc/internal/emitter.h |
Warning: | line 126, column 3 Value stored to 'written' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #ifndef JEMALLOC_INTERNAL_EMITTER_H |
2 | #define JEMALLOC_INTERNAL_EMITTER_H |
3 | |
4 | #include "jemalloc/internal/ql.h" |
5 | |
6 | typedef enum emitter_output_e emitter_output_t; |
7 | enum emitter_output_e { |
8 | emitter_output_json, |
9 | emitter_output_table |
10 | }; |
11 | |
12 | typedef enum emitter_justify_e emitter_justify_t; |
13 | enum emitter_justify_e { |
14 | emitter_justify_left, |
15 | emitter_justify_right, |
16 | /* Not for users; just to pass to internal functions. */ |
17 | emitter_justify_none |
18 | }; |
19 | |
20 | typedef enum emitter_type_e emitter_type_t; |
21 | enum emitter_type_e { |
22 | emitter_type_bool, |
23 | emitter_type_int, |
24 | emitter_type_unsigned, |
25 | emitter_type_uint32, |
26 | emitter_type_uint64, |
27 | emitter_type_size, |
28 | emitter_type_ssize, |
29 | emitter_type_string, |
30 | /* |
31 | * A title is a column title in a table; it's just a string, but it's |
32 | * not quoted. |
33 | */ |
34 | emitter_type_title, |
35 | }; |
36 | |
37 | typedef struct emitter_col_s emitter_col_t; |
38 | struct emitter_col_s { |
39 | /* Filled in by the user. */ |
40 | emitter_justify_t justify; |
41 | int width; |
42 | emitter_type_t type; |
43 | union { |
44 | bool_Bool bool_val; |
45 | int int_val; |
46 | unsigned unsigned_val; |
47 | uint32_t uint32_val; |
48 | uint64_t uint64_val; |
49 | size_t size_val; |
50 | ssize_t ssize_val; |
51 | const char *str_val; |
52 | }; |
53 | |
54 | /* Filled in by initialization. */ |
55 | ql_elm(emitter_col_t)struct { emitter_col_t *qre_next; emitter_col_t *qre_prev; } link; |
56 | }; |
57 | |
58 | typedef struct emitter_row_s emitter_row_t; |
59 | struct emitter_row_s { |
60 | ql_head(emitter_col_t)struct { emitter_col_t *qlh_first; } cols; |
61 | }; |
62 | |
63 | static inline void |
64 | emitter_row_init(emitter_row_t *row) { |
65 | ql_new(&row->cols)do { (&row->cols)->qlh_first = ((void*)0); } while ( 0); |
66 | } |
67 | |
68 | static inline void |
69 | emitter_col_init(emitter_col_t *col, emitter_row_t *row) { |
70 | ql_elm_new(col, link)do { ((col))->link.qre_next = ((col)); ((col))->link.qre_prev = ((col)); } while (0); |
71 | ql_tail_insert(&row->cols, col, link)do { if (((&row->cols)->qlh_first) != ((void*)0)) { do { ((col))->link.qre_prev = (((&row->cols)->qlh_first ))->link.qre_prev; ((col))->link.qre_next = (((&row ->cols)->qlh_first)); ((col))->link.qre_prev->link .qre_next = ((col)); (((&row->cols)->qlh_first))-> link.qre_prev = ((col)); } while (0); } ((&row->cols)-> qlh_first) = (((col))->link.qre_next); } while (0); |
72 | } |
73 | |
74 | typedef struct emitter_s emitter_t; |
75 | struct emitter_s { |
76 | emitter_output_t output; |
77 | /* The output information. */ |
78 | void (*write_cb)(void *, const char *); |
79 | void *cbopaque; |
80 | int nesting_depth; |
81 | /* True if we've already emitted a value at the given depth. */ |
82 | bool_Bool item_at_depth; |
83 | }; |
84 | |
85 | static inline void |
86 | emitter_init(emitter_t *emitter, emitter_output_t emitter_output, |
87 | void (*write_cb)(void *, const char *), void *cbopaque) { |
88 | emitter->output = emitter_output; |
89 | emitter->write_cb = write_cb; |
90 | emitter->cbopaque = cbopaque; |
91 | emitter->item_at_depth = false0; |
92 | emitter->nesting_depth = 0; |
93 | } |
94 | |
95 | /* Internal convenience function. Write to the emitter the given string. */ |
96 | JEMALLOC_FORMAT_PRINTF(2, 3)__attribute__((format(gnu_printf, 2, 3))) |
97 | static inline void |
98 | emitter_printf(emitter_t *emitter, const char *format, ...) { |
99 | va_list ap; |
100 | |
101 | va_start(ap, format)__builtin_va_start(ap, format); |
102 | malloc_vcprintfje_malloc_vcprintf(emitter->write_cb, emitter->cbopaque, format, ap); |
103 | va_end(ap)__builtin_va_end(ap); |
104 | } |
105 | |
106 | /* Write to the emitter the given string, but only in table mode. */ |
107 | JEMALLOC_FORMAT_PRINTF(2, 3)__attribute__((format(gnu_printf, 2, 3))) |
108 | static inline void |
109 | emitter_table_printf(emitter_t *emitter, const char *format, ...) { |
110 | if (emitter->output == emitter_output_table) { |
111 | va_list ap; |
112 | va_start(ap, format)__builtin_va_start(ap, format); |
113 | malloc_vcprintfje_malloc_vcprintf(emitter->write_cb, emitter->cbopaque, format, ap); |
114 | va_end(ap)__builtin_va_end(ap); |
115 | } |
116 | } |
117 | |
118 | static inline void |
119 | emitter_gen_fmt(char *out_fmt, size_t out_size, const char *fmt_specifier, |
120 | emitter_justify_t justify, int width) { |
121 | size_t written; |
122 | if (justify == emitter_justify_none) { |
123 | written = malloc_snprintfje_malloc_snprintf(out_fmt, out_size, |
124 | "%%%s", fmt_specifier); |
125 | } else if (justify == emitter_justify_left) { |
126 | written = malloc_snprintfje_malloc_snprintf(out_fmt, out_size, |
Value stored to 'written' is never read | |
127 | "%%-%d%s", width, fmt_specifier); |
128 | } else { |
129 | written = malloc_snprintfje_malloc_snprintf(out_fmt, out_size, |
130 | "%%%d%s", width, fmt_specifier); |
131 | } |
132 | /* Only happens in case of bad format string, which *we* choose. */ |
133 | assert(written < out_size)do { if (__builtin_expect(!!(config_debug && !(written < out_size)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 133, "written < out_size" ); abort(); } } while (0); |
134 | } |
135 | |
136 | /* |
137 | * Internal. Emit the given value type in the relevant encoding (so that the |
138 | * bool true gets mapped to json "true", but the string "true" gets mapped to |
139 | * json "\"true\"", for instance. |
140 | * |
141 | * Width is ignored if justify is emitter_justify_none. |
142 | */ |
143 | static inline void |
144 | emitter_print_value(emitter_t *emitter, emitter_justify_t justify, int width, |
145 | emitter_type_t value_type, const void *value) { |
146 | size_t str_written; |
147 | #define BUF_SIZE 256 |
148 | #define FMT_SIZE 10 |
149 | /* |
150 | * We dynamically generate a format string to emit, to let us use the |
151 | * snprintf machinery. This is kinda hacky, but gets the job done |
152 | * quickly without having to think about the various snprintf edge |
153 | * cases. |
154 | */ |
155 | char fmt[FMT_SIZE]; |
156 | char buf[BUF_SIZE]; |
157 | |
158 | #define EMIT_SIMPLE(type, format)emitter_gen_fmt(fmt, FMT_SIZE, format, justify, width); emitter_printf (emitter, fmt, *(const type *)value); \ |
159 | emitter_gen_fmt(fmt, FMT_SIZE, format, justify, width); \ |
160 | emitter_printf(emitter, fmt, *(const type *)value); \ |
161 | |
162 | switch (value_type) { |
163 | case emitter_type_bool: |
164 | emitter_gen_fmt(fmt, FMT_SIZE, "s", justify, width); |
165 | emitter_printf(emitter, fmt, *(const bool_Bool *)value ? |
166 | "true" : "false"); |
167 | break; |
168 | case emitter_type_int: |
169 | EMIT_SIMPLE(int, "d")emitter_gen_fmt(fmt, FMT_SIZE, "d", justify, width); emitter_printf (emitter, fmt, *(const int *)value); |
170 | break; |
171 | case emitter_type_unsigned: |
172 | EMIT_SIMPLE(unsigned, "u")emitter_gen_fmt(fmt, FMT_SIZE, "u", justify, width); emitter_printf (emitter, fmt, *(const unsigned *)value); |
173 | break; |
174 | case emitter_type_ssize: |
175 | EMIT_SIMPLE(ssize_t, "zd")emitter_gen_fmt(fmt, FMT_SIZE, "zd", justify, width); emitter_printf (emitter, fmt, *(const ssize_t *)value); |
176 | break; |
177 | case emitter_type_size: |
178 | EMIT_SIMPLE(size_t, "zu")emitter_gen_fmt(fmt, FMT_SIZE, "zu", justify, width); emitter_printf (emitter, fmt, *(const size_t *)value); |
179 | break; |
180 | case emitter_type_string: |
181 | str_written = malloc_snprintfje_malloc_snprintf(buf, BUF_SIZE, "\"%s\"", |
182 | *(const char *const *)value); |
183 | /* |
184 | * We control the strings we output; we shouldn't get anything |
185 | * anywhere near the fmt size. |
186 | */ |
187 | assert(str_written < BUF_SIZE)do { if (__builtin_expect(!!(config_debug && !(str_written < BUF_SIZE)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 187, "str_written < BUF_SIZE" ); abort(); } } while (0); |
188 | emitter_gen_fmt(fmt, FMT_SIZE, "s", justify, width); |
189 | emitter_printf(emitter, fmt, buf); |
190 | break; |
191 | case emitter_type_uint32: |
192 | EMIT_SIMPLE(uint32_t, FMTu32)emitter_gen_fmt(fmt, FMT_SIZE, "u", justify, width); emitter_printf (emitter, fmt, *(const uint32_t *)value); |
193 | break; |
194 | case emitter_type_uint64: |
195 | EMIT_SIMPLE(uint64_t, FMTu64)emitter_gen_fmt(fmt, FMT_SIZE, "l" "u", justify, width); emitter_printf (emitter, fmt, *(const uint64_t *)value); |
196 | break; |
197 | case emitter_type_title: |
198 | EMIT_SIMPLE(char *const, "s")emitter_gen_fmt(fmt, FMT_SIZE, "s", justify, width); emitter_printf (emitter, fmt, *(const char *const *)value);; |
199 | break; |
200 | default: |
201 | unreachable()__builtin_unreachable(); |
202 | } |
203 | #undef BUF_SIZE |
204 | #undef FMT_SIZE |
205 | } |
206 | |
207 | |
208 | /* Internal functions. In json mode, tracks nesting state. */ |
209 | static inline void |
210 | emitter_nest_inc(emitter_t *emitter) { |
211 | emitter->nesting_depth++; |
212 | emitter->item_at_depth = false0; |
213 | } |
214 | |
215 | static inline void |
216 | emitter_nest_dec(emitter_t *emitter) { |
217 | emitter->nesting_depth--; |
218 | emitter->item_at_depth = true1; |
219 | } |
220 | |
221 | static inline void |
222 | emitter_indent(emitter_t *emitter) { |
223 | int amount = emitter->nesting_depth; |
224 | const char *indent_str; |
225 | if (emitter->output == emitter_output_json) { |
226 | indent_str = "\t"; |
227 | } else { |
228 | amount *= 2; |
229 | indent_str = " "; |
230 | } |
231 | for (int i = 0; i < amount; i++) { |
232 | emitter_printf(emitter, "%s", indent_str); |
233 | } |
234 | } |
235 | |
236 | static inline void |
237 | emitter_json_key_prefix(emitter_t *emitter) { |
238 | emitter_printf(emitter, "%s\n", emitter->item_at_depth ? "," : ""); |
239 | emitter_indent(emitter); |
240 | } |
241 | |
242 | static inline void |
243 | emitter_begin(emitter_t *emitter) { |
244 | if (emitter->output == emitter_output_json) { |
245 | assert(emitter->nesting_depth == 0)do { if (__builtin_expect(!!(config_debug && !(emitter ->nesting_depth == 0)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 245, "emitter->nesting_depth == 0" ); abort(); } } while (0); |
246 | emitter_printf(emitter, "{"); |
247 | emitter_nest_inc(emitter); |
248 | } else { |
249 | // tabular init |
250 | emitter_printf(emitter, "%s", ""); |
251 | } |
252 | } |
253 | |
254 | static inline void |
255 | emitter_end(emitter_t *emitter) { |
256 | if (emitter->output == emitter_output_json) { |
257 | assert(emitter->nesting_depth == 1)do { if (__builtin_expect(!!(config_debug && !(emitter ->nesting_depth == 1)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 257, "emitter->nesting_depth == 1" ); abort(); } } while (0); |
258 | emitter_nest_dec(emitter); |
259 | emitter_printf(emitter, "\n}\n"); |
260 | } |
261 | } |
262 | |
263 | /* |
264 | * Note emits a different kv pair as well, but only in table mode. Omits the |
265 | * note if table_note_key is NULL. |
266 | */ |
267 | static inline void |
268 | emitter_kv_note(emitter_t *emitter, const char *json_key, const char *table_key, |
269 | emitter_type_t value_type, const void *value, |
270 | const char *table_note_key, emitter_type_t table_note_value_type, |
271 | const void *table_note_value) { |
272 | if (emitter->output == emitter_output_json) { |
273 | assert(emitter->nesting_depth > 0)do { if (__builtin_expect(!!(config_debug && !(emitter ->nesting_depth > 0)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 273, "emitter->nesting_depth > 0" ); abort(); } } while (0); |
274 | emitter_json_key_prefix(emitter); |
275 | emitter_printf(emitter, "\"%s\": ", json_key); |
276 | emitter_print_value(emitter, emitter_justify_none, -1, |
277 | value_type, value); |
278 | } else { |
279 | emitter_indent(emitter); |
280 | emitter_printf(emitter, "%s: ", table_key); |
281 | emitter_print_value(emitter, emitter_justify_none, -1, |
282 | value_type, value); |
283 | if (table_note_key != NULL((void*)0)) { |
284 | emitter_printf(emitter, " (%s: ", table_note_key); |
285 | emitter_print_value(emitter, emitter_justify_none, -1, |
286 | table_note_value_type, table_note_value); |
287 | emitter_printf(emitter, ")"); |
288 | } |
289 | emitter_printf(emitter, "\n"); |
290 | } |
291 | emitter->item_at_depth = true1; |
292 | } |
293 | |
294 | static inline void |
295 | emitter_kv(emitter_t *emitter, const char *json_key, const char *table_key, |
296 | emitter_type_t value_type, const void *value) { |
297 | emitter_kv_note(emitter, json_key, table_key, value_type, value, NULL((void*)0), |
298 | emitter_type_bool, NULL((void*)0)); |
299 | } |
300 | |
301 | static inline void |
302 | emitter_json_kv(emitter_t *emitter, const char *json_key, |
303 | emitter_type_t value_type, const void *value) { |
304 | if (emitter->output == emitter_output_json) { |
305 | emitter_kv(emitter, json_key, NULL((void*)0), value_type, value); |
306 | } |
307 | } |
308 | |
309 | static inline void |
310 | emitter_table_kv(emitter_t *emitter, const char *table_key, |
311 | emitter_type_t value_type, const void *value) { |
312 | if (emitter->output == emitter_output_table) { |
313 | emitter_kv(emitter, NULL((void*)0), table_key, value_type, value); |
314 | } |
315 | } |
316 | |
317 | static inline void |
318 | emitter_dict_begin(emitter_t *emitter, const char *json_key, |
319 | const char *table_header) { |
320 | if (emitter->output == emitter_output_json) { |
321 | emitter_json_key_prefix(emitter); |
322 | emitter_printf(emitter, "\"%s\": {", json_key); |
323 | emitter_nest_inc(emitter); |
324 | } else { |
325 | emitter_indent(emitter); |
326 | emitter_printf(emitter, "%s\n", table_header); |
327 | emitter_nest_inc(emitter); |
328 | } |
329 | } |
330 | |
331 | static inline void |
332 | emitter_dict_end(emitter_t *emitter) { |
333 | if (emitter->output == emitter_output_json) { |
334 | assert(emitter->nesting_depth > 0)do { if (__builtin_expect(!!(config_debug && !(emitter ->nesting_depth > 0)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 334, "emitter->nesting_depth > 0" ); abort(); } } while (0); |
335 | emitter_nest_dec(emitter); |
336 | emitter_printf(emitter, "\n"); |
337 | emitter_indent(emitter); |
338 | emitter_printf(emitter, "}"); |
339 | } else { |
340 | emitter_nest_dec(emitter); |
341 | } |
342 | } |
343 | |
344 | static inline void |
345 | emitter_json_dict_begin(emitter_t *emitter, const char *json_key) { |
346 | if (emitter->output == emitter_output_json) { |
347 | emitter_dict_begin(emitter, json_key, NULL((void*)0)); |
348 | } |
349 | } |
350 | |
351 | static inline void |
352 | emitter_json_dict_end(emitter_t *emitter) { |
353 | if (emitter->output == emitter_output_json) { |
354 | emitter_dict_end(emitter); |
355 | } |
356 | } |
357 | |
358 | static inline void |
359 | emitter_table_dict_begin(emitter_t *emitter, const char *table_key) { |
360 | if (emitter->output == emitter_output_table) { |
361 | emitter_dict_begin(emitter, NULL((void*)0), table_key); |
362 | } |
363 | } |
364 | |
365 | static inline void |
366 | emitter_table_dict_end(emitter_t *emitter) { |
367 | if (emitter->output == emitter_output_table) { |
368 | emitter_dict_end(emitter); |
369 | } |
370 | } |
371 | |
372 | static inline void |
373 | emitter_json_arr_begin(emitter_t *emitter, const char *json_key) { |
374 | if (emitter->output == emitter_output_json) { |
375 | emitter_json_key_prefix(emitter); |
376 | emitter_printf(emitter, "\"%s\": [", json_key); |
377 | emitter_nest_inc(emitter); |
378 | } |
379 | } |
380 | |
381 | static inline void |
382 | emitter_json_arr_end(emitter_t *emitter) { |
383 | if (emitter->output == emitter_output_json) { |
384 | assert(emitter->nesting_depth > 0)do { if (__builtin_expect(!!(config_debug && !(emitter ->nesting_depth > 0)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 384, "emitter->nesting_depth > 0" ); abort(); } } while (0); |
385 | emitter_nest_dec(emitter); |
386 | emitter_printf(emitter, "\n"); |
387 | emitter_indent(emitter); |
388 | emitter_printf(emitter, "]"); |
389 | } |
390 | } |
391 | |
392 | static inline void |
393 | emitter_json_arr_obj_begin(emitter_t *emitter) { |
394 | if (emitter->output == emitter_output_json) { |
395 | emitter_json_key_prefix(emitter); |
396 | emitter_printf(emitter, "{"); |
397 | emitter_nest_inc(emitter); |
398 | } |
399 | } |
400 | |
401 | static inline void |
402 | emitter_json_arr_obj_end(emitter_t *emitter) { |
403 | if (emitter->output == emitter_output_json) { |
404 | assert(emitter->nesting_depth > 0)do { if (__builtin_expect(!!(config_debug && !(emitter ->nesting_depth > 0)), 0)) { je_malloc_printf( "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n" , "include/jemalloc/internal/emitter.h", 404, "emitter->nesting_depth > 0" ); abort(); } } while (0); |
405 | emitter_nest_dec(emitter); |
406 | emitter_printf(emitter, "\n"); |
407 | emitter_indent(emitter); |
408 | emitter_printf(emitter, "}"); |
409 | } |
410 | } |
411 | |
412 | static inline void |
413 | emitter_json_arr_value(emitter_t *emitter, emitter_type_t value_type, |
414 | const void *value) { |
415 | if (emitter->output == emitter_output_json) { |
416 | emitter_json_key_prefix(emitter); |
417 | emitter_print_value(emitter, emitter_justify_none, -1, |
418 | value_type, value); |
419 | } |
420 | } |
421 | |
422 | static inline void |
423 | emitter_table_row(emitter_t *emitter, emitter_row_t *row) { |
424 | if (emitter->output != emitter_output_table) { |
425 | return; |
426 | } |
427 | emitter_col_t *col; |
428 | ql_foreach(col, &row->cols, link)for (((col)) = (((&row->cols)->qlh_first)); ((col)) != ((void*)0); ((col)) = ((((col))->link.qre_next != (((& row->cols)->qlh_first))) ? ((col))->link.qre_next : ( (void*)0))) { |
429 | emitter_print_value(emitter, col->justify, col->width, |
430 | col->type, (const void *)&col->bool_val); |
431 | } |
432 | emitter_table_printf(emitter, "\n"); |
433 | } |
434 | |
435 | #endif /* JEMALLOC_INTERNAL_EMITTER_H */ |