Last active
February 2, 2018 04:50
-
-
Save ImanolFotia/139924f44680a713af897458fc96ed3c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* SimpleJSON is a lightweight, header only JSON parsing library for C++ | |
* It was created for the purpose of having a very simple parser for small/test projects | |
* If you need pure JSON standard compliance and a robust implementation this is not for you | |
* Please check https://www.json.org/ for mature alternatives | |
* | |
* THIS IS A WORK IN PROGRESS, DON'T REPORT BUGS YET | |
* IT DOESN'T EVEN COMPILES | |
* | |
* Copyright 2018 Imanol Fotia | |
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | |
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation | |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and | |
* to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
#include <string> | |
#include <fstream> | |
#include <iostream> | |
#include <unordered_map> | |
#include <array> | |
#include <memory> | |
#include <streambuf> | |
#include <sstream> | |
#include <vector> | |
#include <stack> | |
#define ERROR -1 | |
namespace Json { | |
template <typename T> | |
class Any; | |
class AnyBase; | |
class JsonObject{ | |
public: | |
template<typename T> | |
void insertValue(std::string key, T value){ | |
mKeys.push_back(key); | |
mValues[key].reset(new Any<T>(value)); | |
} | |
template<typename T> | |
T getValue(std::string key){ | |
return dynamic_cast<Any<T>&>(*mValues[key]).data; | |
} | |
private: | |
std::vector<std::string> mKeys; | |
std::unordered_map<std::string, std::shared_ptr<AnyBase>> mValues; | |
}; | |
template <typename T> | |
class JsonArray{ | |
public: | |
JsonArray(){} | |
typedef T Type; | |
Type get(int index) | |
{ | |
return mArray.at(index); | |
} | |
void insert(T inValue){ | |
mArray.push_back(new Any<T>(inValue)); | |
} | |
private: | |
std::vector<std::shared_ptr<AnyBase>> mArray; | |
}; | |
/* | |
* This pair of classes is used to be able to have a unordered_map with different value types | |
*/ | |
class AnyBase | |
{ | |
public: | |
virtual ~AnyBase() = 0; | |
}; | |
inline AnyBase::~AnyBase() {} | |
template<class T> | |
class Any : public AnyBase | |
{ | |
public: | |
typedef T Type; | |
explicit Any(const Type& data) : data(data) {} | |
Any() {} | |
Type data; | |
JsonObject toObject(){ | |
return dynamic_cast<Any<JsonObject>&>(data); | |
} | |
JsonArray<Type> toArray(){ | |
return dynamic_cast<Any<JsonArray<Type>>&>(data); | |
} | |
std::string toString(){ | |
return dynamic_cast<Any<std::string>&>(data); | |
} | |
}; | |
class JsonDocument { | |
/* | |
Possible values in each node, according to the JSON specification | |
https://www.json.org/ | |
*/ | |
enum VALUE{ | |
JSTRING = 0, | |
JNUMBER, | |
JOBJECT, | |
JARRAY, | |
JTRUE, | |
JFALSE, | |
JNULL | |
}; | |
public: | |
JsonDocument(std::string filePath){ | |
mFile = std::ifstream(filePath.c_str()); | |
this->Parse(); | |
} | |
/* | |
* Parsing the JSON file using simple C++ string comparison | |
* Might change this in the future | |
*/ | |
void Parse(){ | |
int ObjectCounter = 0; | |
std::stack<std::string> ObjectStack; | |
std::stack<std::string> KeyStack; | |
std::shared_ptr<JsonObject> tmpJsonObject; | |
double tmpNumericValue; | |
std::string tmpStringValue; | |
bool tmpBoolValue; | |
std::string buffer; | |
mFile >> buffer; | |
if(buffer != "{"){ | |
std::cout << "ERROR: This .json file is not valid." << std::endl; | |
} | |
else{ | |
//Create object stuff | |
ObjectStack.push(); | |
mRootObject = (std::shared_ptr<JsonObject>) new JsonObject(); | |
} | |
while(!mFile.eof()){ | |
mFile >> buffer; | |
if(buffer == "{"){ | |
//Create object stuff | |
ObjectStack.push(); | |
tmpJsonObject = (std::shared_ptr<JsonObject>) new JsonObject(); | |
} | |
else if(buffer == "["){ | |
//Create array stuff | |
mFile >> buffer; | |
std::shared_ptr<JsonArray> tmpJsonArray; | |
while(buffer[0] == "]") { | |
mFile >> buffer; | |
} | |
if(ObjectStack.size == 1){ | |
mRootObject.insertValue(KeyStack.top, tmpJsonArray); | |
} | |
else{ | |
tmpJsonObject.insertValue(); | |
} | |
KeyStack.pop(); | |
} | |
else if(buffer[0] == "\""){ | |
//It is a value! | |
KeyStack.push(buffer); | |
} | |
else if(buffer[0] == "}"){ | |
//Remove object from stack | |
ObjectStack.pop(); | |
if(ObjectStack.size == 1) | |
mRootObject.insertValue(); | |
else | |
tmpJsonObject.insertValue(); | |
} | |
} | |
} | |
JsonObject toObject() | |
{ | |
} | |
template <typename T> | |
JsonArray<T> toArray(){ | |
} | |
std::vector<std::string> getKeys() { | |
return mKeys; | |
} | |
private: | |
std::ifstream mFile; | |
std::vector<std::string> mKeys; | |
std::unordered_map<std::string, std::unique_ptr<AnyBase> > mValues; | |
std::shared_ptr<JsonObject> mRootObject; | |
std::shared_ptr<JsonArray> mRootArray; | |
//mValues["number"].reset(new Any<int>(5)); | |
//int value = dynamic_cast<Any<int>&>(*mValues["number"]).data; | |
}; | |
} | |
int main(int argc, char** argv){ | |
std::string filePath; | |
if(argc > 1){ | |
filePath = argv[1]; | |
} | |
else{ | |
std::cout << "ERROR: No input file was supplied. Aborting" << std::endl; | |
return ERROR; | |
} | |
Json::JsonDocument ExampleJSON(filePath); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment