1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
#include "libs/jansson.h"
#include "jansson.h"
#include "parse/parselo.h"
namespace {
int json_write_callback(const char *buffer, size_t size, void *data) {
auto* cfp = (CFILE*)data;
if ((size_t)cfwrite(buffer, 1, (int)size, cfp) != size) {
return -1; // Error
} else {
return 0; // Success
}
}
size_t json_read_callback(void *buffer, size_t buflen, void *data) {
auto fp = (CFILE*)data;
return (size_t)cfread(buffer, 1, (int)buflen, fp);
}
SCP_string format_error(const json_error_t& err)
{
SCP_string out;
sprintf(out, "%s(%d:%d): %s", err.source, err.line, err.column, err.text);
return out;
}
}
int json_dump_cfile(const json_t* json, CFILE* file, size_t flags) {
return json_dump_callback(json, json_write_callback, file, flags);
}
json_t* json_load_cfile(CFILE* cfile, size_t flags, json_error_t* error) {
return json_load_callback(json_read_callback, cfile, flags, error);
}
SCP_string json_dump_string(const json_t* json, size_t flags)
{
auto buf = json_dumps(json, flags);
if (buf == nullptr) {
return SCP_string();
}
SCP_string out(buf);
free(buf);
return out;
}
SCP_string json_dump_string_new(json_t* json, size_t flags)
{
auto str = json_dump_string(json, flags);
json_decref(json);
return str;
}
json_exception::json_exception(const json_error_t& error) : std::runtime_error(format_error(error)) {}
namespace json {
namespace detail {
object_iterator::object_iterator(json_t* obj, void* iter) : m_obj(obj), m_iter(iter) {}
object_iterator& object_iterator::operator++()
{
Assertion(m_iter != nullptr, "Tried to increment iterator after it was at the end!");
m_iter = json_object_iter_next(m_obj, m_iter);
return *this;
}
object_iterator::value_type object_iterator::operator*() const
{
return object_iterator::value_type{json_object_iter_key(m_iter), json_object_iter_value(m_iter)};
}
bool operator==(const object_iterator& lhs, const object_iterator& rhs)
{
return lhs.m_obj == rhs.m_obj && lhs.m_iter == rhs.m_iter;
}
bool operator!=(const object_iterator& lhs, const object_iterator& rhs)
{
return !(rhs == lhs);
}
array_iterator::array_iterator(json_t* array, size_t index) : m_array(array), m_index(index) {}
bool operator==(const array_iterator& lhs, const array_iterator& rhs)
{
return lhs.m_array == rhs.m_array && lhs.m_index == rhs.m_index;
}
bool operator!=(const array_iterator& lhs, const array_iterator& rhs)
{
return !(rhs == lhs);
}
array_iterator& array_iterator::operator++()
{
++m_index;
return *this;
}
array_iterator::value_type array_iterator::operator*() const
{
Assertion(m_index < json_array_size(m_array), "Invalid index encountered!");
return json_array_get(m_array, m_index);
}
} // namespace detail
object_range::object_range(json_t* obj) : m_obj(obj)
{
Assertion(json_typeof(m_obj) == JSON_OBJECT, "Invalid object type %d for json value.", json_typeof(m_obj));
}
detail::object_iterator object_range::begin()
{
// Need to suppress the warning here since applying the requested change breaks on other compilers
return detail::object_iterator(m_obj, json_object_iter(m_obj)); // NOLINT(modernize-return-braced-init-list)
}
detail::object_iterator object_range::end()
{
return {m_obj, nullptr};
}
array_range::array_range(json_t* array) : m_array(array)
{
Assertion(json_typeof(m_array) == JSON_ARRAY, "Invalid object type %d for json value.", json_typeof(m_array));
}
detail::array_iterator array_range::begin()
{
return {m_array, 0};
}
detail::array_iterator array_range::end()
{
return {m_array, json_array_size(m_array)};
}
} // namespace json
|