Partial edits of library refactor

This commit is contained in:
2025-03-24 23:45:16 -04:00
parent c20c60f934
commit 1253861ad1
3 changed files with 217 additions and 112 deletions

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;
}
}