Extract format_string function.
Extract format_string function and add a test.
Test: run linker-unit-tests
Change-Id: I794a29aaf62e184438ce1a9224b88aa0586c17b5
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 6601dc1..fe3a6fb 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -81,29 +81,9 @@
std::string origin = dirname(get_realpath());
// FIXME: add $LIB and $PLATFORM.
- std::pair<std::string, std::string> substs[] = {{"ORIGIN", origin}};
+ std::vector<std::pair<std::string, std::string>> params = {{"ORIGIN", origin}};
for (auto&& s : runpaths) {
- size_t pos = 0;
- while (pos < s.size()) {
- pos = s.find("$", pos);
- if (pos == std::string::npos) break;
- for (const auto& subst : substs) {
- const std::string& token = subst.first;
- const std::string& replacement = subst.second;
- if (s.substr(pos + 1, token.size()) == token) {
- s.replace(pos, token.size() + 1, replacement);
- // -1 to compensate for the ++pos below.
- pos += replacement.size() - 1;
- break;
- } else if (s.substr(pos + 1, token.size() + 2) == "{" + token + "}") {
- s.replace(pos, token.size() + 3, replacement);
- pos += replacement.size() - 1;
- break;
- }
- }
- // Skip $ in case it did not match any of the known substitutions.
- ++pos;
- }
+ format_string(&s, params);
}
resolve_paths(runpaths, &dt_runpath_);
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 6df5f6d..5bf88e7 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -36,6 +36,30 @@
#include <sys/stat.h>
#include <unistd.h>
+void format_string(std::string* str, const std::vector<std::pair<std::string, std::string>>& params) {
+ size_t pos = 0;
+ while (pos < str->size()) {
+ pos = str->find("$", pos);
+ if (pos == std::string::npos) break;
+ for (const auto& param : params) {
+ const std::string& token = param.first;
+ const std::string& replacement = param.second;
+ if (str->substr(pos + 1, token.size()) == token) {
+ str->replace(pos, token.size() + 1, replacement);
+ // -1 to compensate for the ++pos below.
+ pos += replacement.size() - 1;
+ break;
+ } else if (str->substr(pos + 1, token.size() + 2) == "{" + token + "}") {
+ str->replace(pos, token.size() + 3, replacement);
+ pos += replacement.size() - 1;
+ break;
+ }
+ }
+ // Skip $ in case it did not match any of the known substitutions.
+ ++pos;
+ }
+}
+
std::string dirname(const char* path) {
const char* last_slash = strrchr(path, '/');
diff --git a/linker/linker_utils.h b/linker/linker_utils.h
index 5881688..740d04b 100644
--- a/linker/linker_utils.h
+++ b/linker/linker_utils.h
@@ -34,6 +34,8 @@
extern const char* const kZipFileSeparator;
+void format_string(std::string* str, const std::vector<std::pair<std::string, std::string>>& params);
+
bool file_is_in_dir(const std::string& file, const std::string& dir);
bool file_is_under_dir(const std::string& file, const std::string& dir);
bool normalize_path(const char* path, std::string* normalized_path);
diff --git a/linker/tests/linker_utils_test.cpp b/linker/tests/linker_utils_test.cpp
index 0cfdf40..dce223a 100644
--- a/linker/tests/linker_utils_test.cpp
+++ b/linker/tests/linker_utils_test.cpp
@@ -34,6 +34,13 @@
#include "../linker_utils.h"
+TEST(linker_utils, format_string) {
+ std::vector<std::pair<std::string, std::string>> params = {{ "LIB", "lib32"}, { "SDKVER", "42"}};
+ std::string str_smoke = "LIB$LIB${LIB${SDKVER}SDKVER$TEST$";
+ format_string(&str_smoke, params);
+ ASSERT_EQ("LIBlib32${LIB42SDKVER$TEST$", str_smoke);
+}
+
TEST(linker_utils, normalize_path_smoke) {
std::string output;
ASSERT_TRUE(normalize_path("/../root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));