Path: Use string_view more to avoid allocations

This commit is contained in:
Henrik Rydgård 2023-11-13 23:24:42 +01:00
parent 70c7bb3b0d
commit d0ee5fc308
8 changed files with 39 additions and 36 deletions

View file

@ -1,12 +1,12 @@
#include "Common/File/AndroidContentURI.h"
bool AndroidContentURI::Parse(const std::string &path) {
bool AndroidContentURI::Parse(std::string_view path) {
const char *prefix = "content://";
if (!startsWith(path, prefix)) {
return false;
}
std::string components = path.substr(strlen(prefix));
std::string_view components = path.substr(strlen(prefix));
std::vector<std::string> parts;
SplitString(components, '/', parts);
@ -60,7 +60,7 @@ AndroidContentURI AndroidContentURI::WithRootFilePath(const std::string &filePat
return uri;
}
AndroidContentURI AndroidContentURI::WithComponent(const std::string &filePath) {
AndroidContentURI AndroidContentURI::WithComponent(std::string_view filePath) {
AndroidContentURI uri = *this;
if (uri.file.empty()) {
// Not sure what to do.
@ -68,16 +68,17 @@ AndroidContentURI AndroidContentURI::WithComponent(const std::string &filePath)
}
if (uri.file.back() == ':') {
// Special case handling for Document URIs: Treat the ':' as a directory separator too (but preserved in the filename).
uri.file = uri.file + filePath;
uri.file.append(filePath);
} else {
uri.file = uri.file + "/" + filePath;
uri.file.push_back('/');
uri.file.append(filePath);
}
return uri;
}
AndroidContentURI AndroidContentURI::WithExtraExtension(const std::string &extension) {
AndroidContentURI AndroidContentURI::WithExtraExtension(std::string_view extension) {
AndroidContentURI uri = *this;
uri.file = uri.file + extension;
uri.file.append(extension);
return uri;
}

View file

@ -23,15 +23,15 @@ private:
std::string file;
public:
AndroidContentURI() {}
explicit AndroidContentURI(const std::string &path) {
explicit AndroidContentURI(std::string_view path) {
Parse(path);
}
bool Parse(const std::string &path);
bool Parse(std::string_view path);
AndroidContentURI WithRootFilePath(const std::string &filePath);
AndroidContentURI WithComponent(const std::string &filePath);
AndroidContentURI WithExtraExtension(const std::string &extension);
AndroidContentURI WithComponent(std::string_view filePath);
AndroidContentURI WithExtraExtension(std::string_view extension); // The ext string contains the dot.
AndroidContentURI WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
AndroidContentURI WithReplacedExtension(const std::string &newExtension) const;

View file

@ -61,16 +61,16 @@ void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj) {
_dbg_assert_(computeRecursiveDirectorySize);
}
bool Android_IsContentUri(const std::string &filename) {
bool Android_IsContentUri(std::string_view filename) {
return startsWith(filename, "content://");
}
int Android_OpenContentUriFd(const std::string &filename, Android_OpenContentUriMode mode) {
int Android_OpenContentUriFd(std::string_view filename, Android_OpenContentUriMode mode) {
if (!g_nativeActivity) {
return -1;
}
std::string fname = filename;
std::string fname(filename);
// PPSSPP adds an ending slash to directories before looking them up.
// TODO: Fix that in the caller (or don't call this for directories).
if (fname.back() == '/')

View file

@ -2,6 +2,7 @@
#include <vector>
#include <string>
#include <string_view>
#include "Common/File/DirListing.h"
@ -39,8 +40,8 @@ extern std::string g_externalDir;
void Android_StorageSetNativeActivity(jobject nativeActivity);
bool Android_IsContentUri(const std::string &uri);
int Android_OpenContentUriFd(const std::string &uri, const Android_OpenContentUriMode mode);
bool Android_IsContentUri(std::string_view uri);
int Android_OpenContentUriFd(std::string_view uri, const Android_OpenContentUriMode mode);
StorageError Android_CreateDirectory(const std::string &parentTreeUri, const std::string &dirName);
StorageError Android_CreateFile(const std::string &parentTreeUri, const std::string &fileName);
StorageError Android_MoveFile(const std::string &fileUri, const std::string &srcParentUri, const std::string &destParentUri);
@ -63,8 +64,8 @@ void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj);
// Stub out the Android Storage wrappers, so that we can avoid ifdefs everywhere.
inline bool Android_IsContentUri(const std::string &uri) { return false; }
inline int Android_OpenContentUriFd(const std::string &uri, const Android_OpenContentUriMode mode) { return -1; }
inline bool Android_IsContentUri(std::string_view uri) { return false; }
inline int Android_OpenContentUriFd(std::string_view uri, const Android_OpenContentUriMode mode) { return -1; }
inline StorageError Android_CreateDirectory(const std::string &parentTreeUri, const std::string &dirName) { return StorageError::UNKNOWN; }
inline StorageError Android_CreateFile(const std::string &parentTreeUri, const std::string &fileName) { return StorageError::UNKNOWN; }
inline StorageError Android_MoveFile(const std::string &fileUri, const std::string &srcParentUri, const std::string &destParentUri) { return StorageError::UNKNOWN; }

View file

@ -22,7 +22,7 @@
#include <sys/stat.h>
#endif
Path::Path(const std::string &str) {
Path::Path(std::string_view str) {
Init(str);
}
@ -33,7 +33,7 @@ Path::Path(const std::wstring &str) {
}
#endif
void Path::Init(const std::string &str) {
void Path::Init(std::string_view str) {
if (str.empty()) {
type_ = PathType::UNDEFINED;
path_.clear();
@ -81,7 +81,7 @@ void Path::Init(const std::string &str) {
// We always use forward slashes internally, we convert to backslash only when
// converted to a wstring.
Path Path::operator /(const std::string &subdir) const {
Path Path::operator /(std::string_view subdir) const {
if (type_ == PathType::CONTENT_URI) {
AndroidContentURI uri(path_);
return Path(uri.WithComponent(subdir).ToString());
@ -104,18 +104,18 @@ Path Path::operator /(const std::string &subdir) const {
return Path(fullPath);
}
void Path::operator /=(const std::string &subdir) {
void Path::operator /=(std::string_view subdir) {
*this = *this / subdir;
}
Path Path::WithExtraExtension(const std::string &ext) const {
Path Path::WithExtraExtension(std::string_view ext) const {
if (type_ == PathType::CONTENT_URI) {
AndroidContentURI uri(path_);
return Path(uri.WithExtraExtension(ext).ToString());
}
_dbg_assert_(!ext.empty() && ext[0] == '.');
return Path(path_ + ext);
return Path(path_ + std::string(ext));
}
Path Path::WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const {
@ -161,7 +161,7 @@ std::string Path::GetFilename() const {
return path_;
}
std::string GetExtFromString(const std::string &str) {
std::string GetExtFromString(std::string_view str) {
size_t pos = str.rfind(".");
if (pos == std::string::npos) {
return "";
@ -171,7 +171,7 @@ std::string GetExtFromString(const std::string &str) {
// Don't want to detect "df/file" from "/as.df/file"
return "";
}
std::string ext = str.substr(pos);
std::string ext(str.substr(pos));
for (size_t i = 0; i < ext.size(); i++) {
ext[i] = tolower(ext[i]);
}

View file

@ -3,6 +3,7 @@
#include "ppsspp_config.h"
#include <string>
#include <string_view>
#if defined(__APPLE__)
@ -36,11 +37,11 @@ enum class PathType {
class Path {
private:
void Init(const std::string &str);
void Init(std::string_view str);
public:
Path() : type_(PathType::UNDEFINED) {}
explicit Path(const std::string &str);
explicit Path(std::string_view str);
#if PPSSPP_PLATFORM(WINDOWS)
explicit Path(const std::wstring &str);
@ -71,13 +72,13 @@ public:
bool IsAbsolute() const;
// Returns a path extended with a subdirectory.
Path operator /(const std::string &subdir) const;
Path operator /(std::string_view subdir) const;
// Navigates down into a subdir.
void operator /=(const std::string &subdir);
void operator /=(std::string_view subdir);
// File extension manipulation.
Path WithExtraExtension(const std::string &ext) const;
Path WithExtraExtension(std::string_view ext) const;
Path WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const;
Path WithReplacedExtension(const std::string &newExtension) const;
@ -139,7 +140,7 @@ private:
};
// Utility function for parsing out file extensions.
std::string GetExtFromString(const std::string &str);
std::string GetExtFromString(std::string_view str);
// Utility function for fixing the case of paths. Only present on Unix-like systems.

View file

@ -284,8 +284,7 @@ std::string_view StripQuotes(std::string_view s) {
return s;
}
void SplitString(const std::string& str, const char delim, std::vector<std::string>& output)
{
void SplitString(std::string_view str, const char delim, std::vector<std::string> &output) {
size_t next = 0;
for (size_t pos = 0, len = str.length(); pos < len; ++pos) {
if (str[pos] == delim) {
@ -296,7 +295,7 @@ void SplitString(const std::string& str, const char delim, std::vector<std::stri
}
if (next == 0) {
output.push_back(str);
output.push_back(std::string(str));
} else if (next < str.length()) {
output.emplace_back(str.substr(next));
}

View file

@ -81,7 +81,8 @@ std::string StripQuotes(const std::string &s);
std::string_view StripSpaces(std::string_view s);
std::string_view StripQuotes(std::string_view s);
void SplitString(const std::string& str, const char delim, std::vector<std::string>& output);
// TODO: Make this a lot more efficient by outputting string_views.
void SplitString(std::string_view str, const char delim, std::vector<std::string>& output);
void GetQuotedStrings(const std::string& str, std::vector<std::string>& output);