1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 17:30:16 +00:00

[windows] Make most file_win.cc functions use malloc for string conversions.

They have been using Dart_ScopeAllocate(), which makes them impossible
to use outside of a scope.

Also turn on inlining in the GN Debug windows build to match the gyp build
and speed things up a bit.

R=asiva@google.com, rmacnak@google.com

Review URL: https://codereview.chromium.org/2439173002 .
This commit is contained in:
Zach Anderson 2016-10-21 14:55:37 -07:00
parent ba04d1d627
commit b6ea87c444
12 changed files with 137 additions and 126 deletions

View File

@ -732,10 +732,11 @@ config("optimize") {
# Turn off optimizations.
config("no_optimize") {
if (is_win) {
# The only difference on windows is that the inlining is less aggressive.
# (We accept the default level). Otherwise it is very slow.
cflags = [
"/O2", # Do some optimizations.
"/Oy-", # Disable omitting frame pointers, must be after /O2.
"/Ob0", # Disable all inlining (on by default).
]
} else if (is_android) {
# On Android we kind of optimize some things that don't affect debugging

View File

@ -50,8 +50,8 @@ const char* PathBuffer::AsScopedString() const {
bool PathBuffer::Add(const char* name) {
const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(name);
return AddW(wide_name);
Utf8ToWideScope wide_name(name);
return AddW(wide_name.wide());
}
@ -377,8 +377,8 @@ static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) {
Directory::ExistsResult Directory::Exists(const char* dir_name) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name);
return ExistsHelper(system_name);
Utf8ToWideScope system_name(dir_name);
return ExistsHelper(system_name.wide());
}
@ -412,19 +412,19 @@ const char* Directory::Current() {
bool Directory::SetCurrent(const char* path) {
const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path);
bool result = SetCurrentDirectoryW(system_path) != 0;
Utf8ToWideScope system_path(path);
bool result = SetCurrentDirectoryW(system_path.wide()) != 0;
return result;
}
bool Directory::Create(const char* dir_name) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(dir_name);
int create_status = CreateDirectoryW(system_name, NULL);
Utf8ToWideScope system_name(dir_name);
int create_status = CreateDirectoryW(system_name.wide(), NULL);
// If the directory already existed, treat it as a success.
if ((create_status == 0) &&
(GetLastError() == ERROR_ALREADY_EXISTS) &&
(ExistsHelper(system_name) == EXISTS)) {
(ExistsHelper(system_name.wide()) == EXISTS)) {
return true;
}
return (create_status != 0);
@ -446,8 +446,8 @@ const char* Directory::CreateTemp(const char* prefix) {
// descriptor inherited from its parent directory.
// The return value is Dart_ScopeAllocated.
PathBuffer path;
const wchar_t* system_prefix = StringUtilsWin::Utf8ToWide(prefix);
if (!path.AddW(system_prefix)) {
Utf8ToWideScope system_prefix(prefix);
if (!path.AddW(system_prefix.wide())) {
return NULL;
}
@ -481,16 +481,16 @@ const char* Directory::CreateTemp(const char* prefix) {
bool Directory::Delete(const char* dir_name, bool recursive) {
bool result = false;
const wchar_t* system_dir_name = StringUtilsWin::Utf8ToWide(dir_name);
Utf8ToWideScope system_dir_name(dir_name);
if (!recursive) {
if (File::GetType(dir_name, true) == File::kIsDirectory) {
result = (RemoveDirectoryW(system_dir_name) != 0);
result = (RemoveDirectoryW(system_dir_name.wide()) != 0);
} else {
SetLastError(ERROR_FILE_NOT_FOUND);
}
} else {
PathBuffer path;
if (path.AddW(system_dir_name)) {
if (path.AddW(system_dir_name.wide())) {
result = DeleteRecursively(&path);
}
}
@ -499,13 +499,13 @@ bool Directory::Delete(const char* dir_name, bool recursive) {
bool Directory::Rename(const char* path, const char* new_path) {
const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path);
const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
ExistsResult exists = ExistsHelper(system_path);
Utf8ToWideScope system_path(path);
Utf8ToWideScope system_new_path(new_path);
ExistsResult exists = ExistsHelper(system_path.wide());
if (exists != EXISTS) {
return false;
}
ExistsResult new_exists = ExistsHelper(system_new_path);
ExistsResult new_exists = ExistsHelper(system_new_path.wide());
// MoveFile does not allow replacing exising directories. Therefore,
// if the new_path is currently a directory we need to delete it
// first.
@ -517,7 +517,7 @@ bool Directory::Rename(const char* path, const char* new_path) {
}
DWORD flags = MOVEFILE_WRITE_THROUGH;
int move_status =
MoveFileExW(system_path, system_new_path, flags);
MoveFileExW(system_path.wide(), system_new_path.wide(), flags);
return (move_status != 0);
}

View File

@ -92,7 +92,7 @@ void FUNCTION_NAME(File_Open)(Dart_NativeArguments args) {
// reading. This is to prevent the opening of directories as
// files. Directories can be opened for reading using the posix
// 'open' call.
File* file = File::ScopedOpen(filename, file_mode);
File* file = File::Open(filename, file_mode);
if (file != NULL) {
Dart_SetReturnValue(args,
Dart_NewInteger(reinterpret_cast<intptr_t>(file)));
@ -677,7 +677,7 @@ CObject* File::OpenRequest(const CObjectArray& request) {
File::DartFileOpenMode dart_file_mode =
static_cast<File::DartFileOpenMode>(mode.Value());
File::FileOpenMode file_mode = File::DartModeToFileMode(dart_file_mode);
file = File::ScopedOpen(filename.CString(), file_mode);
file = File::Open(filename.CString(), file_mode);
if (file != NULL) {
return new CObjectIntptr(
CObject::NewIntptr(reinterpret_cast<intptr_t>(file)));

View File

@ -157,15 +157,8 @@ class File : public ReferenceCounted<File> {
// reading and writing. If mode contains kWrite and the file does
// not exist the file is created. The file is truncated to length 0 if
// mode contains kTruncate. Assumes we are in an API scope.
static File* ScopedOpen(const char* path, FileOpenMode mode);
// Like ScopedOpen(), but no API scope is needed.
static File* Open(const char* path, FileOpenMode mode);
// Caution! On Windows, the static functions below may call
// Dart_ScopeAllocate() to do string conversions! If you call these functions
// without a scope, they will fail on Windows!
// Create a file object for the specified stdio file descriptor
// (stdin, stout or stderr).
static File* OpenStdio(int fd);
@ -181,15 +174,17 @@ class File : public ReferenceCounted<File> {
static int64_t LengthFromPath(const char* path);
static void Stat(const char* path, int64_t* data);
static time_t LastModified(const char* path);
static const char* LinkTarget(const char* pathname);
static bool IsAbsolutePath(const char* path);
static const char* GetCanonicalPath(const char* path);
static const char* PathSeparator();
static const char* StringEscapedPathSeparator();
static Type GetType(const char* path, bool follow_links);
static Identical AreIdentical(const char* file_1, const char* file_2);
static StdioHandleType GetStdioHandleType(int fd);
// LinkTarget and GetCanonicalPath may call Dart_ScopeAllocate.
static const char* LinkTarget(const char* pathname);
static const char* GetCanonicalPath(const char* path);
static FileOpenMode DartModeToFileMode(DartFileOpenMode mode);
static CObject* ExistsRequest(const CObjectArray& request);

View File

@ -183,7 +183,7 @@ File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
}
File* File::ScopedOpen(const char* name, FileOpenMode mode) {
File* File::Open(const char* name, FileOpenMode mode) {
// Report errors for non-regular files.
struct stat st;
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
@ -220,12 +220,6 @@ File* File::ScopedOpen(const char* name, FileOpenMode mode) {
}
File* File::Open(const char* path, FileOpenMode mode) {
// ScopedOpen doesn't actually need a scope.
return ScopedOpen(path, mode);
}
File* File::OpenStdio(int fd) {
return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
}

View File

@ -164,7 +164,7 @@ File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
}
File* File::ScopedOpen(const char* name, FileOpenMode mode) {
File* File::Open(const char* name, FileOpenMode mode) {
// Report errors for non-regular files.
struct stat st;
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
@ -201,12 +201,6 @@ File* File::ScopedOpen(const char* name, FileOpenMode mode) {
}
File* File::Open(const char* path, FileOpenMode mode) {
// ScopedOpen doesn't actually need a scope.
return ScopedOpen(path, mode);
}
File* File::OpenStdio(int fd) {
return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
}

View File

@ -182,7 +182,7 @@ File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
}
File* File::ScopedOpen(const char* name, FileOpenMode mode) {
File* File::Open(const char* name, FileOpenMode mode) {
// Report errors for non-regular files.
struct stat64 st;
if (TEMP_FAILURE_RETRY(stat64(name, &st)) == 0) {
@ -220,12 +220,6 @@ File* File::ScopedOpen(const char* name, FileOpenMode mode) {
}
File* File::Open(const char* path, FileOpenMode mode) {
// ScopedOpen doesn't actually need a scope.
return ScopedOpen(path, mode);
}
File* File::OpenStdio(int fd) {
return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
}

View File

@ -185,7 +185,7 @@ File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
}
File* File::ScopedOpen(const char* name, FileOpenMode mode) {
File* File::Open(const char* name, FileOpenMode mode) {
// Report errors for non-regular files.
struct stat st;
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
@ -223,12 +223,6 @@ File* File::ScopedOpen(const char* name, FileOpenMode mode) {
}
File* File::Open(const char* path, FileOpenMode mode) {
// ScopedOpen doesn't actually need a scope.
return ScopedOpen(path, mode);
}
File* File::OpenStdio(int fd) {
return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
}

View File

@ -40,8 +40,8 @@ intptr_t FileSystemWatcher::WatchPath(intptr_t id,
int events,
bool recursive) {
USE(id);
const wchar_t* name = StringUtilsWin::Utf8ToWide(path);
HANDLE dir = CreateFileW(name,
Utf8ToWideScope name(path);
HANDLE dir = CreateFileW(name.wide(),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ |
FILE_SHARE_WRITE |

View File

@ -233,21 +233,9 @@ File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
}
File* File::ScopedOpen(const char* name, FileOpenMode mode) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
return FileOpenW(system_name, mode);
}
File* File::Open(const char* path, FileOpenMode mode) {
int path_len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
wchar_t* system_name = new wchar_t[path_len];
if (system_name == NULL) {
return NULL;
}
MultiByteToWideChar(CP_UTF8, 0, path, -1, system_name, path_len);
File* file = FileOpenW(system_name, mode);
delete[] system_name;
Utf8ToWideScope system_name(path);
File* file = FileOpenW(system_name.wide(), mode);
return file;
}
@ -270,8 +258,8 @@ File* File::OpenStdio(int fd) {
bool File::Exists(const char* name) {
struct __stat64 st;
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
bool stat_status = _wstat64(system_name, &st);
Utf8ToWideScope system_name(name);
bool stat_status = _wstat64(system_name.wide(), &st);
if (stat_status == 0) {
return ((st.st_mode & S_IFMT) == S_IFREG);
} else {
@ -281,8 +269,8 @@ bool File::Exists(const char* name) {
bool File::Create(const char* name) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
int fd = _wopen(system_name, O_RDONLY | O_CREAT, 0666);
Utf8ToWideScope system_name(name);
int fd = _wopen(system_name.wide(), O_RDONLY | O_CREAT, 0666);
if (fd < 0) {
return false;
}
@ -326,17 +314,17 @@ static const int kMountPointHeaderSize = 4 * sizeof USHORT;
bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
const wchar_t* name = StringUtilsWin::Utf8ToWide(utf8_name);
int create_status = CreateDirectoryW(name, NULL);
Utf8ToWideScope name(utf8_name);
int create_status = CreateDirectoryW(name.wide(), NULL);
// If the directory already existed, treat it as a success.
if ((create_status == 0) &&
((GetLastError() != ERROR_ALREADY_EXISTS) ||
((GetFileAttributesW(name) & FILE_ATTRIBUTE_DIRECTORY) != 0))) {
((GetFileAttributesW(name.wide()) & FILE_ATTRIBUTE_DIRECTORY) != 0))) {
return false;
}
HANDLE dir_handle = CreateFileW(
name,
name.wide(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@ -347,8 +335,8 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
return false;
}
const wchar_t* target = StringUtilsWin::Utf8ToWide(utf8_target);
int target_len = wcslen(target);
Utf8ToWideScope target(utf8_target);
int target_len = wcslen(target.wide());
if (target_len > MAX_PATH - 1) {
CloseHandle(dir_handle);
return false;
@ -357,13 +345,13 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
int reparse_data_buffer_size =
sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR;
REPARSE_DATA_BUFFER* reparse_data_buffer =
reinterpret_cast<REPARSE_DATA_BUFFER*>(Dart_ScopeAllocate(
reparse_data_buffer_size));
reinterpret_cast<REPARSE_DATA_BUFFER*>(malloc(reparse_data_buffer_size));
reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, target);
wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer,
target.wide());
wcscpy(
reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1,
target);
target.wide());
reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0;
reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength =
target_len * sizeof WCHAR;
@ -383,6 +371,7 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
0,
&dummy_received_bytes,
NULL);
free(reparse_data_buffer);
if (CloseHandle(dir_handle) == 0) {
return false;
}
@ -391,20 +380,20 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
bool File::Delete(const char* name) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
int status = _wremove(system_name);
Utf8ToWideScope system_name(name);
int status = _wremove(system_name.wide());
return status != -1;
}
bool File::DeleteLink(const char* name) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
Utf8ToWideScope system_name(name);
bool result = false;
DWORD attributes = GetFileAttributesW(system_name);
DWORD attributes = GetFileAttributesW(system_name.wide());
if ((attributes != INVALID_FILE_ATTRIBUTES) &&
(attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
// It's a junction(link), delete it.
result = (RemoveDirectoryW(system_name) != 0);
result = (RemoveDirectoryW(system_name.wide()) != 0);
} else {
SetLastError(ERROR_NOT_A_REPARSE_POINT);
}
@ -415,11 +404,11 @@ bool File::DeleteLink(const char* name) {
bool File::Rename(const char* old_path, const char* new_path) {
File::Type type = GetType(old_path, false);
if (type == kIsFile) {
const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path);
const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
Utf8ToWideScope system_old_path(old_path);
Utf8ToWideScope system_new_path(new_path);
DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
int move_status =
MoveFileExW(system_old_path, system_new_path, flags);
MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags);
return (move_status != 0);
} else {
SetLastError(ERROR_FILE_NOT_FOUND);
@ -431,11 +420,11 @@ bool File::Rename(const char* old_path, const char* new_path) {
bool File::RenameLink(const char* old_path, const char* new_path) {
File::Type type = GetType(old_path, false);
if (type == kIsLink) {
const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path);
const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
Utf8ToWideScope system_old_path(old_path);
Utf8ToWideScope system_new_path(new_path);
DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
int move_status =
MoveFileExW(system_old_path, system_new_path, flags);
MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags);
return (move_status != 0);
} else {
SetLastError(ERROR_FILE_NOT_FOUND);
@ -447,10 +436,10 @@ bool File::RenameLink(const char* old_path, const char* new_path) {
bool File::Copy(const char* old_path, const char* new_path) {
File::Type type = GetType(old_path, false);
if (type == kIsFile) {
const wchar_t* system_old_path = StringUtilsWin::Utf8ToWide(old_path);
const wchar_t* system_new_path = StringUtilsWin::Utf8ToWide(new_path);
bool success = CopyFileExW(system_old_path,
system_new_path,
Utf8ToWideScope system_old_path(old_path);
Utf8ToWideScope system_new_path(new_path);
bool success = CopyFileExW(system_old_path.wide(),
system_new_path.wide(),
NULL,
NULL,
NULL,
@ -465,8 +454,8 @@ bool File::Copy(const char* old_path, const char* new_path) {
int64_t File::LengthFromPath(const char* name) {
struct __stat64 st;
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
int stat_status = _wstat64(system_name, &st);
Utf8ToWideScope system_name(name);
int stat_status = _wstat64(system_name.wide(), &st);
if (stat_status == 0) {
return st.st_size;
}
@ -565,8 +554,8 @@ void File::Stat(const char* name, int64_t* data) {
data[kType] = type;
if (type != kDoesNotExist) {
struct _stat64 st;
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
int stat_status = _wstat64(system_name, &st);
Utf8ToWideScope system_name(name);
int stat_status = _wstat64(system_name.wide(), &st);
if (stat_status == 0) {
data[kCreatedTime] = st.st_ctime * 1000;
data[kModifiedTime] = st.st_mtime * 1000;
@ -582,8 +571,8 @@ void File::Stat(const char* name, int64_t* data) {
time_t File::LastModified(const char* name) {
struct __stat64 st;
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(name);
int stat_status = _wstat64(system_name, &st);
Utf8ToWideScope system_name(name);
int stat_status = _wstat64(system_name.wide(), &st);
if (stat_status == 0) {
return st.st_mtime;
}
@ -603,9 +592,9 @@ bool File::IsAbsolutePath(const char* pathname) {
const char* File::GetCanonicalPath(const char* pathname) {
const wchar_t* system_name = StringUtilsWin::Utf8ToWide(pathname);
Utf8ToWideScope system_name(pathname);
HANDLE file_handle = CreateFileW(
system_name,
system_name.wide(),
0,
FILE_SHARE_READ,
NULL,
@ -639,7 +628,7 @@ const char* File::GetCanonicalPath(const char* pathname) {
if ((result_size < MAX_PATH - 1 + 4) &&
(result_size > 4) &&
(wcsncmp(path, L"\\\\?\\", 4) == 0) &&
(wcsncmp(system_name, L"\\\\?\\", 4) != 0)) {
(wcsncmp(system_name.wide(), L"\\\\?\\", 4) != 0)) {
result = StringUtilsWin::WideToUtf8(path + 4);
} else {
result = StringUtilsWin::WideToUtf8(path);
@ -670,19 +659,15 @@ File::StdioHandleType File::GetStdioHandleType(int fd) {
File::Type File::GetType(const char* pathname, bool follow_links) {
// Convert to wchar_t string.
int name_len = MultiByteToWideChar(CP_UTF8, 0, pathname, -1, NULL, 0);
wchar_t* name;
name = new wchar_t[name_len];
MultiByteToWideChar(CP_UTF8, 0, pathname, -1, name, name_len);
DWORD attributes = GetFileAttributesW(name);
Utf8ToWideScope name(pathname);
DWORD attributes = GetFileAttributesW(name.wide());
File::Type result = kIsFile;
if (attributes == INVALID_FILE_ATTRIBUTES) {
result = kDoesNotExist;
} else if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
if (follow_links) {
HANDLE dir_handle = CreateFileW(
name,
name.wide(),
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@ -701,7 +686,6 @@ File::Type File::GetType(const char* pathname, bool follow_links) {
} else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
result = kIsDirectory;
}
delete[] name;
return result;
}
@ -710,9 +694,9 @@ File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
BY_HANDLE_FILE_INFORMATION file_info[2];
const char* file_names[2] = { file_1, file_2 };
for (int i = 0; i < 2; ++i) {
const wchar_t* wide_name = StringUtilsWin::Utf8ToWide(file_names[i]);
Utf8ToWideScope wide_name(file_names[i]);
HANDLE file_handle = CreateFileW(
wide_name,
wide_name.wide(),
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,

View File

@ -370,12 +370,12 @@ bool Socket::ReverseLookup(const RawAddr& addr,
bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
int result;
const wchar_t* system_address = StringUtilsWin::Utf8ToWide(address);
Utf8ToWideScope system_address(address);
if (type == SocketAddress::TYPE_IPV4) {
result = InetPton(AF_INET, system_address, &addr->in.sin_addr);
result = InetPton(AF_INET, system_address.wide(), &addr->in.sin_addr);
} else {
ASSERT(type == SocketAddress::TYPE_IPV6);
result = InetPton(AF_INET6, system_address, &addr->in6.sin6_addr);
result = InetPton(AF_INET6, system_address.wide(), &addr->in6.sin6_addr);
}
return result == 1;
}

View File

@ -37,6 +37,61 @@ class StringUtilsWin {
DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtilsWin);
};
// These scopes provide strings converted as indicated by the scope names.
// The provided strings are allocated with 'new' and have the same lifetime as
// the scope.
class WideToUtf8Scope {
public:
explicit WideToUtf8Scope(const wchar_t* wide) {
intptr_t utf8_len = WideCharToMultiByte(
CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL);
char* utf8 = new char[utf8_len];
WideCharToMultiByte(CP_UTF8, 0, wide, -1, utf8, utf8_len, NULL, NULL);
length_ = utf8_len;
utf8_ = utf8;
}
~WideToUtf8Scope() {
delete[] utf8_;
utf8_ = NULL;
}
char* utf8() const { return utf8_; }
intptr_t length() const { return length_; }
private:
intptr_t length_;
char* utf8_;
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(WideToUtf8Scope);
};
class Utf8ToWideScope {
public:
explicit Utf8ToWideScope(const char* utf8) {
int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
wchar_t* wide = new wchar_t[wide_len];
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wide, wide_len);
length_ = wide_len;
wide_ = wide;
}
~Utf8ToWideScope() {
delete[] wide_;
}
wchar_t* wide() const { return wide_; }
intptr_t length() const { return length_; }
private:
intptr_t length_;
wchar_t* wide_;
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8ToWideScope);
};
} // namespace bin
} // namespace dart