Add helper to make native path from internal representaton

This commit is contained in:
Martchus 2022-03-17 22:31:11 +01:00
parent d4cf030ed9
commit 052f8d2bd2
4 changed files with 88 additions and 4 deletions

View File

@ -193,7 +193,30 @@ StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferS
#ifdef PLATFORM_WINDOWS
/*!
* \brief Converts the specified multi-byte string to a wide string using the WinAPI.
* \brief Converts the specified multi-byte string (assumed to be UTF-8) to a wide string using the WinAPI.
* \remarks Only available under Windows.
*/
std::wstring convertMultiByteToWide(std::error_code &ec, std::string_view inputBuffer)
{
// calculate required size
auto widePath = std::wstring();
auto size = MultiByteToWideChar(CP_UTF8, 0, inputBuffer.data(), inputBuffer.size(), nullptr, 0);
if (size <= 0) {
ec = std::error_code(GetLastError(), std::system_category());
return widePath;
}
// do the actual conversion
widePath.resize(static_cast<std::wstring::size_type>(size));
size = MultiByteToWideChar(CP_UTF8, 0, inputBuffer.data(), inputBuffer.size(), widePath.data(), size);
if (size <= 0) {
ec = std::error_code(GetLastError(), std::system_category());
widePath.clear();
}
return widePath;
}
/*!
* \brief Converts the specified multi-byte string (assumed to be UTF-8) to a wide string using the WinAPI.
* \remarks
* - Only available under Windows.
* - If \a inputBufferSize is -1, \a inputBuffer is considered null-terminated.
@ -218,7 +241,7 @@ WideStringData convertMultiByteToWide(std::error_code &ec, const char *inputBuff
}
/*!
* \brief Converts the specified multi-byte string to a wide string using the WinAPI.
* \brief Converts the specified multi-byte string (assumed to be UTF-8) to a wide string using the WinAPI.
* \remarks Only available under Windows.
*/
WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &inputBuffer)
@ -228,7 +251,7 @@ WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &in
}
/*!
* \brief Converts the specified multi-byte string to a wide string using the WinAPI.
* \brief Converts the specified multi-byte string (assumed to be UTF-8) to a wide string using the WinAPI.
* \remarks
* - Only available under Windows.
* - If \a inputBufferSize is -1, \a inputBuffer is considered null-terminated.
@ -240,7 +263,7 @@ WideStringData convertMultiByteToWide(const char *inputBuffer, int inputBufferSi
}
/*!
* \brief Converts the specified multi-byte string to a wide string using the WinAPI.
* \brief Converts the specified multi-byte string (assumed to be UTF-8) to a wide string using the WinAPI.
* \remarks Only available under Windows.
*/
WideStringData convertMultiByteToWide(const std::string &inputBuffer)

View File

@ -58,6 +58,7 @@ CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std
#ifdef PLATFORM_WINDOWS
using WideStringData = std::pair<std::unique_ptr<wchar_t[]>, int>;
CPP_UTILITIES_EXPORT std::wstring convertMultiByteToWide(std::error_code &ec, std::string_view inputBuffer);
CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const char *inputBuffer, int inputBufferSize = -1);
CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(std::error_code &ec, const std::string &inputBuffer);
CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const char *inputBuffer, int inputBufferSize = -1);

View File

@ -3,8 +3,13 @@
#include "../global.h"
#ifdef PLATFORM_WINDOWS
#include "../conversion/stringconversion.h"
#endif
#include <list>
#include <string>
#include <string_view>
#ifdef PLATFORM_WINDOWS
#define PATH_SEP_CHAR '\\'
@ -27,6 +32,34 @@ CPP_UTILITIES_EXPORT std::string_view fileName(std::string_view path);
CPP_UTILITIES_EXPORT std::string_view directory(std::string_view path);
#endif
CPP_UTILITIES_EXPORT void removeInvalidChars(std::string &fileName);
/*!
* \brief Returns \a path in the platform's native encoding.
* \remarks
* - On Windows we store paths internally as UTF-8 strings. So it is assumed that \a path is UTF-8 and a UTF-16
* std::wstring is returned.
* - On any other platforms we store paths internally using the native format (usually UTF-8). So it is assumed
* that \a path is already encoded as intended and passed as-is.
* - This function does basically the same as libstdc++'s `std::filesystem::u8path` implementation. However, the
* C++ standard actually imposes a conversion to UTF-8 when a non-UTF-8 narrow encoding is used. That's not
* wanted here. Besides, that function is deprecated in C++ 20.
*/
inline
#ifdef PLATFORM_WINDOWS
std::wstring
#else
std::string_view
#endif
makeNativePath(std::string_view path)
{
#ifdef PLATFORM_WINDOWS
auto ec = std::error_code();
return convertMultiByteToWide(ec, path);
#else
return path;
#endif
}
} // namespace CppUtilities
#endif // IOUTILITIES_PATHHELPER_H

View File

@ -1,5 +1,23 @@
#include "./testutils.h"
#include "../conversion/stringconversion.h"
/*!
* \brief Allows printing std::wstring using CPPUNIT_ASSERT_EQUAL.
*/
std::ostream &operator<<(std::ostream &out, const std::wstring &s)
{
const auto utf8 = CppUtilities::
#ifdef CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN
convertUtf16LEToUtf8
#else
convertUtf16BEToUtf8
#endif
(reinterpret_cast<const char *>(s.data()), s.size() * (sizeof(std::wstring::value_type) / sizeof(char)));
out.write(utf8.first.get(), utf8.second);
return out;
}
#include "../conversion/conversionexception.h"
#include "../conversion/stringbuilder.h"
@ -312,6 +330,15 @@ void IoTests::testPathUtilities()
string invalidPath("lib/c++uti*lities.so?");
removeInvalidChars(invalidPath);
CPPUNIT_ASSERT(invalidPath == "libc++utilities.so");
const auto input = std::string_view("some/path/täst");
#ifdef PLATFORM_WINDOWS
const auto expected = std::wstring(L"some/path/täst");
#else
const auto expected = input;
#endif
const auto output = makeNativePath(input);
CPPUNIT_ASSERT_EQUAL_MESSAGE("makeNativePath()", expected, output);
}
/*!