mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Common: add ParamPackage
This commit is contained in:
		
							parent
							
								
									ad4097e75c
								
							
						
					
					
						commit
						8a8c0f348b
					
				
					 5 changed files with 188 additions and 0 deletions
				
			
		|  | @ -35,6 +35,7 @@ set(SRCS | ||||||
|             memory_util.cpp |             memory_util.cpp | ||||||
|             microprofile.cpp |             microprofile.cpp | ||||||
|             misc.cpp |             misc.cpp | ||||||
|  |             param_package.cpp | ||||||
|             scm_rev.cpp |             scm_rev.cpp | ||||||
|             string_util.cpp |             string_util.cpp | ||||||
|             symbols.cpp |             symbols.cpp | ||||||
|  | @ -66,6 +67,7 @@ set(HEADERS | ||||||
|             memory_util.h |             memory_util.h | ||||||
|             microprofile.h |             microprofile.h | ||||||
|             microprofileui.h |             microprofileui.h | ||||||
|  |             param_package.h | ||||||
|             platform.h |             platform.h | ||||||
|             quaternion.h |             quaternion.h | ||||||
|             scm_rev.h |             scm_rev.h | ||||||
|  |  | ||||||
							
								
								
									
										120
									
								
								src/common/param_package.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/common/param_package.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <array> | ||||||
|  | #include <vector> | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | #include "common/param_package.h" | ||||||
|  | #include "common/string_util.h" | ||||||
|  | 
 | ||||||
|  | namespace Common { | ||||||
|  | 
 | ||||||
|  | constexpr char KEY_VALUE_SEPARATOR = ':'; | ||||||
|  | constexpr char PARAM_SEPARATOR = ','; | ||||||
|  | constexpr char ESCAPE_CHARACTER = '$'; | ||||||
|  | const std::string KEY_VALUE_SEPARATOR_ESCAPE{ESCAPE_CHARACTER, '0'}; | ||||||
|  | const std::string PARAM_SEPARATOR_ESCAPE{ESCAPE_CHARACTER, '1'}; | ||||||
|  | const std::string ESCAPE_CHARACTER_ESCAPE{ESCAPE_CHARACTER, '2'}; | ||||||
|  | 
 | ||||||
|  | ParamPackage::ParamPackage(const std::string& serialized) { | ||||||
|  |     std::vector<std::string> pairs; | ||||||
|  |     Common::SplitString(serialized, PARAM_SEPARATOR, pairs); | ||||||
|  | 
 | ||||||
|  |     for (const std::string& pair : pairs) { | ||||||
|  |         std::vector<std::string> key_value; | ||||||
|  |         Common::SplitString(pair, KEY_VALUE_SEPARATOR, key_value); | ||||||
|  |         if (key_value.size() != 2) { | ||||||
|  |             LOG_ERROR(Common, "invalid key pair %s", pair.c_str()); | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (std::string& part : key_value) { | ||||||
|  |             part = Common::ReplaceAll(part, KEY_VALUE_SEPARATOR_ESCAPE, {KEY_VALUE_SEPARATOR}); | ||||||
|  |             part = Common::ReplaceAll(part, PARAM_SEPARATOR_ESCAPE, {PARAM_SEPARATOR}); | ||||||
|  |             part = Common::ReplaceAll(part, ESCAPE_CHARACTER_ESCAPE, {ESCAPE_CHARACTER}); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Set(key_value[0], key_value[1]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ParamPackage::ParamPackage(std::initializer_list<DataType::value_type> list) : data(list) {} | ||||||
|  | 
 | ||||||
|  | std::string ParamPackage::Serialize() const { | ||||||
|  |     if (data.empty()) | ||||||
|  |         return ""; | ||||||
|  | 
 | ||||||
|  |     std::string result; | ||||||
|  | 
 | ||||||
|  |     for (const auto& pair : data) { | ||||||
|  |         std::array<std::string, 2> key_value{{pair.first, pair.second}}; | ||||||
|  |         for (std::string& part : key_value) { | ||||||
|  |             part = Common::ReplaceAll(part, {ESCAPE_CHARACTER}, ESCAPE_CHARACTER_ESCAPE); | ||||||
|  |             part = Common::ReplaceAll(part, {PARAM_SEPARATOR}, PARAM_SEPARATOR_ESCAPE); | ||||||
|  |             part = Common::ReplaceAll(part, {KEY_VALUE_SEPARATOR}, KEY_VALUE_SEPARATOR_ESCAPE); | ||||||
|  |         } | ||||||
|  |         result += key_value[0] + KEY_VALUE_SEPARATOR + key_value[1] + PARAM_SEPARATOR; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     result.pop_back(); // discard the trailing PARAM_SEPARATOR
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const { | ||||||
|  |     auto pair = data.find(key); | ||||||
|  |     if (pair == data.end()) { | ||||||
|  |         LOG_DEBUG(Common, "key %s not found", key.c_str()); | ||||||
|  |         return default_value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return pair->second; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int ParamPackage::Get(const std::string& key, int default_value) const { | ||||||
|  |     auto pair = data.find(key); | ||||||
|  |     if (pair == data.end()) { | ||||||
|  |         LOG_DEBUG(Common, "key %s not found", key.c_str()); | ||||||
|  |         return default_value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         return std::stoi(pair->second); | ||||||
|  |     } catch (const std::logic_error&) { | ||||||
|  |         LOG_ERROR(Common, "failed to convert %s to int", pair->second.c_str()); | ||||||
|  |         return default_value; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float ParamPackage::Get(const std::string& key, float default_value) const { | ||||||
|  |     auto pair = data.find(key); | ||||||
|  |     if (pair == data.end()) { | ||||||
|  |         LOG_DEBUG(Common, "key %s not found", key.c_str()); | ||||||
|  |         return default_value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |         return std::stof(pair->second); | ||||||
|  |     } catch (const std::logic_error&) { | ||||||
|  |         LOG_ERROR(Common, "failed to convert %s to float", pair->second.c_str()); | ||||||
|  |         return default_value; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ParamPackage::Set(const std::string& key, const std::string& value) { | ||||||
|  |     data[key] = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ParamPackage::Set(const std::string& key, int value) { | ||||||
|  |     data[key] = std::to_string(value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ParamPackage::Set(const std::string& key, float value) { | ||||||
|  |     data[key] = std::to_string(value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ParamPackage::Has(const std::string& key) const { | ||||||
|  |     return data.find(key) != data.end(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Common
 | ||||||
							
								
								
									
										40
									
								
								src/common/param_package.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/common/param_package.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <initializer_list> | ||||||
|  | #include <string> | ||||||
|  | #include <unordered_map> | ||||||
|  | 
 | ||||||
|  | namespace Common { | ||||||
|  | 
 | ||||||
|  | /// A string-based key-value container supporting serializing to and deserializing from a string
 | ||||||
|  | class ParamPackage { | ||||||
|  | public: | ||||||
|  |     using DataType = std::unordered_map<std::string, std::string>; | ||||||
|  | 
 | ||||||
|  |     ParamPackage() = default; | ||||||
|  |     explicit ParamPackage(const std::string& serialized); | ||||||
|  |     ParamPackage(std::initializer_list<DataType::value_type> list); | ||||||
|  |     ParamPackage(const ParamPackage& other) = default; | ||||||
|  |     ParamPackage(ParamPackage&& other) = default; | ||||||
|  | 
 | ||||||
|  |     ParamPackage& operator=(const ParamPackage& other) = default; | ||||||
|  |     ParamPackage& operator=(ParamPackage&& other) = default; | ||||||
|  | 
 | ||||||
|  |     std::string Serialize() const; | ||||||
|  |     std::string Get(const std::string& key, const std::string& default_value) const; | ||||||
|  |     int Get(const std::string& key, int default_value) const; | ||||||
|  |     float Get(const std::string& key, float default_value) const; | ||||||
|  |     void Set(const std::string& key, const std::string& value); | ||||||
|  |     void Set(const std::string& key, int value); | ||||||
|  |     void Set(const std::string& key, float value); | ||||||
|  |     bool Has(const std::string& key) const; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     DataType data; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace Common
 | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| set(SRCS | set(SRCS | ||||||
|             glad.cpp |             glad.cpp | ||||||
|             tests.cpp |             tests.cpp | ||||||
|  |             common/param_package.cpp | ||||||
|             core/file_sys/path_parser.cpp |             core/file_sys/path_parser.cpp | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										25
									
								
								src/tests/common/param_package.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/tests/common/param_package.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <catch.hpp> | ||||||
|  | #include <math.h> | ||||||
|  | #include "common/param_package.h" | ||||||
|  | 
 | ||||||
|  | namespace Common { | ||||||
|  | 
 | ||||||
|  | TEST_CASE("ParamPackage", "[common]") { | ||||||
|  |     ParamPackage original{ | ||||||
|  |         {"abc", "xyz"}, {"def", "42"}, {"jkl", "$$:1:$2$,3"}, | ||||||
|  |     }; | ||||||
|  |     original.Set("ghi", 3.14f); | ||||||
|  |     ParamPackage copy(original.Serialize()); | ||||||
|  |     REQUIRE(copy.Get("abc", "") == "xyz"); | ||||||
|  |     REQUIRE(copy.Get("def", 0) == 42); | ||||||
|  |     REQUIRE(std::abs(copy.Get("ghi", 0.0f) - 3.14f) < 0.01f); | ||||||
|  |     REQUIRE(copy.Get("jkl", "") == "$$:1:$2$,3"); | ||||||
|  |     REQUIRE(copy.Get("mno", "uvw") == "uvw"); | ||||||
|  |     REQUIRE(copy.Get("abc", 42) == 42); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Common
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue