joinPaths: support adding the trailing slash
Change-Id: I8bcaf08dd17d331c4922d1242f872961631c7caa
Co-authored-by: Jan Kundrát <jan.kundrat@cesnet.cz>
diff --git a/src/utils.cpp b/src/utils.cpp
index d0e8639..978e0a9 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -11,10 +11,26 @@
std::string joinPaths(const std::string& prefix, const std::string& suffix)
{
- if (prefix.empty() || suffix.empty() || prefix == "/")
- return prefix + suffix;
- else
- return prefix + '/' + suffix;
+ // These two if statements are essential for the algorithm:
+ // The first one solves joining nothing and a relative path - the algorithm
+ // down below adds a leading slash, turning it into an absolute path.
+ // The second one would always add a trailing slash to the path.
+ if (prefix.empty()) {
+ return suffix;
+ }
+
+ if (suffix.empty()) {
+ return prefix;
+ }
+
+ // Otherwise, strip slashes where the join is going to happen. This will
+ // also change "/" to "", but the return statement takes care of that and
+ // inserts the slash again.
+ auto prefixWithoutTrailingSlash = !prefix.empty() && prefix.back() == '/' ? prefix.substr(0, prefix.length() - 1) : prefix;
+ auto suffixWithoutLeadingSlash = !suffix.empty() && suffix.front() == '/' ? suffix.substr(1) : suffix;
+
+ // And join the result with a slash.
+ return prefixWithoutTrailingSlash + '/' + suffixWithoutLeadingSlash;
}
std::string stripLastNodeFromPath(const std::string& path)
diff --git a/tests/utils.cpp b/tests/utils.cpp
index a6a982b..7717480 100644
--- a/tests/utils.cpp
+++ b/tests/utils.cpp
@@ -22,4 +22,61 @@
REQUIRE((filterByPrefix(set, "polivkax") == std::set<std::string>{}));
REQUIRE((filterByPrefix(set, "co") == std::set<std::string>{"copak", "coze"}));
}
+
+ SECTION("joinPaths") {
+ std::string prefix, suffix, result;
+
+ SECTION("regular") {
+ prefix = "/example:a";
+ suffix = "leaf";
+ result = "/example:a/leaf";
+ }
+
+ SECTION("no prefix - absolute path") {
+ suffix = "/example:a/leaf";
+ result = "/example:a/leaf";
+ }
+
+ SECTION("no prefix - relative path") {
+ suffix = "example:a/leaf";
+ result = "example:a/leaf";
+ }
+
+ SECTION("no suffix") {
+ prefix = "/example:a/leaf";
+ result = "/example:a/leaf";
+ }
+
+ SECTION("at root") {
+ prefix = "/";
+ suffix = "example:a";
+ result = "/example:a";
+ }
+
+ SECTION("trailing slash") {
+ prefix = "/example:a";
+ suffix = "/";
+ result = "/example:a/";
+ }
+
+ SECTION("prefix ends with slash") {
+ prefix = "/example:a/";
+ suffix = "leaf";
+ result = "/example:a/leaf";
+ }
+
+ SECTION("suffix starts with slash") {
+ prefix = "/example:a";
+ suffix = "/leaf";
+ result = "/example:a/leaf";
+ }
+
+ SECTION("slashes all the way to eleven") {
+ prefix = "/example:a/";
+ suffix = "/leaf";
+ result = "/example:a/leaf";
+ }
+
+ REQUIRE(joinPaths(prefix, suffix) == result);
+ }
}