From 6974150a2c6b3b4e0fa278b08de8b2647d2c95ed Mon Sep 17 00:00:00 2001
From: Richard Walters <rwalters@digitalstirling.com>
Date: Mon, 2 Jul 2018 21:11:01 -0700
Subject: Add NormalizePath method

---
 src/Uri.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

(limited to 'src')

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());
+                    }
+                }
+            }
+        }
+    }
+
 }
-- 
cgit v1.2.3