diff options
Diffstat (limited to 'graphics/asymptote/LspCpp/third_party/uri/src/detail/uri_resolve.cpp')
-rw-r--r-- | graphics/asymptote/LspCpp/third_party/uri/src/detail/uri_resolve.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/graphics/asymptote/LspCpp/third_party/uri/src/detail/uri_resolve.cpp b/graphics/asymptote/LspCpp/third_party/uri/src/detail/uri_resolve.cpp new file mode 100644 index 0000000000..024ee12603 --- /dev/null +++ b/graphics/asymptote/LspCpp/third_party/uri/src/detail/uri_resolve.cpp @@ -0,0 +1,88 @@ +// Copyright 2013-2016 Glyn Matthews. +// Copyright 2013 Hannes Kamecke. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "uri_resolve.hpp" +#include "algorithm_find.hpp" + +using namespace network::algorithm; +using network::uri; +using network::string_view; +namespace network_detail = network::detail; + +namespace { + +// remove_dot_segments +inline void remove_last_segment(std::string &path) { + while (!path.empty()) { + if (path.back() == '/') { + path.pop_back(); + break; + } + path.pop_back(); + } +} + +inline bool starts_with(std::string const &str, const char *range) { + return str.find(range) == 0; +} + +// implementation of http://tools.ietf.org/html/rfc3986#section-5.2.4 +static std::string remove_dot_segments(std::string input) { + std::string result; + + while (!input.empty()) { + if (starts_with(input, "../")) { + input.erase(0, 3); + } else if (starts_with(input, "./")) { + input.erase(0, 2); + } else if (starts_with(input, "/./")) { + input.erase(0, 2); + input.front() = '/'; + } else if (input == "/.") { + input.erase(0, 1); + input.front() = '/'; + } else if (starts_with(input, "/../")) { + input.erase(0, 3); + remove_last_segment(result); + } else if (starts_with(input, "/..")) { + input.erase(0, 2); + input.front() = '/'; + remove_last_segment(result); + } else if (all(input, [](char ch) { return ch == '.'; })) { + input.clear(); + } else { + int n = (input.front() == '/') ? 1 : 0; + std::string::iterator slash = find_nth(input, '/', n); + result.append(std::begin(input), slash); + input.erase(std::begin(input), slash); + } + } + return result; +} + +} // namespace + +std::string network_detail::remove_dot_segments(string_view path) { + return ::remove_dot_segments(path.to_string()); +} + +// implementation of http://tools.ietf.org/html/rfc3986#section-5.2.3 +std::string network_detail::merge_paths(const uri &base, const uri &reference) { + std::string result; + + if (!base.has_path() || base.path().empty()) { + result = "/"; + } else { + const auto &base_path = base.path(); + auto last_slash = algorithm::find_last(base_path, '/'); + if (last_slash != base_path.cend()) ++last_slash; + result.append(std::begin(base_path), last_slash); + } + if (reference.has_path()) { + result.append(reference.path().to_string()); + } + return remove_dot_segments(string_view(result)); +} |