From 4bcd7dd5029a13c07a0491231cab3b2bb44aff4f Mon Sep 17 00:00:00 2001 From: Matthew Glazar Date: Fri, 25 Sep 2020 20:18:29 -0700 Subject: [PATCH] Move posix_fd_file, etc. into their own file I want to use posix_fd_file outside of file.cpp. Move the posix_fd_file class (and the related windows_handle_file class) into its own module so it can be reused. This commit should not change behavior. --- src/CMakeLists.txt | 1 + src/file-handle.cpp | 138 ++++++++++++++++++++++++ src/file.cpp | 114 +------------------- src/include/quick-lint-js/file-handle.h | 71 ++++++++++++ src/include/quick-lint-js/narrow-cast.h | 8 +- 5 files changed, 215 insertions(+), 117 deletions(-) create mode 100644 src/file-handle.cpp create mode 100644 src/include/quick-lint-js/file-handle.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d6108f09c..d9c11c809c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,6 +35,7 @@ quick_lint_js_add_library( assert.cpp char8.cpp error.cpp + file-handle.cpp file.cpp integer.cpp language.cpp diff --git a/src/file-handle.cpp b/src/file-handle.cpp new file mode 100644 index 0000000000..e4940cd776 --- /dev/null +++ b/src/file-handle.cpp @@ -0,0 +1,138 @@ +// quick-lint-js finds bugs in JavaScript programs. +// Copyright (C) 2020 Matthew Glazar +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if QLJS_HAVE_FCNTL_H +#include +#endif + +#if QLJS_HAVE_SYS_STAT_H +#include +#endif + +#if QLJS_HAVE_UNISTD_H +#include +#endif + +#if QLJS_HAVE_WINDOWS_H +#include +#endif + +namespace quick_lint_js { +#if QLJS_HAVE_WINDOWS_H +windows_handle_file::windows_handle_file(HANDLE handle) noexcept + : handle_(handle) {} + +windows_handle_file::~windows_handle_file() { + if (!::CloseHandle(this->handle_)) { + std::fprintf(stderr, "error: failed to close file\n"); + } +} + +HANDLE windows_handle_file::get() noexcept { return this->handle_; } + +std::optional windows_handle_file::read(void *buffer, + int buffer_size) noexcept { + DWORD read_size; + if (!::ReadFile(this->handle_, buffer, narrow_cast(buffer_size), + &read_size, + /*lpOverlapped=*/nullptr)) { + return std::nullopt; + } + return narrow_cast(read_size); +} + +std::string windows_handle_file::get_last_error_message() { + return windows_error_message(::GetLastError()); +} +#endif + +#if QLJS_HAVE_UNISTD_H +posix_fd_file::posix_fd_file(int fd) noexcept : fd_(fd) {} + +posix_fd_file::~posix_fd_file() { + int rc = ::close(this->fd_); + if (rc != 0) { + std::fprintf(stderr, "error: failed to close file: %s\n", + std::strerror(errno)); + } +} + +int posix_fd_file::get() noexcept { return this->fd_; } + +std::optional posix_fd_file::read(void *buffer, int buffer_size) noexcept { + ::ssize_t read_size = + ::read(this->fd_, buffer, narrow_cast(buffer_size)); + if (read_size == -1) { + return std::nullopt; + } + return narrow_cast(read_size); +} + +std::string posix_fd_file::get_last_error_message() { + return std::strerror(errno); +} +#endif + +#if QLJS_HAVE_WINDOWS_H +namespace { +std::string_view remove_suffix_if_present(std::string_view s, + std::string_view suffix) noexcept { + if (s.ends_with(suffix)) { + s.remove_suffix(suffix.size()); + } + return s; +} +} + +std::string windows_error_message(DWORD error) { + // TODO(strager): Use FormatMessageW. + LPSTR get_last_error_message; + DWORD get_last_error_message_length = ::FormatMessageA( + /*dwFlags=*/FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + /*lpSource=*/nullptr, + /*dwMessageId=*/::GetLastError(), + /*dwLanguageId=*/0, + /*lpBuffer=*/reinterpret_cast(&get_last_error_message), + /*nSize=*/(std::numeric_limits::max)(), + /*Arguments=*/nullptr); + if (get_last_error_message_length == 0) { + // FormatMessageA failed. + return "unknown error"; + } + + std::string_view message( + get_last_error_message, + narrow_cast(get_last_error_message_length)); + message = remove_suffix_if_present(message, "\r\n"); + std::string message_copy(message); + static_cast(::LocalFree(get_last_error_message)); + return message_copy; +} +#endif +} diff --git a/src/file.cpp b/src/file.cpp index 99182c9104..ef79a849de 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -19,16 +19,14 @@ #include #include #include -#include #include #include #include +#include #include #include #include -#include #include -#include #if QLJS_HAVE_FCNTL_H #include @@ -38,10 +36,6 @@ #include #endif -#if QLJS_HAVE_UNISTD_H -#include -#endif - #if QLJS_HAVE_WINDOWS_H #include #endif @@ -70,77 +64,9 @@ read_file_result read_file_result::failure(const std::string &error) { namespace { #if defined(QLJS_FILE_WINDOWS) -std::string windows_error_message(DWORD error); -#endif - -#if defined(QLJS_FILE_WINDOWS) -class windows_handle_file { - public: - explicit windows_handle_file(HANDLE handle) noexcept : handle_(handle) {} - - windows_handle_file(const windows_handle_file &) = delete; - windows_handle_file &operator=(const windows_handle_file &) = delete; - - ~windows_handle_file() { - if (!::CloseHandle(this->handle_)) { - std::fprintf(stderr, "error: failed to close file\n"); - } - } - - HANDLE get() noexcept { return this->handle_; } - - std::optional read(void *buffer, int buffer_size) noexcept { - DWORD read_size; - if (!::ReadFile(this->handle_, buffer, narrow_cast(buffer_size), - &read_size, - /*lpOverlapped=*/nullptr)) { - return std::nullopt; - } - return narrow_cast(read_size); - } - - static std::string get_last_error_message() { - return windows_error_message(::GetLastError()); - } - - private: - HANDLE handle_; -}; using platform_file = windows_handle_file; #endif - #if defined(QLJS_FILE_POSIX) -class posix_fd_file { - public: - explicit posix_fd_file(int fd) noexcept : fd_(fd) {} - - posix_fd_file(const posix_fd_file &) = delete; - posix_fd_file &operator=(const posix_fd_file &) = delete; - - ~posix_fd_file() { - int rc = ::close(this->fd_); - if (rc != 0) { - std::fprintf(stderr, "error: failed to close file: %s\n", - std::strerror(errno)); - } - } - - int get() noexcept { return this->fd_; } - - std::optional read(void *buffer, int buffer_size) noexcept { - ::ssize_t read_size = - ::read(this->fd_, buffer, narrow_cast(buffer_size)); - if (read_size == -1) { - return std::nullopt; - } - return narrow_cast(read_size); - } - - static std::string get_last_error_message() { return std::strerror(errno); } - - private: - int fd_; -}; using platform_file = posix_fd_file; #endif @@ -259,42 +185,4 @@ read_file_result read_file(const char *path) { return read_file(path, file); } #endif - -namespace { -#if defined(QLJS_FILE_WINDOWS) -std::string_view remove_suffix_if_present(std::string_view s, - std::string_view suffix) noexcept { - if (s.ends_with(suffix)) { - s.remove_suffix(suffix.size()); - } - return s; -} - -std::string windows_error_message(DWORD error) { - // TODO(strager): Use FormatMessageW. - LPSTR get_last_error_message; - DWORD get_last_error_message_length = ::FormatMessageA( - /*dwFlags=*/FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - /*lpSource=*/nullptr, - /*dwMessageId=*/::GetLastError(), - /*dwLanguageId=*/0, - /*lpBuffer=*/reinterpret_cast(&get_last_error_message), - /*nSize=*/(std::numeric_limits::max)(), - /*Arguments=*/nullptr); - if (get_last_error_message_length == 0) { - // FormatMessageA failed. - return "unknown error"; - } - - std::string_view message( - get_last_error_message, - narrow_cast(get_last_error_message_length)); - message = remove_suffix_if_present(message, "\r\n"); - std::string message_copy(message); - static_cast(::LocalFree(get_last_error_message)); - return message_copy; -} -#endif -} } diff --git a/src/include/quick-lint-js/file-handle.h b/src/include/quick-lint-js/file-handle.h new file mode 100644 index 0000000000..030372df27 --- /dev/null +++ b/src/include/quick-lint-js/file-handle.h @@ -0,0 +1,71 @@ +// quick-lint-js finds bugs in JavaScript programs. +// Copyright (C) 2020 Matthew Glazar +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include + +#if QLJS_HAVE_WINDOWS_H +#include +#endif + +namespace quick_lint_js { +#if QLJS_HAVE_WINDOWS_H +std::string windows_error_message(DWORD error); +#endif + +#if QLJS_HAVE_WINDOWS_H +class windows_handle_file { + public: + explicit windows_handle_file(HANDLE) noexcept; + + windows_handle_file(const windows_handle_file &) = delete; + windows_handle_file &operator=(const windows_handle_file &) = delete; + + ~windows_handle_file(); + + HANDLE get() noexcept; + + std::optional read(void *buffer, int buffer_size) noexcept; + + static std::string get_last_error_message(); + + private: + HANDLE handle_; +}; +#endif + +#if QLJS_HAVE_UNISTD_H +class posix_fd_file { + public: + explicit posix_fd_file(int fd) noexcept; + + posix_fd_file(const posix_fd_file &) = delete; + posix_fd_file &operator=(const posix_fd_file &) = delete; + + ~posix_fd_file(); + + int get() noexcept; + + std::optional read(void *buffer, int buffer_size) noexcept; + + static std::string get_last_error_message(); + + private: + int fd_; +}; +#endif +} diff --git a/src/include/quick-lint-js/narrow-cast.h b/src/include/quick-lint-js/narrow-cast.h index d0b2539ca3..dd1d029e99 100644 --- a/src/include/quick-lint-js/narrow-cast.h +++ b/src/include/quick-lint-js/narrow-cast.h @@ -30,13 +30,13 @@ constexpr bool can_narrow_cast([[maybe_unused]] In x) noexcept { if constexpr (std::is_same_v) { return true; } else if constexpr (std::is_signed_v && std::is_signed_v) { - return out_limits::lowest() <= x && x <= out_limits::max(); + return out_limits::lowest() <= x && x <= (out_limits::max)(); } else if constexpr (std::is_signed_v && !std::is_signed_v) { - return 0 <= x && static_cast(x) <= out_limits::max(); + return 0 <= x && static_cast(x) <= (out_limits::max)(); } else if constexpr (!std::is_signed_v && std::is_signed_v) { - return x <= unsigned_out{out_limits::max()}; + return x <= unsigned_out{(out_limits::max)()}; } else if constexpr (!std::is_signed_v && !std::is_signed_v) { - return x <= out_limits::max(); + return x <= (out_limits::max)(); } }