param_package.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright 2017 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include <stdexcept>
  6. #include <utility>
  7. #include <vector>
  8. #include "common/logging/log.h"
  9. #include "common/param_package.h"
  10. #include "common/string_util.h"
  11. namespace Common {
  12. constexpr char KEY_VALUE_SEPARATOR = ':';
  13. constexpr char PARAM_SEPARATOR = ',';
  14. constexpr char ESCAPE_CHARACTER = '$';
  15. constexpr char KEY_VALUE_SEPARATOR_ESCAPE[] = "$0";
  16. constexpr char PARAM_SEPARATOR_ESCAPE[] = "$1";
  17. constexpr char ESCAPE_CHARACTER_ESCAPE[] = "$2";
  18. /// A placeholder for empty param packages to avoid empty strings
  19. /// (they may be recognized as "not set" by some frontend libraries like qt)
  20. constexpr char EMPTY_PLACEHOLDER[] = "[empty]";
  21. ParamPackage::ParamPackage(const std::string& serialized) {
  22. if (serialized == EMPTY_PLACEHOLDER) {
  23. return;
  24. }
  25. std::vector<std::string> pairs;
  26. Common::SplitString(serialized, PARAM_SEPARATOR, pairs);
  27. for (const std::string& pair : pairs) {
  28. std::vector<std::string> key_value;
  29. Common::SplitString(pair, KEY_VALUE_SEPARATOR, key_value);
  30. if (key_value.size() != 2) {
  31. LOG_ERROR(Common, "invalid key pair {}", pair);
  32. continue;
  33. }
  34. for (std::string& part : key_value) {
  35. part = Common::ReplaceAll(part, KEY_VALUE_SEPARATOR_ESCAPE, {KEY_VALUE_SEPARATOR});
  36. part = Common::ReplaceAll(part, PARAM_SEPARATOR_ESCAPE, {PARAM_SEPARATOR});
  37. part = Common::ReplaceAll(part, ESCAPE_CHARACTER_ESCAPE, {ESCAPE_CHARACTER});
  38. }
  39. Set(key_value[0], std::move(key_value[1]));
  40. }
  41. }
  42. ParamPackage::ParamPackage(std::initializer_list<DataType::value_type> list) : data(list) {}
  43. std::string ParamPackage::Serialize() const {
  44. if (data.empty())
  45. return EMPTY_PLACEHOLDER;
  46. std::string result;
  47. for (const auto& pair : data) {
  48. std::array<std::string, 2> key_value{{pair.first, pair.second}};
  49. for (std::string& part : key_value) {
  50. part = Common::ReplaceAll(part, {ESCAPE_CHARACTER}, ESCAPE_CHARACTER_ESCAPE);
  51. part = Common::ReplaceAll(part, {PARAM_SEPARATOR}, PARAM_SEPARATOR_ESCAPE);
  52. part = Common::ReplaceAll(part, {KEY_VALUE_SEPARATOR}, KEY_VALUE_SEPARATOR_ESCAPE);
  53. }
  54. result += key_value[0] + KEY_VALUE_SEPARATOR + key_value[1] + PARAM_SEPARATOR;
  55. }
  56. result.pop_back(); // discard the trailing PARAM_SEPARATOR
  57. return result;
  58. }
  59. std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const {
  60. auto pair = data.find(key);
  61. if (pair == data.end()) {
  62. LOG_DEBUG(Common, "key '{}' not found", key);
  63. return default_value;
  64. }
  65. return pair->second;
  66. }
  67. int ParamPackage::Get(const std::string& key, int default_value) const {
  68. auto pair = data.find(key);
  69. if (pair == data.end()) {
  70. LOG_DEBUG(Common, "key '{}' not found", key);
  71. return default_value;
  72. }
  73. try {
  74. return std::stoi(pair->second);
  75. } catch (const std::logic_error&) {
  76. LOG_ERROR(Common, "failed to convert {} to int", pair->second);
  77. return default_value;
  78. }
  79. }
  80. float ParamPackage::Get(const std::string& key, float default_value) const {
  81. auto pair = data.find(key);
  82. if (pair == data.end()) {
  83. LOG_DEBUG(Common, "key {} not found", key);
  84. return default_value;
  85. }
  86. try {
  87. return std::stof(pair->second);
  88. } catch (const std::logic_error&) {
  89. LOG_ERROR(Common, "failed to convert {} to float", pair->second);
  90. return default_value;
  91. }
  92. }
  93. void ParamPackage::Set(const std::string& key, std::string value) {
  94. data.insert_or_assign(key, std::move(value));
  95. }
  96. void ParamPackage::Set(const std::string& key, int value) {
  97. data.insert_or_assign(key, std::to_string(value));
  98. }
  99. void ParamPackage::Set(const std::string& key, float value) {
  100. data.insert_or_assign(key, std::to_string(value));
  101. }
  102. bool ParamPackage::Has(const std::string& key) const {
  103. return data.find(key) != data.end();
  104. }
  105. void ParamPackage::Erase(const std::string& key) {
  106. data.erase(key);
  107. }
  108. void ParamPackage::Clear() {
  109. data.clear();
  110. }
  111. } // namespace Common