13#include "../char_maps/char_maps.hpp"
14#include "../utility/utility.hpp"
15#include "../macros.hpp"
20#include <unordered_map>
26hi_export_module(hikogui.path.URL);
31hi_warning_ignore_msvc(26434);
33hi_export
namespace hi {
inline namespace v1 {
51class URL :
public URI {
55 constexpr URL() noexcept = default;
56 constexpr
URL(
URL const&) noexcept = default;
57 constexpr
URL(
URL&&) noexcept = default;
58 constexpr
URL& operator=(
URL const&) noexcept = default;
59 constexpr
URL& operator=(
URL&&) noexcept = default;
75 constexpr explicit URL(std::string_view str) : URI(str) {}
91 constexpr explicit URL(
const char *str) :
URL(
std::string_view{str}) {}
100 explicit URL(std::filesystem::path
const&
path) : URI(make_file_url_string(
path)) {}
109 if (validate_scheme and not(not
scheme() or
scheme() ==
"file")) {
110 throw url_error(
"URL::generic_path() is only valid on a file: scheme URL");
114 auto const& p =
path();
115 auto const first = p.begin();
116 auto const last = p.end();
119 auto has_root_name =
false;
123 if (not server.empty() and server !=
"localhost") {
124 validate_file_server(server);
125 has_root_name =
true;
134 hi_assert(has_root_name ==
false or p.absolute());
136 if (p.double_absolute()) {
140 throw url_error(
"file URL has two server names.");
143 has_root_name =
true;
147 validate_file_server(*it);
153 auto empty_segment =
false;
155 validate_file_segment(*it);
156 empty_segment = it->empty();
158 if (it == first and empty_segment) {
162 }
else if (
auto i = it->find(
':'); i != std::string::npos) {
165 throw url_error(
"file URL contains a device name which is a security issue.");
168 if (has_root_name or p.absolute()) {
171 r += has_root_name ?
'$' :
':';
184 has_root_name =
true;
196 for (; it != last; ++it) {
197 validate_file_segment(*it);
198 empty_segment = it->empty();
203 if (not empty_segment) {
218 if (
auto scheme_ =
scheme()) {
219 if (scheme_ ==
"resource") {
227 if (not search_path.empty()) {
230 search_path += p.string();
232 throw url_error(std::format(
"Resource '{}' not found in search-path: '{}'", to_string(*
this), search_path));
235 }
else if (scheme_ ==
"file") {
238 throw url_error(
"URL can not be converted to a filesystem path.");
248 operator std::filesystem::path()
const
253 [[nodiscard]]
constexpr friend URL operator/(
URL const& base,
URI const& ref)
noexcept
258 [[nodiscard]]
constexpr friend URL operator/(
URL const& base, std::string_view ref)
noexcept
264 constexpr void static validate_file_segment(std::string_view segment)
266 for (
auto c : segment) {
267 if (c ==
'/' or c ==
'\\') {
268 throw url_error(
"Filename server name may not contain slash or back-slash.");
273 constexpr void static validate_file_server(std::string_view server)
275 for (
auto c : server) {
276 if (c ==
'/' or c ==
'\\') {
277 throw url_error(
"Filename segments may not contain slash or back-slash.");
282 static std::string make_file_url_string(std::filesystem::path
const&
path)
284 auto r = std::u8string{};
286 auto const root_name =
path.root_name().generic_u8string();
287 if (root_name.empty()) {
289 if (not
path.root_directory().empty()) {
291 r += u8
"file:" +
path.root_directory().generic_u8string();
297 }
else if (
auto const i = root_name.find(
':'); i != std::string::npos) {
300 r += u8
"file:///" + root_name +
path.root_directory().generic_u8string();
302 throw url_error(
"Paths containing a device are not allowed to be converted to a URL.");
306 r += u8
"file://" + root_name +
path.root_directory().generic_u8string();
307 if (not
path.root_directory().empty()) {
308 throw url_error(
"Invalid path contains server name without a root directory.");
312 return to_string(r +
path.relative_path().generic_u8string());
328struct std::formatter<
hi::URL, char> : std::formatter<hi::URI, char> {
329 auto format(
hi::URL const& t,
auto& fc)
const
331 return std::formatter<hi::URI, char>::format(t, fc);
functions to locate files and directories.
constexpr std::u8string to_u8string(std::u32string_view rhs) noexcept
Conversion from UTF-32 to UTF-8.
Definition to_string.hpp:116
@ other
The gui_event does not have associated data.
Definition gui_event_variant.hpp:24
hi_inline generator< std::filesystem::path > resource_dirs() noexcept
The directories to search for resource files.
hi_inline std::optional< std::filesystem::path > find_path(Locations &&locations, std::filesystem::path const &ref) noexcept
Find a path.
Definition path_location_intf.hpp:40
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
The HikoGUI API version 1.
Definition recursive_iterator.hpp:16
constexpr Out up_cast(In *rhs) noexcept
Cast a pointer to a class to its base class or itself.
Definition cast.hpp:66
A Uniform Resource Identifier.
Definition URI.hpp:45
constexpr std::optional< authority_type > const & authority() const noexcept
Get the authority-component of the URI.
Definition URI.hpp:558
constexpr std::optional< std::string > const & scheme() const noexcept
Get the scheme-component of the URI.
Definition URI.hpp:535
Universal Resource Locator.
Definition URL.hpp:51
constexpr URL() noexcept=default
Create an empty URL.
URL(std::filesystem::path const &path)
Convert a filesystem-path to a file-scheme URL.
Definition URL.hpp:100
constexpr URL(URI &&other) noexcept
Convert a URI to an URL.
Definition URL.hpp:67
operator std::filesystem::path() const
Definition URL.hpp:248
constexpr URL(const char *str)
Construct a URI from a string.
Definition URL.hpp:91
constexpr URL(std::string const &str)
Construct a URI from a string.
Definition URL.hpp:83
std::filesystem::path filesystem_path() const
Create a filesystem path from a file URL.
Definition URL.hpp:216
constexpr std::u8string filesystem_path_generic_u8string(bool validate_scheme=true) const
Return a generic path.
Definition URL.hpp:107
constexpr URL(std::string_view str)
Construct a URI from a string.
Definition URL.hpp:75
Definition exception_intf.hpp:204