Skip to content

Commit 0b22117

Browse files
committed
fix couple of bugs; add optional variant handlers
1 parent 02aadae commit 0b22117

File tree

2 files changed

+98
-5
lines changed

2 files changed

+98
-5
lines changed

jsonwriter.c

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@ struct jsonwriter_data {
2020
size_t (*write)(const void *, size_t, size_t, void *);
2121
void *write_arg;
2222
char tmp[128]; // number buffer
23-
char just_wrote_key;
24-
char compact;
25-
char started;
23+
24+
struct jsonwriter_variant (*to_jsw_variant)(void *);
25+
void (*after_to_jsw_variant)(void *, struct jsonwriter_variant *);
26+
27+
unsigned char just_wrote_key:1;
28+
unsigned char compact:1;
29+
unsigned char started:1;
30+
unsigned char dummy:5;
31+
2632
};
2733

2834
void jsonwriter_set_option(jsonwriter_handle h, enum jsonwriter_option opt) {
@@ -74,7 +80,7 @@ static size_t jsonwriter_writeln(struct jsonwriter_data *data) {
7480
static int jsonwriter_indent(struct jsonwriter_data *data, char closing) {
7581
if(data->just_wrote_key) {
7682
if(data->compact)
77-
data->write(":", 1, 2, data->write_arg);
83+
data->write(":", 1, 1, data->write_arg);
7884
else
7985
data->write(": ", 1, 2, data->write_arg);
8086
data->just_wrote_key = 0;
@@ -205,7 +211,7 @@ int jsonwriter_object_key(jsonwriter_handle h, const char *key, size_t len_or_ze
205211
struct jsonwriter_data *data = h;
206212
if(data->depth < JSONWRITER_MAX_NESTING) {
207213
jsonwriter_indent(data, 0);
208-
jsonwriter_str1(h, key, len_or_zero == 0 ? strlen(key) : len_or_zero == 0);
214+
jsonwriter_str1(h, key, len_or_zero == 0 ? strlen(key) : len_or_zero);
209215
data->just_wrote_key = 1;
210216
return 0;
211217
}
@@ -269,3 +275,45 @@ int jsonwriter_start_object(jsonwriter_handle h) {
269275
int jsonwriter_start_array(jsonwriter_handle h) {
270276
return jsonwriter_go_deeper((struct jsonwriter_data *)h, '[', ']');
271277
}
278+
279+
enum jsonwriter_error jsonwriter_set_variant_handler(
280+
jsonwriter_handle h,
281+
struct jsonwriter_variant (*to_jsw_variant)(void *),
282+
void (*cleanup)(void *, struct jsonwriter_variant *)
283+
) {
284+
struct jsonwriter_data *d = h;
285+
d->after_to_jsw_variant = cleanup;
286+
if(!(d->to_jsw_variant = to_jsw_variant))
287+
return jsonwriter_error_invalid_value;
288+
289+
return jsonwriter_error_ok;
290+
}
291+
292+
enum jsonwriter_error jsonwriter_variant(jsonwriter_handle h, void *data) {
293+
struct jsonwriter_data *d = h;
294+
if(!d->to_jsw_variant)
295+
return jsonwriter_error_misconfiguration;
296+
struct jsonwriter_variant jv = d->to_jsw_variant(data);
297+
298+
int rc = jsonwriter_error_unrecognized_variant_type;
299+
switch(jv.type) {
300+
case jsonwriter_datatype_null:
301+
rc = jsonwriter_null(h);
302+
break;
303+
case jsonwriter_datatype_string:
304+
rc = jsonwriter_str(h, jv.value.str);
305+
break;
306+
case jsonwriter_datatype_integer:
307+
rc = jsonwriter_int(h, jv.value.i);
308+
break;
309+
case jsonwriter_datatype_float:
310+
rc = jsonwriter_dbl(h, jv.value.dbl);
311+
break;
312+
case jsonwriter_datatype_bool:
313+
rc = jsonwriter_bool(h, jv.value.i ? 1 : 0);
314+
break;
315+
}
316+
if(d->after_to_jsw_variant)
317+
d->after_to_jsw_variant(data, &jv);
318+
return rc;
319+
}

jsonwriter.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ extern "C" {
1212
jsonwriter_option_compact = 1
1313
};
1414

15+
enum jsonwriter_error {
16+
jsonwriter_error_ok = 0, // no error
17+
jsonwriter_error_out_of_memory = 1,
18+
jsonwriter_error_invalid_value,
19+
jsonwriter_error_misconfiguration,
20+
jsonwriter_error_unrecognized_variant_type
21+
};
22+
1523
typedef void * jsonwriter_handle;
1624
jsonwriter_handle jsonwriter_new_file(FILE *f);
1725
jsonwriter_handle jsonwriter_new(size_t (*write)(const void *, size_t, size_t, void *),
@@ -37,6 +45,43 @@ extern "C" {
3745
int jsonwriter_int(jsonwriter_handle h, long int i);
3846
int jsonwriter_null(jsonwriter_handle h);
3947

48+
49+
// optionally, you can configure jsonwriter to handle custom variant types
50+
enum jsonwriter_datatype {
51+
jsonwriter_datatype_null = 0,
52+
jsonwriter_datatype_string = 1,
53+
jsonwriter_datatype_integer = 2,
54+
jsonwriter_datatype_float = 3,
55+
jsonwriter_datatype_bool = 4
56+
// possible to do:
57+
// array
58+
// object
59+
};
60+
61+
struct jsonwriter_variant {
62+
enum jsonwriter_datatype type;
63+
union {
64+
unsigned char b; // bool
65+
long int i; // integer
66+
long double dbl; // double
67+
char *str; // string
68+
// possible to do:
69+
// void *array; // will require corresponding function pointers to get array size and elements
70+
// void *object; // will require corresponding function pointers to get object keys and elements
71+
} value;
72+
};
73+
74+
// jsonwriter_set_variant_handler(): provide jsonwriter with a custom function that converts your data to a jsonwriter_variant
75+
// with an optional cleanup callback
76+
// returns 0 on success, nonzero on error
77+
enum jsonwriter_error
78+
jsonwriter_set_variant_handler(jsonwriter_handle h,
79+
struct jsonwriter_variant (*to_jsw_variant)(void *),
80+
void (*cleanup)(void *, struct jsonwriter_variant *));
81+
82+
// write a variant. will use custom to_jsw_variant() to convert data to jsonwriter_variant
83+
enum jsonwriter_error jsonwriter_variant(jsonwriter_handle h, void *data);
84+
4085
#ifdef __cplusplus
4186
}
4287
#endif

0 commit comments

Comments
 (0)