diff options
| -rw-r--r-- | src/json.cpp | 55 | ||||
| -rw-r--r-- | src/json.h | 8 | ||||
| -rw-r--r-- | src/json.hpp | 32 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 4 | ||||
| -rw-r--r-- | src/tokenizer.h | 3 | ||||
| -rw-r--r-- | test/main.cpp | 8 |
6 files changed, 91 insertions, 19 deletions
diff --git a/src/json.cpp b/src/json.cpp index c566c2b..0232a8a 100644 --- a/src/json.cpp +++ b/src/json.cpp @@ -2,7 +2,6 @@ #include "tokenizer.h" #include <cstddef> -#include <iostream> #include <stdexcept> #include <string> @@ -98,13 +97,13 @@ namespace TehJSON tokenizer.appendInput(s); std::vector<Token> stringTokens = tokenizer.tokenize(); - readFromTokens(stringTokens, 0); + readFromTokens(stringTokens); } - int JSON::readFromTokens(std::vector<Token> tokens, int pos) + void JSON::readFromTokens(std::vector<Token> tokens) { this->tokens = tokens; - tokenPos = pos; + tokenPos = 0; consume(TokenType::LBrace); while(nextTokenType() != TokenType::RBrace) @@ -114,31 +113,61 @@ namespace TehJSON consume(TokenType::Colon); switch(nextTokenType()) { - case TokenType::LBrace: tokenPos = children[childName.content].readFromTokens(tokens, tokenPos); break; + case TokenType::LBrace: + { + std::vector<Token> childTokens; + while(nextTokenType() != TokenType::RBrace) + { + childTokens.push_back(consume()); + } + childTokens.push_back(consume(TokenType::RBrace)); + children[childName.content].readFromTokens(childTokens); + break; + } case TokenType::StringLit: children[childName.content].set<std::string>(consume(TokenType::StringLit).content); break; case TokenType::IntLit: children[childName.content].set<int>(std::stoi(consume(TokenType::IntLit).content)); break; case TokenType::FloatLit: children[childName.content].set<float>(std::stof(consume(TokenType::FloatLit).content)); break; + case TokenType::LSquare: + { + consume(TokenType::LSquare); + std::vector<int> vec; + while(nextTokenType() != TokenType::RSquare) + { + if(nextTokenType() != TokenType::IntLit) + throw std::runtime_error("Only int arrays are supported so far"); + vec.push_back(std::stoi(consume(TokenType::IntLit).content)); + if(nextTokenType() == TokenType::Comma) + { + consume(TokenType::Comma); + } + } + consume(TokenType::RSquare); + children[childName.content].set<int>(vec); + break; + }; default: throw std::runtime_error("Token type is not a literal!"); } if(nextTokenType() != TokenType::RBrace) consume(TokenType::Comma); } consume(TokenType::RBrace); - - return tokenPos; } // Serializers for basic types - template <> std::string TehJSON::JSON::serializeData<int>(std::shared_ptr<void> data) + template <> std::string TehJSON::JSON::serializeData<int>(int *data) + { + return std::to_string(*data); + } + template <> std::string TehJSON::JSON::serializeData<float>(float *data) { - return std::to_string(*static_cast<int*>(data.get())); + return std::to_string(*data); } - template <> std::string TehJSON::JSON::serializeData<float>(std::shared_ptr<void> data) + template <> std::string TehJSON::JSON::serializeData<std::string>(std::string *data) { - return std::to_string(*static_cast<float*>(data.get())); + return '"' + *data + '"'; } - template <> std::string TehJSON::JSON::serializeData<std::string>(std::shared_ptr<void> data) + template <> std::string TehJSON::JSON::serializeData<bool>(bool *data) { - return '"' + *static_cast<std::string*>(data.get()) + '"'; + return (*data)?"true":"false"; } } @@ -28,10 +28,14 @@ namespace TehJSON template <typename T> T& get(); template <typename T> + void set(std::vector<T> value); + template <typename T> void set(T value); std::string leafType(); template <typename T> - static std::string serializeData(std::shared_ptr<void> data); + static std::string serializeData(std::vector<T> *data); + template <typename T> + static std::string serializeData(T *data); // Non leaf methods JSON& operator[](std::string name); @@ -46,7 +50,7 @@ namespace TehJSON Token consume(); Token consume(TokenType type); TokenType nextTokenType(); - int readFromTokens(std::vector<Token> tokens, int pos); + void readFromTokens(std::vector<Token> tokens); // Leaf data fields std::shared_ptr<void> data; diff --git a/src/json.hpp b/src/json.hpp index 6f19ddd..8ecd947 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -16,13 +16,41 @@ namespace TehJSON } template<typename T> + std::string TehJSON::JSON::serializeData(std::vector<T>* data) + { + std::string res = "["; + for(int i = 0; i < data->size(); i++) + { + T x = data->at(i); + // res += "inty"; + res += TehJSON::JSON::serializeData<T>(&x); + if(i != data->size() - 1) + res += ", "; + } + res += "]"; + return res; + } + + template<typename T> + void TehJSON::JSON::set(std::vector<T> value) + { + if(children.size() != 0) + throw std::runtime_error("Node is not a leaf (has children already)!"); + isLeaf = true; + dataSerializer = [](std::shared_ptr<void> data) -> std::string { + return TehJSON::JSON::serializeData<T>((std::vector<T>*)(data.get())); + }; + data = std::make_shared<std::vector<T>>(value); + } + template<typename T> void JSON::set(T value) { if(children.size() != 0) throw std::runtime_error("Node is not a leaf (has children already)!"); isLeaf = true; - dataSerializer = JSON::serializeData<T>; + dataSerializer = [](std::shared_ptr<void> data) -> std::string { + return JSON::serializeData<T>((T*)(data.get())); + }; data = std::make_shared<T>(value); } - } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index ac7c215..a32879e 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -9,6 +9,8 @@ namespace TehJSON { case TokenType::LBrace: return "LBrace"; case TokenType::RBrace: return "RBrace"; + case TokenType::LSquare: return "LSquare"; + case TokenType::RSquare: return "RSquare"; case TokenType::Colon: return "Colon"; case TokenType::Comma: return "Comma"; case TokenType::StringLit: return "StringLit"; @@ -78,6 +80,8 @@ namespace TehJSON } case '{': tokens.push_back({TokenType::LBrace, std::string{c}}); break; case '}': tokens.push_back({TokenType::RBrace, std::string{c}}); break; + case '[': tokens.push_back({TokenType::LSquare, std::string{c}}); break; + case ']': tokens.push_back({TokenType::RSquare, std::string{c}}); break; case ':': tokens.push_back({TokenType::Colon, std::string{c}}); break; case ',': tokens.push_back({TokenType::Comma, std::string{c}}); break; default: throw std::runtime_error("Unexpected character: '" + std::string{c} + "'"); diff --git a/src/tokenizer.h b/src/tokenizer.h index 3322553..d0362a3 100644 --- a/src/tokenizer.h +++ b/src/tokenizer.h @@ -9,11 +9,14 @@ namespace TehJSON { LBrace, RBrace, + LSquare, + RSquare, Colon, Comma, StringLit, IntLit, FloatLit, + BoolLit, }; std::string getTokenName(TokenType t); diff --git a/test/main.cpp b/test/main.cpp index 00fca03..456810b 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,19 +1,23 @@ +#include "json.h" #include <json.hpp> #include <tokenizer.h> #include <iostream> #include <memory> +#include <vector> using std::cout, std::endl; int main() { TehJSON::JSON jsonWriter; - // TestClass test1; - // json["test1"].set(test1); jsonWriter["test_string"].set<std::string>("stringy"); jsonWriter["test_int"].set<int>(123); jsonWriter["test_float"].set<float>(51.8); + jsonWriter["test_vecs"]["int"].set<int>({1, 2, 3}); + // jsonWriter["test_vecs"]["float"].set<float>({0.1, 0.2, 0.3}); + // jsonWriter["test_true"].set(true); + // jsonWriter["test_false"].set(false); jsonWriter["test_object"]["test_int"].set<int>(100); jsonWriter["test_object"]["test_float"].set<float>(100); |
