#include "JsonObjs.h"
#include <ostream>
namespace {
class C_ToStr
{
public:
C_ToStr(std::ostream &out, size_t indent = 0): m_out(out), m_indent(indent) {}
void operator()(std::monostate) { m_out <<"null"; }
void operator()(bool y) { m_out <<(y?"true":"false"); }
void operator()(json::jint i) { m_out <<i; }
void operator()(json::jfloat d) { m_out <<d; }
void operator()(const json::array &arr);
void operator()(const json::object &obj);
private:
std::ostream &m_out;
const size_t m_indent;
size_t m_base{};
};
void C_ToStr::operator()(const json::array &arr)
{
if (arr.empty())
{
m_out <<"[]";
return;
}
m_out <<(m_indent?"[\n":"[ ");
m_base += m_indent;
bool first = true;
for (auto &&i: arr)
{
if (first)
first = false;
else
m_out <<(m_base?",\n":", ");
m_out <<std::string(m_base,' ');
std::visit(*this,i);
}
m_base -= m_indent;
if (m_indent)
m_out <<'\n' <<std::string(m_base,' ') <<']';
else
m_out <<" ]";
}
void C_ToStr::operator()(const json::object &obj)
{
if (obj.empty())
{
m_out <<"{}";
return;
}
m_out <<(m_indent?"{\n":"{ ");
m_base += m_indent;
bool first = true;
for (auto &i: obj)
{
if (first)
first = false;
else
m_out <<(m_base?",\n":", ");
std::visit(*this, i.second);
}
m_base -= m_indent;
if (m_indent)
m_out <<'\n' <<std::string(m_base,' ') <<'}';
else
m_out <<" }";
}
}
namespace json {
std::ostream &operator<<(std::ostream &out, const value &src)
{
std::visit(C_ToStr{out}, src);
return out;
}
const value &operator/(const value &root, const std::string &key)
{
for (auto &i: get<object>(root))
if (i.first == key)
return i.second;
}
const value *operator/(const value *root, const std::string &key) noexcept
{
return root? subvalue(*root, key): nullptr;
}
const value *subvalue(const value &root, const std::string &key) noexcept
{
if (holds_alternative<object>(root))
{
for (auto &i: get<object>(root))
if (i.first == key)
return &i.second;
}
return nullptr;
}
void dump(const value &src, std::ostream &out, size_t indent)
{
std::visit(C_ToStr{out,indent}, src);
}
void dump(const array &src, std::ostream &out, size_t indent)
{
C_ToStr{out,indent}(src);
}
void dump(const object &src, std::ostream &out, size_t indent)
{
C_ToStr{out,indent}(src);
}
}
#define RUNTIME_ERROR(fmtStr,...)
Wrap FILE(DATE)#__LINE__ FUNCTION: msg into std::runtime_error.
std::string asciiLiteral(uint32_t utf32)