#include #include #include #include #include #include #include #include #include #include #include void write_tagged_value(const fx_value *data); void write_raw_string(const fx_string *data) { fx_stream_write_cstr(fx_stdout, "\"", NULL); const fx_iterator *it = fx_iterator_begin(data); fx_foreach(val, it) { fx_wchar c; fx_value_get_wchar(val, &c); if (c >= 0x10000) { c -= 0x10000; long hi = 0xD800 | ((c >> 10) & 0x3FF); long lo = 0xDC00 | (c & 0x3FF); fx_stream_write_fmt( fx_stdout, NULL, "\\u%04x\\u%04x", hi, lo); } else if (c <= 0x1F || c >= 0x7F) { fx_stream_write_fmt(fx_stdout, NULL, "\\u%04x", c); } else if (c == '\\' || c == '"') { fx_stream_write_fmt(fx_stdout, NULL, "\\%c", c); } else { fx_stream_write_char(fx_stdout, c); } } fx_iterator_unref(it); fx_stream_write_cstr(fx_stdout, "\"", NULL); } void write_tagged_string(fx_string *data) { fx_stream_write_cstr( fx_stdout, "{ \"type\": \"string\", \"value\": ", NULL); write_raw_string(data); fx_stream_write_cstr(fx_stdout, " }", NULL); } void write_tagged_integer(const fx_value *data) { fx_stream_write_cstr( fx_stdout, "{ \"type\": \"integer\", \"value\": \"", NULL); fx_stream_write_fmt(fx_stdout, NULL, "%lld", data->v_i64, NULL); fx_stream_write_cstr(fx_stdout, "\" }", NULL); } void write_tagged_float(const fx_value *data) { fx_stream_write_cstr( fx_stdout, "{ \"type\": \"float\", \"value\": \"", NULL); double d = data->v_double; if (d == INFINITY) { fx_stream_write_cstr(fx_stdout, "inf", NULL); } else if (d == -INFINITY) { fx_stream_write_cstr(fx_stdout, "-inf", NULL); } else if (d == NAN) { fx_stream_write_cstr(fx_stdout, "nan", NULL); } else if (d == -NAN) { fx_stream_write_cstr(fx_stdout, "-nan", NULL); } else if (d <= 1e-9 || d >= 1e9) { fx_stream_write_fmt(fx_stdout, NULL, "%g", d, NULL); } else { fx_stream_write_fmt(fx_stdout, NULL, "%.9lf", d, NULL); } fx_stream_write_cstr(fx_stdout, "\" }", NULL); } void write_tagged_bool(const fx_value *data) { fx_stream_write_fmt( fx_stdout, NULL, "{ \"type\": \"bool\", \"value\": \"%s\" }", data->v_bool ? "true" : "false", NULL); } void write_tagged_datetime(fx_datetime *data) { bool has_date = fx_datetime_has_date(data); bool has_time = fx_datetime_has_time(data); bool localtime = fx_datetime_is_localtime(data); fx_stream_write_cstr(fx_stdout, "{ \"type\": \"", NULL); if (has_date && has_time) { fx_stream_write_cstr( fx_stdout, localtime ? "datetime-local" : "datetime", NULL); } else if (has_date) { fx_stream_write_cstr( fx_stdout, localtime ? "date-local" : "date", NULL); } else if (has_time) { fx_stream_write_cstr( fx_stdout, localtime ? "time-local" : "time", NULL); } fx_stream_write_cstr(fx_stdout, "\", \"value\": \"", NULL); fx_stringstream *new_data = fx_stringstream_create(); fx_datetime_to_string(data, FX_DATETIME_FORMAT_RFC3339, new_data); fx_stream_write_cstr(fx_stdout, fx_stringstream_ptr(new_data), NULL); fx_stream_write_cstr(fx_stdout, "\" }", NULL); fx_stringstream_unref(new_data); } void write_tagged_hashtable(fx_hashtable *data) { fx_stream_write_cstr(fx_stdout, "{ ", NULL); int i = 0; const fx_iterator *it = fx_iterator_begin(data); fx_foreach(v, it) { fx_hashtable_item *item; fx_value_get_object(v, &item); if (i++ > 0) { fx_stream_write_cstr(fx_stdout, ", ", NULL); } const fx_value *key = fx_hashtable_item_get_key(item); const fx_value *value = fx_hashtable_item_get_value(item); fx_string *key_str; fx_value_get_object(key, &key_str); write_raw_string(key_str); fx_stream_write_cstr(fx_stdout, ": ", NULL); write_tagged_value(value); } fx_iterator_unref(it); fx_stream_write_cstr(fx_stdout, " }", NULL); } void write_tagged_array(fx_array *data) { fx_stream_write_cstr(fx_stdout, "[ ", NULL); int i = 0; const fx_iterator *it = fx_iterator_begin(data); fx_foreach(val, it) { if (i++ > 0) { fx_stream_write_cstr(fx_stdout, ", ", NULL); } write_tagged_value(val); } fx_iterator_unref(it); fx_stream_write_cstr(fx_stdout, " ]", NULL); } void write_tagged_value(const fx_value *data) { if (fx_value_is_type(data, FX_TYPE_HASHTABLE)) { write_tagged_hashtable(data->v_object); } else if (fx_value_is_type(data, FX_TYPE_ARRAY)) { write_tagged_array(data->v_object); } else if (fx_value_is_type(data, FX_TYPE_STRING)) { write_tagged_string(data->v_object); } else if (fx_value_is_type(data, FX_TYPE_DATETIME)) { write_tagged_datetime(data->v_object); } else if (fx_value_is_type(data, FX_TYPE_BOOL)) { write_tagged_bool(data); } else if (fx_value_is_type(data, FX_TYPE_I64)) { write_tagged_integer(data); } else if (fx_value_is_type(data, FX_TYPE_DOUBLE)) { write_tagged_float(data); } } int main(void) { fx_stream *src = fx_stdin; fx_stream *dest = fx_stdout; fx_serial_ctx *ctx = fx_toml_serial_ctx_create(); fx_value data; fx_result result = fx_serial_ctx_deserialise(ctx, src, &data, 0); if (fx_result_is_error(result)) { return 1; } write_tagged_value(&data); fx_stream_write_char(fx_stdout, '\n'); fx_serial_ctx_unref(ctx); fx_value_unset(&data); return 0; }