Skip to content

Instantly share code, notes, and snippets.

@ImanolFotia
Last active February 2, 2018 04:50
Show Gist options
  • Save ImanolFotia/139924f44680a713af897458fc96ed3c to your computer and use it in GitHub Desktop.
Save ImanolFotia/139924f44680a713af897458fc96ed3c to your computer and use it in GitHub Desktop.
/*
* 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