forked from OpenAssetIO/OpenAssetIO
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwindows.cpp
104 lines (83 loc) · 3.25 KB
/
windows.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023-2025 The Foundry Visionmongers Ltd
#include "windows.hpp"
#include <algorithm>
#include <cassert>
#include <string_view>
#include <ada.h>
#include <openassetio/export.h>
#include <openassetio/typedefs.hpp>
#include "common.hpp"
namespace openassetio {
inline namespace OPENASSETIO_CORE_ABI_VERSION {
namespace utils::path::windows {
// ---------------------------------------------------------------------
// FileUrlPathConverter
Str FileUrlPathConverter::pathToUrl(const std::string_view& windowsPath) const {
// Precondition.
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
assert(!windowsPath.empty());
ada::url url;
// Note: url.set_protocol(...) is a no-op, see https://github.com/ada-url/ada/issues/573
url.type = ada::scheme::FILE;
if (!uncUnnormalisedDeviceSharePathHandler.toUrl(windowsPath, url)) {
if (!uncUnnormalisedDeviceDrivePathHandler.toUrl(windowsPath, url)) {
if (!uncSharePathHandler.toUrl(windowsPath, url)) {
// If none of the above, assume a drive path, e.g. `C:\`
drivePathHandler.toUrl(windowsPath, url);
}
}
}
return url.get_href();
}
Str FileUrlPathConverter::pathFromUrl(const std::string_view& url) const {
ada::result<ada::url_aggregator> adaUrl = ada::parse(url);
if (!adaUrl) {
throwError(kErrorUrlParseFailure, url);
}
const std::string_view host = adaUrl->get_host();
const std::string_view encodedPath = adaUrl->get_pathname();
std::string_view trimmedPath = encodedPath;
if (host.empty() && !encodedPath.empty()) {
// E.g. path of `file:///C:/` is `/C:/`, so trim leading `/`.
trimmedPath = encodedPath.substr(1);
}
Str decodedPath = ada::unicode::percent_decode(trimmedPath, trimmedPath.find(kPercent));
// Note: validation is ordered to match swift-url's implementation,
// i.e. it satisfies the error priority of the test suite from the
// swift-url project, which we use for our unit tests.
if (host.empty() && !driveLetterHandler.isAbsoluteDrivePath(decodedPath)) {
throwError(kErrorRelativePath, url);
}
if (GenericPath::containsNullByte(decodedPath)) {
throwError(kErrorNullByte, url);
}
if (urlHandler.containsPercentEncodedSlash(encodedPath)) {
throwError(kErrorEncodedSeparator, url);
}
if (!host.empty() && uncHostHandler.isInvalidHostname(host)) {
throwError(kErrorUnsupportedHostname, url);
}
Str windowsPath;
if (!host.empty()) {
windowsPath += kDoubleBackSlash;
if (const auto ip6Host = urlHandler.ip6ToValidHostname(host)) {
windowsPath += *ip6Host;
} else {
windowsPath += host;
}
}
decodedPath =
forwardSlashSeparatedStringHandler.removeTrailingForwardSlashesInPathSegments(decodedPath);
windowsPath += decodedPath;
std::replace(windowsPath.begin(), windowsPath.end(), kForwardSlash, kBackSlash);
if (windowsPath.size() > kMaxPath) {
windowsPath = host.empty()
? pathTypes::UncUnnormalisedDeviceDrivePath::prefixDrivePath(windowsPath)
: pathTypes::UncUnnormalisedDeviceSharePath::prefixUncSharePath(windowsPath);
}
return windowsPath;
}
} // namespace utils::path::windows
} // namespace OPENASSETIO_CORE_ABI_VERSION
} // namespace openassetio