From af8cace60255320fc4b826e7219d36c1e1f11297 Mon Sep 17 00:00:00 2001 From: "Nicholas \"LB\" Braden" Date: Sat, 20 Apr 2013 22:18:25 -0500 Subject: [PATCH 1/2] exception -> Exception, XML -> JSON --- .gitmodules | 3 ++ build_clang_win.bat | 2 +- config.json | 20 +++++++ config.xml | 16 ------ lib/json-parser | 1 + src/AppStateGame.hpp | 2 +- src/Configuration.hpp | 59 +++++++++++--------- src/Exception.hpp | 67 +++++++++++++++++++---- src/Graphics.cpp | 6 +-- src/JsonReader.hpp | 116 ++++++++++++++++++++++++++++++++++++++++ src/Main.cpp | 12 ++--- src/ResourceManager.hpp | 2 +- src/XMLReader.hpp | 51 ------------------ 13 files changed, 243 insertions(+), 114 deletions(-) create mode 100644 config.json delete mode 100644 config.xml create mode 160000 lib/json-parser create mode 100644 src/JsonReader.hpp delete mode 100644 src/XMLReader.hpp diff --git a/.gitmodules b/.gitmodules index 112d7c0..0eb91ee 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/boost"] path = lib/boost url = git://github.com/ryppl/boost-svn.git +[submodule "lib/json-parser"] + path = lib/json-parser + url = git://github.com/udp/json-parser.git diff --git a/build_clang_win.bat b/build_clang_win.bat index 6d3fdc7..e738a8f 100644 --- a/build_clang_win.bat +++ b/build_clang_win.bat @@ -1,2 +1,2 @@ -clang++ -std=c++11 -o chesspp.exe -isystem lib/boost/boost/ -isystem lib/SFML/include/ -Llib/SFML/lib/ -lsfml-audio -lsfml-graphics -lsfml-main -lsfml-system -lsfml-window src/*.cpp src/board/*.cpp +clang++ -std=c++11 -o chesspp.exe -isystem lib/boost/boost/ -isystem lib/SFML/include/ -isystem lib/json-parser/ -Llib/SFML/lib/ -lsfml-audio -lsfml-graphics -lsfml-main -lsfml-system -lsfml-window lib/json-parser/json.c src/*.cpp src/board/*.cpp pause diff --git a/config.json b/config.json new file mode 100644 index 0000000..5112e74 --- /dev/null +++ b/config.json @@ -0,0 +1,20 @@ +{ + "chesspp": + { + "board": + { + "initial_layout": "res/games/new_game.txt", + "width": 8, + "height": 8, + "cell_width": 80, + "cell_height": 80, + + "images": + { + "board": "res/img/chessboard_640x640.png", + "pieces": "res/img/chess_pieces_80x80_each.png", + "validMove": "res/img/valid_move.png" + } + } + } +} diff --git a/config.xml b/config.xml deleted file mode 100644 index cf5ef1b..0000000 --- a/config.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - res/games/new_game.txt - 8 - 8 - 80 - 80 - - - - res/img/chessboard_640x640.png - res/img/chess_pieces_80x80_each.png - res/img/valid_move.png - - diff --git a/lib/json-parser b/lib/json-parser new file mode 160000 index 0000000..1e58690 --- /dev/null +++ b/lib/json-parser @@ -0,0 +1 @@ +Subproject commit 1e586904a1294576fd43a75cf186599acbbeea2a diff --git a/src/AppStateGame.hpp b/src/AppStateGame.hpp index fd40aa3..dea2413 100644 --- a/src/AppStateGame.hpp +++ b/src/AppStateGame.hpp @@ -20,7 +20,7 @@ namespace chesspp Board* board; graphics::GraphicsHandler graphics; - configuration::BoardConfig boardConfig; + config::BoardConfig boardConfig; public: AppStateGame(Application* _app, sf::RenderWindow *_display); diff --git a/src/Configuration.hpp b/src/Configuration.hpp index 69051da..efb464d 100644 --- a/src/Configuration.hpp +++ b/src/Configuration.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #if defined(__linux__) #include @@ -15,14 +16,14 @@ #include "Exception.hpp" -#include "XMLReader.hpp" +#include "JsonReader.hpp" #include "board/logger.hpp" namespace chesspp { - namespace configuration + namespace config { - class configuration + class Configuration { protected: std::string res_path; @@ -31,62 +32,67 @@ namespace chesspp // /res/img/... should be where resources are stored. //OS x, resource path is defined as the absolute path to the Resources folder of the .app structure. // <.app>/Contents/Resources/res/img... should be where resources are stored. - std::string getResourcePath() + static std::string getResourcePath() { char buf[1024]; - uint32_t size = sizeof(buf); + std::uint32_t size = sizeof(buf); memset(buf, 0, size); std::string ret; #if defined(__linux__) if(readlink("/proc/self/exe", buf, size) == -1) - throw chesspp::exception("Unable to determine executable path on Linux."); + throw Exception("Unable to determine executable path on Linux."); ret = buf; ret = ret.substr(0, ret.find_last_of('/')+1); #elif defined(_WIN32) if(GetModuleFileNameA(NULL, buf, size) == 0) - throw chesspp::exception("Unable to determine executable path on Windows."); + throw Exception("Unable to determine executable path on Windows."); ret = buf; boost::replace_all(ret, "\\", "/"); ret = ret.substr(0, ret.find_last_of('/')+1); #elif defined(__APPLE__) if (_NSGetExecutablePath(buf, &size) != 0) - throw chesspp::exception("Unable to determine executable path on OS x. (Buffer size too small?)"); + throw Exception("Unable to determine executable path on OS x. (Buffer size too small?)"); ret = buf; ret = ret.substr(0, ret.find_last_of('/')+1) + "../Resources/"; //Need to go up one directory because the exe is stored in <.app>/Contents/MacOS/, //And we need <.app>/Contents/Resources #else - throw chesspp::exception("Unknown OS. Unable to determine executable path."); + throw Exception("Unknown OS. Unable to determine executable path."); #endif return ret; } - XMLReader reader; + JsonReader reader; public: - configuration(const std::string &configFile) : res_path(getResourcePath()), reader(getResourcePath() + configFile) {} - virtual ~configuration() {} + Configuration(const std::string &configFile) noexcept(false) : res_path(getResourcePath()), reader(std::ifstream(getResourcePath() + configFile)) + { + } + virtual ~Configuration() noexcept + { + } }; - class BoardConfig : public configuration + class BoardConfig : public Configuration { std::string initial_layout; - uint8_t board_width, board_height; - uint16_t cell_width, cell_height; + std::uint8_t board_width, board_height; + std::uint16_t cell_width, cell_height; public: - BoardConfig() : configuration("config.xml") + BoardConfig() + : Configuration("config.json") + , initial_layout (res_path + std::string(reader()["chesspp"]["board"]["initial_layout"])) + , board_width(reader()["chesspp"]["board"]["width"]) + , board_height(reader()["chesspp"]["board"]["height"]) + , cell_width(reader()["chesspp"]["board"]["cell_width"]) + , cell_height(reader()["chesspp"]["board"]["cell_height"]) { - initial_layout = res_path + reader.getProperty("chesspp.data.board.initial_layout"); - board_width = reader.getProperty("chesspp.data.board.width"); - board_height = reader.getProperty("chesspp.data.board.height"); - cell_width = reader.getProperty("chesspp.data.board.cell_width"); - cell_height = reader.getProperty("chesspp.data.board.cell_height"); } std::string getInitialLayout() { return initial_layout; } @@ -96,16 +102,17 @@ namespace chesspp uint16_t getCellHeight() { return cell_height; } }; - class GraphicsConfig : public configuration + class GraphicsConfig : public Configuration { std::string path_board, path_pieces, path_validMove; public: - GraphicsConfig() : configuration("config.xml") + GraphicsConfig() + : Configuration("config.json") + , path_board(res_path + std::string(reader()["chesspp"]["board"]["images"]["board"])) + , path_pieces(res_path + std::string(reader()["chesspp"]["board"]["images"]["pieces"])) + , path_validMove(res_path + std::string(reader()["chesspp"]["board"]["images"]["validMove"])) { - path_board = res_path + reader.getProperty("chesspp.images.board"); - path_pieces = res_path + reader.getProperty("chesspp.images.pieces"); - path_validMove = res_path + reader.getProperty("chesspp.images.validMove"); } std::string getSpritePath_board() { return path_board; } diff --git a/src/Exception.hpp b/src/Exception.hpp index df13d43..c8ccc96 100644 --- a/src/Exception.hpp +++ b/src/Exception.hpp @@ -3,23 +3,72 @@ #include #include +#include +#include namespace chesspp { - class exception : public std::exception + class Exception : public std::exception { - using std::exception::what; + std::string e; //message + std::exception const&by; //caused by other exception, == *this otherwise + public: - exception() {} - virtual ~exception() {}; - exception(const exception &) {} + Exception(std::string const&e = "") noexcept(noexcept(std::string(std::string("")))) + : e(e), by(*this) //ignore benign warning about use of *this + { + } + Exception(std::string const&e, std::exception const&by) noexcept(noexcept(std::string(std::string("")))) + : e(e), by(by) + { + } + Exception(Exception const&) = default; + Exception(Exception &&) noexcept = default; + Exception &operator=(Exception const&) = default; + Exception &operator=(Exception &&) = default; + virtual ~Exception() noexcept = default; - exception(const std::string &_e) : e(_e) {} - virtual const char *what() { return e.c_str(); } + virtual bool operator==(std::exception const&other) const noexcept + { + return dynamic_cast(&other) == this; + } + friend bool operator==(std::exception const&e1, Exception const&e2) noexcept + { + return e2 == e1; //calls above operator== + } - private: - std::string e; + virtual const char *what() const noexcept + { + return e.c_str(); + } + virtual operator std::string() const noexcept + { + return e; + } + virtual std::exception const&cause() const noexcept + { + return by; + } + std::string fullMessage() const noexcept + { + std::string full = std::string(typeid(*this).name()) + " (::chespp::Exception): message = {" + e + "}"; + if(!(by == *this)) //cannot use !=, `using rel_ops` is below + { + full += ", caused by {"; + if(typeid(by) == typeid(Exception)) + { + full += dynamic_cast(by).fullMessage(); + } + else + { + full += by.what(); + } + full += "}"; + } + return full; + } }; + using std::rel_ops::operator!=; //to avoid defining above } #endif diff --git a/src/Graphics.cpp b/src/Graphics.cpp index 7b62c5f..eca0b48 100644 --- a/src/Graphics.cpp +++ b/src/Graphics.cpp @@ -8,8 +8,8 @@ namespace chesspp { try { - configuration::BoardConfig boardConfig; - configuration::GraphicsConfig graphicsConfig; + config::BoardConfig boardConfig; + config::GraphicsConfig graphicsConfig; board = sf::Sprite(TextureManager::getInstance().Load(graphicsConfig.getSpritePath_board())); pieces = sf::Sprite(TextureManager::getInstance().Load(graphicsConfig.getSpritePath_pieces())); @@ -17,7 +17,7 @@ namespace chesspp cell_size = boardConfig.getCellWidth(); } - catch (chesspp::exception &e) + catch(Exception &e) { #ifdef _DEBUG cout << "Error: " << e.what() << endl; diff --git a/src/JsonReader.hpp b/src/JsonReader.hpp new file mode 100644 index 0000000..dce390c --- /dev/null +++ b/src/JsonReader.hpp @@ -0,0 +1,116 @@ +#ifndef __JavaScriptObjectNotation_Reader_HeaderPlusPlus__ +#define __JavaScriptObjectNotation_Reader_HeaderPlusPlus__ + +#include +#include +#include +#include +#include + +#include "Exception.hpp" + +namespace chesspp +{ + class JsonReader + { + json_value *json {nullptr}; + public: + JsonReader(std::istream &s) noexcept(false) + { + std::string str ((std::istreambuf_iterator(s)), std::istreambuf_iterator()); + json_settings options {}; + char error[128]; //128 from json.c implementation, subject to change + json = json_parse_ex(&options, str.c_str(), str.length(), error); + if(json == nullptr) + { + //no manual cleanup needed + throw Exception(std::string("Error loading JSON: ") + error, Exception(str)); //attached JSON as 'caused by' + } + } + JsonReader(std::istream &&s) noexcept(false) : JsonReader(static_cast(s)) + { + } + ~JsonReader() noexcept + { + json_value_free(json), json = nullptr; + } + + class NestedValue + { + friend class ::chesspp::JsonReader; + json_value const&value; + NestedValue(json_value const&value) noexcept : value(value) + { + } + NestedValue &operator=(NestedValue const&) noexcept = delete; + public: + NestedValue(NestedValue const&) noexcept = default; + NestedValue(NestedValue &&) noexcept = default; + NestedValue &operator=(NestedValue &&) noexcept = default; + ~NestedValue() noexcept = default; + + json_type type() const noexcept //may wish to add an abstraction layer between json-parser + { + return value.type; + } + NestedValue parent() const noexcept(false) + { + if(value.parent) + { + return *value.parent; + } + throw Exception("No parent json value"); + } + + NestedValue operator[](std::string const&name) const noexcept(noexcept(name.c_str())) + { + return value[name.c_str()]; + } + NestedValue operator[](char const*name) //without this, ambiguity occurs + { + return value[name]; + } + NestedValue operator[](std::size_t index) const noexcept + { + return value[static_cast(index)]; + } + operator std::string() const noexcept(noexcept(std::string(""))) + { + return static_cast(value); + } + //I tried an approach with templates, but the compiler was never able to deduce the corect template argument + operator std:: int8_t() const noexcept { return static_cast(static_cast(value)); } + operator std:: uint8_t() const noexcept { return static_cast(static_cast(value)); } + operator std:: int16_t() const noexcept { return static_cast(static_cast(value)); } + operator std::uint16_t() const noexcept { return static_cast(static_cast(value)); } + operator std:: int32_t() const noexcept { return static_cast(static_cast(value)); } + operator std::uint32_t() const noexcept { return static_cast(static_cast(value)); } + operator std:: int64_t() const noexcept { return static_cast(static_cast(value)); } + operator std::uint64_t() const noexcept { return static_cast(static_cast(value)); } + operator bool() const noexcept + { + return value; + } + operator double() const noexcept + { + return value; + } + }; + + NestedValue access() const noexcept + { + return *json; + } + NestedValue operator()() const noexcept + { + return access(); + } + + json_value *&implementation() noexcept //only for extreme-use cases + { + return json; + } + }; +} + +#endif diff --git a/src/Main.cpp b/src/Main.cpp index 008e5c1..94d51d0 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,16 +1,16 @@ +#include + #include "Application.hpp" int main() { try { - chesspp::Application app; - return app.Exec(); + return chesspp::Application().Exec(); } - catch (chesspp::exception& ex) + catch (chesspp::Exception &e) { - std::cout << "Caught in main: " << ex.what() << '\n'; + std::clog << "Caught in main: " << e.fullMessage() << std::endl; + return -1; } - - return 0; } diff --git a/src/ResourceManager.hpp b/src/ResourceManager.hpp index b99eb21..d14eb83 100644 --- a/src/ResourceManager.hpp +++ b/src/ResourceManager.hpp @@ -65,7 +65,7 @@ namespace chesspp //else, load resource ptr_t p(onLoadResource(key)); if(p.get() == NULL) - throw chesspp::exception("Error loading Image at " + key); //figure out better way to throw exceptions later + throw Exception("Error loading Image at " + key); //figure out better way to throw exceptions later m_map.insert(std::make_pair(key, std::move(p))); return *m_map[key].get(); diff --git a/src/XMLReader.hpp b/src/XMLReader.hpp deleted file mode 100644 index b97a964..0000000 --- a/src/XMLReader.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _XMLREADER_H -#define _XMLREADER_H - -#include "Exception.hpp" - -#include -#include -#include -#include - -namespace chesspp -{ - class XMLReader - { - class XMLReaderImpl - { - friend class XMLReader; - boost::property_tree::ptree tree; - - public: - XMLReaderImpl(const std::string &file) - { - try { - boost::property_tree::read_xml(file, tree, boost::property_tree::xml_parser::no_comments | boost::property_tree::xml_parser::trim_whitespace); - } catch(boost::property_tree::xml_parser_error &p) { - throw chesspp::exception(p.what()); - } - } - - ~XMLReaderImpl() {} - }; - - public: - XMLReader(const std::string &file) : impl(new XMLReaderImpl(file)) {}; - ~XMLReader() {} - - template - T getProperty(const std::string &key) - { - boost::optional ret = impl->tree.get_optional(key); - if(ret == boost::optional()) - throw chesspp::exception("Error: XMLReader::getProperty failed."); - return ret.get(); - } - - private: - std::unique_ptr impl; - }; -} - -#endif From 79f7cf2acd39b167aab146706cc1132fe2e07508 Mon Sep 17 00:00:00 2001 From: "Nicholas \"LB\" Braden" Date: Sat, 20 Apr 2013 22:53:50 -0500 Subject: [PATCH 2/2] Remove useless static cast --- src/JsonReader.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonReader.hpp b/src/JsonReader.hpp index dce390c..1ece7d3 100644 --- a/src/JsonReader.hpp +++ b/src/JsonReader.hpp @@ -27,7 +27,7 @@ namespace chesspp throw Exception(std::string("Error loading JSON: ") + error, Exception(str)); //attached JSON as 'caused by' } } - JsonReader(std::istream &&s) noexcept(false) : JsonReader(static_cast(s)) + JsonReader(std::istream &&s) noexcept(false) : JsonReader(s) { } ~JsonReader() noexcept