Restructure
Make the type that will eventually be returned. The idea is that, You'd want it to be easy to traverse the file with it's descending structure. This will also make it easy to turn it back into json.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
#include <optional>
|
||||
#include <map>
|
||||
|
||||
namespace jjx
|
||||
namespace JJX
|
||||
{
|
||||
namespace json {
|
||||
enum class token_type { string, number, syntax, boolean, null };
|
||||
@@ -30,6 +30,5 @@ namespace jjx
|
||||
std::tuple<json::value, std::string> parse(std::string);
|
||||
std::string deparse(json::value, std::string whitespace = "");
|
||||
}
|
||||
|
||||
namespace xml {}
|
||||
}
|
109
include/JJX/ParsedFile.h
Normal file
109
include/JJX/ParsedFile.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace JJX {
|
||||
class ParsedValue;
|
||||
|
||||
class ParsedObject;
|
||||
class ParsedString;
|
||||
class ParsedNumber;
|
||||
class ParsedArray;
|
||||
class ParsedBool;
|
||||
class ParsedNULL;
|
||||
|
||||
class ParsedFile;
|
||||
}
|
||||
|
||||
/** This is kind-of slow, But it makes it easy to traverse the file using dynamic_cast.
|
||||
* If you need bleeding edge speed while parsing you're not doing it right anyway :shrug: - Redacted */
|
||||
class JJX::ParsedValue {
|
||||
protected:
|
||||
std::string key;
|
||||
public:
|
||||
[[nodiscard]] std::string GetKey() const;
|
||||
public:
|
||||
virtual ~ParsedValue() = default;
|
||||
};
|
||||
|
||||
class JJX::ParsedObject : public ParsedValue {
|
||||
private:
|
||||
std::vector<ParsedValue*> values;
|
||||
protected:
|
||||
explicit ParsedObject(const std::vector<ParsedValue*>& values);
|
||||
public:
|
||||
void EraseChildren();
|
||||
[[nodiscard]] std::vector<ParsedValue*> GetValue() const;
|
||||
public:
|
||||
static ParsedObject* Create(const std::vector<ParsedValue*>& values);
|
||||
|
||||
};
|
||||
|
||||
class JJX::ParsedString : public ParsedValue {
|
||||
private:
|
||||
std::string value;
|
||||
protected:
|
||||
ParsedString(const std::string& key, const std::string& value);
|
||||
public:
|
||||
[[nodiscard]] std::string GetValue() const;
|
||||
public:
|
||||
/** This is a trick borrowed from Java, But in this instance, it's to ensure that they're heap allocated. */
|
||||
static ParsedString* Create(const std::string& key, const std::string& value);
|
||||
};
|
||||
|
||||
class JJX::ParsedNumber : public ParsedValue {
|
||||
private:
|
||||
double value;
|
||||
protected:
|
||||
ParsedNumber(const std::string& key, const std::string& value);
|
||||
ParsedNumber(const std::string& key, double value);
|
||||
public:
|
||||
[[nodiscard]] double GetValue() const;
|
||||
public:
|
||||
static ParsedNumber* Create(const std::string& key, const std::string& value);
|
||||
static ParsedNumber* Create(const std::string& key, double value);
|
||||
};
|
||||
|
||||
class JJX::ParsedArray : public ParsedValue {
|
||||
private:
|
||||
std::vector<ParsedValue*> values;
|
||||
protected:
|
||||
ParsedArray(const std::string& key, const std::vector<ParsedValue*>& values);
|
||||
public:
|
||||
void EraseChildren();
|
||||
[[nodiscard]] std::vector<ParsedValue*> GetValue() const;
|
||||
public:
|
||||
static ParsedArray* Create(const std::string& key, const std::vector<ParsedValue*>& values);
|
||||
};
|
||||
|
||||
class JJX::ParsedBool : public ParsedValue {
|
||||
private:
|
||||
bool value;
|
||||
protected:
|
||||
ParsedBool(const std::string& key, bool value);
|
||||
public:
|
||||
[[nodiscard]] bool GetValue() const;
|
||||
public:
|
||||
static ParsedBool* Create(const std::string& key, bool value);
|
||||
};
|
||||
|
||||
class JJX::ParsedNULL : public ParsedValue {
|
||||
protected:
|
||||
explicit ParsedNULL(const std::string& key);
|
||||
public:
|
||||
[[nodiscard]] nullptr_t GetValue() const;
|
||||
public:
|
||||
static ParsedNULL* Create(const std::string& key);
|
||||
};
|
||||
|
||||
class JJX::ParsedFile {
|
||||
private:
|
||||
std::vector<ParsedValue*> content;
|
||||
public:
|
||||
std::vector<ParsedValue*> GetContent();
|
||||
public:
|
||||
explicit ParsedFile(const std::vector<ParsedValue*>& content);
|
||||
~ParsedFile();
|
||||
|
||||
};
|
||||
|
8
main.cpp
8
main.cpp
@@ -1,8 +1,8 @@
|
||||
#include <jjx.hpp>
|
||||
#include <JJX/JJX.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace jjx;
|
||||
using namespace JJX;
|
||||
|
||||
void ParseJsonFile(const std::string& file_path) {
|
||||
std::ifstream file(file_path, std::ios::binary);
|
||||
@@ -23,7 +23,11 @@ void ParseJsonFile(const std::string& file_path) {
|
||||
std::cerr << "Error while parsing json: " << parse_error << std::endl;
|
||||
|
||||
std::cout << json::deparse(text) << std::endl;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
ParseJsonFile("../samples/widgets.json");
|
||||
}
|
||||
|
121
samples/cube.glTF
Normal file
121
samples/cube.glTF
Normal file
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"asset":{
|
||||
"generator":"Khronos glTF Blender I/O v3.6.28",
|
||||
"version":"2.0"
|
||||
},
|
||||
"scene":0,
|
||||
"scenes":[
|
||||
{
|
||||
"name":"Scene",
|
||||
"nodes":[
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes":[
|
||||
{
|
||||
"mesh":0,
|
||||
"name":"Cube"
|
||||
}
|
||||
],
|
||||
"materials":[
|
||||
{
|
||||
"doubleSided":true,
|
||||
"name":"Material",
|
||||
"pbrMetallicRoughness":{
|
||||
"baseColorFactor":[
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1
|
||||
],
|
||||
"metallicFactor":0,
|
||||
"roughnessFactor":0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"meshes":[
|
||||
{
|
||||
"name":"Cube",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":0,
|
||||
"NORMAL":1,
|
||||
"TEXCOORD_0":2
|
||||
},
|
||||
"indices":3,
|
||||
"material":0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"accessors":[
|
||||
{
|
||||
"bufferView":0,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"max":[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"min":[
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":1,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":2,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":3,
|
||||
"componentType":5123,
|
||||
"count":36,
|
||||
"type":"SCALAR"
|
||||
}
|
||||
],
|
||||
"bufferViews":[
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":0,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":288,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":192,
|
||||
"byteOffset":576,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":72,
|
||||
"byteOffset":768,
|
||||
"target":34963
|
||||
}
|
||||
],
|
||||
"buffers":[
|
||||
{
|
||||
"byteLength":840,
|
||||
"uri":"data:application/octet-stream;base64,AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAQAOABQAAQAUAAcACgAGABMACgATABcAFQASAAwAFQAMAA8AEAADAAkAEAAJABYABQACAAgABQAIAAsAEQANAAAAEQAAAAQA"
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
#include <jjx.hpp>
|
||||
#include <JJX/JJX.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace jjx::json {
|
||||
namespace JJX::json {
|
||||
std::string format_error(std::string base, std::string source, int index) {
|
||||
std::ostringstream s;
|
||||
int counter = 0;
|
||||
@@ -191,7 +191,7 @@ namespace jjx::json {
|
||||
if (auto [token, new_index, error] = lexer(raw_json, i); i != new_index) {
|
||||
// Error while lexing, return early
|
||||
if (error.length()) {
|
||||
return std::make_tuple(std::vector<jjx::json::token>{}, error);
|
||||
return std::make_tuple(std::vector<JJX::json::token>{}, error);
|
||||
}
|
||||
|
||||
// Store reference to the original source
|
||||
@@ -206,7 +206,7 @@ namespace jjx::json {
|
||||
if (found) {
|
||||
continue;
|
||||
}
|
||||
return std::make_tuple(std::vector<jjx::json::token>{}, format_error("Unable to lex", raw_json, i));
|
||||
return std::make_tuple(std::vector<JJX::json::token>{}, format_error("Unable to lex", raw_json, i));
|
||||
}
|
||||
return {tokens, ""};
|
||||
}
|
||||
@@ -352,7 +352,7 @@ namespace jjx::json {
|
||||
auto [tokens, error] = json::lex(source);
|
||||
if (error.size())
|
||||
{
|
||||
return std::make_tuple(jjx::json::value{}, error);
|
||||
return std::make_tuple(JJX::json::value{}, error);
|
||||
}
|
||||
|
||||
auto [ast, _, error1] = json::parse(tokens);
|
136
src/ParsedFile.cpp
Normal file
136
src/ParsedFile.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <JJX/ParsedFile.h>
|
||||
|
||||
using namespace JJX;
|
||||
|
||||
std::string JJX::ParsedValue::GetKey() const {
|
||||
return key;
|
||||
}
|
||||
|
||||
JJX::ParsedString::ParsedString(const std::string &key, const std::string& value) {
|
||||
this->key = key;
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
std::string JJX::ParsedString::GetValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
ParsedString* ParsedString::Create(const std::string& key, const std::string& value) {
|
||||
return new ParsedString(key, value);
|
||||
}
|
||||
|
||||
double JJX::ParsedNumber::GetValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
JJX::ParsedNumber::ParsedNumber(const std::string& key, const std::string& value) {
|
||||
this->key = key;
|
||||
this->value = std::stod(value);
|
||||
}
|
||||
|
||||
JJX::ParsedNumber::ParsedNumber(const std::string& key, double value) {
|
||||
this->key = key;
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
ParsedNumber* ParsedNumber::Create(const std::string& key, const std::string& value) {
|
||||
return new ParsedNumber(key, value);
|
||||
}
|
||||
|
||||
ParsedNumber* ParsedNumber::Create(const std::string& key, double value) {
|
||||
return new ParsedNumber(key, value);
|
||||
}
|
||||
|
||||
std::vector<ParsedValue*> JJX::ParsedArray::GetValue() const {
|
||||
return values;
|
||||
}
|
||||
|
||||
ParsedArray::ParsedArray(const std::string& key, const std::vector<ParsedValue*>& values) {
|
||||
this->key = key;
|
||||
this->values = values;
|
||||
}
|
||||
|
||||
void ParsedArray::EraseChildren() {
|
||||
for (auto& value : values)
|
||||
if (auto* array = dynamic_cast<ParsedArray*>(value))
|
||||
array->EraseChildren();
|
||||
else if (auto* object = dynamic_cast<ParsedObject*>(value))
|
||||
object->EraseChildren();
|
||||
else
|
||||
delete value;
|
||||
values = {};
|
||||
}
|
||||
|
||||
ParsedArray* ParsedArray::Create(const std::string& key, const std::vector<ParsedValue*>& values) {
|
||||
return new ParsedArray(key, values);
|
||||
}
|
||||
|
||||
ParsedBool::ParsedBool(const std::string& key, bool value) {
|
||||
this->key = key;
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
bool ParsedBool::GetValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
ParsedBool* ParsedBool::Create(const std::string& key, bool value) {
|
||||
return new ParsedBool(key, value);
|
||||
}
|
||||
|
||||
nullptr_t ParsedNULL::GetValue() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParsedNULL::ParsedNULL(const std::string& key) {
|
||||
this->key = key;
|
||||
}
|
||||
|
||||
ParsedNULL* ParsedNULL::Create(const std::string& key) {
|
||||
return new ParsedNULL(key);
|
||||
}
|
||||
|
||||
std::vector<ParsedValue*> ParsedFile::GetContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
// kick off the recursive deletion.
|
||||
ParsedFile::~ParsedFile() {
|
||||
for (auto& value : content)
|
||||
if (auto* array = dynamic_cast<ParsedArray*>(value))
|
||||
array->EraseChildren();
|
||||
else if (auto* object = dynamic_cast<ParsedObject*>(value))
|
||||
object->EraseChildren();
|
||||
else
|
||||
delete value;
|
||||
content = {};
|
||||
}
|
||||
|
||||
ParsedFile::ParsedFile(const std::vector<ParsedValue*>& content) {
|
||||
this->content = content;
|
||||
}
|
||||
|
||||
ParsedObject::ParsedObject(const std::vector<ParsedValue*>& values) {
|
||||
this->key = "";
|
||||
this->values = values;
|
||||
}
|
||||
|
||||
ParsedObject* ParsedObject::Create(const std::vector<ParsedValue*>& values) {
|
||||
return new ParsedObject(values);
|
||||
}
|
||||
|
||||
void ParsedObject::EraseChildren() {
|
||||
for (auto& value : values)
|
||||
if (auto* array = dynamic_cast<ParsedArray*>(value))
|
||||
array->EraseChildren();
|
||||
else if (auto* object = dynamic_cast<ParsedObject*>(value))
|
||||
object->EraseChildren();
|
||||
else
|
||||
delete value;
|
||||
values = {};
|
||||
|
||||
}
|
||||
|
||||
std::vector<ParsedValue*> ParsedObject::GetValue() const {
|
||||
return values;
|
||||
}
|
@@ -1 +0,0 @@
|
||||
#include "../include/jjx.hpp"
|
Reference in New Issue
Block a user