summaryrefslogtreecommitdiff
path: root/indra/llcommon/fsyspath.h
diff options
context:
space:
mode:
authorJonathan "Geenz" Goodman <geenz@lindenlab.com>2025-09-18 15:25:31 -0400
committerGitHub <noreply@github.com>2025-09-18 15:25:31 -0400
commitf316a92f308be836b57f638514dcd56f3851a89a (patch)
tree9a1431c0c311de41388879b31f26c6faa8bf5e89 /indra/llcommon/fsyspath.h
parentbadeccbebcfa73a11cf0f8a4562c9a0d386834c1 (diff)
parent82e431e0906647dcfc4a64b057e6bc305c9add8e (diff)
Merge pull request #4700 from secondlife/geenz/2025.07-develop
Geenz/2025.07 -> develop
Diffstat (limited to 'indra/llcommon/fsyspath.h')
-rw-r--r--indra/llcommon/fsyspath.h47
1 files changed, 28 insertions, 19 deletions
diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h
index e9c96edce3..2c900c02a7 100644
--- a/indra/llcommon/fsyspath.h
+++ b/indra/llcommon/fsyspath.h
@@ -12,7 +12,10 @@
#if ! defined(LL_FSYSPATH_H)
#define LL_FSYSPATH_H
+#include <boost/iterator/transform_iterator.hpp>
#include <filesystem>
+#include <string>
+#include <string_view>
// While std::filesystem::path can be directly constructed from std::string on
// both Posix and Windows, that's not what we want on Windows. Per
@@ -33,37 +36,43 @@
// char"), the "native narrow encoding" isn't UTF-8, so file paths containing
// non-ASCII characters get mangled.
//
-// Once we're building with C++20, we could pass a UTF-8 std::string through a
-// vector<char8_t> to engage std::filesystem::path's own UTF-8 conversion. But
-// sigh, as of 2024-04-03 we're not yet there.
-//
-// Anyway, encapsulating the important UTF-8 conversions in our own subclass
-// allows us to migrate forward to C++20 conventions without changing
-// referencing code.
+// Encapsulating the important UTF-8 conversions in our own subclass allows us
+// to migrate forward to C++20 conventions without changing referencing code.
class fsyspath: public std::filesystem::path
{
using super = std::filesystem::path;
+ // In C++20 (__cpp_lib_char8_t), std::filesystem::u8path() is deprecated.
+ // std::filesystem::path(iter, iter) performs UTF-8 conversions when the
+ // value_type of the iterators is char8_t. While we could copy into a
+ // temporary std::u8string and from there into std::filesystem::path, to
+ // minimize string copying we'll define a transform_iterator that accepts
+ // a std::string_view::iterator and dereferences to char8_t.
+ struct u8ify
+ {
+ char8_t operator()(char c) const { return char8_t(c); }
+ };
+ using u8iter = boost::transform_iterator<u8ify, std::string_view::iterator>;
+
public:
// default
fsyspath() {}
- // construct from UTF-8 encoded std::string
- fsyspath(const std::string& path): super(std::filesystem::u8path(path)) {}
- // construct from UTF-8 encoded const char*
- fsyspath(const char* path): super(std::filesystem::u8path(path)) {}
+ // construct from UTF-8 encoded string
+ fsyspath(const std::string& path): fsyspath(std::string_view(path)) {}
+ fsyspath(const char* path): fsyspath(std::string_view(path)) {}
+ fsyspath(std::string_view path):
+ super(u8iter(path.begin(), u8ify()), u8iter(path.end(), u8ify()))
+ {}
// construct from existing path
fsyspath(const super& path): super(path) {}
- fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
- fsyspath& operator=(const std::string& p)
- {
- super::operator=(std::filesystem::u8path(p));
- return *this;
- }
- fsyspath& operator=(const char* p)
+ fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
+ fsyspath& operator=(const std::string& p) { return (*this) = std::string_view(p); }
+ fsyspath& operator=(const char* p) { return (*this) = std::string_view(p); }
+ fsyspath& operator=(std::string_view p)
{
- super::operator=(std::filesystem::u8path(p));
+ assign(u8iter(p.begin(), u8ify()), u8iter(p.end(), u8ify()));
return *this;
}