[base] Change Dirname/Basename params to string_view
These functions are already implemented in a way that doesn't
rely on a null terminator, and they show up in the app startup
profile, so worth optimizing
Bug: 237583012
Test: build + boot + UTs
Change-Id: I93ff68edbc3f85d81ce93fd3b40c6b13f9c9d1cf
diff --git a/file.cpp b/file.cpp
index f4f3ad4..1bdcbb9 100644
--- a/file.cpp
+++ b/file.cpp
@@ -498,7 +498,7 @@
}
#if defined(_WIN32)
-std::string Basename(const std::string& path) {
+std::string Basename(std::string_view path) {
// TODO: how much of this is actually necessary for mingw?
// Copy path because basename may modify the string passed in.
@@ -524,21 +524,21 @@
}
#else
// Copied from bionic so that Basename() below can be portable and thread-safe.
-static int __basename_r(const char* path, char* buffer, size_t buffer_size) {
+static int _basename_r(const char* path, size_t path_size, char* buffer, size_t buffer_size) {
const char* startp = nullptr;
const char* endp = nullptr;
int len;
int result;
// Empty or NULL string gets treated as ".".
- if (path == nullptr || *path == '\0') {
+ if (path == nullptr || path_size == 0) {
startp = ".";
len = 1;
goto Exit;
}
// Strip trailing slashes.
- endp = path + strlen(path) - 1;
+ endp = path + path_size - 1;
while (endp > path && *endp == '/') {
endp--;
}
@@ -575,15 +575,15 @@
}
return result;
}
-std::string Basename(const std::string& path) {
- char buf[PATH_MAX];
- __basename_r(path.c_str(), buf, sizeof(buf));
- return buf;
+std::string Basename(std::string_view path) {
+ char buf[PATH_MAX] __attribute__((__uninitialized__));
+ const auto size = _basename_r(path.data(), path.size(), buf, sizeof(buf));
+ return size > 0 ? std::string(buf, size) : std::string();
}
#endif
#if defined(_WIN32)
-std::string Dirname(const std::string& path) {
+std::string Dirname(std::string_view path) {
// TODO: how much of this is actually necessary for mingw?
// Copy path because dirname may modify the string passed in.
@@ -609,20 +609,20 @@
}
#else
// Copied from bionic so that Dirname() below can be portable and thread-safe.
-static int __dirname_r(const char* path, char* buffer, size_t buffer_size) {
+static int _dirname_r(const char* path, size_t path_size, char* buffer, size_t buffer_size) {
const char* endp = nullptr;
int len;
int result;
// Empty or NULL string gets treated as ".".
- if (path == nullptr || *path == '\0') {
+ if (path == nullptr || path_size == 0) {
path = ".";
len = 1;
goto Exit;
}
// Strip trailing slashes.
- endp = path + strlen(path) - 1;
+ endp = path + path_size - 1;
while (endp > path && *endp == '/') {
endp--;
}
@@ -667,10 +667,10 @@
}
return result;
}
-std::string Dirname(const std::string& path) {
- char buf[PATH_MAX];
- __dirname_r(path.c_str(), buf, sizeof(buf));
- return buf;
+std::string Dirname(std::string_view path) {
+ char buf[PATH_MAX] __attribute__((__uninitialized__));
+ const auto size = _dirname_r(path.data(), path.size(), buf, sizeof(buf));
+ return size > 0 ? std::string(buf, size) : std::string();
}
#endif
diff --git a/include/android-base/file.h b/include/android-base/file.h
index 23812f1..b11b305 100644
--- a/include/android-base/file.h
+++ b/include/android-base/file.h
@@ -119,8 +119,8 @@
// Like the regular basename and dirname, but thread-safe on all
// platforms and capable of correctly handling exotic Windows paths.
-std::string Basename(const std::string& path);
-std::string Dirname(const std::string& path);
+std::string Basename(std::string_view path);
+std::string Dirname(std::string_view path);
} // namespace base
} // namespace android