aboutsummaryrefslogtreecommitdiff
path: root/src/Uri.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Uri.cpp')
-rw-r--r--src/Uri.cpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/Uri.cpp b/src/Uri.cpp
index 77e561a..0153e5f 100644
--- a/src/Uri.cpp
+++ b/src/Uri.cpp
@@ -702,4 +702,73 @@ namespace Uri {
return impl_->fragment;
}
+ void Uri::NormalizePath() {
+ /*
+ * This is a straight-up implementation of the
+ * algorithm from section 5.2.4 of
+ * RFC 3986 (https://tools.ietf.org/html/rfc3986).
+ */
+ // Step 1
+ auto oldPath = std::move(impl_->path);
+ impl_->path.clear();
+ // Step 2
+ while (!oldPath.empty()) {
+ // Step 2A
+ if (
+ (oldPath[0] == ".")
+ || (oldPath[0] == "..")
+ ) {
+ oldPath.erase(oldPath.begin());
+ } else
+
+ // Step 2B
+ if (
+ (oldPath.size() >= 2)
+ && (oldPath[0] == "")
+ && (oldPath[1] == ".")
+ ) {
+ oldPath.erase(oldPath.begin() + 1);
+ } else
+
+ // Step 2C
+ if (
+ (oldPath.size() >= 2)
+ && (oldPath[0] == "")
+ && (oldPath[1] == "..")
+ ) {
+ oldPath.erase(oldPath.begin() + 1);
+ impl_->path.pop_back();
+ } else
+
+ // Step 2D
+ if (
+ (oldPath.size() == 1)
+ && (
+ (oldPath[0] == ".")
+ || (oldPath[0] == "..")
+ )
+ ) {
+ oldPath.erase(oldPath.begin());
+ } else
+
+ // Step 2E
+ {
+ if (oldPath[0] == "") {
+ if (impl_->path.empty()) {
+ impl_->path.push_back("");
+ }
+ oldPath.erase(oldPath.begin());
+ }
+ if (!oldPath.empty()) {
+ impl_->path.push_back(oldPath[0]);
+ if (oldPath.size() > 1) {
+ oldPath[0] = "";
+ } else {
+ oldPath.erase(oldPath.begin());
+ }
+ }
+ }
+ }
+ }
+
}