diff --git a/CMakeLists.txt b/CMakeLists.txt index 9290e70..8927072 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,8 +136,8 @@ set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}") set(META_APP_DESCRIPTION "Useful C++ classes and routines such as argument parser, IO and conversion utilities") set(META_FEATURES_FOR_COMPILER_DETECTION_HEADER cxx_thread_local) set(META_VERSION_MAJOR 4) -set(META_VERSION_MINOR 15) -set(META_VERSION_PATCH 1) +set(META_VERSION_MINOR 16) +set(META_VERSION_PATCH 0) # find required 3rd party libraries include(3rdParty) diff --git a/conversion/stringconversion.cpp b/conversion/stringconversion.cpp index 34cb77f..c65cefb 100644 --- a/conversion/stringconversion.cpp +++ b/conversion/stringconversion.cpp @@ -8,12 +8,17 @@ #include #include +#include #include #include #include #include +#ifdef PLATFORM_WINDOWS +#include +#endif + using namespace std; /*! @@ -192,6 +197,40 @@ StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferS return descriptor.convertString(inputBuffer, inputBufferSize); } +#ifdef PLATFORM_WINDOWS +/*! + * \brief Converts the specified multi-byte string to a wide string using the WinAPI. + * \remarks + * - Only available under Windows. + * - If \a inputBufferSize is -1, \a inputBuffer is considered null-terminated. + */ +std::unique_ptr convertMultiByteToWide(const char *inputBuffer, int inputBufferSize) +{ + // calculate required size + int requiredSize = MultiByteToWideChar(CP_UTF8, 0, inputBuffer, inputBufferSize, nullptr, 0); + std::unique_ptr widePath; + if (requiredSize <= 0) { + return widePath; + } + // do the actual conversion + widePath = make_unique(static_cast(requiredSize)); + requiredSize = MultiByteToWideChar(CP_UTF8, 0, inputBuffer, inputBufferSize, widePath.get(), requiredSize); + if (requiredSize <= 0) { + widePath.reset(); + } + return widePath; +} + +/*! + * \brief Converts the specified multi-byte string to a wide string using the WinAPI. + * \remarks Only available under Windows. + */ +std::unique_ptr convertMultiByteToWide(const std::string &inputBuffer) +{ + return convertMultiByteToWide(inputBuffer.data(), inputBuffer.size() < numeric_limits::max() ? static_cast(inputBuffer.size()) : -1); +} +#endif + /*! * \brief Truncates all characters after the first occurrence of the * specified \a terminationChar and the termination character as well. diff --git a/conversion/stringconversion.h b/conversion/stringconversion.h index 3571e0d..4a71b27 100644 --- a/conversion/stringconversion.h +++ b/conversion/stringconversion.h @@ -47,6 +47,11 @@ CPP_UTILITIES_EXPORT StringData convertUtf16BEToUtf8(const char *inputBuffer, st CPP_UTILITIES_EXPORT StringData convertLatin1ToUtf8(const char *inputBuffer, std::size_t inputBufferSize); CPP_UTILITIES_EXPORT StringData convertUtf8ToLatin1(const char *inputBuffer, std::size_t inputBufferSize); +#ifdef PLATFORM_WINDOWS +CPP_UTILITIES_EXPORT std::unique_ptr convertMultiByteToWide(const char *inputBuffer, int inputBufferSize = -1); +CPP_UTILITIES_EXPORT std::unique_ptr convertMultiByteToWide(const std::string &inputBuffer); +#endif + CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0'); /*! diff --git a/io/nativefilestream.cpp b/io/nativefilestream.cpp index 476f0af..2675138 100644 --- a/io/nativefilestream.cpp +++ b/io/nativefilestream.cpp @@ -3,6 +3,10 @@ #ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER #include "./catchiofailure.h" +#ifdef PLATFORM_WINDOWS +#include "../conversion/stringconversion.h" +#endif + // include header files for file buffer implementation #if defined(CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF) #include @@ -262,7 +266,6 @@ std::unique_ptr> NativeFileStream::makeFileBuffer(int // compute native params const NativeFileParams nativeParams(openMode); - #ifdef CPP_UTILITIES_USE_GNU_CXX_STDIO_FILEBUF // open file handle to initialize stdio_filebuf #ifdef PLATFORM_WINDOWS @@ -291,13 +294,8 @@ std::unique_ptr> NativeFileStream::makeFileBuffer(int #ifdef PLATFORM_WINDOWS std::unique_ptr NativeFileStream::makeWidePath(const std::string &path) { - int requiredSize = MultiByteToWideChar(CP_UTF8, 0, path.data(), -1, nullptr, 0); - if (requiredSize <= 0) { - ::IoUtilities::throwIoFailure("Unable to calculate buffer size for conversion of path to UTF-16"); - } - auto widePath = make_unique(static_cast(requiredSize)); - requiredSize = MultiByteToWideChar(CP_UTF8, 0, path.data(), -1, widePath.get(), requiredSize); - if (requiredSize <= 0) { + auto widePath = ::ConversionUtilities::convertMultiByteToWide(path); + if (!widePath) { ::IoUtilities::throwIoFailure("Unable to convert path to UTF-16"); } return widePath; diff --git a/tests/testutils.cpp b/tests/testutils.cpp index e0413c1..f563fac 100644 --- a/tests/testutils.cpp +++ b/tests/testutils.cpp @@ -6,8 +6,8 @@ #include "../io/ansiescapecodes.h" #include "../io/catchiofailure.h" #include "../io/misc.h" -#include "../io/path.h" #include "../io/nativefilestream.h" +#include "../io/path.h" #include #include