Files
weaseljson/src/callbacks.h
Andrew Noyes f6cd807da3 Remove on_{begin,end}_{string,number}
And add `done` arg to data callback
2025-05-25 21:01:37 -04:00

135 lines
4.0 KiB
C++

#pragma once
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#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<Cursor> 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;
}