json-parser-in-c-2/src/json_cpp.cpp
2026-03-29 15:46:36 +02:00

192 lines
4.5 KiB
C++

#include "json.h"
#include "json.hpp"
#include "json_collections.h"
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
namespace json {
class Underlying {
public:
virtual auto ptr() -> struct json_value*& = 0;
virtual auto ptr() const -> const struct json_value* const& = 0;
virtual auto alloc_ptr() -> struct blockalloc* = 0;
private:
};
class ValuePtr final : public Underlying {
public:
explicit ValuePtr(struct blockalloc* alloc, struct json_value* value)
: m_alloc(alloc)
, m_value(value) { };
auto ptr() -> struct json_value*& override
{
return m_value;
}
auto ptr() const -> const struct json_value* const& override
{
return m_value;
}
auto alloc_ptr() -> struct blockalloc* override
{
return m_alloc;
}
private:
struct blockalloc* m_alloc;
struct json_value* m_value;
};
auto Value::is(Type type) const -> bool
{
return json_is(m_underlying->ptr(), (enum json_type)type);
}
auto Value::get_type() const -> Type
{
return (Type)json_get_type(m_underlying->ptr());
}
auto Value::get_bool() const -> bool
{
return json_get_bool(m_underlying->ptr());
}
auto Value::get_int() const -> std::int64_t
{
return json_get_int(m_underlying->ptr());
}
auto Value::get_float() const -> double
{
return json_get_float(m_underlying->ptr());
}
auto Value::get_string() const -> std::string_view
{
return json_get_string(m_underlying->ptr());
}
void Value::set_null()
{
json_set_null(&m_underlying->ptr());
}
void Value::set_bool(bool val)
{
json_set_bool(&m_underlying->ptr(), val);
}
void Value::set_int(int64_t val)
{
json_set_int(&m_underlying->ptr(), val);
}
void Value::set_float(double val)
{
json_set_float(&m_underlying->ptr(), val);
}
void Value::set_string(std::string_view val)
{
char* own_str
= (char*)blockalloc_alloc(m_underlying->alloc_ptr(), val.size() + 1, 2);
std::strncpy(own_str, val.data(), val.size() + 1);
json_set_string(m_underlying->ptr(), own_str);
}
auto Value::count() const -> std::size_t
{
return json_array_count(m_underlying->ptr());
}
auto Value::get(std::size_t idx) -> std::unique_ptr<Value>
{
return std::make_unique<Value>(std::make_unique<ValuePtr>(
m_underlying->alloc_ptr(), json_idx(m_underlying->ptr(), idx)));
}
auto Value::get(std::size_t idx) const -> std::unique_ptr<const Value>
{
return std::make_unique<Value>(std::make_unique<ValuePtr>(
m_underlying->alloc_ptr(), json_idx(m_underlying->ptr(), idx)));
}
void Value::push(std::unique_ptr<Value> value)
{
json_push(m_underlying->ptr(), value->m_underlying->ptr());
}
auto Value::get(std::string_view key) -> std::unique_ptr<Value>
{
return std::make_unique<Value>(
std::make_unique<ValuePtr>(m_underlying->alloc_ptr(),
json_key_sized(m_underlying->ptr(), key.data(), key.size())));
}
auto Value::get(std::string_view key) const -> std::unique_ptr<const Value>
{
return std::make_unique<Value>(
std::make_unique<ValuePtr>(m_underlying->alloc_ptr(),
json_key_sized(m_underlying->ptr(), key.data(), key.size())));
}
void Value::set(std::string_view key, std::unique_ptr<Value> value)
{
json_set_sized(m_underlying->ptr(),
key.data(),
key.size(),
value->m_underlying->ptr());
}
auto Value::query(const std::string& query) -> std::unique_ptr<Value>
{
return std::make_unique<Value>(
std::make_unique<ValuePtr>(m_underlying->alloc_ptr(),
json_query(m_underlying->ptr(), query.c_str())));
}
class Doc final : public Underlying {
public:
explicit Doc()
{
blockalloc_construct(&m_alloc);
}
~Doc()
{
blockalloc_destroy(&m_alloc);
if (m_value) {
json_free(m_value);
}
}
int parse(std::string_view text)
{
m_value = json_parse(text.data(), text.size(), &m_alloc);
if (!m_value)
return 1;
return 0;
}
auto ptr() -> struct json_value*& override
{
return m_value;
}
auto ptr() const -> const struct json_value* const& override
{
return m_value;
}
auto alloc_ptr() -> struct blockalloc* override
{
return &m_alloc;
}
private:
struct blockalloc m_alloc;
struct json_value* m_value = nullptr;
};
auto parse(std::string_view text) -> std::unique_ptr<Value>
{
auto doc = std::make_unique<Doc>();
if (doc->parse(text) != 0)
return nullptr;
return std::make_unique<Value>(std::move(doc));
}
}