Compare commits
4 Commits
2c95011e73
...
46a8736f17
Author | SHA1 | Date |
---|---|---|
Mr_Goldberg | 46a8736f17 | |
Mr_Goldberg | 6884c1e551 | |
Mr_Goldberg | 3b9366e71b | |
Mr_Goldberg | e13a3c632d |
|
@ -62,7 +62,7 @@ build_windows:
|
||||||
- dnf -y install wine wget p7zip sed dos2unix
|
- dnf -y install wine wget p7zip sed dos2unix
|
||||||
- unix2dos *.txt
|
- unix2dos *.txt
|
||||||
- unix2dos files_example/*.txt files_example/*/*.txt
|
- unix2dos files_example/*.txt files_example/*/*.txt
|
||||||
- sed -i 's/..\\vcpkg\\installed\\/.\\/g' build_set_protobuf_directories.bat
|
- sed -i 's/..\\vcpkg\\installed\\/.\\protobuf_/g' build_set_protobuf_directories.bat
|
||||||
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/48db8f434a193aae872279dc4f5dde6a/sdk_standalone.7z'
|
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/48db8f434a193aae872279dc4f5dde6a/sdk_standalone.7z'
|
||||||
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/0119304e030098b4821d73170fe52084/protobuf_x64-windows-static.7z'
|
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/0119304e030098b4821d73170fe52084/protobuf_x64-windows-static.7z'
|
||||||
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/4185a97ab363ddc1859127e59ec68581/protobuf_x86-windows-static.7z'
|
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/4185a97ab363ddc1859127e59ec68581/protobuf_x86-windows-static.7z'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@echo off
|
@echo off
|
||||||
cd /d "%~dp0"
|
cd /d "%~dp0"
|
||||||
SET PROTOBUF_X86_DIRECTORY=..\vcpkg\installed\protobuf_x86-windows-static
|
SET PROTOBUF_X86_DIRECTORY=..\vcpkg\installed\x86-windows-static
|
||||||
SET PROTOBUF_X64_DIRECTORY=..\vcpkg\installed\protobuf_x64-windows-static
|
SET PROTOBUF_X64_DIRECTORY=..\vcpkg\installed\x64-windows-static
|
||||||
|
|
||||||
rem location of protoc in protobuf directories:
|
rem location of protoc in protobuf directories:
|
||||||
SET PROTOC_X86_EXE=%PROTOBUF_X86_DIRECTORY%\tools\protobuf\protoc.exe
|
SET PROTOC_X86_EXE=%PROTOBUF_X86_DIRECTORY%\tools\protobuf\protoc.exe
|
||||||
|
|
|
@ -381,8 +381,7 @@ bool RemoveFavoriteGame( AppId_t nAppID, uint32 nIP, uint16 nConnPort, uint16 nQ
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
//
|
//
|
||||||
#define LOBBY_SEARCH_TIMEOUT 3.0 //defined by steam as being 20 seconds max and 3 seconds typically (Should be no less than 3 because or else SGZH doesn't work).
|
#define LOBBY_SEARCH_TIMEOUT 0.2 //Tested on real steam
|
||||||
//Sanctum 2 needs this to be 2 seconds for the game to appear in the list though.
|
|
||||||
STEAM_CALL_RESULT( LobbyMatchList_t )
|
STEAM_CALL_RESULT( LobbyMatchList_t )
|
||||||
SteamAPICall_t RequestLobbyList()
|
SteamAPICall_t RequestLobbyList()
|
||||||
{
|
{
|
||||||
|
@ -457,7 +456,7 @@ void AddRequestLobbyListFilterSlotsAvailable( int nSlotsAvailable )
|
||||||
// sets the distance for which we should search for lobbies (based on users IP address to location map on the Steam backed)
|
// sets the distance for which we should search for lobbies (based on users IP address to location map on the Steam backed)
|
||||||
void AddRequestLobbyListDistanceFilter( ELobbyDistanceFilter eLobbyDistanceFilter )
|
void AddRequestLobbyListDistanceFilter( ELobbyDistanceFilter eLobbyDistanceFilter )
|
||||||
{
|
{
|
||||||
PRINT_DEBUG("AddRequestLobbyListDistanceFilter\n");
|
PRINT_DEBUG("AddRequestLobbyListDistanceFilter %i\n", eLobbyDistanceFilter);
|
||||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||||
|
|
||||||
|
|
||||||
|
@ -652,6 +651,7 @@ void LeaveLobby( CSteamID steamIDLobby )
|
||||||
if (lobbies.end() != lobby) {
|
if (lobbies.end() != lobby) {
|
||||||
if (!lobby->deleted()) {
|
if (!lobby->deleted()) {
|
||||||
on_self_enter_leave_lobby((uint64)lobby->room_id(), lobby->type(), true);
|
on_self_enter_leave_lobby((uint64)lobby->room_id(), lobby->type(), true);
|
||||||
|
self_lobby_member_data.erase(lobby->room_id());
|
||||||
if (lobby->owner() != settings->get_local_steam_id().ConvertToUint64()) {
|
if (lobby->owner() != settings->get_local_steam_id().ConvertToUint64()) {
|
||||||
PRINT_DEBUG("LeaveLobby not owner\n");
|
PRINT_DEBUG("LeaveLobby not owner\n");
|
||||||
leave_lobby(&(*lobby), settings->get_local_steam_id());
|
leave_lobby(&(*lobby), settings->get_local_steam_id());
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <json/json.hpp>
|
#include <json/json.hpp>
|
||||||
|
#include <json/fifo_map.hpp>
|
||||||
|
|
||||||
class CurlGlobal
|
class CurlGlobal
|
||||||
{
|
{
|
||||||
|
@ -230,6 +231,7 @@ public:
|
||||||
|
|
||||||
std::string steam_apikey;
|
std::string steam_apikey;
|
||||||
std::string app_id;
|
std::string app_id;
|
||||||
|
std::string output_path;
|
||||||
|
|
||||||
#if defined(WIN32) || defined(_WIN32)
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -274,7 +276,7 @@ static void generate_achievements(CurlEasy &easy)
|
||||||
easy.perform();
|
easy.perform();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::ofstream ach_file("achievements.json", std::ios::trunc | std::ios::out);
|
std::ofstream ach_file(output_path + "/achievements.json", std::ios::trunc | std::ios::out);
|
||||||
nlohmann::json json = nlohmann::json::parse(easy.get_answer());
|
nlohmann::json json = nlohmann::json::parse(easy.get_answer());
|
||||||
nlohmann::json output_json = nlohmann::json::array();
|
nlohmann::json output_json = nlohmann::json::array();
|
||||||
|
|
||||||
|
@ -299,7 +301,7 @@ static void generate_achievements(CurlEasy &easy)
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string icon_path = "images/" + item.value()["name"].get<std::string>() + ".jpg";
|
std::string icon_path = "images/" + item.value()["name"].get<std::string>() + ".jpg";
|
||||||
std::ofstream achievement_icon(icon_path, std::ios::out | std::ios::trunc | std::ios::binary);
|
std::ofstream achievement_icon(output_path + "/" + icon_path, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||||
if (!achievement_icon)
|
if (!achievement_icon)
|
||||||
{
|
{
|
||||||
std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl;
|
std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl;
|
||||||
|
@ -316,7 +318,7 @@ static void generate_achievements(CurlEasy &easy)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::string icon_path = "images/" + item.value()["name"].get<std::string>() + "_gray.jpg";
|
std::string icon_path = "images/" + item.value()["name"].get<std::string>() + "_gray.jpg";
|
||||||
std::ofstream achievement_icon(icon_path, std::ios::out | std::ios::trunc | std::ios::binary);
|
std::ofstream achievement_icon(output_path + "/" + icon_path, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||||
if (!achievement_icon)
|
if (!achievement_icon)
|
||||||
{
|
{
|
||||||
std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl;
|
std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl;
|
||||||
|
@ -350,6 +352,11 @@ static void generate_achievements(CurlEasy &easy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class K, class V, class dummy_compare, class A>
|
||||||
|
using my_workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
|
||||||
|
using fifo_json = nlohmann::basic_json<my_workaround_fifo_map>;
|
||||||
|
|
||||||
|
|
||||||
static void generate_items(CurlEasy& easy)
|
static void generate_items(CurlEasy& easy)
|
||||||
{
|
{
|
||||||
std::string url = "https://api.steampowered.com/IInventoryService/GetItemDefMeta/v1?key=";
|
std::string url = "https://api.steampowered.com/IInventoryService/GetItemDefMeta/v1?key=";
|
||||||
|
@ -373,12 +380,12 @@ static void generate_items(CurlEasy& easy)
|
||||||
easy.set_url(url);
|
easy.set_url(url);
|
||||||
easy.perform();
|
easy.perform();
|
||||||
|
|
||||||
nlohmann::json item_json = nlohmann::json::object();
|
fifo_json item_json;
|
||||||
nlohmann::json default_item_json = nlohmann::json::object();
|
fifo_json default_item_json;
|
||||||
|
|
||||||
json = nlohmann::json::parse(easy.get_answer());
|
json = nlohmann::json::parse(easy.get_answer());
|
||||||
std::ofstream items_file("items.json", std::ios::trunc | std::ios::out);
|
std::ofstream items_file(output_path + "/items.json", std::ios::trunc | std::ios::out);
|
||||||
std::ofstream default_items_file("default_items.json", std::ios::trunc | std::ios::out);
|
std::ofstream default_items_file(output_path + "/default_items.json", std::ios::trunc | std::ios::out);
|
||||||
|
|
||||||
for (auto &i : json)
|
for (auto &i : json)
|
||||||
{
|
{
|
||||||
|
@ -434,14 +441,99 @@ static void generate_items(CurlEasy& easy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
static std::string get_appid_name(CurlEasy& easy, uint32_t appid)
|
||||||
{
|
{
|
||||||
if (!create_directory("images"))
|
static std::map<uint32_t, std::string> appid_names;
|
||||||
{
|
static bool done;
|
||||||
std::cerr << "Cannot create directory \"images\"" << std::endl;
|
|
||||||
return -1;
|
if (!done) {
|
||||||
|
std::string url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/";
|
||||||
|
std::cout << "getting app list" << std::endl;
|
||||||
|
easy.set_url(url);
|
||||||
|
easy.perform();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nlohmann::json json = nlohmann::json::parse(easy.get_answer());
|
||||||
|
for (auto &app : json["applist"]["apps"]) {
|
||||||
|
appid_names[app["appid"].get<uint32_t>()] = app["name"].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to get infos: ";
|
||||||
|
long code;
|
||||||
|
if (easy.get_html_code(code) == CURLE_OK && code == 403)
|
||||||
|
{
|
||||||
|
std::cerr << "Error 403 while getting app list";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Error while parsing json. With " << url << "";
|
||||||
|
}
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
if (!appid_names.count(appid)) {
|
||||||
|
std::cout << "getting app name: " << appid << std::endl;
|
||||||
|
std::string s_appid = std::to_string(appid);
|
||||||
|
std::string url = "https://store.steampowered.com/api/appdetails/?appids=" + s_appid;
|
||||||
|
easy.set_url(url);
|
||||||
|
easy.perform();
|
||||||
|
nlohmann::json json = nlohmann::json::parse(easy.get_answer());
|
||||||
|
appid_names[appid] = json[s_appid]["data"]["name"].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return appid_names[appid];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void generate_dlcs(CurlEasy& easy)
|
||||||
|
{
|
||||||
|
std::string base_url = "https://store.steampowered.com/api/appdetails/?appids=";
|
||||||
|
std::string url = base_url + app_id;
|
||||||
|
easy.set_url(url);
|
||||||
|
easy.perform();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nlohmann::json json = nlohmann::json::parse(easy.get_answer());
|
||||||
|
std::list<uint32_t> dlcs;
|
||||||
|
std::map<uint32_t, std::string> dlc_names;
|
||||||
|
|
||||||
|
for (auto& dlc : json[app_id]["data"]["dlc"])
|
||||||
|
{
|
||||||
|
dlcs.push_back(dlc.get<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream dlc_file(output_path + "/DLC.txt", std::ios::trunc | std::ios::out);
|
||||||
|
for (auto &dlc: dlcs) {
|
||||||
|
dlc_file << dlc << "=" << get_appid_name(easy, dlc) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to get infos: ";
|
||||||
|
long code;
|
||||||
|
if (easy.get_html_code(code) == CURLE_OK && code == 403)
|
||||||
|
{
|
||||||
|
std::cerr << "Error 403 while getting dlcs";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Error while parsing json. With " << url << "";
|
||||||
|
}
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
CurlGlobal& cglobal = CurlGlobal::Inst();
|
CurlGlobal& cglobal = CurlGlobal::Inst();
|
||||||
cglobal.init();
|
cglobal.init();
|
||||||
|
|
||||||
|
@ -449,15 +541,50 @@ int main()
|
||||||
if (easy.init())
|
if (easy.init())
|
||||||
{
|
{
|
||||||
easy.skip_verifypeer();
|
easy.skip_verifypeer();
|
||||||
std::cout << "Enter the game appid: ";
|
|
||||||
std::cin >> app_id;
|
|
||||||
std::cout << "Enter your webapi key: ";
|
|
||||||
std::cin.clear();
|
|
||||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
|
||||||
std::cin >> steam_apikey;
|
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
app_id = argv[2];
|
||||||
|
steam_apikey = argv[1];
|
||||||
|
} else {
|
||||||
|
std::cout << "Usage: " << argv[0] << " steam_api_key app_id <output_path (default is folder with app_id/steam_settings)>" << std::endl;
|
||||||
|
std::cout << "Enter the game appid: ";
|
||||||
|
std::cin >> app_id;
|
||||||
|
std::cout << "Enter your webapi key: ";
|
||||||
|
std::cin.clear();
|
||||||
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||||
|
std::cin >> steam_apikey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
output_path = argv[3];
|
||||||
|
} else {
|
||||||
|
output_path = app_id;
|
||||||
|
create_directory(output_path);
|
||||||
|
output_path += "/steam_settings";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!create_directory(output_path))
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot create directory: " << output_path << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!create_directory(output_path + "/images"))
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot create directory \"images\"" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ofstream appid_file(output_path + "/steam_appid.txt", std::ios::trunc | std::ios::out);
|
||||||
|
appid_file << app_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Generating DLC.txt" << std::endl;
|
||||||
|
generate_dlcs(easy);
|
||||||
|
std::cout << "Generating achievements" << std::endl;
|
||||||
generate_achievements(easy);
|
generate_achievements(easy);
|
||||||
|
std::cout << "Generating items" << std::endl;
|
||||||
generate_items(easy);
|
generate_items(easy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,547 @@
|
||||||
|
/*
|
||||||
|
The code is licensed under the MIT License <http://opensource.org/licenses/MIT>:
|
||||||
|
|
||||||
|
Copyright (c) 2015-2017 Niels Lohmann.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NLOHMANN_FIFO_MAP_HPP
|
||||||
|
#define NLOHMANN_FIFO_MAP_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief namespace for Niels Lohmann
|
||||||
|
@see https://github.com/nlohmann
|
||||||
|
*/
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class Key>
|
||||||
|
class fifo_map_compare
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// constructor given a pointer to a key storage
|
||||||
|
fifo_map_compare(
|
||||||
|
std::unordered_map<Key, std::size_t>* keys,
|
||||||
|
std::size_t timestamp = 1)
|
||||||
|
:
|
||||||
|
m_timestamp(timestamp),
|
||||||
|
m_keys(keys)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
This function compares two keys with respect to the order in which they
|
||||||
|
were added to the container. For this, the mapping keys is used.
|
||||||
|
*/
|
||||||
|
bool operator()(const Key& lhs, const Key& rhs) const
|
||||||
|
{
|
||||||
|
// look up timestamps for both keys
|
||||||
|
const auto timestamp_lhs = m_keys->find(lhs);
|
||||||
|
const auto timestamp_rhs = m_keys->find(rhs);
|
||||||
|
|
||||||
|
if (timestamp_lhs == m_keys->end())
|
||||||
|
{
|
||||||
|
// timestamp for lhs not found - cannot be smaller than for rhs
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timestamp_rhs == m_keys->end())
|
||||||
|
{
|
||||||
|
// timestamp for rhs not found - timestamp for lhs is smaller
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare timestamps
|
||||||
|
return timestamp_lhs->second < timestamp_rhs->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_key(const Key& key)
|
||||||
|
{
|
||||||
|
m_keys->insert({key, m_timestamp++});
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_key(const Key& key)
|
||||||
|
{
|
||||||
|
m_keys->erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// helper to access m_timestamp from fifo_map copy ctor,
|
||||||
|
/// must have same number of template args as fifo_map
|
||||||
|
template <
|
||||||
|
class MapKey,
|
||||||
|
class MapT,
|
||||||
|
class MapCompare,
|
||||||
|
class MapAllocator
|
||||||
|
> friend class fifo_map;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// the next valid insertion timestamp
|
||||||
|
std::size_t m_timestamp = 1;
|
||||||
|
|
||||||
|
/// pointer to a mapping from keys to insertion timestamps
|
||||||
|
std::unordered_map<Key, std::size_t>* m_keys = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Key,
|
||||||
|
class T,
|
||||||
|
class Compare = fifo_map_compare<Key>,
|
||||||
|
class Allocator = std::allocator<std::pair<const Key, T>>
|
||||||
|
> class fifo_map
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using key_type = Key;
|
||||||
|
using mapped_type = T;
|
||||||
|
using value_type = std::pair<const Key, T>;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using key_compare = Compare;
|
||||||
|
using allocator_type = Allocator;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using pointer = typename std::allocator_traits<Allocator>::pointer;
|
||||||
|
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
|
||||||
|
|
||||||
|
using internal_map_type = std::map<Key, T, Compare, Allocator>;
|
||||||
|
|
||||||
|
using iterator = typename internal_map_type::iterator;
|
||||||
|
using const_iterator = typename internal_map_type::const_iterator;
|
||||||
|
using reverse_iterator = typename internal_map_type::reverse_iterator;
|
||||||
|
using const_reverse_iterator = typename internal_map_type::const_reverse_iterator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// default constructor
|
||||||
|
fifo_map() : m_keys(), m_compare(&m_keys), m_map(m_compare) {}
|
||||||
|
|
||||||
|
/// copy constructor
|
||||||
|
fifo_map(const fifo_map &f) : m_keys(f.m_keys), m_compare(&m_keys, f.m_compare.m_timestamp), m_map(f.m_map.begin(), f.m_map.end(), m_compare) {}
|
||||||
|
|
||||||
|
/// constructor for a range of elements
|
||||||
|
template<class InputIterator>
|
||||||
|
fifo_map(InputIterator first, InputIterator last)
|
||||||
|
: m_keys(), m_compare(&m_keys), m_map(m_compare)
|
||||||
|
{
|
||||||
|
for (auto it = first; it != last; ++it)
|
||||||
|
{
|
||||||
|
insert(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// constructor for a list of elements
|
||||||
|
fifo_map(std::initializer_list<value_type> init) : fifo_map()
|
||||||
|
{
|
||||||
|
for (auto x : init)
|
||||||
|
{
|
||||||
|
insert(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Element access
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// access specified element with bounds checking
|
||||||
|
T& at(const Key& key)
|
||||||
|
{
|
||||||
|
return m_map.at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// access specified element with bounds checking
|
||||||
|
const T& at(const Key& key) const
|
||||||
|
{
|
||||||
|
return m_map.at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// access specified element
|
||||||
|
T& operator[](const Key& key)
|
||||||
|
{
|
||||||
|
m_compare.add_key(key);
|
||||||
|
return m_map[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// access specified element
|
||||||
|
T& operator[](Key&& key)
|
||||||
|
{
|
||||||
|
m_compare.add_key(key);
|
||||||
|
return m_map[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterators
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// returns an iterator to the beginning
|
||||||
|
iterator begin() noexcept
|
||||||
|
{
|
||||||
|
return m_map.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the end
|
||||||
|
iterator end() noexcept
|
||||||
|
{
|
||||||
|
return m_map.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the beginning
|
||||||
|
const_iterator begin() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the end
|
||||||
|
const_iterator end() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the beginning
|
||||||
|
const_iterator cbegin() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the end
|
||||||
|
const_iterator cend() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a reverse iterator to the beginning
|
||||||
|
reverse_iterator rbegin() noexcept
|
||||||
|
{
|
||||||
|
return m_map.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a reverse iterator to the end
|
||||||
|
reverse_iterator rend() noexcept
|
||||||
|
{
|
||||||
|
return m_map.rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a reverse iterator to the beginning
|
||||||
|
const_reverse_iterator rbegin() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a reverse iterator to the end
|
||||||
|
const_reverse_iterator rend() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a reverse iterator to the beginning
|
||||||
|
const_reverse_iterator crbegin() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.crbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns a reverse iterator to the end
|
||||||
|
const_reverse_iterator crend() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.crend();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Capacity
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// checks whether the container is empty
|
||||||
|
bool empty() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the number of elements
|
||||||
|
size_type size() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the maximum possible number of elements
|
||||||
|
size_type max_size() const noexcept
|
||||||
|
{
|
||||||
|
return m_map.max_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifiers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// clears the contents
|
||||||
|
void clear() noexcept
|
||||||
|
{
|
||||||
|
m_map.clear();
|
||||||
|
m_keys.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insert value
|
||||||
|
std::pair<iterator, bool> insert(const value_type& value)
|
||||||
|
{
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
return m_map.insert(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insert value
|
||||||
|
template<class P>
|
||||||
|
std::pair<iterator, bool> insert( P&& value )
|
||||||
|
{
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
return m_map.insert(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insert value with hint
|
||||||
|
iterator insert(const_iterator hint, const value_type& value)
|
||||||
|
{
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
return m_map.insert(hint, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insert value with hint
|
||||||
|
iterator insert(const_iterator hint, value_type&& value)
|
||||||
|
{
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
return m_map.insert(hint, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insert value range
|
||||||
|
template<class InputIt>
|
||||||
|
void insert(InputIt first, InputIt last)
|
||||||
|
{
|
||||||
|
for (const_iterator it = first; it != last; ++it)
|
||||||
|
{
|
||||||
|
m_compare.add_key(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_map.insert(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insert value list
|
||||||
|
void insert(std::initializer_list<value_type> ilist)
|
||||||
|
{
|
||||||
|
for (auto value : ilist)
|
||||||
|
{
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_map.insert(ilist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// constructs element in-place
|
||||||
|
template<class... Args>
|
||||||
|
std::pair<iterator, bool> emplace(Args&& ... args)
|
||||||
|
{
|
||||||
|
typename fifo_map::value_type value(std::forward<Args>(args)...);
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
return m_map.emplace(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// constructs element in-place with hint
|
||||||
|
template<class... Args>
|
||||||
|
iterator emplace_hint(const_iterator hint, Args&& ... args)
|
||||||
|
{
|
||||||
|
typename fifo_map::value_type value(std::forward<Args>(args)...);
|
||||||
|
m_compare.add_key(value.first);
|
||||||
|
return m_map.emplace_hint(hint, std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// remove element at position
|
||||||
|
iterator erase(const_iterator pos)
|
||||||
|
{
|
||||||
|
m_compare.remove_key(pos->first);
|
||||||
|
return m_map.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// remove elements in range
|
||||||
|
iterator erase(const_iterator first, const_iterator last)
|
||||||
|
{
|
||||||
|
for (const_iterator it = first; it != last; ++it)
|
||||||
|
{
|
||||||
|
m_compare.remove_key(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_map.erase(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// remove elements with key
|
||||||
|
size_type erase(const key_type& key)
|
||||||
|
{
|
||||||
|
size_type res = m_map.erase(key);
|
||||||
|
|
||||||
|
if (res > 0)
|
||||||
|
{
|
||||||
|
m_compare.remove_key(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// swaps the contents
|
||||||
|
void swap(fifo_map& other)
|
||||||
|
{
|
||||||
|
std::swap(m_map, other.m_map);
|
||||||
|
std::swap(m_compare, other.m_compare);
|
||||||
|
std::swap(m_keys, other.m_keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// returns the number of elements matching specific key
|
||||||
|
size_type count(const Key& key) const
|
||||||
|
{
|
||||||
|
return m_map.count(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// finds element with specific key
|
||||||
|
iterator find(const Key& key)
|
||||||
|
{
|
||||||
|
return m_map.find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// finds element with specific key
|
||||||
|
const_iterator find(const Key& key) const
|
||||||
|
{
|
||||||
|
return m_map.find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns range of elements matching a specific key
|
||||||
|
std::pair<iterator, iterator> equal_range(const Key& key)
|
||||||
|
{
|
||||||
|
return m_map.equal_range(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns range of elements matching a specific key
|
||||||
|
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const
|
||||||
|
{
|
||||||
|
return m_map.equal_range(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the first element not less than the given key
|
||||||
|
iterator lower_bound(const Key& key)
|
||||||
|
{
|
||||||
|
return m_map.lower_bound(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the first element not less than the given key
|
||||||
|
const_iterator lower_bound(const Key& key) const
|
||||||
|
{
|
||||||
|
return m_map.lower_bound(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the first element greater than the given key
|
||||||
|
iterator upper_bound(const Key& key)
|
||||||
|
{
|
||||||
|
return m_map.upper_bound(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns an iterator to the first element greater than the given key
|
||||||
|
const_iterator upper_bound(const Key& key) const
|
||||||
|
{
|
||||||
|
return m_map.upper_bound(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Observers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// returns the function that compares keys
|
||||||
|
key_compare key_comp() const
|
||||||
|
{
|
||||||
|
return m_compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-member functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
friend bool operator==(const fifo_map& lhs, const fifo_map& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_map == rhs.m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(const fifo_map& lhs, const fifo_map& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_map != rhs.m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<(const fifo_map& lhs, const fifo_map& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_map < rhs.m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator<=(const fifo_map& lhs, const fifo_map& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_map <= rhs.m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator>(const fifo_map& lhs, const fifo_map& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_map > rhs.m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator>=(const fifo_map& lhs, const fifo_map& rhs)
|
||||||
|
{
|
||||||
|
return lhs.m_map >= rhs.m_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// the keys
|
||||||
|
std::unordered_map<Key, std::size_t> m_keys;
|
||||||
|
/// the comparison object
|
||||||
|
Compare m_compare;
|
||||||
|
/// the internal data structure
|
||||||
|
internal_map_type m_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// specialization of std::swap
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <class Key, class T, class Compare, class Allocator>
|
||||||
|
inline void swap(nlohmann::fifo_map<Key, T, Compare, Allocator>& m1,
|
||||||
|
nlohmann::fifo_map<Key, T, Compare, Allocator>& m2)
|
||||||
|
{
|
||||||
|
m1.swap(m2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue