From 7d1326948069ba7965c79c3882496d3e6e79f1e0 Mon Sep 17 00:00:00 2001 From: jancoow Date: Sun, 22 May 2016 23:19:05 +0200 Subject: [PATCH] Refactor johan branch for compiling with g++ --- .idea/.gitignore | 6 + CMakeLists.txt | 15 + CrystalJohan.cpp | 2 + CrystalJohan.h | 2 +- Entity.cpp | 1 + Main.cpp | 2 +- Model.h | 2 +- Player.h | 2 +- Vector.cpp | 4 +- Vector.h | 4 +- World.cpp | 9 +- json.cpp | 1476 ++++++++++++++++++++++------------------------ json.h | 40 +- 13 files changed, 773 insertions(+), 792 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 CMakeLists.txt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..9d0f847 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,6 @@ +/workspace.xml +/vcs.xml +/modules.xml +/misc.xml +/encodings.xml +/CrystalPoint.iml diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..180810f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.5) +project(CrystalPoint) + +file(GLOB SOURCE_FILES + "*.h" + "*.cpp" + ) + +add_executable(CrystalPoint ${SOURCE_FILES}) + +find_package(OpenGL REQUIRED) +find_package(GLUT REQUIRED) +include_directories( ${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS} ) +target_link_libraries(CrystalPoint ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall ") diff --git a/CrystalJohan.cpp b/CrystalJohan.cpp index a784572..03abf3b 100644 --- a/CrystalJohan.cpp +++ b/CrystalJohan.cpp @@ -1,6 +1,8 @@ #include "CrystalJohan.h" #include +#include +#include #include "World.h" void CrystalJohan::init() diff --git a/CrystalJohan.h b/CrystalJohan.h index 0fe1945..51a42ad 100644 --- a/CrystalJohan.h +++ b/CrystalJohan.h @@ -1,7 +1,7 @@ #pragma once class World; -#include "vector.h" +#include "Vector.h" class KeyboardState { diff --git a/Entity.cpp b/Entity.cpp index b6a3bba..51efb39 100644 --- a/Entity.cpp +++ b/Entity.cpp @@ -1,6 +1,7 @@ #include "Entity.h" #include +#include #include "Model.h" diff --git a/Main.cpp b/Main.cpp index 14ce684..fdcb565 100644 --- a/Main.cpp +++ b/Main.cpp @@ -2,7 +2,7 @@ #include "CrystalJohan.h" #include -#include "vector.h" +#include "Vector.h" void configureOpenGL(void); diff --git a/Model.h b/Model.h index a8a9f8c..a16b45f 100644 --- a/Model.h +++ b/Model.h @@ -4,7 +4,7 @@ #include #include #include -#include "vector.h" +#include "Vector.h" class Model { diff --git a/Player.h b/Player.h index 2e8aea3..abb694e 100644 --- a/Player.h +++ b/Player.h @@ -2,7 +2,7 @@ #include "Singleton.h" -#include "vector.h" +#include "Vector.h" class Model; diff --git a/Vector.cpp b/Vector.cpp index 21b8169..d0ca764 100644 --- a/Vector.cpp +++ b/Vector.cpp @@ -12,7 +12,7 @@ Vec3f::Vec3f() this->y = 0; this->z = 0; } -Vec3f::Vec3f(Vec3f &other) +Vec3f::Vec3f(const Vec3f &other) { this->x = other.x; this->y = other.y; @@ -46,7 +46,7 @@ Vec2f::Vec2f() this->x = 0; this->y = 0; } -Vec2f::Vec2f(Vec2f &other) +Vec2f::Vec2f(const Vec2f &other) { this->x = other.x; this->y = other.y; diff --git a/Vector.h b/Vector.h index c8e057c..3c65dd3 100644 --- a/Vector.h +++ b/Vector.h @@ -12,7 +12,7 @@ public: float v[3]; }; Vec3f(); - Vec3f(Vec3f &other); + Vec3f(const Vec3f &other); Vec3f(float x, float y, float z); float& operator [](int); Vec3f operator + (const Vec3f &other); @@ -32,7 +32,7 @@ public: }; Vec2f(); Vec2f(float x, float y); - Vec2f(Vec2f &other); + Vec2f(const Vec2f &other); float& operator [](int); Vec2f operator + (const Vec2f &other); }; diff --git a/World.cpp b/World.cpp index 2c9789c..b31b697 100644 --- a/World.cpp +++ b/World.cpp @@ -4,11 +4,16 @@ #include "LevelObject.h" #include "json.h" #include +#include World::World() : player(Player::getInstance()) { - json::Value v = json::readJson(std::ifstream("worlds/world1.json")); - + std::ifstream file("worlds/world1.json"); + if(!file.is_open()) + std::cout<<"Uhoh, can't open file\n"; + json::Value v = json::readJson(file); + std::cout< #include #include -#include +#include +#include +#include namespace json { - Value Value::null; - //constructors - Value::Value() - { - type = Type::nullValue; - value.objectValue = NULL; - } - - Value::Value(Type type) - { - this->type = type; - if (type == Type::stringValue) - value.stringValue = new std::string(); - if (type == Type::arrayValue) - value.arrayValue = new std::vector(); - if (type == Type::objectValue) - value.objectValue = new std::map(); - } - - Value::Value(int value) - { - type = Type::intValue; - this->value.intValue = value; - } - - Value::Value(__int64 value) - { - //todo: value too big ? - type = Type::intValue; - this->value.intValue = value; - } - - Value::Value(float value) - { - type = Type::floatValue; - this->value.floatValue = value; - } - - Value::Value(bool value) - { - type = Type::boolValue; - this->value.boolValue = value; - } - - Value::Value(const std::string &value) - { - type = Type::stringValue; - this->value.stringValue = new std::string(); - this->value.stringValue->assign(value); - } - Value::Value(const char* value) - { - type = Type::stringValue; - this->value.stringValue = new std::string(); - this->value.stringValue->assign(value); - } - - Value::Value(const Value& other) : Value(other.type) - { - if (type == Type::objectValue) - *this->value.objectValue = *other.value.objectValue; - else if (type == Type::arrayValue) - *this->value.arrayValue = *other.value.arrayValue; - else if (type == Type::stringValue) - this->value.stringValue->assign(*other.value.stringValue); - else - this->value = other.value; - } - - void Value::operator=(const Value& other) - { - if (type != other.type) - { - if (type == Type::stringValue) - delete value.stringValue; - if (type == Type::arrayValue) - delete value.arrayValue; - if (type == Type::objectValue) - delete value.objectValue; - this->type = other.type; - if (type == Type::stringValue) - value.stringValue = new std::string(); - if (type == Type::arrayValue) - value.arrayValue = new std::vector(); - if (type == Type::objectValue) - value.objectValue = new std::map(); - } - - if (type == Type::objectValue) - *this->value.objectValue = *other.value.objectValue; - else if (type == Type::arrayValue) - *this->value.arrayValue = *other.value.arrayValue; - else if (type == Type::stringValue) - this->value.stringValue->assign(*other.value.stringValue); - else - this->value = other.value; - } - - Value::~Value() - { - if (type == Type::stringValue) - delete value.stringValue; - else if (type == Type::arrayValue) - delete value.arrayValue; - else if (type == Type::objectValue) - delete value.objectValue; - } - - size_t Value::size() const - { - assert(type == Type::arrayValue || type == Type::objectValue); - if (type == Type::arrayValue) - return value.arrayValue->size(); - else if (type == Type::objectValue) - return value.objectValue->size(); - throw "Unsupported"; - } - - void Value::push_back(const Value& value) - { - assert(type == Type::arrayValue || type == Type::nullValue); - if (type == Type::nullValue) - { - type = Type::arrayValue; - this->value.arrayValue = new std::vector(); - } - this->value.arrayValue->push_back(value); - } - - - Value& Value::operator[](const std::string &key) - { - assert(type == Type::objectValue || type == Type::nullValue); - if (type == Type::nullValue) - { - type = Type::objectValue; - value.objectValue = new std::map(); - } - return (*value.objectValue)[key]; - } - Value& Value::operator[](const std::string &key) const - { - assert(type == Type::objectValue); - return (*value.objectValue)[key]; - } - - Value& Value::operator[](const char* key) - { - assert(type == Type::objectValue || type == Type::nullValue); - if (type == Type::nullValue) - { - type = Type::objectValue; - value.objectValue = new std::map(); - } - return (*value.objectValue)[std::string(key)]; - } - - Value& Value::operator[](const char* key) const - { - assert(type == Type::objectValue); - return (*value.objectValue)[std::string(key)]; - } - - Value& Value::operator[](size_t index) - { - assert(type == Type::arrayValue); - return (*value.arrayValue)[index]; - } - Value& Value::operator[](size_t index) const - { - assert(type == Type::arrayValue); - return (*value.arrayValue)[index]; - } - Value& Value::operator[](int index) - { - assert(type == Type::arrayValue); - return (*value.arrayValue)[index]; - } - Value& Value::operator[](int index) const - { - assert(type == Type::arrayValue); - return (*value.arrayValue)[index]; - } - - void Value::erase(size_t index) - { - throw "Cannot cast"; - } - - - - - - - - - - - - - - - Value::Iterator Value::end() const - { - if (type == Type::objectValue) - return Iterator(value.objectValue->end()); - else if (type == Type::arrayValue) - return Iterator(value.arrayValue->end()); - throw "oops"; - } - - Value::Iterator Value::begin() const - { - if (type == Type::objectValue) - return Iterator(value.objectValue->begin()); - else if (type == Type::arrayValue) - return Iterator(value.arrayValue->begin()); - throw "oops"; - } - - ///iterator stuff - - Value Value::Iterator::operator*() - { - if (type == Type::objectValue) - return this->objectIterator->second; - else if (type == Type::arrayValue) - return *arrayIterator; - throw "Oops"; - } - - bool Value::Iterator::operator!=(const Iterator &other) - { - if (type == Type::objectValue) - return this->objectIterator != other.objectIterator; - else if (type == Type::arrayValue) - return this->arrayIterator != other.arrayIterator; - throw "Oops"; - } - - void Value::Iterator::operator++() - { - if (type == Type::objectValue) - this->objectIterator++; - else if (type == Type::arrayValue) - this->arrayIterator++; - } - void Value::Iterator::operator++(int) - { - if (type == Type::objectValue) - this->objectIterator++; - else if (type == Type::arrayValue) - this->arrayIterator++; - } - - Value::Iterator::Iterator(const std::vector::iterator& arrayIterator) - { - type = Type::arrayValue; - this->arrayIterator = arrayIterator; - } - - Value::Iterator::Iterator(const std::map::iterator& objectIterator) - { - type = Type::objectValue; - this->objectIterator = objectIterator; - } - - std::string Value::Iterator::key() - { - assert(type == Type::objectValue); - return this->objectIterator->first; - } - Value& Value::Iterator::value() - { - assert(type == Type::objectValue); - return this->objectIterator->second; - } - - - - - - - - static int lineNumber; - - static void ltrim(std::istream& stream); - static void eatComment(std::istream& stream); - static Value eatString(std::istream& stream); - static Value eatObject(std::istream& stream); - static Value eatArray(std::istream& stream); - static Value eatNumeric(std::istream& stream, char firstChar); - static Value eatBool(std::istream& stream); - static Value eatNull(std::istream& stream); - static Value eatValue(std::istream& stream); - - //reading - static void ltrim(std::istream& stream) - { - char c = stream.peek(); - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') - { - if (c == '\n') - lineNumber++; - stream.get(); - c = stream.peek(); - } - }; - - - static Value eatString(std::istream& stream) - { - std::string value = ""; - bool escaped = false; - while (!stream.eof()) - { - char c = stream.get(); - if (c == '\\' && !escaped) - escaped = !escaped; - else if (c == '\"' && !escaped) - return Value(value); - else - { - value += c; - escaped = false; - } - } - return Value(value); - }; - - - - - static Value eatObject(std::istream& stream) - { - Value obj(Type::objectValue); - while (!stream.eof()) - { - ltrim(stream); - char token = stream.get(); - if (token == '}') - break; //empty object - if (token == '/') - { - eatComment(stream); - token = stream.get(); - } - - assert(token == '"'); - Value key = eatString(stream); - ltrim(stream); - token = stream.get(); - assert(token == ':'); - ltrim(stream); - Value val = eatValue(stream); - obj[key.asString()] = val; - ltrim(stream); - - token = stream.get(); - if (token == '}') - break; - if (token != ',') - throw "arg"; - assert(token == ','); - } - return obj; - }; - static Value eatArray(std::istream& stream) - { - Value obj(Type::arrayValue); - while (!stream.eof()) - { - ltrim(stream); - if (stream.peek() == ']') - { - stream.get(); - break; - } - obj.push_back(eatValue(stream)); - ltrim(stream); - char token = stream.get(); - if (token == '/') - { - eatComment(stream); - token = stream.get(); - } - if (token == ']') - break; - assert(token == ','); - } - return obj; - }; - static Value eatNumeric(std::istream& stream, char firstChar) - { - std::string numeric(1, firstChar); - while (!stream.eof()) - { - char token = stream.peek(); - if ((token >= '0' && token <= '9') || token == '.' || token == '-' || token == 'E') - numeric += stream.get(); - else - break; - } - if (numeric.find('.') == std::string::npos) - return Value(atoi(numeric.c_str())); - else - return Value((float)atof(numeric.c_str())); - }; - - static Value eatBool(std::istream& stream) - { - char token = stream.get(); - if (token == 'a') //fAlse - { - stream.get(); //l - stream.get(); //s - stream.get(); //e - return false; - } - else if (token == 'r') //tRue - { - stream.get(); // u - stream.get(); // e - return true; - } - return Value(Type::nullValue); - }; - static Value eatNull(std::istream& stream) - { - stream.get(); // u - stream.get(); // l - stream.get(); // l - return Value(Type::nullValue); - }; - - //precondition: / is already eaten - static void eatComment(std::istream& stream) - { - char token = stream.get(); - assert(token == '/' || token == '*'); - if (token == '*') - { - char last = token; - while ((last != '*' || token != '/') && !stream.eof()) - { - last = token; - token = stream.get(); - } - } - else if (token == '/') - while (token != '\n' && !stream.eof()) - token = stream.get(); - ltrim(stream); - } - - - static Value eatValue(std::istream& stream) - { - ltrim(stream); - char token = stream.get(); - if (token == '{') - return eatObject(stream); - if (token == '[') - return eatArray(stream); - if ((token >= '0' && token <= '9') || token == '.' || token == '-') - return eatNumeric(stream, token); - if (token == '"') - return eatString(stream); - if (token == 't' || token == 'f') - return eatBool(stream); - if (token == 'n') - return eatNull(stream); - if (token == '/') - { - eatComment(stream); - return eatValue(stream); - } - throw "Unable to parse json"; - }; - - - Value readJson(const std::string &data) - { - std::stringstream stream; - stream << data; - lineNumber = 1; - return eatValue(stream); - } - - Value readJson(std::istream &stream) - { - assert(!stream.eof() && stream.good() && !stream.bad()); - lineNumber = 1; - return eatValue(stream); - } - - - - std::ostream& indent(std::ostream& stream, int level) - { - for (int i = 0; i < level; i++) - stream << '\t'; - return stream; - } - - std::ostream& Value::prettyPrint(std::ostream& stream, json::Value& printConfig, int level) const - { - stream << std::fixed << std::setprecision(6); - switch (type) - { - case Type::intValue: - stream << value.intValue; - break; - case Type::floatValue: - assert(!isnan(value.floatValue)); - //assert(isnormal(value.floatValue)); - if (value.floatValue >= 0) - stream << " "; - stream << value.floatValue; - break; - case Type::boolValue: - stream << (value.boolValue ? "true" : "false"); - break; - case Type::stringValue: - stream << "\"" << *value.stringValue << "\""; //TODO: escape \'s - break; - case Type::arrayValue: - { - stream << "["; - int wrap = 99999; - if (value.arrayValue->size() > 10) - wrap = 1; - if (value.arrayValue->at(0).isArray() || value.arrayValue->at(0).isObject()) - wrap = 1; - else - wrap = 3; - - std::string seperator = " "; - - if (!printConfig.isNull() && printConfig.isMember("wrap")) - wrap = printConfig["wrap"]; - if (!printConfig.isNull() && printConfig.isMember("seperator")) - seperator = printConfig["seperator"].asString(); - - - int index = 0; - - if ((long)size() > wrap) - { - stream << "\n"; - indent(stream, level + 1); - } - for (auto v : *this) - { - if (index > 0) - { - stream << "," << seperator; - if (index % wrap == 0) - { - stream << "\n"; - indent(stream, level + 1); - } - } - - json::Value childPrintConfig = json::Value::null; - if (!printConfig.isNull()) - { - if (printConfig.isMember("elements")) - childPrintConfig = printConfig["elements"]; - else if (printConfig.isMember("recursive") && printConfig["recursive"].asBool() == true) - childPrintConfig = printConfig; - } - - v.prettyPrint(stream, childPrintConfig, level + 1); - index++; - } - if ((long)size() > wrap) - { - stream << "\n"; - indent(stream, level); - } - stream << "]"; - break; - } - case Type::objectValue: - { - stream << "{\n"; - int wrap = 99999; - if (value.arrayValue->size() > 10) - wrap = 1; - if (value.arrayValue->at(0).isArray() || value.arrayValue->at(0).isObject()) - wrap = 1; - else - wrap = 3; - - std::string seperator = " "; - - if (!printConfig.isNull() && printConfig.isMember("wrap")) - wrap = printConfig["wrap"]; - if (!printConfig.isNull() && printConfig.isMember("seperator")) - seperator = printConfig["seperator"].asString(); - - - int index = 0; - indent(stream, level + 1); - - - - //for (auto v : *value.objectValue) - auto printEl = [&](const std::pair v) - { - if (index > 0) - { - stream << "," << seperator; - if (index % wrap == 0) - { - stream << "\n"; - indent(stream, level + 1); - } - } - stream << "\"" << v.first << "\" : "; - if ( - (v.second.isArray() || v.second.isObject()) && - (printConfig.isNull() || - ( - printConfig.isMember(v.first) && - printConfig[v.first].isObject() && - printConfig[v.first].isMember("wrap") && - printConfig[v.first]["wrap"].asInt() < (int)v.second.size()) - ) - ) - { - stream << "\n"; - indent(stream, level + 1); - } - - json::Value childPrintConfig = json::Value::null; - if (!printConfig.isNull()) - { - if (printConfig.isMember(v.first)) - childPrintConfig = printConfig[v.first]; - else if (printConfig.isMember("recursive") && printConfig["recursive"].asBool() == true) - childPrintConfig = printConfig; - } - - v.second.prettyPrint(stream, childPrintConfig, level + 1);; - index++; - }; - - - - std::set printed; - if (!printConfig.isNull()) - { - if (printConfig.isMember("sort")) - { - for (std::string el : printConfig["sort"]) - { - if (isMember(el)) - { - printEl(std::pair(el, (*value.objectValue)[el])); - printed.insert(el); - } - } - } - } - - for (auto v : *value.objectValue) - if (printed.find(v.first) == printed.end()) - printEl(v); - - stream << "\n"; - indent(stream, level); - stream << "}"; - break; - } - case Type::nullValue: - stream << "null"; - break; - } - return stream; - } - - const Value& Value::get(const char* key, const Value& default) const - { - if (isMember(key)) - return (*this)[key]; - return default; - } - - - std::string& operator <<(std::string &string, const Value& value) - { - std::stringstream stream; - stream << value; - string += stream.str(); - return string; - } - - - std::ostream & operator<<(std::ostream &stream, const Value& value) - { - stream << std::fixed << std::setprecision(6); - switch (value.type) - { - case Type::intValue: - stream << value.value.intValue; - break; - case Type::floatValue: - assert(!isnan(value.value.floatValue)); - //assert(isnormal(value.value.floatValue)); - stream << value.value.floatValue; - break; - case Type::boolValue: - stream << (value.value.boolValue ? "true" : "false"); - break; - case Type::stringValue: - { - std::string escaped = *value.value.stringValue; - escaped = std::regex_replace(escaped, std::regex("\\\\"), "\\\\"); - stream << "\"" << escaped << "\""; //TODO: escape \'s - break; - } - case Type::arrayValue: - { - stream << "["; - bool first = true; - for (auto v : value) - { - if (!first) - stream << ", "; - stream << v; - first = false; - } - stream << "]"; - break; - } - case Type::objectValue: - { - stream << "{"; - bool first = true; - for (auto v : *value.value.objectValue) - { - if (!first) - stream << ", "; - stream << "\"" << v.first << "\" : " << v.second << std::endl; - first = false; - } - stream << "}"; - break; - } - case Type::nullValue: - stream << "null"; - break; - } - return stream; - } +Value Value::null; +//constructors +Value::Value() +{ + type = Type::nullValue; + value.objectValue = NULL; +} + +Value::Value(Type type) +{ + this->type = type; + if (type == Type::stringValue) + value.stringValue = new std::string(); + if (type == Type::arrayValue) + value.arrayValue = new std::vector(); + if (type == Type::objectValue) + value.objectValue = new std::map(); +} + +Value::Value(int value) +{ + type = Type::intValue; + this->value.intValue = value; +} + +Value::Value(float value) +{ + type = Type::floatValue; + this->value.floatValue = value; +} + +Value::Value(bool value) +{ + type = Type::boolValue; + this->value.boolValue = value; +} + +Value::Value(const std::string &value) +{ + type = Type::stringValue; + this->value.stringValue = new std::string(); + this->value.stringValue->assign(value); +} +Value::Value(const char* value) +{ + type = Type::stringValue; + this->value.stringValue = new std::string(); + this->value.stringValue->assign(value); +} + +Value::Value(const Value& other) : Value(other.type) +{ + if (type == Type::objectValue) + *this->value.objectValue = *other.value.objectValue; + else if (type == Type::arrayValue) + *this->value.arrayValue = *other.value.arrayValue; + else if (type == Type::stringValue) + this->value.stringValue->assign(*other.value.stringValue); + else + this->value = other.value; +} + +void Value::operator=(const Value& other) +{ + if (type != other.type) + { + if (type == Type::stringValue) + delete value.stringValue; + if (type == Type::arrayValue) + delete value.arrayValue; + if (type == Type::objectValue) + delete value.objectValue; + this->type = other.type; + if (type == Type::stringValue) + value.stringValue = new std::string(); + if (type == Type::arrayValue) + value.arrayValue = new std::vector(); + if (type == Type::objectValue) + value.objectValue = new std::map(); + } + + if (type == Type::objectValue) + *this->value.objectValue = *other.value.objectValue; + else if (type == Type::arrayValue) + *this->value.arrayValue = *other.value.arrayValue; + else if (type == Type::stringValue) + this->value.stringValue->assign(*other.value.stringValue); + else + this->value = other.value; +} + +Value::~Value() +{ + if (type == Type::stringValue) + delete value.stringValue; + else if (type == Type::arrayValue) + delete value.arrayValue; + else if (type == Type::objectValue) + delete value.objectValue; +} + +size_t Value::size() const +{ + assert(type == Type::arrayValue || type == Type::objectValue); + if (type == Type::arrayValue) + return value.arrayValue->size(); + else if (type == Type::objectValue) + return value.objectValue->size(); + throw "Unsupported"; +} + +void Value::push_back(const Value& value) +{ + assert(type == Type::arrayValue || type == Type::nullValue); + if (type == Type::nullValue) + { + type = Type::arrayValue; + this->value.arrayValue = new std::vector(); + } + this->value.arrayValue->push_back(value); +} + + +Value& Value::operator[](const std::string &key) +{ + assert(type == Type::objectValue); + return (*value.objectValue)[key]; +} +Value& Value::operator[](const std::string &key) const +{ + assert(type == Type::objectValue); + return (*value.objectValue)[key]; +} + +Value& Value::operator[](const char* key) +{ + assert(type == Type::objectValue || type == Type::nullValue); + if (type == Type::nullValue) + { + type = Type::objectValue; + value.objectValue = new std::map(); + } + return (*value.objectValue)[std::string(key)]; +} + +Value& Value::operator[](const char* key) const +{ + assert(type == Type::objectValue); + return (*value.objectValue)[std::string(key)]; +} + +Value& Value::operator[](size_t index) +{ + assert(type == Type::arrayValue); + return (*value.arrayValue)[index]; +} +Value& Value::operator[](size_t index) const +{ + assert(type == Type::arrayValue); + return (*value.arrayValue)[index]; +} +Value& Value::operator[](int index) +{ + assert(type == Type::arrayValue); + return (*value.arrayValue)[index]; +} +Value& Value::operator[](int index) const +{ + assert(type == Type::arrayValue); + return (*value.arrayValue)[index]; +} + +void Value::erase(size_t index) +{ + throw "Cannot cast"; +} + + + + + + + + + + + + + + +Value::Iterator Value::end() const +{ + if (type == Type::objectValue) + return Iterator(value.objectValue->end()); + else if (type == Type::arrayValue) + return Iterator(value.arrayValue->end()); + throw "oops"; +} + +Value::Iterator Value::begin() const +{ + if (type == Type::objectValue) + return Iterator(value.objectValue->begin()); + else if (type == Type::arrayValue) + return Iterator(value.arrayValue->begin()); + throw "oops"; +} + +///iterator stuff + +Value Value::Iterator::operator*() +{ + if (type == Type::objectValue) + return this->objectIterator->second; + else if (type == Type::arrayValue) + return *arrayIterator; + throw "Oops"; +} + +bool Value::Iterator::operator!=(const Iterator &other) +{ + if (type == Type::objectValue) + return this->objectIterator != other.objectIterator; + else if (type == Type::arrayValue) + return this->arrayIterator != other.arrayIterator; + throw "Oops"; +} + +void Value::Iterator::operator++() +{ + if (type == Type::objectValue) + this->objectIterator++; + else if (type == Type::arrayValue) + this->arrayIterator++; +} +void Value::Iterator::operator++(int) +{ + if (type == Type::objectValue) + this->objectIterator++; + else if (type == Type::arrayValue) + this->arrayIterator++; +} + +Value::Iterator::Iterator(const std::vector::iterator& arrayIterator) +{ + type = Type::arrayValue; + this->arrayIterator = arrayIterator; +} + +Value::Iterator::Iterator(const std::map::iterator& objectIterator) +{ + type = Type::objectValue; + this->objectIterator = objectIterator; +} + +std::string Value::Iterator::key() +{ + assert(type == Type::objectValue); + return this->objectIterator->first; +} +Value& Value::Iterator::value() +{ + assert(type == Type::objectValue); + return this->objectIterator->second; +} + + + + + + + +static void ltrim(std::istream& stream); +static void eatComment(std::istream& stream); +static Value eatString(std::istream& stream); +static Value eatObject(std::istream& stream); +static Value eatArray(std::istream& stream); +static Value eatNumeric(std::istream& stream, char firstChar); +static Value eatBool(std::istream& stream); +static Value eatNull(std::istream& stream); +static Value eatValue(std::istream& stream); + +//reading +static void ltrim(std::istream& stream) +{ + char c = stream.peek(); + while (c == ' ' || c == '\t' || c == '\n' || c == '\r') + { + stream.get(); + c = stream.peek(); + } +}; + + +static Value eatString(std::istream& stream) +{ + std::string value = ""; + bool escaped = false; + while (!stream.eof()) + { + char c = stream.get(); + if (c == '\\' && !escaped) + escaped = !escaped; + else if (c == '\"' && !escaped) + return Value(value); + else + { + value += c; + escaped = false; + } + } + return Value(value); +}; + + + + +static Value eatObject(std::istream& stream) +{ + Value obj(Type::objectValue); + while (!stream.eof()) + { + ltrim(stream); + char token = stream.get(); + if (token == '}') + break; //empty object + if (token == '/') + { + eatComment(stream); + token = stream.get(); + } + + assert(token == '"'); + Value key = eatString(stream); + ltrim(stream); + token = stream.get(); + assert(token == ':'); + ltrim(stream); + Value val = eatValue(stream); + obj[key.asString()] = val; + ltrim(stream); + + token = stream.get(); + if (token == '}') + break; + assert(token == ','); + } + return obj; +}; +static Value eatArray(std::istream& stream) +{ + Value obj(Type::arrayValue); + while (!stream.eof()) + { + ltrim(stream); + if (stream.peek() == ']') + { + stream.get(); + break; + } + obj.push_back(eatValue(stream)); + ltrim(stream); + char token = stream.get(); + if (token == '/') + { + eatComment(stream); + token = stream.get(); + } + if (token == ']') + break; + assert(token == ','); + } + return obj; +}; +static Value eatNumeric(std::istream& stream, char firstChar) +{ + std::string numeric(1, firstChar); + while (!stream.eof()) + { + char token = stream.peek(); + if ((token >= '0' && token <= '9') || token == '.' || token == '-') + numeric += stream.get(); + else + break; + } + if (numeric.find('.') == std::string::npos) + return Value(atoi(numeric.c_str())); + else + return Value((float)atof(numeric.c_str())); +}; + +static Value eatBool(std::istream& stream) +{ + char token = stream.get(); + if (token == 'a') //fAlse + { + stream.get(); //l + stream.get(); //s + stream.get(); //e + return false; + } + else if (token == 'r') //tRue + { + stream.get(); // u + stream.get(); // e + return true; + } + return Value(Type::nullValue); +}; +static Value eatNull(std::istream& stream) +{ + return Value(Type::nullValue); +}; + +//precondition: / is already eaten +static void eatComment(std::istream& stream) +{ + char token = stream.get(); + assert(token == '/' || token == '*'); + if (token == '*') + { + char last = token; + while ((last != '*' || token != '/') && !stream.eof()) + { + last = token; + token = stream.get(); + } + } + else if (token == '/') + while (token != '\n' && !stream.eof()) + token = stream.get(); + ltrim(stream); +} + + +static Value eatValue(std::istream& stream) +{ + ltrim(stream); + char token = stream.get(); + if (token == '{') + return eatObject(stream); + if (token == '[') + return eatArray(stream); + if ((token >= '0' && token <= '9') || token == '.' || token == '-') + return eatNumeric(stream, token); + if (token == '"') + return eatString(stream); + if (token == 't' || token == 'f') + return eatBool(stream); + if (token == 'n') + return eatNull(stream); + if (token == '/') + { + eatComment(stream); + return eatValue(stream); + } + throw "Unable to parse json"; +}; + + +Value readJson(const std::string &data) +{ + std::stringstream stream; + stream << data; + printf("%s", "test"); + + return eatValue(stream); +} + +Value readJson(std::istream &stream) +{ + return eatValue(stream); +} + + + +std::ostream& indent(std::ostream& stream, int level) +{ + for (int i = 0; i < level; i++) + stream << '\t'; + return stream; +} + +std::ostream& Value::prettyPrint(std::ostream& stream, json::Value& printConfig, int level) const +{ + stream << std::fixed << std::setprecision(6); + switch (type) + { + case Type::intValue: + stream << value.intValue; + break; + case Type::floatValue: + assert(!isnan(value.floatValue)); + //assert(isnormal(value.floatValue)); + if (value.floatValue >= 0) + stream << " "; + stream << value.floatValue; + break; + case Type::boolValue: + stream << (value.boolValue ? "true" : "false"); + break; + case Type::stringValue: + stream << "\"" << *value.stringValue << "\""; //TODO: escape \'s + break; + case Type::arrayValue: + { + stream << "["; + int wrap = 99999; + if (value.arrayValue->size() > 10) + wrap = 1; + if (value.arrayValue->at(0).isArray() || value.arrayValue->at(0).isObject()) + wrap = 1; + else + wrap = 3; + + std::string seperator = " "; + + if (!printConfig.isNull() && printConfig.isMember("wrap")) + wrap = printConfig["wrap"]; + if (!printConfig.isNull() && printConfig.isMember("seperator")) + seperator = printConfig["seperator"].asString(); + + + int index = 0; + + if ((long)size() > wrap) + { + stream << "\n"; + indent(stream, level + 1); + } + for (auto v : *this) + { + if (index > 0) + { + stream << "," << seperator; + if (index % wrap == 0) + { + stream << "\n"; + indent(stream, level + 1); + } + } + + json::Value childPrintConfig = json::Value::null; + if (!printConfig.isNull()) + { + if (printConfig.isMember("elements")) + childPrintConfig = printConfig["elements"]; + else if (printConfig.isMember("recursive") && printConfig["recursive"].asBool() == true) + childPrintConfig = printConfig; + } + + v.prettyPrint(stream, childPrintConfig, level + 1); + index++; + } + if ((long)size() > wrap) + { + stream << "\n"; + indent(stream, level); + } + stream << "]"; + break; + } + case Type::objectValue: + { + stream << "{\n"; + int wrap = 99999; + if (value.arrayValue->size() > 10) + wrap = 1; + if (value.arrayValue->at(0).isArray() || value.arrayValue->at(0).isObject()) + wrap = 1; + else + wrap = 3; + + std::string seperator = " "; + + if (!printConfig.isNull() && printConfig.isMember("wrap")) + wrap = printConfig["wrap"]; + if (!printConfig.isNull() && printConfig.isMember("seperator")) + seperator = printConfig["seperator"].asString(); + + + int index = 0; + indent(stream, level + 1); + + + + //for (auto v : *value.objectValue) + auto printEl = [&](const std::pair v) + { + if (index > 0) + { + stream << "," << seperator; + if (index % wrap == 0) + { + stream << "\n"; + indent(stream, level + 1); + } + } + stream << "\"" << v.first << "\" : "; + if ( + (v.second.isArray() || v.second.isObject()) && + (printConfig.isNull() || + ( + printConfig.isMember(v.first) && + printConfig[v.first].isObject() && + printConfig[v.first].isMember("wrap") && + printConfig[v.first]["wrap"].asInt() < (int)v.second.size()) + ) + ) + { + stream << "\n"; + indent(stream, level + 1); + } + + json::Value childPrintConfig = json::Value::null; + if (!printConfig.isNull()) + { + if (printConfig.isMember(v.first)) + childPrintConfig = printConfig[v.first]; + else if (printConfig.isMember("recursive") && printConfig["recursive"].asBool() == true) + childPrintConfig = printConfig; + } + + v.second.prettyPrint(stream, childPrintConfig, level + 1);; + index++; + }; + + + + std::set printed; + if (!printConfig.isNull()) + { + if (printConfig.isMember("sort")) + { + for (std::string el : printConfig["sort"]) + { + if (isMember(el)) + { + printEl(std::pair(el, (*value.objectValue)[el])); + printed.insert(el); + } + } + } + } + + for (auto v : *value.objectValue) + if (printed.find(v.first) == printed.end()) + printEl(v); + + stream << "\n"; + indent(stream, level); + stream << "}"; + break; + } + case Type::nullValue: + stream << "null"; + break; + } + return stream; +} + + +std::ostream & operator<<(std::ostream &stream, const Value& value) +{ + stream << std::fixed<< std::setprecision(6); + switch (value.type) + { + case Type::intValue: + stream << value.value.intValue; + break; + case Type::floatValue: + assert(!isnan(value.value.floatValue)); + //assert(isnormal(value.value.floatValue)); + stream << value.value.floatValue; + break; + case Type::boolValue: + stream << (value.value.boolValue ? "true" : "false"); + break; + case Type::stringValue: + stream << "\"" << *value.value.stringValue << "\""; //TODO: escape \'s + break; + case Type::arrayValue: + { + stream << "["; + bool first = true; + for (auto v : value) + { + if (!first) + stream << ", "; + stream << v; + first = false; + } + stream << "]"; + break; + } + case Type::objectValue: + { + stream << "{"; + bool first = true; + for (auto v : *value.value.objectValue) + { + if (!first) + stream << ", "; + stream << "\"" << v.first << "\" : " << v.second << std::endl; + first = false; + } + stream << "}"; + break; + } + case Type::nullValue: + stream << "null"; + break; + } + return stream; +} } \ No newline at end of file diff --git a/json.h b/json.h index e0738aa..946e181 100644 --- a/json.h +++ b/json.h @@ -37,7 +37,6 @@ namespace json Value(); Value(Type type); Value(int value); - Value(__int64 value); Value(float value); Value(bool value); Value(const std::string &value); @@ -50,24 +49,24 @@ namespace json - inline operator int() const { return asInt(); } - inline operator float() const { return asFloat(); } - inline operator bool() const { return asBool(); } - inline operator const std::string&() const { return asString(); } + inline operator int() const { return asInt(); } + inline operator float() const { return asFloat(); } + inline operator bool() const { return asBool(); } + inline operator const std::string&() const { return asString(); } - inline int asInt() const { assert(type == Type::intValue); return value.intValue; } - inline float asFloat() const { assert(type == Type::floatValue || type == Type::intValue); return type == Type::floatValue ? value.floatValue : value.intValue; } - inline bool asBool() const { assert(type == Type::boolValue); return value.boolValue; } - inline const std::string& asString() const { assert(type == Type::stringValue); return *value.stringValue; } - inline bool isNull() const { return type == Type::nullValue; } - inline bool isString() const { return type == Type::stringValue; } - inline bool isInt() const { return type == Type::intValue; } - inline bool isBool() const { return type == Type::boolValue; } - inline bool isFloat() const { return type == Type::floatValue; } - inline bool isObject() const { return type == Type::objectValue; } - inline bool isArray() const { return type == Type::arrayValue; } - inline bool isMember(const std::string &name) const { if (type != Type::objectValue) return false; return value.objectValue->find(name) != value.objectValue->end(); } + inline int asInt() const { assert(type == Type::intValue); return value.intValue; } + inline float asFloat() const { assert(type == Type::floatValue || type == Type::intValue); return type == Type::floatValue ? value.floatValue : value.intValue; } + inline bool asBool() const { assert(type == Type::boolValue); return value.boolValue; } + inline const std::string& asString() const { assert(type == Type::stringValue); return *value.stringValue; } + inline bool isNull() const { return type == Type::nullValue; } + inline bool isString() const { return type == Type::stringValue; } + inline bool isInt() const { return type == Type::intValue; } + inline bool isBool() const { return type == Type::boolValue; } + inline bool isFloat() const { return type == Type::floatValue; } + inline bool isObject() const { return type == Type::objectValue; } + inline bool isArray() const { return type == Type::arrayValue; } + inline bool isMember(const std::string &name) const { assert(type == Type::objectValue); return value.objectValue->find(name) != value.objectValue->end(); } //array/object virtual size_t size() const; //array @@ -83,8 +82,6 @@ namespace json virtual Value& operator [] (const std::string &key) const; virtual Value& operator [] (const char* key) const; - virtual const Value& get(const char* key, const Value& default) const; - virtual bool operator == (const std::string &other) { return asString() == other; } virtual bool operator == (const int other) { return asInt() == other; } virtual bool operator == (const float other) { return asFloat() == other; } @@ -93,9 +90,6 @@ namespace json std::ostream& prettyPrint(std::ostream& stream, json::Value& printConfig = null, int level = 0) const; class Iterator; - private: - - public: Iterator begin() const; Iterator end() const; }; @@ -125,8 +119,6 @@ namespace json Value readJson(const std::string &data); Value readJson(std::istream &stream); std::ostream &operator << (std::ostream &stream, const Value& value); //serializes json data - std::string &operator << (std::string &stream, const Value& value); //serializes json data - } \ No newline at end of file