Parsodus/examples/json/json.cpp

271 lines
5.8 KiB
C++

#include "json.h"
#include <iostream>
#include <algorithm>
#include <cmath>
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<std::string>(idx)];
} else if (idx.type == Num) {
return (*this)[static_cast<int>(std::round(static_cast<double>(idx)))];
} else {
throw JSONError("Not a subscriptable JSON value");
}
}
std::string JSON::to_string() const {
return static_cast<std::string>(*this);
}
double JSON::to_double() const {
return static_cast<double>(*this);
}
bool JSON::to_bool() const {
return static_cast<bool>(*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<JSON>();
else if (t == Object)
val.obj = new std::map<std::string, JSON>();
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<std::string, JSON>(*other.val.obj);
else if (type == Array)
val.arr = new std::deque<JSON>(*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<std::string, JSON>(*other.val.obj);
else if (type == Array)
val.arr = new std::deque<JSON>(*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;
}
}