12 static bool is_insensitive = []()
14 auto timestamp = fs::file_time_type::clock::now();
15 auto temp_path = fs::temp_directory_path();
17 auto salt = std::to_string(int64_t(timestamp.time_since_epoch().count())) + std::to_string(std::rand());
18 std::string temp_name_lower =
"_case_sensitivity_test_" + salt +
".txt";
19 std::string temp_name_upper =
"_CASE_SENSITIVITY_TEST_" + salt +
".txt";
21 auto file_lower = temp_path / temp_name_lower;
22 auto file_upper = temp_path / temp_name_upper;
29 bool result = fs::equivalent(file_upper, file_lower, ec);
30 fs::remove(file_lower, ec);
35 return is_insensitive;
40bool is_parent_path(
const path& parent,
const path& child)
42 return child.parent_path() == parent;
45bool is_indirect_parent_path(
const path& parent,
const path& child)
47 path rel = child.lexically_relative(parent);
48 return !rel.empty() && rel.begin()->string() !=
"." && rel.begin()->string() !=
"..";
51bool begins_with(
const std::string& str,
const std::string& value)
54 if(str.length() < value.length())
58 if(str.empty() || value.empty())
64 auto s1 = str.substr(0, value.length());
66 return s1.compare(value) == 0;
68static std::string replace_seq(
const std::string& str,
const std::string& old_sequence,
const std::string& new_sequence)
71 std::string::size_type location = 0;
72 std::string::size_type old_length = old_sequence.length();
73 std::string::size_type new_length = new_sequence.length();
78 while(std::string::npos != (location =
s.find(old_sequence, location)))
80 s.replace(location, old_length, new_sequence);
81 location += new_length;
84 if(location >=
s.length())
96std::string
to_lower(
const std::string& str)
99 std::transform(
s.begin(),
s.end(),
s.begin(), tolower);
103template<
typename Container = std::
string,
typename CharT =
char,
typename Traits = std::
char_traits<
char>>
104auto read_stream_into_container(std::basic_istream<CharT, Traits>& in, Container& container) ->
bool
107 std::is_same<Container, std::basic_string<CharT, Traits, typename Container::allocator_type>>::value ||
108 std::is_same<Container, std::vector<CharT, typename Container::allocator_type>>::value ||
109 std::is_same<Container,
110 std::vector<std::make_unsigned_t<CharT>,
typename Container::allocator_type>>::value ||
111 std::is_same<Container, std::vector<std::make_signed_t<CharT>,
typename Container::allocator_type>>::value,
112 "only strings and vectors of ((un)signed) CharT allowed");
114 auto const start_pos = in.tellg();
115 if(std::streamsize(-1) == start_pos || !in.good())
120 if(!in.seekg(0, std::ios_base::end) || !in.good())
125 auto const end_pos = in.tellg();
127 if(std::streamsize(-1) == end_pos || !in.good())
132 auto const char_count = end_pos - start_pos;
134 if(!in.seekg(start_pos) || !in.good())
139 container.resize(
static_cast<std::size_t
>(char_count));
141 if(!container.empty())
143 in.read(
reinterpret_cast<CharT*
>(&container[0]), char_count);
144 container.resize(in.gcount());
147 return in.good() || in.eof();
203 static const std::string separator =
":/";
204 const auto string_path = _path.generic_string();
205 auto pos = string_path.find(separator, 0);
206 if(pos == std::string::npos)
211 const auto root = string_path.substr(0, pos);
218 static const std::string separator =
":/";
219 const auto string_path = _path.generic_string();
220 auto pos = string_path.find(separator, 0);
221 if(pos == std::string::npos)
226 const auto root = string_path.substr(0, pos);
228 fs::path relative_path = string_path.substr(pos + separator.size());
232 auto it = protocols.find(root);
234 if(it == std::end(protocols))
239 auto result = path(it->second);
240 if(!relative_path.empty())
242 result = result / relative_path.make_preferred();
249 static const std::string separator =
":/";
251 const auto string_path = _path.generic_string();
252 auto pos = string_path.find(separator, 0);
253 if(pos == std::string::npos)
258 const auto root = string_path.substr(0, pos);
263 return (protocols.find(root) != std::end(protocols));
269 auto canonical_path = fs::weakly_canonical(_path, ec);
270 const auto string_path = fs::path(canonical_path).make_preferred().string();
274 const protocols_t::value_type* best_protocol{};
275 for(
const auto& protocol_pair : protocols)
278 const auto& resolved_protocol = protocol_pair.second;
280 if(detail::begins_with(string_path, resolved_protocol))
284 if(best_protocol->second.size() < resolved_protocol.size())
286 best_protocol = &protocol_pair;
291 best_protocol = &protocol_pair;
297 const auto& protocol = best_protocol->first;
298 const auto& resolved_protocol = best_protocol->second;
300 auto arg1 = path(string_path).generic_string();
301 auto arg2 = path(resolved_protocol).generic_string();
303 return replace(arg1, arg2, protocol +
":").generic_string();
path replace(const path &_path, const path &_sequence, const path &_new_sequence)
Replacing any occurences of the specified path sequence with another.