[XAM] Fixed issue with Content not being close due to upper-lower characters difference.
- Added string_key_insensitive
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
#ifndef XENIA_BASE_STRING_KEY_H_
|
#ifndef XENIA_BASE_STRING_KEY_H_
|
||||||
#define XENIA_BASE_STRING_KEY_H_
|
#define XENIA_BASE_STRING_KEY_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
@@ -58,6 +59,41 @@ struct string_key : internal::string_key_base {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct string_key_insensitive : internal::string_key_base {
|
||||||
|
public:
|
||||||
|
explicit string_key_insensitive(const std::string_view value)
|
||||||
|
: string_key_base(value) {}
|
||||||
|
explicit string_key_insensitive(std::string value) : string_key_base(value) {}
|
||||||
|
|
||||||
|
static string_key_insensitive create(const std::string_view value) {
|
||||||
|
return string_key_insensitive(std::string(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static string_key_insensitive create(std::string value) {
|
||||||
|
return string_key_insensitive(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const string_key_insensitive& other) const {
|
||||||
|
return other.view().size() == view().size() &&
|
||||||
|
std::ranges::equal(
|
||||||
|
other.view(), view(), {},
|
||||||
|
[](char ch) {
|
||||||
|
return std::tolower(static_cast<unsigned char>(ch));
|
||||||
|
},
|
||||||
|
[](char ch) {
|
||||||
|
return std::tolower(static_cast<unsigned char>(ch));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hash() const { return utf8::hash_fnv1a(view()); }
|
||||||
|
|
||||||
|
struct Hash {
|
||||||
|
size_t operator()(const string_key_insensitive& t) const {
|
||||||
|
return t.hash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct string_key_case : internal::string_key_base {
|
struct string_key_case : internal::string_key_base {
|
||||||
public:
|
public:
|
||||||
explicit string_key_case(const std::string_view value)
|
explicit string_key_case(const std::string_view value)
|
||||||
@@ -91,6 +127,13 @@ struct hash<xe::string_key> {
|
|||||||
std::size_t operator()(const xe::string_key& t) const { return t.hash(); }
|
std::size_t operator()(const xe::string_key& t) const { return t.hash(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<xe::string_key_insensitive> {
|
||||||
|
std::size_t operator()(const xe::string_key_insensitive& t) const {
|
||||||
|
return t.hash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct hash<xe::string_key_case> {
|
struct hash<xe::string_key_case> {
|
||||||
std::size_t operator()(const xe::string_key_case& t) const {
|
std::size_t operator()(const xe::string_key_case& t) const {
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ X_RESULT ContentManager::CreateContent(const std::string_view root_name,
|
|||||||
const XCONTENT_AGGREGATE_DATA& data) {
|
const XCONTENT_AGGREGATE_DATA& data) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
if (open_packages_.count(string_key(root_name))) {
|
if (open_packages_.count(string_key_insensitive(root_name))) {
|
||||||
// Already content open with this root name.
|
// Already content open with this root name.
|
||||||
return X_ERROR_ALREADY_EXISTS;
|
return X_ERROR_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,8 @@ X_RESULT ContentManager::CreateContent(const std::string_view root_name,
|
|||||||
auto package = ResolvePackage(root_name, xuid, data);
|
auto package = ResolvePackage(root_name, xuid, data);
|
||||||
assert_not_null(package);
|
assert_not_null(package);
|
||||||
|
|
||||||
open_packages_.insert({string_key::create(root_name), package.release()});
|
open_packages_.insert(
|
||||||
|
{string_key_insensitive::create(root_name), package.release()});
|
||||||
|
|
||||||
return X_ERROR_SUCCESS;
|
return X_ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -396,7 +397,7 @@ X_RESULT ContentManager::OpenContent(const std::string_view root_name,
|
|||||||
const uint32_t disc_number) {
|
const uint32_t disc_number) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
if (open_packages_.count(string_key(root_name))) {
|
if (open_packages_.count(string_key_insensitive(root_name))) {
|
||||||
// Already content open with this root name.
|
// Already content open with this root name.
|
||||||
return X_ERROR_ALREADY_EXISTS;
|
return X_ERROR_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
@@ -425,7 +426,8 @@ X_RESULT ContentManager::OpenContent(const std::string_view root_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open_packages_.insert({string_key::create(root_name), package.release()});
|
open_packages_.insert(
|
||||||
|
{string_key_insensitive::create(root_name), package.release()});
|
||||||
|
|
||||||
return X_ERROR_SUCCESS;
|
return X_ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -433,7 +435,9 @@ X_RESULT ContentManager::OpenContent(const std::string_view root_name,
|
|||||||
X_RESULT ContentManager::CloseContent(const std::string_view root_name) {
|
X_RESULT ContentManager::CloseContent(const std::string_view root_name) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
auto it = open_packages_.find(string_key(root_name));
|
// 415607D6 - Uses XamContentCreate with name "save", but XamContentClose with
|
||||||
|
// "SAVE".
|
||||||
|
auto it = open_packages_.find(string_key_insensitive(root_name));
|
||||||
if (it == open_packages_.end()) {
|
if (it == open_packages_.end()) {
|
||||||
return X_ERROR_FILE_NOT_FOUND;
|
return X_ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@@ -509,10 +513,11 @@ std::filesystem::path ContentManager::ResolveGameUserContentPath(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ContentManager::IsContentOpen(const XCONTENT_AGGREGATE_DATA& data) const {
|
bool ContentManager::IsContentOpen(const XCONTENT_AGGREGATE_DATA& data) const {
|
||||||
return std::any_of(open_packages_.cbegin(), open_packages_.cend(),
|
return std::any_of(
|
||||||
[data](std::pair<string_key, ContentPackage*> content) {
|
open_packages_.cbegin(), open_packages_.cend(),
|
||||||
return data == content.second->GetPackageContentData();
|
[data](std::pair<string_key_insensitive, ContentPackage*> content) {
|
||||||
});
|
return data == content.second->GetPackageContentData();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentManager::CloseOpenedFilesFromContent(
|
void ContentManager::CloseOpenedFilesFromContent(
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class ContentManager {
|
|||||||
|
|
||||||
// TODO(benvanik): remove use of global lock, it's bad here!
|
// TODO(benvanik): remove use of global lock, it's bad here!
|
||||||
xe::global_critical_region global_critical_region_;
|
xe::global_critical_region global_critical_region_;
|
||||||
std::unordered_map<string_key, ContentPackage*> open_packages_;
|
std::unordered_map<string_key_insensitive, ContentPackage*> open_packages_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xam
|
} // namespace xam
|
||||||
|
|||||||
Reference in New Issue
Block a user