hermes-json-0.9.0.0: cbits/lib.cpp
#include "../simdjson/singleheader/simdjson.h"
using namespace simdjson;
extern "C" {
ondemand::parser *parser_init(size_t max_cap) {
return new ondemand::parser{max_cap};
}
void parser_destroy(ondemand::parser *parser) {
delete parser;
}
ondemand::document *make_document() {
return new ondemand::document{};
}
void delete_document(ondemand::document *doc) {
delete doc;
}
padded_string *make_input(const char *bytes, size_t len) {
return new padded_string{bytes, len};
}
void delete_input(padded_string *str) {
delete str;
}
error_code get_document_value(
ondemand::parser &parser,
padded_string &input,
ondemand::document &doc,
ondemand::value &out) {
auto error = parser.iterate(input).get(doc);
if (error != SUCCESS) { return error; }
return doc.get_value().get(out);
}
error_code at_pointer(
const char *pointer,
size_t len,
ondemand::document &doc,
ondemand::value &out) {
std::string_view pointerSv { pointer, len };
return doc.at_pointer(pointerSv).get(out);
}
error_code get_object_from_value(ondemand::value &val) {
return val.get_object().error();
}
error_code get_object_iter_from_value(ondemand::value &val) {
ondemand::object obj;
auto error = val.get_object().get(obj);
if (error != SUCCESS) { return error; }
return obj.begin().error();
}
bool obj_iter_is_done(ondemand::object_iterator &obj) {
return obj.operator==(obj);
}
error_code obj_iter_get_current(
ondemand::object_iterator &obj,
const char **key,
size_t *len,
ondemand::value &out) {
ondemand::field f;
auto error = obj.operator*().get(f);
if (error != SUCCESS) { return error; }
std::string_view uek;
error = f.unescaped_key(true).get(uek);
*key = uek.data();
*len = uek.length();
out = f.value();
return error;
}
void obj_iter_move_next(ondemand::object_iterator &obj) {
++obj;
}
error_code get_array_from_value(
ondemand::value &val,
ondemand::array &out) {
return val.get_array().get(out);
}
error_code get_array_len_from_value(
ondemand::value &val,
size_t &len) {
ondemand::array out;
auto error = val.get_array().get(out);
if (error) { return error; }
return out.count_elements().get(len);
}
error_code int_array(ondemand::array &arr, int64_t out[]) {
for(auto x : arr) {
auto error = x.get_int64().get(*out);
if (error) { return error; }
++out;
}
return SUCCESS;
}
error_code double_array(ondemand::array &arr, double out[]) {
for(auto x : arr) {
auto error = x.get_double().get(*out);
if (error) { return error; }
++out;
}
return SUCCESS;
}
error_code get_array_iter_from_value(ondemand::value &val) {
ondemand::array arr;
auto error = val.get_array().get(arr);
if (error != SUCCESS) { return error; }
return arr.begin().error();
}
error_code get_array_iter_len_from_value(ondemand::value &val, size_t &len) {
ondemand::array arr;
auto error = val.get_array().get(arr);
if (error != SUCCESS) { return error; }
error = arr.begin().error();
if (error != SUCCESS) { return error; }
return arr.count_elements().get(len);
}
bool arr_iter_is_done(ondemand::array_iterator &arr) {
return arr.operator==(arr);
}
error_code arr_iter_get_current(ondemand::array_iterator &arr, ondemand::value &out) {
return arr.operator*().get(out);
}
void arr_iter_move_next(ondemand::array_iterator &arr) {
++arr;
}
void reset_array(ondemand::array &arr) {
arr.reset();
}
void reset_object(ondemand::object &obj) {
obj.reset();
}
error_code find_field(
ondemand::object &obj,
const char *key,
size_t len,
ondemand::value &out) {
std::string_view keySv { key, len };
return obj.find_field(keySv).get(out);
}
error_code find_field_unordered(
ondemand::object &obj,
const char *key,
size_t len,
ondemand::value &out) {
std::string_view keySv { key, len };
return obj.find_field_unordered(keySv).get(out);
}
error_code get_int(ondemand::value &val, int64_t &out) {
return val.get_int64().get(out);
}
error_code get_uint(ondemand::value &val, uint64_t &out) {
return val.get_uint64().get(out);
}
error_code get_double(ondemand::value &val, double &out) {
return val.get_double().get(out);
}
error_code get_bool(ondemand::value &val, bool &out) {
return val.get_bool().get(out);
}
error_code get_string(
ondemand::value &val,
const char **out,
size_t &len) {
std::string_view buf;
auto error = val.get_string().get(buf);
*out = buf.data();
len = buf.length();
return error;
}
void get_raw_json_token(
ondemand::value &val,
const char **out,
size_t &len) {
std::string_view buf = val.raw_json_token();
*out = buf.data();
len = buf.length();
}
error_code get_raw_json(
ondemand::value &val,
const char **out,
size_t &len) {
std::string_view buf;
auto error = val.raw_json().get(buf);
if (error) {
return error;
}
*out = buf.data();
len = buf.length();
return SUCCESS;
}
// Parses a number token as coefficient * 10^exponent. Writes to out:
// [0] coefficient, or its sign when the digits do not fit in int64
// [1] exponent
// [2..5] integer digits and fraction digits as (pointer, length) pairs
// Returns 0, -1 when the coefficient must be built from the digits,
// or an error code.
int get_scientific(ondemand::value &val, int64_t *out) {
std::string_view tok = val.raw_json_token();
const char *p = tok.data();
const char *end = p + tok.size();
auto digit = [&] { return p < end && unsigned(*p - '0') < 10; };
if (p == end || !(*p == '-' || unsigned(*p - '0') < 10)) { return INCORRECT_TYPE; }
bool neg = *p == '-';
if (neg) { ++p; }
uint64_t m = 0;
const char *intStart = p;
while (digit()) { m = m * 10 + unsigned(*p - '0'); ++p; }
const char *intEnd = p;
if (intStart == intEnd || (*intStart == '0' && intEnd - intStart > 1)) { return NUMBER_ERROR; }
const char *fracStart = p;
const char *fracEnd = p;
if (p < end && *p == '.') {
fracStart = ++p;
while (digit()) { m = m * 10 + unsigned(*p - '0'); ++p; }
fracEnd = p;
if (fracStart == fracEnd) { return NUMBER_ERROR; }
}
int64_t e = 0;
if (p < end && (*p == 'e' || *p == 'E')) {
++p;
bool eneg = p < end && *p == '-';
if (p < end && (*p == '+' || *p == '-')) { ++p; }
const char *expStart = p;
while (p < end && *p == '0') { ++p; }
const char *expDigits = p;
while (digit()) {
if (p - expDigits == 18) { return NUMBER_ERROR; }
e = e * 10 + (*p - '0');
++p;
}
if (p == expStart) { return NUMBER_ERROR; }
if (eneg) { e = -e; }
}
while (p < end && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')) { ++p; }
if (p != end) { return NUMBER_ERROR; }
out[1] = e - (fracEnd - fracStart);
if ((intEnd - intStart) + (fracEnd - fracStart) <= 18) {
out[0] = neg ? -int64_t(m) : int64_t(m);
return 0;
}
out[0] = neg ? -1 : 1;
out[2] = int64_t(reinterpret_cast<intptr_t>(intStart));
out[3] = intEnd - intStart;
out[4] = int64_t(reinterpret_cast<intptr_t>(fracStart));
out[5] = fracEnd - fracStart;
return -1;
}
error_code is_null(ondemand::value &val, bool &out) {
return val.is_null().get(out);
}
error_code get_type(ondemand::value &val, ondemand::json_type &out) {
return val.type().get(out);
}
const char *get_error_message(error_code error) {
return error_message(error);
}
}