Skip to content

Commit

Permalink
Added support for windows paths
Browse files Browse the repository at this point in the history
  • Loading branch information
sopyer committed Jul 13, 2021
1 parent 2888511 commit 7b250ab
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
2 changes: 1 addition & 1 deletion core/include/tangram/util/url.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class Url {
// parts describes URL components by their location within the buffer.
struct Parts {
struct Range {
uint16_t start = 0, count = 0;
size_t start = 0, count = 0;
} scheme, location, path, parameters, query, fragment, media, data;
} parts;

Expand Down
16 changes: 16 additions & 0 deletions core/src/util/url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstdlib>
#include <cassert>
#include <algorithm>

namespace Tangram {

Expand Down Expand Up @@ -239,6 +240,12 @@ Url Url::resolve(const Url& b, const Url& r) {
// If the relative URL's path starts with '/', it is absolute.
if (r.buffer[r.parts.path.start] == '/') {
t.buffer.append(r.buffer, r.parts.path.start, r.parts.path.count);
#ifdef TANGRAM_WINDOWS
// On Windows if the relative URL's path starts with '<letter>:', it is absolute path starting with driver name.
} else if (r.parts.path.count > 1 && r.buffer[r.parts.path.start + 1] == ':') {
if (!t.buffer.empty() && t.buffer.back() != '/') { t.buffer += '/'; }
t.buffer.append(r.buffer, r.parts.path.start, r.parts.path.count);
#endif
} else {
// Merge the relative path with the base path.
if (b.hasNetLocation() && !b.hasPath()) {
Expand Down Expand Up @@ -320,6 +327,10 @@ std::string Url::removeDotSegmentsFromString(std::string path) {
}

void Url::parse() {
#ifdef TANGRAM_WINDOWS
// Normalize Windows paths. Chromium also does this.
std::replace(buffer.begin(), buffer.end(), '\\', '/');
#endif

// The parsing process roughly follows https://tools.ietf.org/html/rfc1808#section-2.4

Expand Down Expand Up @@ -351,7 +362,12 @@ void Url::parse() {
}

// If a scheme is present, it must be followed by a ':'.
#ifdef TANGRAM_WINDOWS
// Check also if 'scheme' is longer than 1 - could be a Windows disk drive
if (c == ':' && i - start > 1) {
#else
if (c == ':') {
#endif
parts.scheme.start = start;
parts.scheme.count = i - start;

Expand Down
39 changes: 36 additions & 3 deletions tests/unit/urlTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,46 @@ TEST_CASE("Maintain URL components when 'standardized'", "[URL]") {

}

#ifdef TANGRAM_WINDOWS
TEST_CASE("Windows specific URL tests", "[Url]") {
{
Url base("http://a/b/c/d;p?q");
CHECK(base.resolve(Url("g:")).string() == "http://a/g:");
CHECK(base.resolve(Url("g:\\")).string() == "http://a/g:/");
CHECK(base.resolve(Url("g:/")).string() == "http://a/g:/");
CHECK(base.resolve(Url("g:\\a")).string() == "http://a/g:/a");
}

{
Url base("a/b/c/d;p?q");
CHECK(base.resolve(Url("g:")).string() == "g:");
CHECK(base.resolve(Url("g:\\")).string() == "g:/");
CHECK(base.resolve(Url("g:/")).string() == "g:/");
CHECK(base.resolve(Url("g:\\a")).string() == "g:/a");
}

{
Url base("");
CHECK(base.resolve(Url("g:")).string() == "g:");
CHECK(base.resolve(Url("g:\\")).string() == "g:/");
CHECK(base.resolve(Url("g:/")).string() == "g:/");
CHECK(base.resolve(Url("g:\\a")).string() == "g:/a");
}

{
Url base("file:///a/b/c");
CHECK(base.resolve(Url("d:")).string() == "file://d:");
}
}
#endif

TEST_CASE("Resolve a URL against an absolute base URL", "[Url]") {

// https://tools.ietf.org/html/rfc3986#section-5.4.1

Url base("http://a/b/c/d;p?q");

CHECK(base.resolve(Url("g:h")).string() == "g:h");
CHECK(base.resolve(Url("scheme:h")).string() == "scheme:h");
CHECK(base.resolve(Url("g")).string() == "http://a/b/c/g");
CHECK(base.resolve(Url("./g")).string() == "http://a/b/c/g");
CHECK(base.resolve(Url("g/")).string() == "http://a/b/c/g/");
Expand All @@ -158,7 +191,7 @@ TEST_CASE("Resolve a URL against a relative base URL", "[Url]") {

Url base("a/b/c/d;p?q");

CHECK(base.resolve(Url("g:h")).string() == "g:h");
CHECK(base.resolve(Url("scheme:h")).string() == "scheme:h");
CHECK(base.resolve(Url("g")).string() == "a/b/c/g");
CHECK(base.resolve(Url("./g")).string() == "a/b/c/g");
CHECK(base.resolve(Url("g/")).string() == "a/b/c/g/");
Expand All @@ -179,7 +212,7 @@ TEST_CASE("Resolve a relative URL against an empty base URL", "[Url]") {

Url base("");

CHECK(base.resolve(Url("g:h")).string() == "g:h");
CHECK(base.resolve(Url("scheme:h")).string() == "scheme:h");
CHECK(base.resolve(Url("g")).string() == "g");
CHECK(base.resolve(Url("./g")).string() == "g");
CHECK(base.resolve(Url("g/")).string() == "g/");
Expand Down

0 comments on commit 7b250ab

Please sign in to comment.