#include "blue/object/datetime.h" #include #include #include #include #include #include #include #include void write_tagged_value(b_object *data); void write_raw_string(const b_string *data) { b_stream_write_string(b_stdout, "\"", NULL); b_string_iterator it; b_string_foreach(&it, data) { b_wchar c = it.char_value; if (c >= 0x10000) { c -= 0x10000; long hi = 0xD800 | ((c >> 10) & 0x3FF); long lo = 0xDC00 | (c & 0x3FF); b_stream_write_fmt(b_stdout, NULL, "\\u%04x\\u%04x", hi, lo); } else if (c <= 0x1F || c >= 0x7F) { b_stream_write_fmt(b_stdout, NULL, "\\u%04x", c); } else if (c == '\\' || c == '"') { b_stream_write_fmt(b_stdout, NULL, "\\%c", c); } else { b_stream_write_char(b_stdout, c); } } b_stream_write_string(b_stdout, "\"", NULL); } void write_tagged_string(b_string *data) { b_stream_write_string(b_stdout, "{ \"type\": \"string\", \"value\": ", NULL); write_raw_string(data); b_stream_write_string(b_stdout, " }", NULL); } void write_tagged_integer(b_number *data) { b_stream_write_string( b_stdout, "{ \"type\": \"integer\", \"value\": \"", NULL); if (b_number_is_inf_positive(data)) { b_stream_write_string(b_stdout, "inf", NULL); } else if (b_number_is_inf_negative(data)) { b_stream_write_string(b_stdout, "-inf", NULL); } else if (b_number_is_nan_positive(data)) { b_stream_write_string(b_stdout, "nan", NULL); } else if (b_number_is_nan_negative(data)) { b_stream_write_string(b_stdout, "-nan", NULL); } else { b_stream_write_fmt( b_stdout, NULL, "%lld", b_number_get_longlong(data), NULL); } b_stream_write_string(b_stdout, "\" }", NULL); } void write_tagged_float(b_number *data) { b_stream_write_string( b_stdout, "{ \"type\": \"float\", \"value\": \"", NULL); if (b_number_is_inf_positive(data)) { b_stream_write_string(b_stdout, "inf", NULL); } else if (b_number_is_inf_negative(data)) { b_stream_write_string(b_stdout, "-inf", NULL); } else if (b_number_is_nan_positive(data)) { b_stream_write_string(b_stdout, "nan", NULL); } else if (b_number_is_nan_negative(data)) { b_stream_write_string(b_stdout, "-nan", NULL); } else { double v = b_number_get_double(data); if ((v <= 0.00000001 && v > 0) || (v >= -0.00000001 && v < 0) || (v >= 1000000000) || (v <= -1000000000)) { b_stream_write_fmt(b_stdout, NULL, "%.15e", v, NULL); } else { b_stream_write_fmt(b_stdout, NULL, "%.15f", v, NULL); } } b_stream_write_string(b_stdout, "\" }", NULL); } void write_tagged_bool(b_number *data) { int v = b_number_get_int8(data); b_stream_write_fmt( b_stdout, NULL, "{ \"type\": \"bool\", \"value\": \"%s\" }", (v > 0) ? "true" : "false", NULL); } void write_tagged_datetime(b_datetime *data) { bool has_date = b_datetime_has_date(data); bool has_time = b_datetime_has_time(data); bool localtime = b_datetime_is_localtime(data); b_stream_write_string(b_stdout, "{ \"type\": \"", NULL); if (has_date && has_time) { b_stream_write_string( b_stdout, localtime ? "datetime-local" : "datetime", NULL); } else if (has_date) { b_stream_write_string( b_stdout, localtime ? "date-local" : "date", NULL); } else if (has_time) { b_stream_write_string( b_stdout, localtime ? "time-local" : "time", NULL); } b_stream_write_string(b_stdout, "\", \"value\": \"", NULL); b_string *new_data = b_string_create(); b_datetime_to_string(data, B_DATETIME_FORMAT_RFC3339, new_data); b_stream_write_string(b_stdout, b_string_ptr(new_data), NULL); b_stream_write_string(b_stdout, "\" }", NULL); b_string_release(new_data); } void write_tagged_dict(b_dict *data) { b_stream_write_string(b_stdout, "{ ", NULL); int i = 0; b_dict_iterator it; b_dict_foreach(&it, data) { if (i++ > 0) { b_stream_write_string(b_stdout, ", ", NULL); } write_raw_string(it.key); b_stream_write_string(b_stdout, ": ", NULL); write_tagged_value(it.value); } b_stream_write_string(b_stdout, " }", NULL); } void write_tagged_array(b_array *data) { b_stream_write_string(b_stdout, "[ ", NULL); int i = 0; b_array_iterator it; b_array_foreach(&it, data) { if (i++ > 0) { b_stream_write_string(b_stdout, ", ", NULL); } write_tagged_value(it.value); } b_stream_write_string(b_stdout, " ]", NULL); } void write_tagged_value(b_object *data) { b_object_type_id typeid = B_TYPEID(data); switch (typeid) { case B_OBJECT_TYPE_DICT: write_tagged_dict(B_DICT(data)); break; case B_OBJECT_TYPE_ARRAY: write_tagged_array(B_ARRAY(data)); break; case B_OBJECT_TYPE_STRING: write_tagged_string(B_STRING(data)); break; case B_OBJECT_TYPE_DATETIME: write_tagged_datetime(B_DATETIME(data)); break; case B_OBJECT_TYPE_NUMBER: switch (b_number_get_type(B_NUMBER(data))) { case B_NUMBER_LONGLONG: write_tagged_integer(B_NUMBER(data)); break; case B_NUMBER_INT8: write_tagged_bool(B_NUMBER(data)); break; case B_NUMBER_DOUBLE: write_tagged_float(B_NUMBER(data)); break; default: break; } break; default: break; } } int main(void) { b_stream *src = b_stdin; b_stream *dest = b_stdout; b_serial_ctx *ctx; b_serial_ctx_create(&ctx); b_object *data; b_status status = b_serial_ctx_deserialise( ctx, B_SERIAL_FORMAT_TOML, src, &data, 0); if (!B_OK(status)) { return 1; } write_tagged_value(data); b_stream_write_char(b_stdout, '\n'); b_serial_ctx_destroy(ctx); b_release(data); return 0; }