Revert "Drop all path-related methods from android::String8"
This reverts commit b9dc1c2991de9ca87bdbf00c413b7f2bb4477fe2.
Reason for revert: http://b/299624573
Change-Id: I0d5993295df65ec31c180b6b5a76fbe939891f45
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index a2cfc08..2b72847 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -430,6 +430,31 @@
// ---------------------------------------------------------------------------
// Path functions
+static void setPathName(String8& s, const char* name) {
+ size_t len = strlen(name);
+ char* buf = s.lockBuffer(len);
+
+ memcpy(buf, name, len);
+
+ // remove trailing path separator, if present
+ if (len > 0 && buf[len - 1] == OS_PATH_SEPARATOR) len--;
+ buf[len] = '\0';
+
+ s.unlockBuffer(len);
+}
+
+String8 String8::getPathLeaf(void) const
+{
+ const char* cp;
+ const char*const buf = mString;
+
+ cp = strrchr(buf, OS_PATH_SEPARATOR);
+ if (cp == nullptr)
+ return String8(*this);
+ else
+ return String8(cp+1);
+}
+
String8 String8::getPathDir(void) const
{
const char* cp;
@@ -442,4 +467,115 @@
return String8(str, cp - str);
}
+String8 String8::walkPath(String8* outRemains) const
+{
+ const char* cp;
+ const char*const str = mString;
+ const char* buf = str;
+
+ cp = strchr(buf, OS_PATH_SEPARATOR);
+ if (cp == buf) {
+ // don't include a leading '/'.
+ buf = buf+1;
+ cp = strchr(buf, OS_PATH_SEPARATOR);
+ }
+
+ if (cp == nullptr) {
+ String8 res = buf != str ? String8(buf) : *this;
+ if (outRemains) *outRemains = String8("");
+ return res;
+ }
+
+ String8 res(buf, cp-buf);
+ if (outRemains) *outRemains = String8(cp+1);
+ return res;
+}
+
+/*
+ * Helper function for finding the start of an extension in a pathname.
+ *
+ * Returns a pointer inside mString, or NULL if no extension was found.
+ */
+char* String8::find_extension(void) const
+{
+ const char* lastSlash;
+ const char* lastDot;
+ const char* const str = mString;
+
+ // only look at the filename
+ lastSlash = strrchr(str, OS_PATH_SEPARATOR);
+ if (lastSlash == nullptr)
+ lastSlash = str;
+ else
+ lastSlash++;
+
+ // find the last dot
+ lastDot = strrchr(lastSlash, '.');
+ if (lastDot == nullptr)
+ return nullptr;
+
+ // looks good, ship it
+ return const_cast<char*>(lastDot);
+}
+
+String8 String8::getPathExtension(void) const
+{
+ char* ext;
+
+ ext = find_extension();
+ if (ext != nullptr)
+ return String8(ext);
+ else
+ return String8("");
+}
+
+String8 String8::getBasePath(void) const
+{
+ char* ext;
+ const char* const str = mString;
+
+ ext = find_extension();
+ if (ext == nullptr)
+ return String8(*this);
+ else
+ return String8(str, ext - str);
+}
+
+String8& String8::appendPath(const char* name)
+{
+ // TODO: The test below will fail for Win32 paths. Fix later or ignore.
+ if (name[0] != OS_PATH_SEPARATOR) {
+ if (*name == '\0') {
+ // nothing to do
+ return *this;
+ }
+
+ size_t len = length();
+ if (len == 0) {
+ // no existing filename, just use the new one
+ setPathName(*this, name);
+ return *this;
+ }
+
+ // make room for oldPath + '/' + newPath
+ int newlen = strlen(name);
+
+ char* buf = lockBuffer(len+1+newlen);
+
+ // insert a '/' if needed
+ if (buf[len-1] != OS_PATH_SEPARATOR)
+ buf[len++] = OS_PATH_SEPARATOR;
+
+ memcpy(buf+len, name, newlen+1);
+ len += newlen;
+
+ unlockBuffer(len);
+
+ return *this;
+ } else {
+ setPathName(*this, name);
+ return *this;
+ }
+}
+
}; // namespace android
diff --git a/libutils/String8_fuzz.cpp b/libutils/String8_fuzz.cpp
index cbce050..6f7a54f 100644
--- a/libutils/String8_fuzz.cpp
+++ b/libutils/String8_fuzz.cpp
@@ -68,6 +68,30 @@
int start_index = dataProvider->ConsumeIntegralInRange<int>(0, str1->size());
str1->find(str2->c_str(), start_index);
},
+
+ // Path handling
+ [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+ str1->getBasePath();
+ },
+ [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+ str1->getPathExtension();
+ },
+ [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+ str1->getPathLeaf();
+ },
+ [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+ str1->getPathDir();
+ },
+ [](FuzzedDataProvider*, android::String8* str1, android::String8*) -> void {
+ std::shared_ptr<android::String8> path_out_str =
+ std::make_shared<android::String8>();
+ str1->walkPath(path_out_str.get());
+ path_out_str->clear();
+ },
+ [](FuzzedDataProvider* dataProvider, android::String8* str1,
+ android::String8*) -> void {
+ str1->appendPath(dataProvider->ConsumeBytesWithTerminator<char>(5).data());
+ },
};
void fuzzFormat(FuzzedDataProvider* dataProvider, android::String8* str1, bool shouldAppend) {
diff --git a/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump b/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump
index 55e1e27..46badde 100644
--- a/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump
+++ b/libutils/abi-dumps/arm64/source-based/libutils.so.lsdump
@@ -704,6 +704,9 @@
"name" : "_ZN7android7RefBaseD2Ev"
},
{
+ "name" : "_ZN7android7String810appendPathEPKc"
+ },
+ {
"name" : "_ZN7android7String810lockBufferEm"
},
{
@@ -1142,12 +1145,27 @@
"name" : "_ZNK7android7String810getPathDirEv"
},
{
+ "name" : "_ZNK7android7String811getBasePathEv"
+ },
+ {
+ "name" : "_ZNK7android7String811getPathLeafEv"
+ },
+ {
+ "name" : "_ZNK7android7String814find_extensionEv"
+ },
+ {
+ "name" : "_ZNK7android7String816getPathExtensionEv"
+ },
+ {
"name" : "_ZNK7android7String84findEPKcm"
},
{
"name" : "_ZNK7android7String86lengthEv"
},
{
+ "name" : "_ZNK7android7String88walkPathEPS0_"
+ },
+ {
"name" : "_ZNK7android8String1610startsWithEPKDs"
},
{
@@ -6791,6 +6809,22 @@
"source_file" : "system/core/libutils/include/utils/RefBase.h"
},
{
+ "function_name" : "android::String8::appendPath",
+ "linker_set_key" : "_ZN7android7String810appendPathEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
"function_name" : "android::String8::lockBuffer",
"linker_set_key" : "_ZN7android7String810lockBufferEm",
"parameters" :
@@ -9070,7 +9104,6 @@
"source_file" : "system/core/libutils/include/utils/RefBase.h"
},
{
- "access" : "private",
"function_name" : "android::String8::getPathDir",
"linker_set_key" : "_ZNK7android7String810getPathDirEv",
"parameters" :
@@ -9084,6 +9117,59 @@
"source_file" : "system/core/libutils/include/utils/String8.h"
},
{
+ "function_name" : "android::String8::getBasePath",
+ "linker_set_key" : "_ZNK7android7String811getBasePathEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathLeaf",
+ "linker_set_key" : "_ZNK7android7String811getPathLeafEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String8::find_extension",
+ "linker_set_key" : "_ZNK7android7String814find_extensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathExtension",
+ "linker_set_key" : "_ZNK7android7String816getPathExtensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
"function_name" : "android::String8::find",
"linker_set_key" : "_ZNK7android7String84findEPKcm",
"parameters" :
@@ -9117,6 +9203,23 @@
"source_file" : "system/core/libutils/include/utils/String8.h"
},
{
+ "function_name" : "android::String8::walkPath",
+ "linker_set_key" : "_ZNK7android7String88walkPathEPS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
"function_name" : "android::String16::startsWith",
"linker_set_key" : "_ZNK7android8String1610startsWithEPKDs",
"parameters" :
diff --git a/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump b/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump
index c144698..219c766 100644
--- a/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump
+++ b/libutils/abi-dumps/arm_arm64/source-based/libutils.so.lsdump
@@ -704,6 +704,9 @@
"name" : "_ZN7android7RefBaseD2Ev"
},
{
+ "name" : "_ZN7android7String810appendPathEPKc"
+ },
+ {
"name" : "_ZN7android7String810lockBufferEj"
},
{
@@ -1142,12 +1145,27 @@
"name" : "_ZNK7android7String810getPathDirEv"
},
{
+ "name" : "_ZNK7android7String811getBasePathEv"
+ },
+ {
+ "name" : "_ZNK7android7String811getPathLeafEv"
+ },
+ {
+ "name" : "_ZNK7android7String814find_extensionEv"
+ },
+ {
+ "name" : "_ZNK7android7String816getPathExtensionEv"
+ },
+ {
"name" : "_ZNK7android7String84findEPKcj"
},
{
"name" : "_ZNK7android7String86lengthEv"
},
{
+ "name" : "_ZNK7android7String88walkPathEPS0_"
+ },
+ {
"name" : "_ZNK7android8String1610startsWithEPKDs"
},
{
@@ -6787,6 +6805,22 @@
"source_file" : "system/core/libutils/include/utils/RefBase.h"
},
{
+ "function_name" : "android::String8::appendPath",
+ "linker_set_key" : "_ZN7android7String810appendPathEPKc",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ },
+ {
+ "referenced_type" : "_ZTIPKc"
+ }
+ ],
+ "return_type" : "_ZTIRN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
"function_name" : "android::String8::lockBuffer",
"linker_set_key" : "_ZN7android7String810lockBufferEj",
"parameters" :
@@ -9066,7 +9100,6 @@
"source_file" : "system/core/libutils/include/utils/RefBase.h"
},
{
- "access" : "private",
"function_name" : "android::String8::getPathDir",
"linker_set_key" : "_ZNK7android7String810getPathDirEv",
"parameters" :
@@ -9080,6 +9113,59 @@
"source_file" : "system/core/libutils/include/utils/String8.h"
},
{
+ "function_name" : "android::String8::getBasePath",
+ "linker_set_key" : "_ZNK7android7String811getBasePathEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathLeaf",
+ "linker_set_key" : "_ZNK7android7String811getPathLeafEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "access" : "private",
+ "function_name" : "android::String8::find_extension",
+ "linker_set_key" : "_ZNK7android7String814find_extensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIPc",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
+ "function_name" : "android::String8::getPathExtension",
+ "linker_set_key" : "_ZNK7android7String816getPathExtensionEv",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
"function_name" : "android::String8::find",
"linker_set_key" : "_ZNK7android7String84findEPKcj",
"parameters" :
@@ -9113,6 +9199,23 @@
"source_file" : "system/core/libutils/include/utils/String8.h"
},
{
+ "function_name" : "android::String8::walkPath",
+ "linker_set_key" : "_ZNK7android7String88walkPathEPS0_",
+ "parameters" :
+ [
+ {
+ "is_this_ptr" : true,
+ "referenced_type" : "_ZTIPKN7android7String8E"
+ },
+ {
+ "default_arg" : true,
+ "referenced_type" : "_ZTIPN7android7String8E"
+ }
+ ],
+ "return_type" : "_ZTIN7android7String8E",
+ "source_file" : "system/core/libutils/include/utils/String8.h"
+ },
+ {
"function_name" : "android::String16::startsWith",
"linker_set_key" : "_ZNK7android8String1610startsWithEPKDs",
"parameters" :
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index 9cef9f6..ea25c6a 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -130,10 +130,80 @@
void toLower();
-private:
- String8 getPathDir(void) const;
+ /*
+ * These methods operate on the string as if it were a path name.
+ */
+
+ /*
+ * Get just the filename component.
+ *
+ * "/tmp/foo/bar.c" --> "bar.c"
+ */
+ String8 getPathLeaf(void) const;
+
+ /*
+ * Remove the last (file name) component, leaving just the directory
+ * name.
+ *
+ * "/tmp/foo/bar.c" --> "/tmp/foo"
+ * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
+ * "bar.c" --> ""
+ */
+ String8 getPathDir(void) const;
+
+ /*
+ * Retrieve the front (root dir) component. Optionally also return the
+ * remaining components.
+ *
+ * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c")
+ * "/tmp" --> "tmp" (remain = "")
+ * "bar.c" --> "bar.c" (remain = "")
+ */
+ String8 walkPath(String8* outRemains = nullptr) const;
+
+ /*
+ * Return the filename extension. This is the last '.' and any number
+ * of characters that follow it. The '.' is included in case we
+ * decide to expand our definition of what constitutes an extension.
+ *
+ * "/tmp/foo/bar.c" --> ".c"
+ * "/tmp" --> ""
+ * "/tmp/foo.bar/baz" --> ""
+ * "foo.jpeg" --> ".jpeg"
+ * "foo." --> ""
+ */
+ String8 getPathExtension(void) const;
+
+ /*
+ * Return the path without the extension. Rules for what constitutes
+ * an extension are described in the comment for getPathExtension().
+ *
+ * "/tmp/foo/bar.c" --> "/tmp/foo/bar"
+ */
+ String8 getBasePath(void) const;
+
+ /*
+ * Add a component to the pathname. We guarantee that there is
+ * exactly one path separator between the old path and the new.
+ * If there is no existing name, we just copy the new name in.
+ *
+ * If leaf is a fully qualified path (i.e. starts with '/', it
+ * replaces whatever was there before.
+ */
+ String8& appendPath(const char* leaf);
+ String8& appendPath(const String8& leaf) { return appendPath(leaf.c_str()); }
+
+ /*
+ * Like appendPath(), but does not affect this string. Returns a new one instead.
+ */
+ String8 appendPathCopy(const char* leaf) const
+ { String8 p(*this); p.appendPath(leaf); return p; }
+ String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.c_str()); }
+
+private:
status_t real_append(const char* other, size_t numChars);
+ char* find_extension(void) const;
const char* mString;
};