Text File Parsing Warcrime
This commit is contained in:
@@ -6,52 +6,4 @@
|
||||
#include <optional>
|
||||
#include <map>
|
||||
|
||||
namespace JJX
|
||||
{
|
||||
namespace json {
|
||||
enum class token_type { string, number, syntax, boolean, null };
|
||||
enum class value_type { string, number, object, array, boolean, null};
|
||||
struct token {
|
||||
std::string value;
|
||||
token_type type;
|
||||
int location;
|
||||
std::shared_ptr<std::string> full_source;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct string_val: value { std::string data; };
|
||||
|
||||
struct number_val : value { double data; };
|
||||
|
||||
struct boolean_val : value { bool data; };
|
||||
|
||||
struct object_val : value { std::map<std::string, value> data; };
|
||||
|
||||
struct array_val : value { std::vector<value> data; };
|
||||
|
||||
std::tuple<std::vector<json::token>, std::string> lex(std::string);
|
||||
std::tuple<json::value, int, std::string> parse(std::vector<json::token>, int index = 0);
|
||||
std::tuple<json::value, std::string> parse(std::string);
|
||||
std::string deparse(json::value, std::string whitespace = "");
|
||||
|
||||
value string(const std::string& text);
|
||||
|
||||
value number(double input);
|
||||
|
||||
value boolean(bool input);
|
||||
|
||||
value array(std::vector<value> input);
|
||||
|
||||
template <typename T>
|
||||
value array_of(const std::vector<T>& input);
|
||||
}
|
||||
namespace xml {}
|
||||
}
|
||||
#include <JJX/JSON.hpp>
|
81
include/JJX/JSON.hpp
Normal file
81
include/JJX/JSON.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
namespace JJX::json {
|
||||
enum class token_type { string, number, syntax, boolean, null };
|
||||
enum class value_type { string, number, object, array, boolean, null};
|
||||
struct token {
|
||||
std::string value;
|
||||
token_type type;
|
||||
int location;
|
||||
std::shared_ptr<std::string> full_source;
|
||||
};
|
||||
|
||||
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 operator double() const { return number.value(); }
|
||||
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::map<std::string, value>() const { return object.value(); }
|
||||
};
|
||||
|
||||
struct string_val : value
|
||||
{
|
||||
void operator=(const std::string& me)
|
||||
{
|
||||
string = me;
|
||||
}
|
||||
operator std::string()
|
||||
{
|
||||
return string.value();
|
||||
}
|
||||
};
|
||||
struct number_val : value {};
|
||||
struct boolean_val : value {};
|
||||
struct object_val : value
|
||||
{
|
||||
void add(const std::string& key, value val);
|
||||
void add(const std::string& key, const std::string& val);
|
||||
value& operator[] (const std::string& key);
|
||||
|
||||
};
|
||||
struct array_val : value
|
||||
{
|
||||
void add(value val);
|
||||
value& operator[] (int key);
|
||||
};
|
||||
|
||||
std::tuple<std::vector<json::token>, std::string> lex(std::string);
|
||||
std::tuple<json::value, int, std::string> parse(std::vector<json::token>, int index = 0);
|
||||
std::tuple<json::value, std::string> parse(std::string);
|
||||
std::string deparse(json::value, std::string whitespace = "");
|
||||
|
||||
string_val string(const std::string& text);
|
||||
|
||||
value number(double input);
|
||||
|
||||
value 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);
|
||||
}
|
101
main.cpp
101
main.cpp
@@ -61,9 +61,104 @@ Vector3 json_to_vector3(const json::value& obj)
|
||||
return value;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
parse_json_file("../samples/product_info.json");
|
||||
|
||||
struct product_info
|
||||
{
|
||||
struct rating_metrics {
|
||||
double average;
|
||||
int total;
|
||||
};
|
||||
|
||||
struct review
|
||||
{
|
||||
int rating;
|
||||
std::string review_text;
|
||||
std::string user;
|
||||
|
||||
operator json::object_val() const
|
||||
{
|
||||
json::object_val obj = json::object();
|
||||
obj["rating"] = json::number(rating);
|
||||
obj["review_text"] = json::string(review_text);
|
||||
obj["user"] = json::string(user);
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
std::string category;
|
||||
std::string description;
|
||||
bool is_available;
|
||||
std::string manufacturer;
|
||||
std::string name;
|
||||
double price;
|
||||
std::string product_id;
|
||||
rating_metrics ratings;
|
||||
std::string release_date;
|
||||
std::vector<review> reviews;
|
||||
};
|
||||
|
||||
|
||||
std::cout << json::deparse(vector3_to_json({2,4.5f, 31}));
|
||||
product_info pinfo_fromjson(json::value root)
|
||||
{
|
||||
if (root.type != json::value_type::object)
|
||||
std::cerr << "Malformed product info file!" << std::endl;
|
||||
|
||||
product_info this_product;
|
||||
|
||||
json::object_val better_root = static_cast<json::object_val>(root);
|
||||
|
||||
this_product.category = better_root["category"];
|
||||
this_product.description = better_root["description"];
|
||||
this_product.is_available = bool(better_root["is_available"]);
|
||||
this_product.manufacturer = better_root["manufacturer"];
|
||||
this_product.name = better_root["name"];
|
||||
this_product.price = double(better_root["price"]);
|
||||
|
||||
|
||||
json::object_val subobj = static_cast<json::object_val>(better_root["reviews"]);
|
||||
|
||||
for (auto& review_data : subobj)
|
||||
{
|
||||
product_info::review going_in;
|
||||
going_in.rating = review_data.object.value().at("rating").number.value();
|
||||
going_in.user = review_data.object.value().at("user").string.value();
|
||||
going_in.review_text = review_data.object.value().at("review_text").string.value();
|
||||
this_product.reviews.push_back(going_in);
|
||||
}
|
||||
|
||||
return this_product;
|
||||
}
|
||||
|
||||
json::value pinfo_tojson(product_info input)
|
||||
{
|
||||
json::object_val root = json::object();
|
||||
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["name"] = input.name;
|
||||
root["reviews"] = json::array();
|
||||
for (auto& rev : input.reviews) {
|
||||
root["reviews"].array.value().push_back(rev);
|
||||
}
|
||||
|
||||
root["taters"] = 5.0;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
//parse_json_file("../samples/product_info.json");
|
||||
auto file_contents = read_file("../samples/product_info.json");
|
||||
|
||||
auto [text, err] = json::parse(file_contents);
|
||||
|
||||
product_info test = pinfo_fromjson(text);
|
||||
|
||||
|
||||
auto result = pinfo_tojson(test);
|
||||
|
||||
std::cout << json::deparse(result);
|
||||
}
|
||||
|
95
src/JSON.cpp
95
src/JSON.cpp
@@ -1,4 +1,5 @@
|
||||
#include <JJX/JJX.hpp>
|
||||
#include <JJX/JSON.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace JJX::json {
|
||||
@@ -172,6 +173,61 @@ namespace JJX::json {
|
||||
return lex_keyword(raw_json, "false", token_type::boolean, index);
|
||||
}
|
||||
|
||||
void value::operator=(double in)
|
||||
{
|
||||
type = value_type::number;
|
||||
number = in;
|
||||
}
|
||||
|
||||
void value::operator=(const std::string& in)
|
||||
{
|
||||
type = value_type::string;
|
||||
string = in;
|
||||
}
|
||||
|
||||
void value::operator=(bool in)
|
||||
{
|
||||
type = value_type::boolean;
|
||||
boolean = in;
|
||||
}
|
||||
|
||||
void value::operator=(std::vector<value> in)
|
||||
{
|
||||
type = value_type::array;
|
||||
array = in;
|
||||
}
|
||||
|
||||
void value::operator=(std::map<std::string, value> in)
|
||||
{
|
||||
type = value_type::object;
|
||||
object = in;
|
||||
}
|
||||
|
||||
void object_val::add(const std::string& key, value val)
|
||||
{
|
||||
object.value().emplace(key, val);
|
||||
}
|
||||
|
||||
void object_val::add(const std::string& key, const std::string& val)
|
||||
{
|
||||
object.value().emplace(key, json::string(val));
|
||||
}
|
||||
|
||||
value& object_val::operator[](const std::string& key)
|
||||
{
|
||||
return object.value()[key];
|
||||
}
|
||||
|
||||
void array_val::add(value val)
|
||||
{
|
||||
array.value().push_back(val);
|
||||
}
|
||||
|
||||
value& array_val::operator[](int key)
|
||||
{
|
||||
return array.value()[key];
|
||||
}
|
||||
|
||||
std::tuple<std::vector<json::token>, std::string> lex(std::string raw_json) {
|
||||
std::vector<json::token> tokens;
|
||||
// All tokens will embed a pointer to the raw JSON for debugging purposes
|
||||
@@ -400,11 +456,12 @@ namespace JJX::json {
|
||||
}
|
||||
}
|
||||
|
||||
value string(const std::string &text) {
|
||||
return {
|
||||
.string = text,
|
||||
.type = value_type::string
|
||||
};
|
||||
string_val string(const std::string &text) {
|
||||
string_val out;
|
||||
out.type = value_type::string;
|
||||
out.string = text;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
value number(double input) {
|
||||
@@ -421,9 +478,9 @@ namespace JJX::json {
|
||||
};
|
||||
}
|
||||
|
||||
value array(std::vector<value> input)
|
||||
array_val array(std::vector<value> input)
|
||||
{
|
||||
value arr;
|
||||
array_val arr;
|
||||
arr.type = value_type::array;
|
||||
arr.array = std::vector<value>();
|
||||
|
||||
@@ -434,4 +491,28 @@ namespace JJX::json {
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
array_val array()
|
||||
{
|
||||
array_val out;
|
||||
out.type = value_type::array;
|
||||
out.array = std::vector<value>();
|
||||
return out;
|
||||
}
|
||||
|
||||
object_val object(std::map<std::string, value> input)
|
||||
{
|
||||
object_val out;
|
||||
out.type = value_type::object;
|
||||
out.object = input;
|
||||
return out;
|
||||
}
|
||||
|
||||
object_val object()
|
||||
{
|
||||
object_val out;
|
||||
out.type = value_type::object;
|
||||
out.object = std::map<std::string, value>();
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user