diff --git a/apclient.hpp b/apclient.hpp index 212a173..63091a1 100644 --- a/apclient.hpp +++ b/apclient.hpp @@ -31,12 +31,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI //#define AP_PREFER_UNENCRYPTED // try unencrypted connection first, then encrypted -#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include +#include +#include + +// check for optional #if defined(_MSC_VER) && _MSC_VER < 1910 // older msvc doesn't like the has_include #define NO_OPTIONAL #else @@ -56,11 +65,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #endif -#include -#include -#include -#include -#include #ifndef WSWRAP_VERSION @@ -90,12 +94,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ class APDataPackageStore { protected: - typedef nlohmann::json json; + using json = nlohmann::json; APDataPackageStore() {} public: - virtual ~APDataPackageStore() {} + virtual ~APDataPackageStore() = default; virtual bool load(const std::string& game, const std::string& checksum, json& data) = 0; virtual bool save(const std::string& game, const json& data) = 0; @@ -159,7 +163,7 @@ class APClient { // fix up URI (add ws:// and default port if none is given) if (!uri.empty()) { auto p = uri.find("://"); - if (p == uri.npos) { + if (p == std::string::npos) { #if WSWRAP_VERSION >= 10100 || defined __EMSCRIPTEN__ _tryWSS = true; #ifdef AP_PREFER_UNENCRYPTED @@ -176,18 +180,18 @@ class APClient { } else { _uri = uri; } - auto pColon = _uri.find(":", p + 3); // FIXME: this fails for IPv6 addresses - auto pSlash = _uri.find("/", p + 3); - if (pColon == _uri.npos || (pSlash != _uri.npos && pColon > pSlash)) { + const auto pColon = _uri.find(':', p + 3); // FIXME: this fails for IPv6 addresses + const auto pSlash = _uri.find('/', p + 3); + if (pColon == std::string::npos || (pSlash != std::string::npos && pColon > pSlash)) { auto tmp = _uri.substr(0, pSlash) + ":38281"; - if (pSlash != _uri.npos) tmp += _uri.substr(pSlash); + if (pSlash != std::string::npos) tmp += _uri.substr(pSlash); _uri = tmp; } } if (!_dataPackageStore) { #ifndef AP_NO_DEFAULT_DATA_PACKAGE_STORE - _autoDataPackageStore.reset(new DefaultDataPackageStore()); + _autoDataPackageStore = std::make_unique(); _dataPackageStore =_autoDataPackageStore.get(); #else const char* msg = "dataPackageStore is required if compiled with AP_NO_DEFAULT_DATA_PACKAGE_STORE"; @@ -215,9 +219,7 @@ class APClient { connect_socket(); } - virtual ~APClient() - { - } + virtual ~APClient() = default; enum class State { DISCONNECTED, @@ -299,7 +301,7 @@ class APClient { struct NetworkSlot { std::string name; std::string game; - SlotType type; + SlotType type{}; std::list members; }; @@ -395,72 +397,72 @@ class APClient { } }; - void set_socket_connected_handler(std::function f) + void set_socket_connected_handler(std::function f) { - _hOnSocketConnected = f; + _hOnSocketConnected = std::move(f); } void set_socket_error_handler(std::function f) { - _hOnSocketError = f; + _hOnSocketError = std::move(f); } - void set_socket_disconnected_handler(std::function f) + void set_socket_disconnected_handler(std::function f) { - _hOnSocketDisconnected = f; + _hOnSocketDisconnected = std::move(f); } void set_slot_connected_handler(std::function f) { - _hOnSlotConnected = f; + _hOnSlotConnected = std::move(f); } void set_slot_refused_handler(std::function&)> f) { - _hOnSlotRefused = f; + _hOnSlotRefused = std::move(f); } - void set_slot_disconnected_handler(std::function f) + void set_slot_disconnected_handler(std::function f) { - _hOnSlotDisconnected = f; + _hOnSlotDisconnected = std::move(f); } - void set_room_info_handler(std::function f) + void set_room_info_handler(std::function f) { - _hOnRoomInfo = f; + _hOnRoomInfo = std::move(f); } - void set_room_update_handler(std::function f) + void set_room_update_handler(std::function f) { - _hOnRoomUpdate = f; + _hOnRoomUpdate = std::move(f); } void set_items_received_handler(std::function&)> f) { - _hOnItemsReceived = f; + _hOnItemsReceived = std::move(f); } void set_location_info_handler(std::function&)> f) { - _hOnLocationInfo = f; + _hOnLocationInfo = std::move(f); } void set_data_package_changed_handler(std::function f) { - _hOnDataPackageChanged = f; + _hOnDataPackageChanged = std::move(f); } void set_print_handler(std::function f) { - _hOnPrint = f; + _hOnPrint = std::move(f); } void set_print_json_handler(std::function f) { - _hOnPrintJson = f; + _hOnPrintJson = std::move(f); } - void set_print_json_handler(std::function f) + void set_print_json_handler(const std::function& f) { set_print_json_handler([f](const json& command) { if (!f) return; @@ -490,8 +492,8 @@ class APClient { it = command.find("item"); if (it != command.end()) { - item.item = it->value("item", (int64_t) 0); - item.location = it->value("location", (int64_t) 0); + item.item = it->value("item", static_cast(0)); + item.location = it->value("location", static_cast(0)); item.player = it->value("player", 0); item.flags = it->value("flags", 0U); item.index = -1; @@ -538,7 +540,7 @@ class APClient { }); } - void set_print_json_handler(std::function&, const NetworkItem*, const int*)> f) + void set_print_json_handler(const std::function&, const NetworkItem*, const int*)>& f) { set_print_json_handler([f](const PrintJSONArgs& args) { if (!f) return; @@ -546,7 +548,7 @@ class APClient { }); } - void set_print_json_handler(std::function&)> f) + void set_print_json_handler(const std::function&)>& f) { set_print_json_handler([f](const json& command) { if (!f) return; @@ -561,7 +563,7 @@ class APClient { }); } - void set_print_json_handler(std::function&, const json& extra)> f) + void set_print_json_handler(const std::function&, const json& extra)>& f) { set_print_json_handler([f](const json& command) { if (!f) @@ -584,15 +586,15 @@ class APClient { void set_bounced_handler(std::function f) { - _hOnBounced = f; + _hOnBounced = std::move(f); } void set_location_checked_handler(std::function&)> f) { - _hOnLocationChecked = f; + _hOnLocationChecked = std::move(f); } - void set_retrieved_handler(std::function&)> f) + void set_retrieved_handler(const std::function&)>& f) { set_retrieved_handler([f](const std::map& keys, const json&) { if (!f) @@ -604,15 +606,15 @@ class APClient { void set_retrieved_handler(std::function&, const json& message)> f) { - _hOnRetrieved = f; + _hOnRetrieved = std::move(f); } void set_set_reply_handler(std::function f) { - _hOnSetReply = f; + _hOnSetReply = std::move(f); } - void set_set_reply_handler(std::function f) { + void set_set_reply_handler(const std::function& f) { set_set_reply_handler([f](const json& command) { if (!f) return; f(command["key"].get(), command["value"], command["original_value"]); @@ -635,12 +637,12 @@ class APClient { return _receiveOwnLocations; } - const std::set get_checked_locations() const + std::set get_checked_locations() const { return _checkedLocations; } - const std::set get_missing_locations() const + std::set get_missing_locations() const { return _missingLocations; } @@ -650,7 +652,7 @@ class APClient { return _players; } - std::string get_player_alias(int slot) + std::string get_player_alias(const int slot) const { if (slot == 0) return "Server"; @@ -664,15 +666,15 @@ class APClient { return "Unknown"; } - const std::string& get_player_game(int player) + const std::string& get_player_game(const int player) const { static const std::string ARCHIPELAGO_STRING = "Archipelago"; - static const std::string BLANK = ""; + static const std::string BLANK; if (player == 0) return ARCHIPELAGO_STRING; - auto slotIt = _slotInfo.find(player); + const auto slotIt = _slotInfo.find(player); if (slotIt != _slotInfo.end()) return slotIt->second.game; @@ -680,21 +682,21 @@ class APClient { } /// Get the currently played game name or an empty string - const std::string& get_game() + const std::string& get_game() const { return get_player_game(get_player_number()); } - std::string get_location_name(int64_t code, const std::string& game) + std::string get_location_name(const int64_t code, const std::string& game) const { if (game.empty()) { // old code path ("global" ids) - auto it = _locations.find(code); + const auto it = _locations.find(code); if (it != _locations.end()) return it->second; } else { - auto locationsIt = _gameLocations.find(game); + const auto locationsIt = _gameLocations.find(game); if (locationsIt != _gameLocations.end()) { - auto it = locationsIt->second.find(code); + const auto it = locationsIt->second.find(code); if (it != locationsIt->second.end()) { return it->second; } @@ -719,16 +721,16 @@ class APClient { return INVALID_NAME_ID; } - std::string get_item_name(int64_t code, const std::string& game) + std::string get_item_name(const int64_t code, const std::string& game) const { if (game.empty()) { // old code path ("global" ids) - auto it = _items.find(code); + const auto it = _items.find(code); if (it != _items.end()) return it->second; } else { - auto itemsIt = _gameItems.find(game); + const auto itemsIt = _gameItems.find(game); if (itemsIt != _gameItems.end()) { - auto it = itemsIt->second.find(code); + const auto it = itemsIt->second.find(code); if (it != itemsIt->second.end()) { return it->second; } @@ -753,11 +755,11 @@ class APClient { return INVALID_NAME_ID; } - bool slot_concerns_self(int slot) const + bool slot_concerns_self(const int slot) const { if (slot == _slotnr) return true; - auto it = _slotInfo.find(slot); + const auto it = _slotInfo.find(slot); if (it != _slotInfo.end()) { const auto& members = it->second.members; return std::find(members.begin(), members.end(), _slotnr) != members.end(); @@ -765,7 +767,7 @@ class APClient { return false; } - std::string render_json(const std::list& msg, RenderFormat fmt = RenderFormat::TEXT) + std::string render_json(const std::list& msg, RenderFormat fmt = RenderFormat::TEXT) const { // TODO: implement RenderFormat::HTML if (fmt == RenderFormat::HTML) @@ -823,7 +825,7 @@ class APClient { return out; } - bool LocationChecks(std::list locations) + bool LocationChecks(const std::list& locations) { // returns true if checks were sent or queued if (_state == State::SLOT_CONNECTED) { @@ -847,7 +849,7 @@ class APClient { return true; } - bool LocationScouts(std::list locations, int create_as_hint = 0) + bool LocationScouts(const std::list& locations, int create_as_hint = 0) { // returns true if scouts were sent or queued if (_state == State::SLOT_CONNECTED) { @@ -905,7 +907,7 @@ class APClient { {"player", target_player}, }}; - if (hint_status != INT_MIN) { + if (hint_status != static_cast(INT_MIN)) { packet[0]["status"] = hint_status; } @@ -1028,7 +1030,7 @@ class APClient { // prefer to fetch 2 games at once for better use of compression window // if it's an odd number, the last fetch should be 1 game size_t n = 0; - size_t count = include.size(); + const size_t count = include.size(); std::vector games; for (const auto& game: include) { games.push_back(game); @@ -1049,8 +1051,8 @@ class APClient { return true; } - bool Bounce(const json& data, std::list games = {}, - std::list slots = {}, std::list tags = {}) + bool Bounce(const json& data, const std::list& games = {}, + const std::list& slots = {}, const std::list& tags = {}) { if (_state < State::ROOM_INFO) return false; // or SLOT_CONNECTED? @@ -1375,7 +1377,7 @@ class APClient { playedGames.emplace("Archipelago"); } else if (command["datapackage_versions"].is_array()) { // 0.1.x: get games from datapackage_versions - for (auto itV: command["datapackage_versions"].items()) { + for (const auto& itV: command["datapackage_versions"].items()) { playedGames.emplace(itV.key()); } } else { @@ -1390,7 +1392,7 @@ class APClient { if (itVersions != command.end() && !playedGames.empty()) { // pre 0.3.2: exclude games that exist but are not being played - for (auto itV: command["datapackage_versions"].items()) { + for (const auto& itV: command["datapackage_versions"].items()) { if (!playedGames.count(itV.key())) { exclude.push_back(itV.key()); } @@ -1466,8 +1468,8 @@ class APClient { _state = State::SLOT_CONNECTED; _team = command["team"]; _slotnr = command["slot"]; - _hintPoints = command.value("hint_points", command["checked_locations"].size()); - _locationCount = command["missing_locations"].size() + command["checked_locations"].size(); + _hintPoints = command.value("hint_points", static_cast(command["checked_locations"].size())); + _locationCount = static_cast(command["missing_locations"].size() + command["checked_locations"].size()); _players.clear(); for (auto& player: command["players"]) { _players.push_back({ @@ -1489,7 +1491,7 @@ class APClient { LocationChecks(queuedChecks); } if (command["slot_info"].is_object()) { - for (auto it: command["slot_info"].items()) { + for (const auto& it: command["slot_info"].items()) { NetworkSlot slot; const auto& j = it.value(); j.at("name").get_to(slot.name); @@ -1601,10 +1603,10 @@ class APClient { auto data = _dataPackage; if (!data["games"].is_object()) data["games"] = json(json::value_t::object); - for (auto gamepair: command["data"]["games"].items()) { + for (const auto& gamePair: command["data"]["games"].items()) { if (_dataPackageStore) - _dataPackageStore->save(gamepair.key(), gamepair.value()); - data["games"][gamepair.key()] = gamepair.value(); + _dataPackageStore->save(gamePair.key(), gamePair.value()); + data["games"][gamePair.key()] = gamePair.value(); } data["version"] = command["data"].value("version", -1); // -1 for backwards compatibility _dataPackageValid = false; @@ -1676,7 +1678,7 @@ class APClient { _state = State::SOCKET_CONNECTING; try { - _ws.reset(new WS(_uri, + _ws = std::make_unique(_uri, [this]() { onopen(); }, [this]() { onclose(); }, [this](const std::string& s) { onmessage(s); }, @@ -1688,7 +1690,7 @@ class APClient { #if WSWRAP_VERSION >= 10100 , _certStore #endif - )); + ); } catch (const std::exception& ex) { _ws = nullptr; if (_tryWSS && _uri.rfind("ws://", 0) == 0) { @@ -1703,7 +1705,7 @@ class APClient { // NOTE: browsers have a very badly implemented connection rate limit // alternatively we could always wait for onclose() to get the actual // allowed rate once we are over it - unsigned long maxReconnectInterval = std::max(15000UL, _ws ? _ws->get_ok_connect_interval() : 0); + const unsigned long maxReconnectInterval = std::max(15000UL, _ws ? _ws->get_ok_connect_interval() : 0); if (_socketReconnectInterval > maxReconnectInterval) _socketReconnectInterval = maxReconnectInterval; } @@ -1711,17 +1713,17 @@ class APClient { void _set_data_package(const json& data) { _dataPackage = data; - for (auto gamepair: _dataPackage["games"].items()) { - const auto& gamedata = gamepair.value(); - _dataPackage["games"][gamepair.key()] = gamedata; - auto& gameItems = _gameItems[gamepair.key()]; - for (auto pair: gamedata["item_name_to_id"].items()) { + for (const auto& gamePair: _dataPackage["games"].items()) { + const auto& gameData = gamePair.value(); + _dataPackage["games"][gamePair.key()] = gameData; + auto& gameItems = _gameItems[gamePair.key()]; + for (const auto& pair: gameData["item_name_to_id"].items()) { auto id = pair.value().get(); _items[id] = pair.key(); gameItems[id] = pair.key(); } - auto& gameLocations = _gameLocations[gamepair.key()]; - for (auto pair: gamedata["location_name_to_id"].items()) { + auto& gameLocations = _gameLocations[gamePair.key()]; + for (const auto& pair: gameData["location_name_to_id"].items()) { auto id = pair.value().get(); _locations[id] = pair.key(); gameLocations[id] = pair.key(); @@ -1729,7 +1731,7 @@ class APClient { } } - std::string color2ansi(const std::string& color) + static std::string color2ansi(const std::string& color) { // convert color to ansi color command if (color == "red") return "\x1b[31m"; @@ -1746,7 +1748,7 @@ class APClient { return "\x1b[0m"; } - void deansify(std::string& text) + static void deansify(std::string& text) { // disable ansi commands in text by replacing ESC by space std::replace(text.begin(), text.end(), '\x1b', ' '); @@ -1762,9 +1764,9 @@ class APClient { #endif return static_cast(GetTickCount()); #else - timespec ts; + timespec ts{}; clock_gettime(CLOCK_MONOTONIC, &ts); - unsigned long ms = static_cast( + auto ms = static_cast( static_cast(ts.tv_sec) * 1000); ms += static_cast(ts.tv_nsec / 1000000); return ms; @@ -1797,7 +1799,7 @@ class APClient { std::function&, const json&)> _hOnRetrieved = nullptr; std::function _hOnSetReply = nullptr; - unsigned long _lastSocketConnect; + unsigned long _lastSocketConnect{}; unsigned long _socketReconnectInterval = 1500; bool _reconnectNow = false; std::set _checkQueue; diff --git a/apuuid.hpp b/apuuid.hpp index f9a4537..44e7d3e 100644 --- a/apuuid.hpp +++ b/apuuid.hpp @@ -17,8 +17,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI * If calling srand() is a problem for the callee, you'll have to provide your own UUID generator. */ -#include -#include +#include +#include #include #include #include @@ -28,15 +28,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #else -#include -#include +#include +#include #endif namespace AP { class UUID { public: - UUID(uint8_t bytes[16]) + explicit UUID(const uint8_t bytes[16]) { const char hex[] = "0123456789abcdef"; _string.resize(32); @@ -49,7 +49,7 @@ namespace AP { } } - virtual ~UUID() {} + virtual ~UUID() = default; const std::string& string() const { @@ -63,7 +63,7 @@ namespace AP { class UUIDFactory { public: static UUIDFactory* instance(); - virtual ~UUIDFactory() {} + virtual ~UUIDFactory() = default; void setFilename(const std::string& filename); UUID getPersistentUUID(const std::string& hostname_or_url); @@ -72,7 +72,7 @@ namespace AP { uint8_t randByte() const; UUID generate() const; void generate(uint8_t bytes[8]) const; - uint8_t hash(const std::string& name) const; + static uint8_t hash(const std::string& name) ; std::string _filename; std::fstream _f; @@ -121,7 +121,7 @@ namespace AP { uint64_t dummy = 0; uint8_t bytes[16]; _f.seekg(0); - for (uint8_t i=0; i<16; i++) { + for (unsigned char& byte : bytes) { char c; uint8_t b = 0; for (uint8_t n=0; n<2; n++) { @@ -134,7 +134,7 @@ namespace AP { if (c >= 'A' && c <= 'F') b |= (uint8_t)(c - 'A' + 0x0a); } - bytes[i] = b; + byte = b; } _f.seekp(32); _f.write((const char*)&state, sizeof(state)); @@ -145,7 +145,7 @@ namespace AP { } // 32 byte at start of file reserved for back compat // then each entry is 8 byte state + 8 byte reserved + 16 byte uuid - size_t offset = 32 + (size_t) hash(name) * 32; + std::streamoff offset = 32 + (std::streamoff) hash(name) * 32; _f.seekg(offset); uint64_t state; uint64_t dummy; @@ -189,7 +189,7 @@ namespace AP { return UUID(bytes); } - uint8_t UUIDFactory::hash(const std::string& name) const + uint8_t UUIDFactory::hash(const std::string& name) { uint8_t res = 0; for (char c: name) { @@ -216,7 +216,7 @@ namespace AP { #else UUIDFactory::UUIDFactory() { - srand ((unsigned int) time (NULL)); + srand((unsigned int) time (nullptr)); } uint8_t UUIDFactory::randByte() const diff --git a/defaultdatapackagestore.hpp b/defaultdatapackagestore.hpp index cbb2f51..c7d07ba 100644 --- a/defaultdatapackagestore.hpp +++ b/defaultdatapackagestore.hpp @@ -10,12 +10,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #ifndef _DEFAULTDATAPACKAGESTORE_HPP #define _DEFAULTDATAPACKAGESTORE_HPP -#include "apclient.hpp" #include #include +#include #include +#include #include -#include +#include "apclient.hpp" #if defined WIN32 || defined _WIN32 #include @@ -38,8 +39,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #ifndef NO_STD_FILESYSTEM #define NO_STD_FILESYSTEM #endif -#include -#include +#include +#include #endif class DefaultDataPackageStore : public APDataPackageStore @@ -48,11 +49,11 @@ class DefaultDataPackageStore : public APDataPackageStore #if defined WIN32 || defined _WIN32 typedef std::wstring TString; typedef wchar_t TCHAR; - static const wchar_t CSLASH = L'/'; + static constexpr wchar_t CSLASH = L'/'; #else typedef std::string TString; typedef char TCHAR; - static const char CSLASH = '/'; + static constexpr char CSLASH = '/'; #endif private: @@ -67,8 +68,8 @@ class DefaultDataPackageStore : public APDataPackageStore public: path() = default; - path(const TString& s) - : s(s) + path(TString s) + : s(std::move(s)) { } @@ -137,7 +138,7 @@ class DefaultDataPackageStore : public APDataPackageStore if (s == slash()) return slash(); auto p = s.rfind(slash()); - if (p == s.npos) + if (p == TString::npos) return {}; return s.substr(0, p); } @@ -166,7 +167,7 @@ class DefaultDataPackageStore : public APDataPackageStore static const TCHAR* slash() { - static const TCHAR val[] = {CSLASH, 0}; + static constexpr TCHAR val[] = {CSLASH, 0}; return val; } }; @@ -218,8 +219,8 @@ class DefaultDataPackageStore : public APDataPackageStore ut.modtime = ut.actime; _wutime64(filename.c_str(), &ut); #else - struct utimbuf ut; - ut.actime = time(NULL); + utimbuf ut{}; + ut.actime = time(nullptr); ut.modtime = ut.actime; utime(filename.c_str(), &ut); #endif @@ -252,16 +253,16 @@ class DefaultDataPackageStore : public APDataPackageStore #endif if (!fallbackPath.empty()) return path(fallbackPath) / "cache"; - return path("cache"); + return {"cache"}; } public: - DefaultDataPackageStore(const std::string fallbackPath = "") + explicit DefaultDataPackageStore(const std::string& fallbackPath = "") : _path(get_default_cache_dir(fallbackPath) / "datapackage") { } - virtual bool load(const std::string& game, const std::string& checksum, json& data) override + bool load(const std::string& game, const std::string& checksum, json& data) override { auto p = get_path(game, checksum); if (p.empty()) { @@ -286,7 +287,7 @@ class DefaultDataPackageStore : public APDataPackageStore } } - virtual bool save(const std::string& game, const json& data) override + bool save(const std::string& game, const json& data) override { #ifndef NO_STD_FILESYSTEM using std::filesystem::create_directories;