Browse Source

missing json files

test
nicolas-arnaud 2 years ago
parent
commit
98b27bdace
  1. 131
      srcs/json/Nodes.hpp
  2. 213
      srcs/json/Parser.hpp
  3. 159
      srcs/json/Token.hpp

131
srcs/json/Nodes.hpp

@ -0,0 +1,131 @@
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#define DEBUG 0
using std::cout;
using std::string;
class JSONNode;
typedef std::map<string, JSONNode *> JSONObject;
typedef std::vector<JSONNode *> JSONList;
class JSONNode {
public:
JSONObject obj() {
if (type == OBJECT)
return *values.object;
throw std::logic_error("Improper return");
}
JSONList lst() {
if (type == LIST)
return *values.list;
throw std::logic_error("Improper return");
}
string str() {
if (type == STRING)
return *values.str;
throw std::logic_error("Improper return");
}
int nbr() {
if (type == NUMBER)
return values.nbr;
throw std::logic_error("Improper return");
}
private:
enum Type { OBJECT, LIST, STRING, NUMBER, BOOLEAN, NULL_TYPE };
union Values {
JSONObject *object;
JSONList *list;
string *str;
int nbr;
bool bValue;
} values;
Type type;
void setObject(JSONObject *object) {
this->values.object = object;
type = OBJECT;
}
void setList(JSONList *list) {
this->values.list = list;
type = LIST;
}
void setString(string *str) {
this->values.str = str;
type = STRING;
}
void setNumber(int nbr) {
this->values.nbr = nbr;
type = NUMBER;
}
void setBoolean(bool v) {
this->values.bValue = v;
type = BOOLEAN;
}
void setNull() { type = NULL_TYPE; }
string stringify(int indentationLevel) {
string spaceString = string(indentationLevel, ' ');
// sstreams
std::stringstream output;
// cout < type << "\n";
switch (type) {
case STRING: {
output << spaceString << *values.str;
break;
}
case NUMBER: {
output << spaceString << values.nbr;
break;
}
case BOOLEAN: {
output << spaceString << (values.bValue ? "true" : "false");
break;
}
case NULL_TYPE: {
output << spaceString << "null";
break;
}
case LIST: {
// cout << "[";
output << spaceString << "[\n";
unsigned int index = 0;
for (JSONList::iterator i = (*values.list).begin();
i != (*values.list).end(); i++) {
output << (*i)->stringify(indentationLevel + 1);
if (index < (*values.list).size() - 1) {
output << ",\n";
}
index++;
};
output << "\n" << spaceString << "]\n";
break;
}
case OBJECT: {
output << spaceString << "{\n";
for (JSONObject::iterator i = (*values.object).begin();
i != (*values.object).end(); i++) {
output << spaceString << " "
<< "\"" << i->first << "\""
<< ": ";
output << i->second->stringify(indentationLevel + 1);
JSONObject::iterator next = i;
next++;
if ((next) != (*values.object).end()) {
output << ",\n";
}
output << spaceString << "\n";
}
output << spaceString << "}";
return output.str();
}
}
return output.str();
}
friend class JSONParser;
};

213
srcs/json/Parser.hpp

@ -0,0 +1,213 @@
#include "Token.hpp"
#include <cstdlib>
class JSONParser {
std::fstream file;
JSONNode *root;
JSONNode *current;
Tokenizer tokenizer;
public:
JSONParser(const string filename) : tokenizer(filename) {}
JSONNode *parse() {
string key = "";
JSONNode *parsed;
while (tokenizer.hasMoreTokens()) {
Token token;
try {
token = tokenizer.getToken();
switch (token.type) {
case CURLY_OPEN: {
parsed = parseObject();
break;
}
case ARRAY_OPEN: {
parsed = parseList();
break;
}
case STRING: {
tokenizer.rollBackToken();
parsed = parseString();
break;
}
case NUMBER: {
tokenizer.rollBackToken();
parsed = parseNumber();
break;
}
case BOOLEAN: {
tokenizer.rollBackToken();
parsed = parseBoolean();
break;
}
default:
break;
}
} catch (std::logic_error &e) {
break;
}
}
return parsed;
}
JSONNode *parseObject() {
JSONNode *node = new JSONNode;
JSONObject *keyObjectMap = new JSONObject;
while (1) {
if (tokenizer.hasMoreTokens()) {
Token token = tokenizer.getToken();
string key = token.value;
tokenizer.getToken();
token = tokenizer.getToken();
switch (token.type) {
case CURLY_OPEN: {
if (DEBUG)
cout << "=object=|" << key << "|===>>\n";
(*keyObjectMap)[key] = parseObject();
if (DEBUG)
cout << "<<===end object\n";
break;
}
case ARRAY_OPEN: {
if (DEBUG)
cout << "-list-|" << key << "|--->>\n";
(*keyObjectMap)[key] = parseList();
if (DEBUG)
cout << "<<---end list\n";
break;
}
case STRING: {
tokenizer.rollBackToken();
(*keyObjectMap)[key] = parseString();
if (DEBUG)
cout << key << "='" << (*keyObjectMap)[key]->str()
<< "'\n";
break;
}
case NUMBER: {
tokenizer.rollBackToken();
(*keyObjectMap)[key] = parseNumber();
if (DEBUG)
cout << key << "=" << (*keyObjectMap)[key]->nbr()
<< "\n";
break;
}
case BOOLEAN: {
tokenizer.rollBackToken();
(*keyObjectMap)[key] = parseBoolean();
if (DEBUG)
cout << key << "(BOOL)\n";
break;
}
case NULL_TYPE: {
(*keyObjectMap)[key] = parseNull();
break;
}
default:
break;
}
token = tokenizer.getToken();
if (token.type == CURLY_CLOSE)
break;
} else {
throw std::logic_error("No more tokens");
}
}
node->setObject(keyObjectMap);
return node;
}
JSONNode *parseList() {
JSONNode *node = new JSONNode();
JSONList *list = new JSONList();
bool hasCompleted = false;
while (!hasCompleted) {
if (!tokenizer.hasMoreTokens()) {
throw std::logic_error("No more tokens");
} else {
Token token = tokenizer.getToken();
JSONNode *subNode;
switch (token.type) {
case CURLY_OPEN: {
if (DEBUG)
cout << "=object===>>\n";
subNode = parseObject();
if (DEBUG)
cout << "<<===end object\n";
break;
}
case ARRAY_OPEN: {
if (DEBUG)
cout << "-list--->>\n";
subNode = parseList();
if (DEBUG)
cout << "<<---end list\n";
break;
}
case STRING: {
tokenizer.rollBackToken();
subNode = parseString();
if (DEBUG)
cout << "|'" << subNode->str() << "'";
break;
}
case NUMBER: {
tokenizer.rollBackToken();
subNode = parseNumber();
if (DEBUG)
cout << "|" << subNode->nbr();
break;
}
case BOOLEAN: {
tokenizer.rollBackToken();
subNode = parseBoolean();
break;
}
case NULL_TYPE: {
subNode = parseNull();
break;
}
default:
break;
}
list->push_back(subNode);
token = tokenizer.getToken();
if (token.type == ARRAY_CLOSE) {
hasCompleted = true;
}
}
}
node->setList(list);
return node;
}
JSONNode *parseString() {
JSONNode *node = new JSONNode();
Token token = tokenizer.getToken();
string *sValue = new string(token.value);
node->setString(sValue);
return node;
}
JSONNode *parseNumber() {
JSONNode *node = new JSONNode();
Token token = tokenizer.getToken();
string value = token.value;
int nbr = std::atoi(value.c_str());
node->setNumber(nbr);
return node;
}
JSONNode *parseBoolean() {
JSONNode *node = new JSONNode();
Token token = tokenizer.getToken();
node->setBoolean(token.value == "True" ? true : false);
return node;
}
JSONNode *parseNull() {
JSONNode *node = new JSONNode();
node->setNull();
return node;
}
};

159
srcs/json/Token.hpp

@ -0,0 +1,159 @@
#include "Nodes.hpp"
#include <fstream>
enum TOKEN {
CURLY_OPEN,
CURLY_CLOSE,
COLON,
STRING,
NUMBER,
ARRAY_OPEN,
ARRAY_CLOSE,
COMMA,
BOOLEAN,
NULL_TYPE
};
typedef struct Token_s {
string value;
TOKEN type;
string toString() {
switch (type) {
case CURLY_OPEN: {
return "Curly open";
}
case CURLY_CLOSE: {
return "Curly close";
}
case COLON: {
return "COLON";
}
case NUMBER: {
return "Number: " + value;
}
case STRING: {
return "String: " + value;
}
case ARRAY_OPEN: {
return "Array open";
}
case ARRAY_CLOSE: {
return "Array close";
}
case COMMA: {
return "Comma";
}
case BOOLEAN: {
return "Boolean: " + value;
}
case NULL_TYPE: {
return "Null";
}
default:
return "Other...";
}
}
} Token;
class Tokenizer {
std::fstream file;
size_t prevPos;
public:
Tokenizer(string fileName) {
file.open(fileName.c_str(), std::ios::in);
if (!file.good())
cout << "File open error"
<< "\n";
};
bool hasMoreTokens() { return !file.eof(); }
char getWithoutWhiteSpace() {
char c = ' ';
while ((c == ' ' || c == '\n') || c == '\t') {
file.get(c); // check
if ((c == ' ' || c == '\n') && !file.good()) {
// cout << file.eof() << " " << file.fail() << "\n";
throw std::logic_error("Ran out of tokens");
} else if (!file.good()) {
return c;
}
}
return c;
};
void rollBackToken() {
if (file.eof())
file.clear();
file.seekg(prevPos);
};
Token getToken() {
char c;
if (file.eof()) {
cout << "Exhaused tokens"
<< "\n";
// throw std::exception("Exhausted tokens");
}
prevPos = file.tellg();
c = getWithoutWhiteSpace();
Token token;
token.type = NULL_TYPE;
if (c == '"') {
token.type = STRING;
token.value = "";
file.get(c);
while (c != '"') {
token.value += c;
file.get(c);
}
} else if (c == '{') {
token.type = CURLY_OPEN;
} else if (c == '}') {
token.type = CURLY_CLOSE;
} else if (c == '-' || (c >= '0' && c <= '9')) {
// Check if string is numeric
token.type = NUMBER;
token.value = "";
token.value += c;
std::streampos prevCharPos = file.tellg();
while ((c == '-') || (c >= '0' && c <= '9') || c == '.') {
prevCharPos = file.tellg();
file.get(c);
if (file.eof()) {
break;
} else {
if ((c == '-') || (c >= '0' && c <= '9') || (c == '.')) {
token.value += c;
} else {
file.seekg(prevCharPos);
}
}
}
} else if (c == 'f') {
token.type = BOOLEAN;
token.value = "False";
file.seekg(4, std::ios_base::cur);
} else if (c == 't') {
token.type = BOOLEAN;
token.value = "True";
file.seekg(3, std::ios_base::cur);
} else if (c == 'n') {
token.type = NULL_TYPE;
file.seekg(3, std::ios_base::cur);
} else if (c == '[') {
token.type = ARRAY_OPEN;
} else if (c == ']') {
token.type = ARRAY_CLOSE;
} else if (c == ':') {
token.type = COLON;
} else if (c == ',') {
token.type = COMMA;
}
// cout << token.type << " : " << token.value << "\n";
return token;
};
};
Loading…
Cancel
Save