Fixes two issues with file handling on windows:

. If UNICODE is set, then win32 functions taking file paths use wide
  (utf-16) strings. For example, FindFirstFile really calls to
  FindFirstFileW, which takes a wchar_t*. This adds support for
  the unicode path.
. SetContents() changes from "w" to "wb". This is necessary as
  windows will do some amount of encoding without "b", which results
  in much different values being written.

PiperOrigin-RevId: 564842317
This commit is contained in:
MediaPipe Team 2023-09-12 14:57:24 -07:00 committed by Copybara-Service
parent dbcdb44f7c
commit 5b08a09446

View File

@ -17,6 +17,9 @@
#ifdef _WIN32
#include <Windows.h>
#include <direct.h>
#include <codecvt>
#include <locale>
#else
#include <dirent.h>
#endif // _WIN32
@ -86,11 +89,32 @@ class DirectoryListing {
struct dirent* next_entry_ = nullptr;
};
#else
#if defined(UNICODE)
using PathString = std::wstring;
PathString Utf8ToNative(const std::string& string) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
return converter.from_bytes(string.data(), string.data() + string.size());
}
std::string NativeToUtf8(const PathString& string) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
return converter.to_bytes(string.data(), string.data() + string.size());
}
#define FILE_PATH_LITERAL_INTERNAL(x) L##x
#define FILE_PATH_LITERAL(x) FILE_PATH_LITERAL_INTERNAL(x)
#else
using PathString = std::string;
PathString Utf8ToNative(const std::string& string) { return string; }
std::string NativeToUtf8(const PathString& string) { return string; }
#define FILE_PATH_LITERAL_INTERNAL(x) ##x
#define FILE_PATH_LITERAL(x) FILE_PATH_LITERAL_INTERNAL(x)
#endif
class DirectoryListing {
public:
explicit DirectoryListing(const std::string& directory) {
directory_ = directory;
std::string search_string = directory + "\\*.*";
explicit DirectoryListing(const std::string& directory)
: directory_(Utf8ToNative(directory)) {
PathString search_string = directory_ + Utf8ToNative("\\*.*");
find_handle_ = FindFirstFile(search_string.c_str(), &find_data_);
}
@ -107,10 +131,10 @@ class DirectoryListing {
// after the one that is returned, if it exists.
std::string NextEntry() {
if (HasNextEntry()) {
std::string result =
std::string(directory_ + "\\" + find_data_.cFileName);
PathString result =
directory_ + Utf8ToNative("\\") + PathString(find_data_.cFileName);
ReadNextEntry();
return result;
return NativeToUtf8(result);
} else {
return std::string();
}
@ -119,8 +143,9 @@ class DirectoryListing {
private:
void ReadNextEntry() {
int find_result = FindNextFile(find_handle_, &find_data_);
while (find_result != 0 && (std::string(find_data_.cFileName) == "." ||
std::string(find_data_.cFileName) == "..")) {
while (find_result != 0 &&
(PathString(find_data_.cFileName) == FILE_PATH_LITERAL(".") ||
PathString(find_data_.cFileName) == FILE_PATH_LITERAL(".."))) {
find_result = FindNextFile(find_handle_, &find_data_);
}
@ -130,7 +155,7 @@ class DirectoryListing {
}
}
std::string directory_;
const PathString directory_;
HANDLE find_handle_ = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA find_data_;
};
@ -162,7 +187,7 @@ absl::Status GetContents(absl::string_view file_name, std::string* output,
absl::Status SetContents(absl::string_view file_name,
absl::string_view content) {
FILE* fp = fopen(file_name.data(), "w");
FILE* fp = fopen(file_name.data(), "wb");
if (fp == NULL) {
return mediapipe::InvalidArgumentErrorBuilder(MEDIAPIPE_LOC)
<< "Can't open file: " << file_name;