mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
AndroidContentURI: Move code from the header to cpp. Some assorted cleanup, add a unit test for Download paths
This commit is contained in:
1 parent
acea6deb00
commit
cf9a628a2e
21 files changed
+317
-256
No files matched your search
@@ -0,0 +1,182 @@
|
||||
#include "Common/File/AndroidContentURI.h"
|
||||
|
||||
bool AndroidContentURI::Parse(const std::string &path) {
|
||||
const char *prefix = "content://";
|
||||
if (!startsWith(path, prefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string components = path.substr(strlen(prefix));
|
||||
|
||||
std::vector<std::string> parts;
|
||||
SplitString(components, '/', parts);
|
||||
if (parts.size() == 3) {
|
||||
// Single file URI.
|
||||
provider = parts[0];
|
||||
if (parts[1] == "tree") {
|
||||
// Single directory URI.
|
||||
// Not sure when we encounter these?
|
||||
// file empty signals this type.
|
||||
root = UriDecode(parts[2]);
|
||||
return true;
|
||||
} else if (parts[1] == "document") {
|
||||
// root empty signals this type.
|
||||
file = UriDecode(parts[2]);
|
||||
return true;
|
||||
} else {
|
||||
// What's this?
|
||||
return false;
|
||||
}
|
||||
} else if (parts.size() == 5) {
|
||||
// Tree URI
|
||||
provider = parts[0];
|
||||
if (parts[1] != "tree") {
|
||||
return false;
|
||||
}
|
||||
root = UriDecode(parts[2]);
|
||||
if (parts[3] != "document") {
|
||||
return false;
|
||||
}
|
||||
file = UriDecode(parts[4]);
|
||||
// Sanity check file path.
|
||||
return startsWith(file, root);
|
||||
} else {
|
||||
// Invalid Content URI
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithRootFilePath(const std::string &filePath) {
|
||||
if (root.empty()) {
|
||||
ERROR_LOG(SYSTEM, "WithRootFilePath cannot be used with single file URIs.");
|
||||
return *this;
|
||||
}
|
||||
|
||||
AndroidContentURI uri = *this;
|
||||
uri.file = uri.root;
|
||||
if (!filePath.empty()) {
|
||||
uri.file += "/" + filePath;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithComponent(const std::string &filePath) {
|
||||
AndroidContentURI uri = *this;
|
||||
uri.file = uri.file + "/" + filePath;
|
||||
return uri;
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithExtraExtension(const std::string &extension) {
|
||||
AndroidContentURI uri = *this;
|
||||
uri.file = uri.file + extension;
|
||||
return uri;
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const {
|
||||
_dbg_assert_(!oldExtension.empty() && oldExtension[0] == '.');
|
||||
_dbg_assert_(!newExtension.empty() && newExtension[0] == '.');
|
||||
AndroidContentURI uri = *this;
|
||||
if (endsWithNoCase(file, oldExtension)) {
|
||||
uri.file = file.substr(0, file.size() - oldExtension.size()) + newExtension;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
AndroidContentURI AndroidContentURI::WithReplacedExtension(const std::string &newExtension) const {
|
||||
_dbg_assert_(!newExtension.empty() && newExtension[0] == '.');
|
||||
AndroidContentURI uri = *this;
|
||||
if (file.empty()) {
|
||||
return uri;
|
||||
}
|
||||
std::string extension = GetFileExtension();
|
||||
uri.file = file.substr(0, file.size() - extension.size()) + newExtension;
|
||||
return uri;
|
||||
}
|
||||
|
||||
bool AndroidContentURI::CanNavigateUp() const {
|
||||
if (root.empty()) {
|
||||
return false;
|
||||
}
|
||||
return file.size() > root.size();
|
||||
}
|
||||
|
||||
// Only goes downwards in hierarchies. No ".." will ever be generated.
|
||||
bool AndroidContentURI::ComputePathTo(const AndroidContentURI &other, std::string &path) const {
|
||||
size_t offset = FilePath().size() + 1;
|
||||
std::string otherFilePath = other.FilePath();
|
||||
if (offset >= otherFilePath.size()) {
|
||||
ERROR_LOG(SYSTEM, "Bad call to PathTo. '%s' -> '%s'", FilePath().c_str(), other.FilePath().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
path = other.FilePath().substr(FilePath().size() + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string AndroidContentURI::GetFileExtension() const {
|
||||
size_t pos = file.rfind(".");
|
||||
if (pos == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
size_t slash_pos = file.rfind("/");
|
||||
if (slash_pos != std::string::npos && slash_pos > pos) {
|
||||
// Don't want to detect "df/file" from "/as.df/file"
|
||||
return "";
|
||||
}
|
||||
std::string ext = file.substr(pos);
|
||||
for (size_t i = 0; i < ext.size(); i++) {
|
||||
ext[i] = tolower(ext[i]);
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
std::string AndroidContentURI::GetLastPart() const {
|
||||
if (file.empty()) {
|
||||
// Can't do anything anyway.
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (!CanNavigateUp()) {
|
||||
size_t colon = file.rfind(':');
|
||||
if (colon == std::string::npos) {
|
||||
return std::string();
|
||||
}
|
||||
return file.substr(colon + 1);
|
||||
}
|
||||
|
||||
size_t slash = file.rfind('/');
|
||||
if (slash == std::string::npos) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string part = file.substr(slash + 1);
|
||||
return part;
|
||||
}
|
||||
|
||||
bool AndroidContentURI::NavigateUp() {
|
||||
if (!CanNavigateUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t slash = file.rfind('/');
|
||||
if (slash == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file = file.substr(0, slash);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string AndroidContentURI::ToString() const {
|
||||
if (file.empty()) {
|
||||
// Tree URI
|
||||
return StringFromFormat("content://%s/tree/%s", provider.c_str(), UriEncode(root).c_str());
|
||||
} else if (root.empty()) {
|
||||
// Single file URI
|
||||
return StringFromFormat("content://%s/document/%s", provider.c_str(), UriEncode(file).c_str());
|
||||
} else {
|
||||
// File URI from Tree
|
||||
return StringFromFormat("content://%s/tree/%s/document/%s", provider.c_str(), UriEncode(root).c_str(), UriEncode(file).c_str());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user