#pragma once #include #include #include #include #include "weaseljson.h" inline WeaselJsonCallbacks printCallbacks() { WeaselJsonCallbacks result; result.on_begin_object = +[](void *) { puts("on_begin_object"); }; result.on_end_object = +[](void *) { puts("on_end_object"); }; result.on_string_data = +[](void *, const char *buf, int len, int /*done*/) { printf("on_string_data `%.*s`\n", len, buf); }; result.on_begin_array = +[](void *) { puts("on_begin_array"); }; result.on_end_array = +[](void *) { puts("on_end_array"); }; result.on_number_data = +[](void *, const char *buf, int len, int /*done*/) { printf("on_number_data `%.*s`\n", len, buf); }; result.on_true_literal = +[](void *) { puts("on_true_literal"); }; result.on_false_literal = +[](void *) { puts("on_false_literal"); }; result.on_null_literal = +[](void *) { puts("on_null_literal"); }; return result; } inline WeaselJsonCallbacks noopCallbacks() { WeaselJsonCallbacks result; result.on_begin_object = +[](void *) {}; result.on_end_object = +[](void *) {}; result.on_string_data = +[](void *, const char *, int, int) {}; result.on_begin_array = +[](void *) {}; result.on_end_array = +[](void *) {}; result.on_number_data = +[](void *, const char *, int, int) {}; result.on_true_literal = +[](void *) {}; result.on_false_literal = +[](void *) {}; result.on_null_literal = +[](void *) {}; return result; } struct SerializeState { bool isKey = false; struct Cursor { int64_t index; bool isObject; }; std::string result; void on_begin_value() { if (!stack.empty()) { auto &back = stack.back(); if (back.isObject && back.index % 2 == 0 && back.index > 0) { result.append(","); } if (back.isObject && back.index % 2 == 1 && back.index > 0) { result.append(":"); } if (!back.isObject && back.index > 0) { result.append(","); } ++back.index; } } std::vector stack; bool startedData = false; }; inline WeaselJsonCallbacks serializeCallbacks() { WeaselJsonCallbacks result; result.on_begin_object = +[](void *p) { auto *state = (SerializeState *)p; state->on_begin_value(); state->stack.push_back({0, true}); state->result.append("{"); }; result.on_end_object = +[](void *p) { auto *state = (SerializeState *)p; state->stack.pop_back(); state->result.append("}"); }; result.on_string_data = +[](void *p, const char *buf, int len, int done) { auto *state = (SerializeState *)p; if (!state->startedData) { state->startedData = true; state->on_begin_value(); state->result.append("<"); } state->result.append(std::string(buf, len)); if (done) { state->startedData = false; state->result.append(">"); } }; result.on_begin_array = +[](void *p) { auto *state = (SerializeState *)p; state->on_begin_value(); state->stack.push_back({0, false}); state->result.append("["); }; result.on_end_array = +[](void *p) { auto *state = (SerializeState *)p; state->stack.pop_back(); state->result.append("]"); }; result.on_number_data = +[](void *p, const char *buf, int len, int done) { auto *state = (SerializeState *)p; if (!state->startedData) { state->startedData = true; state->on_begin_value(); state->result.append("("); } state->result.append(std::string(buf, len)); if (done) { state->startedData = false; state->result.append(")"); } }; result.on_true_literal = +[](void *p) { auto *state = (SerializeState *)p; state->on_begin_value(); state->result.append("true"); }; result.on_false_literal = +[](void *p) { auto *state = (SerializeState *)p; state->on_begin_value(); state->result.append("false"); }; result.on_null_literal = +[](void *p) { auto *state = (SerializeState *)p; state->on_begin_value(); state->result.append("null"); }; return result; }