Partial edits of library refactor
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
// TODO: Implement standard iterators for json::object_val and json::array_val
|
||||
|
||||
|
||||
namespace JJX::json {
|
||||
enum class token_type { string, number, syntax, boolean, null };
|
||||
@@ -16,64 +18,159 @@ namespace JJX::json {
|
||||
std::shared_ptr<std::string> full_source;
|
||||
};
|
||||
|
||||
struct string_val;
|
||||
struct number_val;
|
||||
struct boolean_val;
|
||||
struct object_val;
|
||||
struct array_val;
|
||||
struct string;
|
||||
struct number;
|
||||
struct boolean;
|
||||
struct object;
|
||||
struct array;
|
||||
|
||||
struct value {
|
||||
|
||||
struct value
|
||||
{
|
||||
std::optional<std::string> string;
|
||||
std::optional<double> number;
|
||||
std::optional<bool> boolean;
|
||||
std::optional<std::vector<value>> array;
|
||||
std::optional<std::map<std::string, value>> object;
|
||||
|
||||
value_type type;
|
||||
|
||||
|
||||
void operator=(double in);
|
||||
void operator=(const std::string& in);
|
||||
void operator=(bool in);
|
||||
void operator=(std::vector<value> in);
|
||||
void operator=(std::map<std::string, value> in);
|
||||
explicit value() : type(value_type::null) { }
|
||||
explicit value(double v) : type(value_type::number), number(v) {}
|
||||
explicit value(const std::string& v) : type(value_type::string), string(v) {}
|
||||
|
||||
//explicit value(bool v) : type(value_type::boolean), boolean(v) {}
|
||||
explicit value(const std::vector<value>& v) : type(value_type::array), array(v) {}
|
||||
explicit value(const std::map<std::string, value>& v) : type(value_type::object), object(v) {}
|
||||
explicit value(const std::pair<std::string, value>& kvp) : type(value_type::object), object({kvp}) {}
|
||||
explicit value(const std::vector<std::pair<std::string, value>>& kvp_list) : type(value_type::object)
|
||||
{
|
||||
for (auto& kvp : kvp_list)
|
||||
object->insert(kvp);
|
||||
}
|
||||
|
||||
|
||||
value& operator=(double in);
|
||||
value& operator=(const std::string& in);
|
||||
value& operator=(bool in);
|
||||
value& operator=(const std::vector<value>& in);
|
||||
value& operator=(const std::map<std::string, value>& in);
|
||||
|
||||
explicit operator double() const { return number.value(); }
|
||||
operator std::string() const { return string.value(); }
|
||||
explicit operator std::string() const { return string.value(); }
|
||||
explicit operator bool() const { return boolean.value(); }
|
||||
explicit operator std::vector<value>() const { return array.value(); }
|
||||
explicit operator std::vector<value>() const { return this->value::array.value(); }
|
||||
explicit operator std::map<std::string, value>() const { return object.value(); }
|
||||
|
||||
|
||||
[[nodiscard]] object_val as_object() const;
|
||||
[[nodiscard]] array_val as_array() const;
|
||||
[[nodiscard]] string_val as_string() const;
|
||||
[[nodiscard]] number_val as_number() const;
|
||||
[[nodiscard]] boolean_val as_boolean() const;
|
||||
[[nodiscard]] struct object as_object() const;
|
||||
[[nodiscard]] struct array as_array() const;
|
||||
[[nodiscard]] struct string as_string() const;
|
||||
[[nodiscard]] struct number as_number() const;
|
||||
[[nodiscard]] struct boolean as_boolean() const;
|
||||
|
||||
|
||||
/// Converts all JSON values contained in this object / array to the derived json value types.
|
||||
void convert_descendants();
|
||||
|
||||
};
|
||||
|
||||
struct string_val : value
|
||||
{
|
||||
void operator=(const std::string& me);
|
||||
struct string : value {
|
||||
explicit string() : value("") {}
|
||||
explicit string(const std::string& v) : value(v) {}
|
||||
|
||||
|
||||
operator std::string();
|
||||
};
|
||||
struct number_val : value {};
|
||||
struct boolean_val : value {};
|
||||
struct object_val : value
|
||||
struct number : value {
|
||||
explicit number() : value(0.0) {}
|
||||
explicit number(double v) : value(v) {}
|
||||
};
|
||||
struct boolean : value {
|
||||
explicit boolean() : value(false) {}
|
||||
explicit boolean(bool v) : value(v) {}
|
||||
};
|
||||
struct object : value
|
||||
{
|
||||
void add(const std::string& key, value val);
|
||||
void add(const std::string& key, const std::string& val);
|
||||
explicit object() : value(std::map<std::string, value>{}) {}
|
||||
explicit object(const std::map<std::string, value>& v) : value(v) {}
|
||||
|
||||
|
||||
void insert(const std::pair<std::string, value>& kvp)
|
||||
{
|
||||
value::object->insert(kvp);
|
||||
}
|
||||
|
||||
void insert(const std::string& key, const value& val)
|
||||
{
|
||||
value::object->insert({key, val});
|
||||
}
|
||||
|
||||
|
||||
json::object& operator+=(const std::pair<std::string, value>& kvp) {
|
||||
insert(kvp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
json::object& operator+=(const std::pair<std::string, bool>& kvp) {
|
||||
insert({kvp.first, json::boolean(kvp.second)});
|
||||
return *this;
|
||||
}
|
||||
|
||||
json::object& operator+=(const std::pair<std::string, double>& kvp) {
|
||||
insert({kvp.first, json::number(kvp.second)});
|
||||
return *this;
|
||||
}
|
||||
|
||||
json::object& operator+=(const std::pair<std::string, std::string>& kvp) {
|
||||
insert({kvp.first, json::string(kvp.second)});
|
||||
return *this;
|
||||
}
|
||||
|
||||
value& at(const std::string& key);
|
||||
value& operator[] (const std::string& key);
|
||||
|
||||
bool contains(const std::string& key);
|
||||
|
||||
json::value_type type_of(const std::string& key);
|
||||
|
||||
|
||||
|
||||
};
|
||||
struct array_val : value
|
||||
{
|
||||
void add(value val);
|
||||
struct array : value {
|
||||
explicit array() : value(std::vector<value>{}) {}
|
||||
explicit array(const std::vector<value>& v) : value(v) {}
|
||||
explicit array(const value& v) {
|
||||
if (v.type == value_type::array)
|
||||
{
|
||||
this->value::array = v.value::array;
|
||||
}
|
||||
}
|
||||
explicit array(const array& v) = default;
|
||||
|
||||
void push_back(const value& element);
|
||||
|
||||
value& operator+= (const value& v);
|
||||
|
||||
value& operator+= (bool v) { push_back(json::boolean(v)); return *this; }
|
||||
value& operator+= (double v) { push_back(json::number(v)); return *this; }
|
||||
value& operator+= (const std::string& v) { push_back(json::string(v)); return *this; }
|
||||
|
||||
value& operator[] (int key);
|
||||
|
||||
json::value_type type_of(int index);
|
||||
|
||||
using iterator = std::vector<value>::iterator;
|
||||
using const_iterator = std::vector<value>::const_iterator;
|
||||
|
||||
iterator begin() { return value::array->begin(); }
|
||||
iterator end() { return value::array->end(); }
|
||||
|
||||
[[nodiscard]] const_iterator begin() const;
|
||||
[[nodiscard]] const_iterator end() const;
|
||||
|
||||
[[nodiscard]] const_iterator cbegin() const;
|
||||
[[nodiscard]] const_iterator cend() const;
|
||||
};
|
||||
|
||||
std::tuple<std::vector<json::token>, std::string> lex(std::string);
|
||||
@@ -81,18 +178,4 @@ namespace JJX::json {
|
||||
std::tuple<json::value, std::string> parse(std::string);
|
||||
std::string deparse(json::value, std::string whitespace = "");
|
||||
|
||||
string_val string(const std::string& text);
|
||||
|
||||
number_val number(double input);
|
||||
|
||||
boolean_val boolean(bool input);
|
||||
|
||||
array_val array(std::vector<value> input);
|
||||
array_val array();
|
||||
|
||||
object_val object(std::map<std::string, value> input);
|
||||
object_val object();
|
||||
|
||||
template <typename T>
|
||||
value array_of(const std::vector<T>& input);
|
||||
}
|
||||
|
14
main.cpp
14
main.cpp
@@ -114,12 +114,12 @@ product_info pinfo_fromjson(json::value root)
|
||||
this_product.name = better_root["name"];
|
||||
this_product.price = double(better_root["price"]);
|
||||
|
||||
auto subobj = better_root["reviews"].as_array();
|
||||
json::array subobj(better_root["reviews"]);
|
||||
|
||||
|
||||
for (auto& review_data_pre : subobj.array.value())
|
||||
for (auto& review_data_pre : subobj)
|
||||
{
|
||||
auto review_data = static_cast<json::object_val>(review_data_pre);
|
||||
json::object review_data = review_data_pre.as_object();
|
||||
product_info::review going_in;
|
||||
going_in.rating = double(review_data["rating"]);
|
||||
going_in.user = review_data["user"];
|
||||
@@ -132,12 +132,12 @@ product_info pinfo_fromjson(json::value root)
|
||||
|
||||
json::value pinfo_tojson(product_info input)
|
||||
{
|
||||
json::object_val root = json::object();
|
||||
json::object root;
|
||||
root["category"] = json::string(input.category);
|
||||
root["manufacturer"] = json::string(input.manufacturer);
|
||||
root["is_available"] = input.is_available;
|
||||
//root.add("category", input.category);
|
||||
root.add("description", input.description);
|
||||
root += {"description", input.description};
|
||||
root["name"] = input.name;
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ json::value pinfo_tojson(product_info input)
|
||||
review["review_text"] = rev.review_text;
|
||||
review["user"] = rev.user;
|
||||
|
||||
root_review_list.add(rev);
|
||||
root_review_list += review;
|
||||
}
|
||||
root["reviews"] = root_review_list;
|
||||
root["taters"] = 5.0;
|
||||
@@ -177,6 +177,8 @@ void test_tile_data() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Some progress has been made on small scale.
|
||||
int main(int argc, char* argv[]) {
|
||||
test_tile_data();
|
||||
|
144
src/JSON.cpp
144
src/JSON.cpp
@@ -173,54 +173,59 @@ namespace JJX::json {
|
||||
return lex_keyword(raw_json, "false", token_type::boolean, index);
|
||||
}
|
||||
|
||||
void value::operator=(double in)
|
||||
json::value& value::operator=(double in)
|
||||
{
|
||||
type = value_type::number;
|
||||
number = in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void value::operator=(const std::string& in)
|
||||
json::value& value::operator=(const std::string& in)
|
||||
{
|
||||
type = value_type::string;
|
||||
string = in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void value::operator=(bool in)
|
||||
json::value& value::operator=(bool in)
|
||||
{
|
||||
type = value_type::boolean;
|
||||
boolean = in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void value::operator=(std::vector<value> in)
|
||||
value& value::operator=(const std::vector<value>& in)
|
||||
{
|
||||
type = value_type::array;
|
||||
array = in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void value::operator=(std::map<std::string, value> in)
|
||||
value& value::operator=(const std::map<std::string, value>& in)
|
||||
{
|
||||
type = value_type::object;
|
||||
object = in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
object_val value::as_object() const {
|
||||
return static_cast<object_val>(*this);
|
||||
struct json::object json::value::as_object() const {
|
||||
return json::object(object.value());
|
||||
}
|
||||
|
||||
array_val value::as_array() const {
|
||||
return static_cast<array_val>(*this);
|
||||
struct json::array json::value::as_array() const {
|
||||
return json::array(array.value());
|
||||
}
|
||||
|
||||
string_val value::as_string() const {
|
||||
return static_cast<string_val>(*this);
|
||||
struct json::string json::value::as_string() const {
|
||||
return json::string(string.value());
|
||||
}
|
||||
|
||||
number_val value::as_number() const {
|
||||
return static_cast<number_val>(*this);
|
||||
struct json::number json::value::as_number() const {
|
||||
return json::number(number.value());
|
||||
}
|
||||
|
||||
boolean_val value::as_boolean() const {
|
||||
return static_cast<boolean_val>(*this);
|
||||
struct json::boolean json::value::as_boolean() const {
|
||||
return json::boolean(boolean.value());
|
||||
}
|
||||
|
||||
void value::convert_descendants() {
|
||||
@@ -277,39 +282,42 @@ namespace JJX::json {
|
||||
}
|
||||
}
|
||||
|
||||
void string_val::operator=(const std::string& me)
|
||||
string::operator std::string()
|
||||
{
|
||||
string = me;
|
||||
return this->value::string.value();
|
||||
}
|
||||
|
||||
string_val::operator std::string()
|
||||
|
||||
value& object::operator[](const std::string& key)
|
||||
{
|
||||
return string.value();
|
||||
return this->value::object.value()[key];
|
||||
}
|
||||
|
||||
void object_val::add(const std::string& key, value val)
|
||||
|
||||
value& array::operator[](int key)
|
||||
{
|
||||
object.value().emplace(key, val);
|
||||
return this->value::array.value()[key];
|
||||
}
|
||||
|
||||
void object_val::add(const std::string& key, const std::string& val)
|
||||
{
|
||||
object.value().emplace(key, json::string(val));
|
||||
json::value_type array::type_of(int index) {
|
||||
return this->value::array->at(index).type;
|
||||
}
|
||||
|
||||
value& object_val::operator[](const std::string& key)
|
||||
{
|
||||
return object.value()[key];
|
||||
value &array::operator+=(const value &v) {
|
||||
push_back(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void array_val::add(value val)
|
||||
{
|
||||
array.value().push_back(val);
|
||||
}
|
||||
array::const_iterator array::begin() const { return value::array->cbegin(); }
|
||||
|
||||
value& array_val::operator[](int key)
|
||||
{
|
||||
return array.value()[key];
|
||||
array::const_iterator array::end() const { return value::array->cend(); }
|
||||
|
||||
array::const_iterator array::cbegin() const { return value::array->cbegin();}
|
||||
|
||||
array::const_iterator array::cend() const { return value::array->cend();}
|
||||
|
||||
void array::push_back(const value &element) {
|
||||
value::array->push_back(element);
|
||||
}
|
||||
|
||||
std::tuple<std::vector<json::token>, std::string> lex(std::string raw_json) {
|
||||
@@ -460,27 +468,27 @@ namespace JJX::json {
|
||||
auto token = tokens[index];
|
||||
switch(token.type) {
|
||||
case token_type::number: {
|
||||
auto n = std::stod(token.value);
|
||||
return {json::value{.number = n, .type = value_type::number}, index+1, ""};
|
||||
double n = std::stod(token.value);
|
||||
return {json::value(n), index + 1, ""};
|
||||
}
|
||||
case token_type::boolean:
|
||||
return {json::value{.boolean = token.value == "true", .type = value_type::boolean}, index + 1, ""};
|
||||
return {json::value(token.value == "true"), index + 1, ""};
|
||||
case token_type::null:
|
||||
return {json::value{.type = value_type::null}, index+1, ""};
|
||||
return {json::value(), index+1, ""};
|
||||
case token_type::string:
|
||||
return {json::value{.string = token.value, .type = value_type::string}, index+1, ""};
|
||||
return {json::value(token.value), index+1, ""};
|
||||
case token_type::syntax: {
|
||||
if (token.value == "[") {
|
||||
auto [array, new_index, error] = parse_array(tokens, index + 1);
|
||||
return {json::value{.array = array, .type = value_type::array}, new_index, error};
|
||||
return {json::value(array), new_index, error};
|
||||
}
|
||||
if (token.value == "{") {
|
||||
auto [object, new_index, error] = parse_object(tokens, index + 1);
|
||||
return {json::value{.object = std::optional(object), .type = value_type::object}, new_index, error};
|
||||
return {json::value(object), new_index, error};
|
||||
}
|
||||
}
|
||||
default:
|
||||
return {{}, index, format_parse_error("Failed to parse", token)};
|
||||
return {json::value(), index, format_parse_error("Failed to parse", token)};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,62 +544,74 @@ namespace JJX::json {
|
||||
}
|
||||
}
|
||||
|
||||
string_val string(const std::string &text) {
|
||||
string_val out;
|
||||
struct string string(const std::string &text) {
|
||||
struct string out;
|
||||
out.type = value_type::string;
|
||||
out.string = text;
|
||||
out.value::string = text;
|
||||
return out;
|
||||
}
|
||||
|
||||
number_val number(double input) {
|
||||
number_val out;
|
||||
struct number number(double input) {
|
||||
struct number out;
|
||||
out.type = value_type::number;
|
||||
out.number = input;
|
||||
out.value::number = input;
|
||||
return out;
|
||||
}
|
||||
|
||||
boolean_val boolean(bool input) {
|
||||
boolean_val out;
|
||||
struct boolean boolean(bool input) {
|
||||
struct boolean out;
|
||||
out.type = value_type::boolean;
|
||||
out.number = input;
|
||||
return out;
|
||||
}
|
||||
|
||||
array_val array(std::vector<value> input)
|
||||
struct array array(std::vector<value> input)
|
||||
{
|
||||
array_val arr;
|
||||
struct array arr;
|
||||
arr.type = value_type::array;
|
||||
arr.array = std::vector<value>();
|
||||
arr.value::array = std::vector<value>();
|
||||
|
||||
for (auto& elem: input)
|
||||
{
|
||||
arr.array->push_back(elem);
|
||||
arr.value::array->push_back(elem);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
array_val array()
|
||||
/*struct array array()
|
||||
{
|
||||
array_val out;
|
||||
struct json::array out;
|
||||
out.type = value_type::array;
|
||||
out.array = std::vector<value>();
|
||||
return out;
|
||||
}
|
||||
|
||||
object_val object(std::map<std::string, value> input)
|
||||
struct object object(std::map<std::string, value> input)
|
||||
{
|
||||
object_val out;
|
||||
struct object out;
|
||||
out.type = value_type::object;
|
||||
out.object = input;
|
||||
out.value::object = input;
|
||||
return out;
|
||||
}
|
||||
|
||||
object_val object()
|
||||
struct object object()
|
||||
{
|
||||
object_val out;
|
||||
struct object out;
|
||||
out.type = value_type::object;
|
||||
out.object = std::map<std::string, value>();
|
||||
out.value::object = std::map<std::string, value>();
|
||||
return out;
|
||||
}*/
|
||||
|
||||
bool object::contains(const std::string &key) {
|
||||
return this->value::object->contains(key);
|
||||
}
|
||||
|
||||
value &object::at(const std::string &key) {
|
||||
return this->value::object.value()[key];
|
||||
}
|
||||
|
||||
json::value_type object::type_of(const std::string &key) {
|
||||
return this->value::object->at(key).type;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user