input_profiles.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <fmt/format.h>
  5. #include "common/common_paths.h"
  6. #include "common/file_util.h"
  7. #include "yuzu/configuration/config.h"
  8. #include "yuzu/configuration/input_profiles.h"
  9. namespace FS = Common::FS;
  10. namespace {
  11. bool ProfileExistsInFilesystem(std::string_view profile_name) {
  12. return FS::Exists(fmt::format("{}input" DIR_SEP "{}.ini",
  13. FS::GetUserPath(FS::UserPath::ConfigDir), profile_name));
  14. }
  15. bool IsINI(std::string_view filename) {
  16. const std::size_t index = filename.rfind('.');
  17. if (index == std::string::npos) {
  18. return false;
  19. }
  20. return filename.substr(index) == ".ini";
  21. }
  22. std::string GetNameWithoutExtension(const std::string& filename) {
  23. const std::size_t index = filename.rfind('.');
  24. if (index == std::string::npos) {
  25. return filename;
  26. }
  27. return filename.substr(0, index);
  28. }
  29. } // namespace
  30. InputProfiles::InputProfiles() {
  31. const std::string input_profile_loc =
  32. fmt::format("{}input", FS::GetUserPath(FS::UserPath::ConfigDir));
  33. FS::ForeachDirectoryEntry(
  34. nullptr, input_profile_loc,
  35. [this](u64* entries_out, const std::string& directory, const std::string& filename) {
  36. if (IsINI(filename) && IsProfileNameValid(GetNameWithoutExtension(filename))) {
  37. map_profiles.insert_or_assign(
  38. GetNameWithoutExtension(filename),
  39. std::make_unique<Config>(GetNameWithoutExtension(filename),
  40. Config::ConfigType::InputProfile));
  41. }
  42. return true;
  43. });
  44. }
  45. InputProfiles::~InputProfiles() = default;
  46. std::vector<std::string> InputProfiles::GetInputProfileNames() {
  47. std::vector<std::string> profile_names;
  48. profile_names.reserve(map_profiles.size());
  49. for (const auto& [profile_name, config] : map_profiles) {
  50. if (!ProfileExistsInFilesystem(profile_name)) {
  51. DeleteProfile(profile_name);
  52. continue;
  53. }
  54. profile_names.push_back(profile_name);
  55. }
  56. return profile_names;
  57. }
  58. bool InputProfiles::IsProfileNameValid(std::string_view profile_name) {
  59. return profile_name.find_first_of("<>:;\"/\\|,.!?*") == std::string::npos;
  60. }
  61. bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t player_index) {
  62. if (ProfileExistsInMap(profile_name)) {
  63. return false;
  64. }
  65. map_profiles.insert_or_assign(
  66. profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile));
  67. return SaveProfile(profile_name, player_index);
  68. }
  69. bool InputProfiles::DeleteProfile(const std::string& profile_name) {
  70. if (!ProfileExistsInMap(profile_name)) {
  71. return false;
  72. }
  73. if (!ProfileExistsInFilesystem(profile_name) ||
  74. FS::Delete(map_profiles[profile_name]->GetConfigFilePath())) {
  75. map_profiles.erase(profile_name);
  76. }
  77. return !ProfileExistsInMap(profile_name) && !ProfileExistsInFilesystem(profile_name);
  78. }
  79. bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t player_index) {
  80. if (!ProfileExistsInMap(profile_name)) {
  81. return false;
  82. }
  83. if (!ProfileExistsInFilesystem(profile_name)) {
  84. map_profiles.erase(profile_name);
  85. return false;
  86. }
  87. map_profiles[profile_name]->ReadControlPlayerValue(player_index);
  88. return true;
  89. }
  90. bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t player_index) {
  91. if (!ProfileExistsInMap(profile_name)) {
  92. return false;
  93. }
  94. map_profiles[profile_name]->SaveControlPlayerValue(player_index);
  95. return true;
  96. }
  97. bool InputProfiles::ProfileExistsInMap(const std::string& profile_name) const {
  98. return map_profiles.find(profile_name) != map_profiles.end();
  99. }