#include "json.h" #include #include namespace json { JSON::operator std::string() const { if (type != String) throw JSONError("Not a JSON string"); else return (*val.str); } JSON::operator double() const { if (type != Num) throw JSONError("Not a JSON number"); else return val.num; } JSON::operator bool() const { if (type != Bool && type != Null) throw JSONError("Not a JSON bool"); else if (type == Null) return false; else return val.b; } JSON& JSON::operator[] (int i) const { if (type == Array) return (*val.arr)[i]; else throw JSONError("Not a JSON array"); } JSON& JSON::operator[] (std::string s) const { if (type != Object) throw JSONError("Not a JSON object"); else return (*val.obj)[s]; } JSON& JSON::operator[] (const char* s) const { if (type != Object) throw JSONError("Not a JSON object"); else return (*val.obj)[s]; } JSON& JSON::operator[] (const JSON& idx) const { if (idx.type == String) { return (*this)[static_cast(idx)]; } else if (idx.type == Num) { return (*this)[static_cast(std::round(static_cast(idx)))]; } else { throw JSONError("Not a subscriptable JSON value"); } } std::string JSON::to_string() const { return static_cast(*this); } double JSON::to_double() const { return static_cast(*this); } bool JSON::to_bool() const { return static_cast(*this); } bool JSON::isNull() const { return type == Null; } std::size_t JSON::size() const { if (type == Object) { return val.obj->size(); } else if (type == Array) { return val.arr->size(); } else { throw JSONError("Not a JSON value with a size"); } } void JSON::push_back(const JSON& other) { if (type == Array) { val.arr->push_back(other); } else { throw JSONError("Not a JSON array"); } } void JSON::push_front(const JSON& other) { if (type == Array) { val.arr->push_front(other); } else { throw JSONError("Not a JSON array"); } } Type JSON::getType() const { return type; } JSON JSON::num(double n) { Value v; v.num = n; return JSON(Num, v); } JSON JSON::string(const std::string& s) { Value v; v.str = new std::string(s); return JSON(String, v); } JSON JSON::object() { return JSON(Object); } JSON JSON::array() { return JSON(Array); } JSON JSON::boolean(bool b) { Value v; v.b = b; return JSON(Bool, v); } JSON JSON::null() { return JSON(Null); } JSON::JSON(Type t) : type(t) { if (t == Array) val.arr = new std::deque(); else if (t == Object) val.obj = new std::map(); else if (t == String) val.str = new std::string(); } JSON::JSON(Type t, Value v) : type(t), val(v) {} JSON::JSON() : type(Null) {} JSON::JSON(const JSON& other) : type(other.type), val(other.val) { if (type == String) val.str = new std::string(*other.val.str); else if (type == Object) val.obj = new std::map(*other.val.obj); else if (type == Array) val.arr = new std::deque(*other.val.arr); } JSON::JSON(JSON&& other) : type(other.type), val(other.val) { if (type == String) other.val.str = nullptr; else if (type == Object) other.val.obj = nullptr; else if (type == Array) other.val.arr = nullptr; } JSON& JSON::operator=(const JSON& other) { if (type == String) delete val.str; else if (type == Object) delete val.obj; else if (type == Array) delete val.arr; type = other.type; if (type == String) val.str = new std::string(*other.val.str); else if (type == Object) val.obj = new std::map(*other.val.obj); else if (type == Array) val.arr = new std::deque(*other.val.arr); else val = other.val; return *this; } JSON& JSON::operator=(JSON&& other) { if (type == String) delete val.str; else if (type == Object) delete val.obj; else if (type == Array) delete val.arr; type = other.type; val = other.val; if (type == String) other.val.str = nullptr; else if (type == Object) other.val.obj = nullptr; else if (type == Array) other.val.arr = nullptr; return *this; } JSON::~JSON() { if (type == String) delete val.str; else if (type == Object) delete val.obj; else if (type == Array) delete val.arr; } std::ostream& operator<<(std::ostream& os, const JSON& j) { switch (j.type) { case Num: os << j.val.num; break; case String: os << '"' << *j.val.str << '"'; break; case Object: os << '{'; { bool first = true; for (const auto& p : *j.val.obj) { if (!first) os << ", "; first = false; os << JSON::string(p.first) << ": " << p.second; } } os << '}'; break; case Array: os << '['; { bool first = true; for (const auto& e : *j.val.arr) { if (!first) os << ", "; first = false; os << e; } } os << ']'; break; case Bool: if (j.val.b) { os << "true"; } else { os << "false"; } break; case Null: os << "null"; break; } return os; } }