summaryrefslogtreecommitdiff
path: root/graphics/asymptote/LspCpp/third_party/uri/src/detail/uri_resolve.cpp
diff options
context:
space:
mode:
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.cpp88
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));
+}