summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/fsyspath.h74
-rw-r--r--indra/llcommon/lua_function.cpp6
-rw-r--r--indra/llcommon/lua_function.h4
4 files changed, 80 insertions, 5 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index aed9ee080b..aa0b66f2f4 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -127,6 +127,7 @@ set(llcommon_HEADER_FILES
commoncontrol.h
ctype_workaround.h
fix_macros.h
+ fsyspath.h
function_types.h
indra_constants.h
lazyeventapi.h
diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h
new file mode 100644
index 0000000000..aa4e0132bc
--- /dev/null
+++ b/indra/llcommon/fsyspath.h
@@ -0,0 +1,74 @@
+/**
+ * @file fsyspath.h
+ * @author Nat Goodspeed
+ * @date 2024-04-03
+ * @brief Adapt our UTF-8 std::strings for std::filesystem::path
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Copyright (c) 2024, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_FSYSPATH_H)
+#define LL_FSYSPATH_H
+
+#include <filesystem>
+
+// 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
+// https://en.cppreference.com/w/cpp/filesystem/path/path:
+
+// ... the method of conversion to the native character set depends on the
+// character type used by source.
+//
+// * If the source character type is char, the encoding of the source is
+// assumed to be the native narrow encoding (so no conversion takes place on
+// POSIX systems).
+// * If the source character type is char8_t, conversion from UTF-8 to native
+// filesystem encoding is used. (since C++20)
+// * If the source character type is wchar_t, the input is assumed to be the
+// native wide encoding (so no conversion takes places on Windows).
+
+// The trouble is that on Windows, from std::string ("source character type is
+// 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.
+
+class fsyspath: public std::filesystem::path
+{
+ using super = std::filesystem::path;
+
+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 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)
+ {
+ super::operator=(std::filesystem::u8path(p));
+ return *this;
+ }
+
+ // shadow base-class string() method with UTF-8 aware method
+ std::string string() const { return super::u8string(); }
+};
+
+#endif /* ! defined(LL_FSYSPATH_H) */
diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
index cd83f40e85..7a5668f384 100644
--- a/indra/llcommon/lua_function.cpp
+++ b/indra/llcommon/lua_function.cpp
@@ -17,13 +17,13 @@
// std headers
#include <algorithm>
#include <exception>
-#include <filesystem>
#include <iomanip> // std::quoted
#include <map>
#include <memory> // std::unique_ptr
#include <typeinfo>
// external library headers
// other Linden headers
+#include "fsyspath.h"
#include "hexdump.h"
#include "lleventcoro.h"
#include "llsd.h"
@@ -68,7 +68,7 @@ int lluau::loadstring(lua_State *L, const std::string &desc, const std::string &
return luau_load(L, desc.data(), bytecode.get(), bytecodeSize, 0);
}
-std::filesystem::path lluau::source_path(lua_State* L)
+fsyspath lluau::source_path(lua_State* L)
{
//Luau lua_Debug and lua_getinfo() are different compared to default Lua:
//see https://github.com/luau-lang/luau/blob/80928acb92d1e4b6db16bada6d21b1fb6fa66265/VM/include/lua.h
@@ -577,7 +577,7 @@ std::pair<int, LLSD> LuaState::expr(const std::string& desc, const std::string&
// the next call to lua_next."
// https://www.lua.org/manual/5.1/manual.html#lua_next
if (lua_type(mState, -2) == LUA_TSTRING &&
- std::filesystem::path(lua_tostdstring(mState, -2)).stem() == "fiber")
+ fsyspath(lua_tostdstring(mState, -2)).stem() == "fiber")
{
found = true;
break;
diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h
index 785aadeb0c..ec1e6cdb10 100644
--- a/indra/llcommon/lua_function.h
+++ b/indra/llcommon/lua_function.h
@@ -16,9 +16,9 @@
#include "luau/lua.h"
#include "luau/luaconf.h"
#include "luau/lualib.h"
+#include "fsyspath.h"
#include "stringize.h"
#include <exception> // std::uncaught_exceptions()
-#include <filesystem>
#include <memory> // std::shared_ptr
#include <utility> // std::pair
@@ -51,7 +51,7 @@ namespace lluau
int dostring(lua_State* L, const std::string& desc, const std::string& text);
int loadstring(lua_State* L, const std::string& desc, const std::string& text);
- std::filesystem::path source_path(lua_State* L);
+ fsyspath source_path(lua_State* L);
} // namespace lluau
std::string lua_tostdstring(lua_State* L, int index);