Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1624)

Unified Diff: runtime/bin/file_win.cc

Issue 2761673002: [dart:io][windows] Use WriteFile instead of _write (Closed)
Patch Set: Format stdio.dart Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/file_unsupported.cc ('k') | runtime/bin/io_natives.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/file_win.cc
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 883b911a13b0f571995859177f61852903d562bc..87734a9e20321420081b64ab2767154d3fd203d7 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -26,48 +26,13 @@ namespace bin {
class FileHandle {
public:
- explicit FileHandle(int fd)
- : fd_(fd), real_fd_(-1), binary_(true), is_atty_(false) {}
+ explicit FileHandle(int fd) : fd_(fd) {}
~FileHandle() {}
int fd() const { return fd_; }
void set_fd(int fd) { fd_ = fd; }
- int real_fd() const {
- ASSERT(is_atty_);
- return real_fd_;
- }
- void set_real_fd(int real_fd) {
- ASSERT(is_atty_);
- real_fd_ = real_fd;
- }
-
- bool binary() const { return binary_; }
- void SetBinary(bool binary) {
- ASSERT(fd_ >= 0);
- if (binary) {
- // Setting the mode to _O_TEXT is needed first to reset _write to allow
- // an odd number of bytes, which setting to _O_BINARY alone doesn't
- // accomplish.
- if (binary != binary_) {
- _setmode(fd_, _O_TEXT);
- }
- _setmode(fd_, _O_BINARY);
- } else {
- // Only allow non-binary modes if we're attached to a terminal.
- ASSERT(_isatty(fd_));
- _setmode(fd_, _O_WTEXT);
- }
- binary_ = binary;
- }
-
- bool is_atty() const { return is_atty_; }
- void set_is_atty(bool is_atty) { is_atty_ = is_atty; }
-
private:
int fd_;
- int real_fd_;
- bool binary_;
- bool is_atty_;
DISALLOW_COPY_AND_ASSIGN(FileHandle);
};
@@ -84,13 +49,7 @@ File::~File() {
void File::Close() {
ASSERT(handle_->fd() >= 0);
- int closing_fd;
- if (handle_->is_atty()) {
- close(handle_->fd());
- closing_fd = handle_->real_fd();
- } else {
- closing_fd = handle_->fd();
- }
+ int closing_fd = handle_->fd();
if ((closing_fd == _fileno(stdout)) || (closing_fd == _fileno(stderr))) {
int fd = _open("NUL", _O_WRONLY);
ASSERT(fd >= 0);
@@ -173,15 +132,33 @@ int64_t File::Read(void* buffer, int64_t num_bytes) {
int64_t File::Write(const void* buffer, int64_t num_bytes) {
int fd = handle_->fd();
ASSERT(fd >= 0);
- if (handle_->binary()) {
- return _write(fd, buffer, num_bytes);
- } else {
- // If we've done _setmode(fd, _O_WTEXT) then _write() expects
- // a buffer of wchar_t with an even unmber of bytes.
- Utf8ToWideScope wide(reinterpret_cast<const char*>(buffer), num_bytes);
- ASSERT((wide.size_in_bytes() % 2) == 0);
- return _write(fd, wide.wide(), wide.size_in_bytes());
+ HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ DWORD written = 0;
+ BOOL result = WriteFile(handle, buffer, num_bytes, &written, NULL);
+ if (!result) {
+ return -1;
}
+ DWORD mode;
+ int64_t bytes_written = written;
+ if (GetConsoleMode(handle, &mode)) {
+ // If `handle` is for a console, then `written` may refer to the number of
+ // characters printed to the screen rather than the number of bytes of the
+ // buffer that were actually consumed. To compute the number of bytes that
+ // were actually consumed, we convert the buffer to a wchar_t using the
+ // console's current code page, filling as many characters as were
+ // printed, and then convert that many characters back to the encoding for
+ // the code page, which gives the number of bytes of `buffer` used to
+ // generate the characters that were printed.
+ wchar_t* wide = new wchar_t[written];
+ int cp = GetConsoleOutputCP();
+ MultiByteToWideChar(cp, 0, reinterpret_cast<const char*>(buffer), -1, wide,
+ written);
+ int buffer_len =
+ WideCharToMultiByte(cp, 0, wide, written, NULL, 0, NULL, NULL);
+ delete wide;
+ bytes_written = buffer_len;
+ }
+ return bytes_written;
}
@@ -218,17 +195,6 @@ bool File::SetPosition(int64_t position) {
}
-void File::SetTranslation(DartFileTranslation translation) {
- ASSERT(handle_->fd() >= 0);
- // Only allow setting the translation mode if we're attached to a terminal.
- // TODO(zra): Is this restriction needed? Is it already handled correctly
- // by _write()?
- if (handle_->is_atty()) {
- handle_->SetBinary(translation == kBinary);
- }
-}
-
-
bool File::Truncate(int64_t length) {
ASSERT(handle_->fd() >= 0);
return _chsize_s(handle_->fd(), length) == 0;
@@ -342,22 +308,8 @@ File* File::OpenStdio(int fd) {
default:
UNREACHABLE();
}
- FileHandle* handle;
- if (_isatty(stdio_fd)) {
- // We _dup these fds to avoid different Isoaltes racing on calls to
- // _setmode() and _write() on the same file descriptor. That is, a call to
- // _setmode() followed by a call to _write() on the same file descriptor is
- // not atomic. When the corresponding Dart File object is closed, these
- // dup'd fds will be closed.
- int stdio_fd_dup = _dup(stdio_fd);
- handle = new FileHandle(stdio_fd_dup);
- handle->set_is_atty(true);
- handle->set_real_fd(stdio_fd);
- } else {
- handle = new FileHandle(stdio_fd);
- }
- handle->SetBinary(true);
- return new File(handle);
+ _setmode(stdio_fd, _O_BINARY);
+ return new File(new FileHandle(stdio_fd));
}
« no previous file with comments | « runtime/bin/file_unsupported.cc ('k') | runtime/bin/io_natives.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698