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