]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Remove usage of deprecated codecvt header (#1172)
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>
Wed, 5 Oct 2022 20:10:24 +0000 (23:10 +0300)
committerGitHub <noreply@github.com>
Wed, 5 Oct 2022 20:10:24 +0000 (22:10 +0200)
Based on https://stackoverflow.com/a/69410299/764870.

src/util/file.cpp
unittest/test_util_file.cpp

index b3d3771fcf332e29030fb8b68724aa41aea85f08..964d684611e35d26d3dffcc9664e2900eaf1fd38 100644 (file)
@@ -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
index 9b99d15014665a83284d2a4024e3733dc9fe07a2..cc677137886f2fd971834a38c21f8b6bccc466df 100644 (file)
@@ -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