diff --git a/include/jsoncons/utility/uri.hpp b/include/jsoncons/utility/uri.hpp index dac4444d8..c763c6ca3 100644 --- a/include/jsoncons/utility/uri.hpp +++ b/include/jsoncons/utility/uri.hpp @@ -821,7 +821,7 @@ namespace jsoncons { namespace utility { 3. Finally, the output buffer is returned as the result of remove_dot_segments. */ - static std::string remove_dot_segments(jsoncons::string_view path) + static std::string remove_dot_segments2(jsoncons::string_view path) { std::string input{path}; std::string output; @@ -898,6 +898,95 @@ namespace jsoncons { namespace utility { return output; } + static std::string remove_dot_segments(jsoncons::string_view path) + { + std::string input{path}; + std::string output; + + std::size_t rel = 0; + const std::size_t buflen = input.size(); + while (rel < buflen) + { + std::size_t len = buflen - rel; + if (len >= 3 && input[rel] == '.' && input[rel+1] == '.' && input[rel+2] == '/') + { + //input.erase(0,3); + rel += 3; + } + else if (len >= 2 && input[rel] == '.' && input[rel+1] == '/') + { + //input.erase(0,2); + rel += 2; + } + else if (len >= 3 && input[rel] == '/' && input[rel+1] == '.' && input[rel+2] == '/') + { + //input.erase(0,2); + rel += 2; + input[rel] = '/'; + } + else if (len == 2 && input[rel] == '/' && input[rel+1] == '.') + { + //input.erase(0,1); + ++rel; + input[rel] = '/'; + } + else if (len >= 4 && input[rel] == '/' && input[rel+1] == '.' && input[rel+2] == '.' && input[rel+3] == '/') + { + //input.erase(0,3); + rel += 3; + input[rel] = '/'; + auto rslash = output.rfind('/'); + if (rslash != std::string::npos) + { + output.erase(rslash); + } + } + else if (len >= 3 && input[rel] == '/' && input[rel+1] == '.' && input[rel+2] == '.') + { + //input.erase(0,2); + rel += 2; + input[rel] = '/'; + auto rslash = output.rfind('/'); + if (rslash != std::string::npos) + { + output.erase(rslash); + } + } + else if (len == 1 && input[rel] == '.') + { + //input.erase(0,1); + ++rel; + } + else if (len == 2 && input[rel] == '.' && input[rel+1] == '.') + { + //input.erase(0,2); + rel += 2; + } + else + { + const auto first = input.data() + rel; + const auto last = first+(len); + auto it = std::find(first+1, last, '/'); + if (it != last) + { + output.append(first, it - first); + //input.erase(0, it - first); + rel += (it - first); + } + else + { + output.append(first, len); + //input.erase(0, len); + rel += len; + } + } + } + + //std::cout << "path: " << path << ", output: " << output << "\n"; + + return output; + } + static std::string merge_paths(const uri& base, const uri& relative) { std::string result; diff --git a/test/corelib/src/utility/uri_tests.cpp b/test/corelib/src/utility/uri_tests.cpp index d63a0715d..3444b46f4 100644 --- a/test/corelib/src/utility/uri_tests.cpp +++ b/test/corelib/src/utility/uri_tests.cpp @@ -504,12 +504,14 @@ TEST_CASE("cpp-netib uri resolve tests") CHECK(uri.encoded_query() == jsoncons::string_view("q=1")); CHECK("http://a/g/x/y?q=1#s" == uri.string()); } + SECTION("remove_dot_segments1") { jsoncons::uri reference{"./g"}; auto uri = reference.resolve(base_uri); CHECK("http://a/b/c/g" == uri.string()); } + SECTION("base_has_path__path_is_merged_1") { jsoncons::uri reference{"g/"}; @@ -697,4 +699,3 @@ TEST_CASE("cpp-netib uri resolve tests") CHECK("http://a/b/c/g#s/../x" == uri.string()); } } -