# HG changeset patch # User David Demelier # Date 1539368680 -7200 # Node ID fbfc2555bda567b57e2563a7b06cef9577ec7840 # Parent 23ee2b6091e885d4b937f5b0f8b639460fc20f9d Common: cleanup diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/CMakeLists.txt --- a/libcommon/CMakeLists.txt Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/CMakeLists.txt Fri Oct 12 20:24:40 2018 +0200 @@ -23,12 +23,13 @@ set( HEADERS + ${libmlk-common_SOURCE_DIR}/malikania/error/auth_error.hpp ${libmlk-common_SOURCE_DIR}/malikania/error/error.hpp - ${libmlk-common_SOURCE_DIR}/malikania/error/auth_error.hpp ${libmlk-common_SOURCE_DIR}/malikania/game.hpp ${libmlk-common_SOURCE_DIR}/malikania/loader.hpp ${libmlk-common_SOURCE_DIR}/malikania/locator.hpp ${libmlk-common_SOURCE_DIR}/malikania/size.hpp + ${libmlk-common_SOURCE_DIR}/malikania/socket.hpp ${libmlk-common_SOURCE_DIR}/malikania/tileset.hpp ${libmlk-common_SOURCE_DIR}/malikania/unicode.hpp ${libmlk-common_SOURCE_DIR}/malikania/util.hpp @@ -39,6 +40,7 @@ ${libmlk-common_SOURCE_DIR}/malikania/error/auth_error.cpp ${libmlk-common_SOURCE_DIR}/malikania/loader.cpp ${libmlk-common_SOURCE_DIR}/malikania/locator.cpp + ${libmlk-common_SOURCE_DIR}/malikania/socket.cpp ${libmlk-common_SOURCE_DIR}/malikania/unicode.cpp ${libmlk-common_SOURCE_DIR}/malikania/util.cpp ) diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/game.hpp --- a/libcommon/malikania/game.hpp Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/malikania/game.hpp Fri Oct 12 20:24:40 2018 +0200 @@ -24,22 +24,19 @@ * \brief Game description. */ -#include #include -#include namespace mlk { /** * \brief Basic game description. */ -class game { -public: - std::string name; - std::string version; - std::string requires; - std::string license; - std::string author; +struct game { + std::string name; + std::string version; + std::string requires; + std::string license; + std::string author; }; } // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/loader.cpp --- a/libcommon/malikania/loader.cpp Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/malikania/loader.cpp Fri Oct 12 20:24:40 2018 +0200 @@ -24,76 +24,85 @@ namespace mlk { +namespace { + +auto load_tileset_tile_properties(const nlohmann::json& json) -> tileset::properties_map +{ + auto it = json.find("properties"); + + if (it == json.end()) + return {}; + + tileset::properties_map props; + + for (auto pair = it->begin(); pair != it->end(); ++pair) { + // TODO: maxi convert + if (!pair->is_string()) + continue; + + props.emplace(pair.key(), pair->get()); + } + + return props; +} + +auto load_tileset_tiles_properties(const nlohmann::json& json) -> tileset::tile_properties_map +{ + auto tiles = json.find("tiles"); + + if (tiles == json.end()) + return {}; + + tileset::tile_properties_map props; + + for (auto it = tiles->begin(); it != tiles->end(); ++it) + props.emplace(std::stoi(it.key()), load_tileset_tile_properties(*it)); + + return props; +} + +} // !namespace + loader::loader(mlk::locator& locator) - : m_locator(locator) + : locator_(locator) { } -game loader::load_game() const +auto loader::get_locator() noexcept -> locator& { - auto value = nlohmann::json::parse(m_locator.read("game.json")); - - if (!value.is_object()) { - throw std::runtime_error("game.json: not a JSON object"); - } - - return game{util::json::require_string(value, "/name"_json_pointer), - util::json::require_string(value, "/version"_json_pointer), - util::json::require_string(value, "/requires"_json_pointer), - value.count("license") > 0 ? value["license"] : "", - value.count("author") > 0 ? value["author"] : ""}; + return locator_; } -tileset::properties_map load_tileset_tile_properties(const nlohmann::json& json) +auto loader::load_game() const -> game { - auto it = json.find("properties"); + auto value = nlohmann::json::parse(locator_.read("game.json")); - if (it == json.end()) - return {}; - - tileset::properties_map props; + if (!value.is_object()) + throw std::runtime_error("game.json: not a JSON object"); - for (auto pair = it->begin(); pair != it->end(); ++pair) { - // TODO: maxi convert - if (!pair->is_string()) - continue; - - props.emplace(pair.key(), pair->get()); - } - - return props; + return game{ + util::json::require_string(value, "/name"_json_pointer), + util::json::require_string(value, "/version"_json_pointer), + util::json::require_string(value, "/requires"_json_pointer), + value.count("license") > 0 ? value["license"] : "", + value.count("author") > 0 ? value["author"] : "" + }; } -tileset::tile_properties_map load_tileset_tiles_properties(const nlohmann::json& json) +auto loader::load_tileset(std::string_view id) const -> tileset { - auto tiles = json.find("tiles"); - - if (tiles == json.end()) - return {}; + auto value = nlohmann::json::parse(locator_.read(id)); - tileset::tile_properties_map props; - - for (auto it = tiles->begin(); it != tiles->end(); ++it) - props.emplace(std::stoi(it.key()), load_tileset_tile_properties(*it)); - - return props; -} + if (!value.is_object()) + throw std::runtime_error("not a valid tileset"); -tileset loader::load_tileset(const std::string& id) const -{ - auto value = nlohmann::json::parse(m_locator.read(id)); - - if (!value.is_object()) - throw std::runtime_error(id + ": not a valid tileset"); + tileset tileset; - tileset tileset( - util::json::require_string(value, "/image"_json_pointer), - util::json::require_size(value, "/cell"_json_pointer) - ); + tileset.image = util::json::require_string(value, "/image"_json_pointer); + tileset.cell = util::json::require_size(value, "/cell"_json_pointer); + tileset.tile_properties = load_tileset_tiles_properties(value); - tileset.set_tile_properties(load_tileset_tiles_properties(value)); - - return tileset; + return tileset; } } // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/loader.hpp --- a/libcommon/malikania/loader.hpp Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/malikania/loader.hpp Fri Oct 12 20:24:40 2018 +0200 @@ -23,9 +23,10 @@ namespace mlk { -class game; +struct game; +struct tileset; + class locator; -class tileset; /** * \brief Open resources files using a locator. @@ -37,47 +38,44 @@ */ class loader { private: - mlk::locator& m_locator; + locator& locator_; public: - /** - * Construct the resources loader. - * - * \param locator the locator - */ - loader(mlk::locator& locator); + /** + * Construct the resources loader. + * + * \param locator the locator + */ + loader(locator& locator); - /** - * Virtual destructor defaulted. - */ - virtual ~loader() noexcept = default; + /** + * Virtual destructor defaulted. + */ + virtual ~loader() noexcept = default; - /** - * Get the underlying locator. - * - * \return the locator - */ - inline mlk::locator& locator() noexcept - { - return m_locator; - } + /** + * Get the underlying locator. + * + * \return the locator + */ + auto get_locator() noexcept -> locator&; - /** - * Load a game. - * - * \return the game - * \throw std::runtime_error on errors - */ - virtual game load_game() const; + /** + * Load a game. + * + * \return the game + * \throw std::runtime_error on errors + */ + virtual auto load_game() const -> game; - /** - * Load a tileset. - * - * \param id the tileset id - * \return a tileset ready to use - * \throw std::runtime_error on errors - */ - virtual tileset load_tileset(const std::string& id) const; + /** + * Load a tileset. + * + * \param id the tileset id + * \return a tileset ready to use + * \throw std::runtime_error on errors + */ + virtual auto load_tileset(std::string_view id) const -> tileset; }; } // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/locator.cpp --- a/libcommon/malikania/locator.cpp Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/malikania/locator.cpp Fri Oct 12 20:24:40 2018 +0200 @@ -20,37 +20,50 @@ #include #include #include +#include #include #include "locator.hpp" namespace mlk { +auto directory_locator::make_path(std::string_view id) -> std::string +{ + std::ostringstream oss; + + oss << path_; + oss << "/"; + oss << id; + + return oss.str(); +} + directory_locator::directory_locator(std::string path) noexcept - : m_path(std::move(path)) + : path_(std::move(path)) { } -std::string directory_locator::read(const std::string &id) +auto directory_locator::read(std::string_view id) -> std::string { - std::ifstream in(m_path + "/" + id, std::ifstream::in | std::ifstream::binary); + std::ifstream in(make_path(id), std::ifstream::in | std::ifstream::binary); - if (!in) { - throw std::runtime_error(std::strerror(errno)); - } + if (!in) + throw std::runtime_error(std::strerror(errno)); - return std::string(std::istreambuf_iterator(in.rdbuf()), std::istreambuf_iterator()); + return std::string( + std::istreambuf_iterator(in.rdbuf()), + std::istreambuf_iterator() + ); } -std::unique_ptr directory_locator::open(const std::string &id) +auto directory_locator::open(std::string_view id) -> std::unique_ptr { - auto ptr = std::make_unique(m_path + "/" + id); + auto ptr = std::make_unique(make_path(id)); - if (!(*ptr)) { - throw std::runtime_error(std::strerror(errno)); - } + if (!(*ptr)) + throw std::runtime_error(std::strerror(errno)); - return std::move(ptr); + return std::move(ptr); } } // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/locator.hpp --- a/libcommon/malikania/locator.hpp Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/malikania/locator.hpp Fri Oct 12 20:24:40 2018 +0200 @@ -19,9 +19,10 @@ #ifndef MALIKANIA_LOCATOR_HPP #define MALIKANIA_LOCATOR_HPP -#include +#include #include -#include +#include +#include namespace mlk { @@ -30,28 +31,28 @@ */ class locator { public: - /** - * Default destructor. - */ - virtual ~locator() = default; + /** + * Default destructor. + */ + virtual ~locator() = default; - /** - * Read a whole resource as a string. - * - * \param id the resource id - * \return the string - * \throw std::runtime_error on any errors - */ - virtual std::string read(const std::string& id) = 0; + /** + * Read a whole resource as a string. + * + * \param id the resource id + * \return the string + * \throw std::runtime_error on any errors + */ + virtual auto read(std::string_view id) -> std::string = 0; - /** - * Open a resource as a stream. - * - * \param id the resource id - * \return the stream - * \throw std::runtime_error on any errors - */ - virtual std::unique_ptr open(const std::string& id) = 0; + /** + * Open a resource as a stream. + * + * \param id the resource id + * \return the stream + * \throw std::runtime_error on any errors + */ + virtual auto open(std::string_view id) -> std::unique_ptr = 0; }; /** @@ -59,25 +60,27 @@ */ class directory_locator : public locator { private: - std::string m_path; + std::string path_; + + auto make_path(std::string_view) -> std::string; public: - /** - * Load the game from the directory. - * - * \param path the base directory - */ - directory_locator(std::string path) noexcept; + /** + * Load the game from the directory. + * + * \param path the base directory + */ + directory_locator(std::string path) noexcept; - /** - * \copydoc locator::read - */ - std::string read(const std::string& id) override; + /** + * \copydoc locator::read + */ + auto read(std::string_view id) -> std::string override; - /** - * \copydoc locator::open - */ - std::unique_ptr open(const std::string& id) override; + /** + * \copydoc locator::open + */ + auto open(std::string_view id) -> std::unique_ptr override; }; } // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/network_stream.cpp --- a/libcommon/malikania/network_stream.cpp Tue Aug 21 10:55:13 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * network_stream.cpp -- network socket - * - * Copyright (c) 2013-2018 David Demelier - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include "network_stream.hpp" - -namespace mlk { - -void network_stream::do_recv(network_recv_handler handler) -{ - boost::asio::async_read_until(socket_, rbuffer_, "\r\n\r\n", [this, handler] (auto code, auto xfer) { - if (code) - handler(std::move(code), nullptr); - else if (xfer == 0U) - handler(make_error_code(boost::system::errc::network_down), nullptr); - else { - std::string str( - boost::asio::buffers_begin(rbuffer_.data()), - boost::asio::buffers_begin(rbuffer_.data()) + xfer - 4 - ); - - // Remove early in case of errors. - rbuffer_.consume(xfer); - - // TODO: catch nlohmann::json::parse_error when 3.0.0 is released. - nlohmann::json message; - - try { - message = nlohmann::json::parse(str); - } catch (...) {} - - if (!message.is_object()) - handler(make_error_code(boost::system::errc::invalid_argument), nullptr); - else - handler(code, std::move(message)); - } - }); -} - -void network_stream::do_send(const std::string& str, network_send_handler handler) -{ - boost::asio::async_write(socket_, boost::asio::buffer(str), [handler] (auto code, auto xfer) { - if (xfer == 0U) - handler(make_error_code(boost::system::errc::network_down)); - else - handler(code); - }); -} - -void network_stream::rflush() -{ - if (rqueue_.empty()) - return; - - do_recv([this] (auto code, auto json) { - auto handler = rqueue_.front(); - - rqueue_.pop_front(); - handler(code, std::move(json)); - - if (!code) - rflush(); - }); -} - -void network_stream::sflush() -{ - if (squeue_.empty()) - return; - - do_send(squeue_.front().first, [this] (auto code) { - auto handler = squeue_.front().second; - - squeue_.pop_front(); - - if (handler) - handler(code); - if (!code) - sflush(); - }); -} - -void network_stream::recv(network_recv_handler handler) -{ - assert(handler); - - auto in_progress = !rqueue_.empty(); - - rqueue_.push_back(std::move(handler)); - - if (!in_progress) - rflush(); -} - -void network_stream::send(nlohmann::json json, network_send_handler handler) -{ - assert(json.is_object()); - - auto in_progress = !squeue_.empty(); - - squeue_.emplace_back(json.dump(0) + "\r\n\r\n", std::move(handler)); - - if (!in_progress) - sflush(); -} - -} // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/network_stream.hpp --- a/libcommon/malikania/network_stream.hpp Tue Aug 21 10:55:13 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * network_stream.hpp -- network socket - * - * Copyright (c) 2013-2018 David Demelier - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef MALIKANIA_COMMON_NETWORK_STREAM_HPP -#define MALIKANIA_COMMON_NETWORK_STREAM_HPP - -/** - * \file network_stream.cpp - * \brief Network socket. - */ - -#include "sysconfig.hpp" - -#include -#include -#include -#include - -#include -#include - -#include - -namespace mlk { - -/** - * Read handler. - * - * Call this function when a receive operation has finished on success or - * failure. - */ -using network_recv_handler = std::function; - -/** - * Send handler. - * - * Call this function when a send operation has finished on success or failure. - */ -using network_send_handler = std::function; - -/** - * \brief Base shared network stream. - * - * This class can be used to perform I/O over a networking socket, it is - * implemented as asynchronous operations over Boost.Asio. - * - * All recv/send operations are placed in a queue and performed when possible. - */ -class network_stream { -private: - using socket_t = boost::asio::ssl::stream; - using rbuffer_t = boost::asio::streambuf; - using rqueue_t = std::deque; - using squeue_t = std::deque>; - - socket_t socket_; - rbuffer_t rbuffer_; - rqueue_t rqueue_; - squeue_t squeue_; - - void rflush(); - void sflush(); - void do_recv(network_recv_handler); - void do_send(const std::string&, network_send_handler); - -public: - /** - * Construct the stream. - * - * \param service the IO service - * \param ctx the SSL context - */ - inline network_stream(boost::asio::io_service& service, - boost::asio::ssl::context& ctx) - : socket_(service, ctx) - { - } - - /** - * Get the underlying socket. - * - * \return the socket - */ - inline const socket_t& socket() const noexcept - { - return socket_; - } - - /** - * Overloaded function. - * - * \return the socket - */ - inline socket_t& socket() noexcept - { - return socket_; - } - - /** - * Tells if receive operations are pending. - * - * \return true if receiving is in progress - */ - inline bool is_receiving() const noexcept - { - return !rqueue_.empty(); - } - - /** - * Tells if send operations are pending. - * - * \return true if sending is in progress - */ - inline bool is_sending() const noexcept - { - return !squeue_.empty(); - } - - /** - * Tells if there are any I/O pending. - * - * \return true if sending is in progress - */ - inline bool is_active() const noexcept - { - return is_receiving() || is_sending(); - } - - /** - * Request a receive operation. - * - * \pre handler != nullptr - * \param handler the handler - */ - void recv(network_recv_handler); - - /** - * Request a send operation. - * - * \pre json.is_object() - * \param json the json message - * \param handler the optional handler - */ - void send(nlohmann::json json, network_send_handler = nullptr); -}; - -} // !mlk - -#endif // MALIKANIA_COMMON_NETWORK_STREAM_HPP diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/socket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon/malikania/socket.cpp Fri Oct 12 20:24:40 2018 +0200 @@ -0,0 +1,154 @@ +/* + * socket.cpp -- SSL socket using JSON messages + * + * Copyright (c) 2013-2018 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "socket.hpp" + +namespace mlk { + +void socket::do_recv(recv_handler handler) +{ + boost::asio::async_read_until(socket_, rbuffer_, "\r\n\r\n", [this, handler] (auto code, auto xfer) { + if (code) + handler(std::move(code), nullptr); + else if (xfer == 0U) + handler(make_error_code(boost::system::errc::network_down), nullptr); + else { + std::string str( + boost::asio::buffers_begin(rbuffer_.data()), + boost::asio::buffers_begin(rbuffer_.data()) + xfer - 4 + ); + + // Remove early in case of errors. + rbuffer_.consume(xfer); + + // TODO: catch nlohmann::json::parse_error when 3.0.0 is released. + nlohmann::json message; + + try { + message = nlohmann::json::parse(str); + } catch (...) {} + + if (!message.is_object()) + handler(make_error_code(boost::system::errc::invalid_argument), nullptr); + else + handler(code, std::move(message)); + } + }); +} + +void socket::do_send(const std::string& str, send_handler handler) +{ + boost::asio::async_write(socket_, boost::asio::buffer(str), [handler] (auto code, auto xfer) { + if (xfer == 0U) + handler(make_error_code(boost::system::errc::network_down)); + else + handler(code); + }); +} + +socket::socket(boost::asio::io_service& service, + boost::asio::ssl::context& ctx) + : socket_(service, ctx) +{ +} + +auto socket::get_socket() const noexcept -> const socket_t& +{ + return socket_; +} + +auto socket::get_socket() noexcept -> socket_t& +{ + return socket_; +} + +auto socket::is_receiving() const noexcept -> bool +{ + return !rqueue_.empty(); +} + +auto socket::is_sending() const noexcept -> bool +{ + return !squeue_.empty(); +} + +auto socket::is_active() const noexcept -> bool +{ + return is_receiving() || is_sending(); +} + +void socket::rflush() +{ + if (rqueue_.empty()) + return; + + do_recv([this] (auto code, auto json) { + auto handler = rqueue_.front(); + + rqueue_.pop_front(); + handler(code, std::move(json)); + + if (!code) + rflush(); + }); +} + +void socket::sflush() +{ + if (squeue_.empty()) + return; + + do_send(squeue_.front().first, [this] (auto code) { + auto handler = squeue_.front().second; + + squeue_.pop_front(); + + if (handler) + handler(code); + if (!code) + sflush(); + }); +} + +void socket::recv(recv_handler handler) +{ + assert(handler); + + auto in_progress = !rqueue_.empty(); + + rqueue_.push_back(std::move(handler)); + + if (!in_progress) + rflush(); +} + +void socket::send(nlohmann::json json, send_handler handler) +{ + assert(json.is_object()); + + auto in_progress = !squeue_.empty(); + + squeue_.emplace_back(json.dump(0) + "\r\n\r\n", std::move(handler)); + + if (!in_progress) + sflush(); +} + +} // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/socket.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon/malikania/socket.hpp Fri Oct 12 20:24:40 2018 +0200 @@ -0,0 +1,148 @@ +/* + * socket.hpp -- SSL socket using JSON messages + * + * Copyright (c) 2013-2018 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MALIKANIA_COMMON_SOCKET_HPP +#define MALIKANIA_COMMON_SOCKET_HPP + +/** + * \file socket.hpp + * \brief SSL socket using JSON messages + */ + +#include "sysconfig.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace mlk { + +/** + * \brief SSL socket using JSON messages + * + * This class can be used to perform I/O over a networking socket, it is + * implemented as asynchronous operations over Boost.Asio. + * + * All recv/send operations are placed in a queue and performed when possible. + */ +class socket { +public: + /** + * Read handler. + * + * Call this function when a receive operation has finished on success or + * failure. + */ + using recv_handler = std::function; + + /** + * Send handler. + * + * Call this function when a send operation has finished on success or failure. + */ + using send_handler = std::function; + +private: + using socket_t = boost::asio::ssl::stream; + using rbuffer_t = boost::asio::streambuf; + using rqueue_t = std::deque; + using squeue_t = std::deque>; + + socket_t socket_; + rbuffer_t rbuffer_; + rqueue_t rqueue_; + squeue_t squeue_; + + void rflush(); + void sflush(); + void do_recv(recv_handler); + void do_send(const std::string&, send_handler); + +public: + /** + * Construct the socket. + * + * \param service the IO service + * \param ctx the SSL context + */ + socket(boost::asio::io_service& service, + boost::asio::ssl::context& ctx); + + /** + * Get the underlying socket. + * + * \return the socket + */ + auto get_socket() const noexcept -> const socket_t&; + + /** + * Overloaded function. + * + * \return the socket + */ + auto get_socket() noexcept -> socket_t&; + + /** + * Tells if receive operations are pending. + * + * \return true if receiving is in progress + */ + auto is_receiving() const noexcept -> bool; + + /** + * Tells if send operations are pending. + * + * \return true if sending is in progress + */ + auto is_sending() const noexcept -> bool; + + /** + * Tells if there are any I/O pending. + * + * \return true if sending is in progress + */ + auto is_active() const noexcept -> bool; + + /** + * Request a receive operation. + * + * \pre handler != nullptr + * \param handler the handler + */ + void recv(recv_handler); + + /** + * Request a send operation. + * + * \pre json.is_object() + * \param json the json message + * \param handler the optional handler + */ + void send(nlohmann::json json, send_handler = nullptr); +}; + +} // !mlk + +#endif // MALIKANIA_COMMON_SOCKET_HPP diff -r 23ee2b6091e8 -r fbfc2555bda5 libcommon/malikania/tileset.hpp --- a/libcommon/malikania/tileset.hpp Tue Aug 21 10:55:13 2018 +0200 +++ b/libcommon/malikania/tileset.hpp Fri Oct 12 20:24:40 2018 +0200 @@ -36,113 +36,21 @@ /** * \brief Map tileset definition. */ -class tileset { -public: - /** - * Map of general properties. - */ - using properties_map = std::unordered_map; - - /** - * Per tile properties. - */ - using tile_properties_map = std::unordered_map; - -private: - std::string image_; - size cell_; - properties_map properties_; - tile_properties_map tile_properties_; - -public: - /** - * Constructor. - */ - inline tileset(std::string image, size cell) noexcept - : image_(std::move(image)) - , cell_(std::move(cell)) - { - } - - /** - * Get the image identifier. - * - * \return the image identifier - */ - inline const std::string& get_image() const noexcept - { - return image_; - } - - /** - * Get the tile cell size. - * - * \return the cell size - */ - inline const size& get_cell() const noexcept - { - return cell_; - } +struct tileset { + /** + * Map of general properties. + */ + using properties_map = std::unordered_map; - /** - * Get the general properties. - * - * \return the properties - */ - inline properties_map& get_properties() noexcept - { - return properties_; - } - - /** - * Get the general properties. - * - * \return the properties - */ - inline const properties_map& get_properties() const noexcept - { - return properties_; - } - - /** - * Set the general properties. - * - * \param properties the properties - */ - inline void set_properties(properties_map properties) noexcept - { - properties_ = std::move(properties); - } + /** + * Per tile properties. + */ + using tile_properties_map = std::unordered_map; - /** - * Get the per-tile properties. - * - * \return the properties for each tile - */ - inline tile_properties_map& get_tile_properties() noexcept - { - return tile_properties_; - } - - /** - * Get the per-tile properties. - * - * \return the properties for each tile - */ - inline const tile_properties_map& get_tile_properties() const noexcept - { - return tile_properties_; - } - - /** - * Set the per-tile properties. - * - * \param properties the properties for each tile - */ - inline void set_tile_properties(tile_properties_map properties) noexcept - { - tile_properties_ = std::move(properties); - } + std::string image; + size cell; + properties_map properties; + tile_properties_map tile_properties; }; } // !mlk diff -r 23ee2b6091e8 -r fbfc2555bda5 tests/tools/tileset/main.cpp --- a/tests/tools/tileset/main.cpp Tue Aug 21 10:55:13 2018 +0200 +++ b/tests/tools/tileset/main.cpp Fri Oct 12 20:24:40 2018 +0200 @@ -28,35 +28,33 @@ class test_tileset { protected: - mlk::directory_locator locator_{CMAKE_CURRENT_BINARY_DIR}; - mlk::loader loader_{locator_}; + mlk::directory_locator locator_{CMAKE_CURRENT_BINARY_DIR}; + mlk::loader loader_{locator_}; }; BOOST_FIXTURE_TEST_SUITE(test_tileset_suite, test_tileset) BOOST_AUTO_TEST_CASE(tileset) { - const std::vector list{ - "tileset.json", - "tileset_embedded.json", - "tileset_external.json" - }; + const std::vector list{ + "tileset.json", + "tileset_embedded.json", + "tileset_external.json" + }; - for (const auto& t : list) { - auto tileset = loader_.load_tileset(t); + for (const auto& t : list) { + auto tileset = loader_.load_tileset(t); - BOOST_REQUIRE_EQUAL("worldmapchip5fo.png", tileset.get_image()); - BOOST_REQUIRE_EQUAL(32U, tileset.get_cell().width); - BOOST_REQUIRE_EQUAL(32U, tileset.get_cell().height); - BOOST_REQUIRE_EQUAL(3U, tileset.get_tile_properties().size()); + BOOST_REQUIRE_EQUAL("worldmapchip5fo.png", tileset.image); + BOOST_REQUIRE_EQUAL(32U, tileset.cell.width); + BOOST_REQUIRE_EQUAL(32U, tileset.cell.height); + BOOST_REQUIRE_EQUAL(3U, tileset.tile_properties.size()); - auto tp = tileset.get_tile_properties(); + // Index 8. + BOOST_REQUIRE_EQUAL("value", tileset.tile_properties[8]["test"]); - // Index 8. - BOOST_REQUIRE_EQUAL("value", tp[8]["test"]); - - // TODO: postpone collisions once made. - } + // TODO: postpone collisions once made. + } } BOOST_AUTO_TEST_SUITE_END()