summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2022-10-05 23:10:24 +0300
committerGitHub <noreply@github.com>2022-10-05 22:10:24 +0200
commita6072098415e3ccf8a2ac6542db35d1f72f8d08b (patch)
tree0cc82573e53dcf3e24f182147497d72ca3a8e761
parente9ddf6800eaed6ce45bcb01f976995ef423c6ae2 (diff)
downloadccache-a6072098415e3ccf8a2ac6542db35d1f72f8d08b.tar.gz
fix: Remove usage of deprecated codecvt header (#1172)
Based on https://stackoverflow.com/a/69410299/764870.
-rw-r--r--src/util/file.cpp36
-rw-r--r--unittest/test_util_file.cpp8
2 files changed, 38 insertions, 6 deletions
diff --git a/src/util/file.cpp b/src/util/file.cpp
index b3d3771f..964d6846 100644
--- a/src/util/file.cpp
+++ b/src/util/file.cpp
@@ -21,6 +21,7 @@
#include <Fd.hpp>
#include <Logging.hpp>
#include <Stat.hpp>
+#include <Win32Util.hpp>
#include <fmtmacros.hpp>
#include <util/Bytes.hpp>
@@ -47,7 +48,6 @@
#include <sys/types.h>
#include <cerrno>
-#include <codecvt>
#include <cstring>
#include <fstream>
#include <locale>
@@ -171,11 +171,35 @@ read_file(const std::string& path, size_t size_hint)
// it's actually needed.
if (has_utf16_le_bom(result)) {
result.erase(0, 2); // Remove BOM.
- std::u16string result_as_u16((result.size() / 2) + 1, '\0');
- result_as_u16 = reinterpret_cast<const char16_t*>(result.c_str());
- std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>
- converter;
- result = converter.to_bytes(result_as_u16);
+ if (result.empty())
+ return result;
+
+ std::wstring result_as_u16((result.size() / 2) + 1, '\0');
+ result_as_u16 = reinterpret_cast<const wchar_t*>(result.c_str());
+
+ const int size = WideCharToMultiByte(CP_UTF8,
+ WC_ERR_INVALID_CHARS,
+ result_as_u16.c_str(),
+ int(result_as_u16.size()),
+ nullptr,
+ 0,
+ nullptr,
+ nullptr);
+ if (size <= 0)
+ return nonstd::make_unexpected(
+ FMT("Failed to convert {} from UTF-16LE to UTF-8: {}",
+ path,
+ Win32Util::error_message(GetLastError())));
+
+ result = std::string(size, '\0');
+ WideCharToMultiByte(CP_UTF8,
+ 0,
+ result_as_u16.c_str(),
+ int(result_as_u16.size()),
+ &result.at(0),
+ size,
+ nullptr,
+ nullptr);
}
}
#endif
diff --git a/unittest/test_util_file.cpp b/unittest/test_util_file.cpp
index 9b99d150..cc677137 100644
--- a/unittest/test_util_file.cpp
+++ b/unittest/test_util_file.cpp
@@ -120,6 +120,14 @@ TEST_CASE("util::read_file<std::string> with UTF-16 little endian encoding")
auto read_data = util::read_file<std::string>("test");
REQUIRE(read_data);
CHECK(*read_data == "abc");
+
+ data.push_back('\0');
+ data.push_back(static_cast<unsigned char>(0xd8));
+ data.push_back('d');
+ data.push_back('\0');
+ CHECK(util::write_file("test", data));
+ read_data = util::read_file<std::string>("test");
+ REQUIRE(!read_data);
}
#endif