diff --git a/format.cc b/format.cc index 1a6e4e22..124d552f 100644 --- a/format.cc +++ b/format.cc @@ -487,6 +487,11 @@ FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { return 0; } +# ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wshadow" +# endif + FMT_FUNC void fmt::WindowsError::init( int error_code, StringRef format_str, ArgList args) { error_code_ = error_code; @@ -496,6 +501,10 @@ FMT_FUNC void fmt::WindowsError::init( base = std::runtime_error(w.str()); } +# ifdef __GNUC__ +# pragma GCC diagnostic pop +# endif + #endif FMT_FUNC void fmt::internal::format_system_error( diff --git a/posix.cc b/posix.cc index b4893cd6..be5f8eba 100644 --- a/posix.cc +++ b/posix.cc @@ -30,7 +30,7 @@ #include "posix.h" -#include +#include #include #include @@ -96,12 +96,35 @@ void fmt::BufferedFile::close() { } int fmt::BufferedFile::fileno() const { + assert(file_ && "File has been closed"); int fd = FMT_POSIX_CALL(fileno(file_)); if (fd == -1) throw SystemError(errno, "cannot get file descriptor"); return fd; } +void fmt::BufferedFile::flush() const { + assert(file_ && "File has been closed"); + if (FMT_SYSTEM(fflush(file_)) != 0) { + throw SystemError(errno, "cannot flush file"); + } +} + +void fmt::BufferedFile::write(fmt::StringRef str) { + assert(file_ && "File has been closed"); + size_t result = FMT_SYSTEM(fwrite(str.c_str(), str.size(), 1, file_)); + if (result < str.size()) { + // FIXME: Will fwrite set errno? + throw SystemError(errno, "failed to write raw string, only {} character(s) written", result); + } +} + +void fmt::BufferedFile::write(char c) { + assert(file_ && "File has been closed"); + if (FMT_SYSTEM(fputc(c, file_)) == EOF) + throw SystemError(errno, "failed to write '{}'", c); +} + fmt::File::File(fmt::StringRef path, int oflag) { int mode = S_IRUSR | S_IWUSR; #ifdef _WIN32 @@ -134,13 +157,13 @@ void fmt::File::close() { fmt::LongLong fmt::File::size() const { #ifdef _WIN32 - LARGE_INTEGER size = {}; + LARGE_INTEGER filesize = {}; HANDLE handle = reinterpret_cast(_get_osfhandle(fd_)); - if (!FMT_SYSTEM(GetFileSizeEx(handle, &size))) + if (!FMT_SYSTEM(GetFileSizeEx(handle, &filesize))) throw WindowsError(GetLastError(), "cannot get file size"); - FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(size.QuadPart), + FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(filesize.QuadPart), "return type of File::size is not large enough"); - return size.QuadPart; + return filesize.QuadPart; #else typedef struct stat Stat; Stat file_stat = Stat(); @@ -228,7 +251,7 @@ fmt::BufferedFile fmt::File::fdopen(const char *mode) { long fmt::getpagesize() { #ifdef _WIN32 - SYSTEM_INFO si = {}; + SYSTEM_INFO si; GetSystemInfo(&si); return si.dwPageSize; #else diff --git a/posix.h b/posix.h index a2cf2b13..6d0e4dab 100644 --- a/posix.h +++ b/posix.h @@ -33,6 +33,7 @@ #include #include +#include #include "format.h" @@ -43,9 +44,9 @@ #ifndef FMT_POSIX # ifdef _WIN32 // Fix warnings about deprecated symbols. -# define FMT_POSIX(call) _##call +# define FMT_POSIX(symbol) _##symbol # else -# define FMT_POSIX(call) call +# define FMT_POSIX(symbol) symbol # endif #endif @@ -53,7 +54,7 @@ #ifdef FMT_SYSTEM # define FMT_POSIX_CALL(call) FMT_SYSTEM(call) #else -# define FMT_SYSTEM(call) call +# define FMT_SYSTEM(call) ::call # ifdef _WIN32 // Fix warnings about deprecated symbols. # define FMT_POSIX_CALL(call) ::_##call @@ -188,12 +189,34 @@ public: // Returns the pointer to a FILE object representing this file. FILE *get() const FMT_NOEXCEPT { return file_; } + // Returns the system file number of this file int fileno() const; + // Flushes the buffer of this file + void flush() const; + + // Writes raw string without formatting + void write(fmt::StringRef str); + + // Writes a single charactor without formatting + void write(char c); + + // Writes a new line + void writeln() { + write('\n'); + } + void print(fmt::StringRef format_str, const ArgList &args) { + assert(file_ && "File has been closed"); fmt::print(file_, format_str, args); } + void printf(fmt::StringRef format_str, const ArgList &args) { + assert(file_ && "File has been closed"); + fmt::fprintf(file_, format_str, args); + } + FMT_VARIADIC(void, print, fmt::StringRef) + FMT_VARIADIC(void, printf, fmt::StringRef) }; // A file. Closed file is represented by a File object with descriptor -1. diff --git a/test/posix-test.cc b/test/posix-test.cc index c9529688..fe18cd62 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -178,6 +178,18 @@ int test::fileno(FILE *stream) { return ::FMT_POSIX(fileno(stream)); } +int test::fflush(FILE *stream) { + return ::fflush(stream); +} + +int test::fwrite(const void *str, size_t size, size_t count, FILE *stream) { + return ::fwrite(str, size, count, stream); +} + +int test::fputc(int ch, FILE *stream) { + return ::fputc(ch, stream); +} + #ifndef _WIN32 # define EXPECT_RETRY(statement, func, message) \ func##_count = 1; \ diff --git a/test/posix-test.h b/test/posix-test.h index 4768cb94..7ab69bcb 100644 --- a/test/posix-test.h +++ b/test/posix-test.h @@ -73,7 +73,10 @@ int pipe(int *pfds, unsigned psize, int textmode); FILE *fopen(const char *filename, const char *mode); int fclose(FILE *stream); int fileno(FILE *stream); +int fflush(FILE *stream); +int fwrite(const void *str, size_t size, size_t count, FILE *stream); +int fputc(int ch, FILE *stream); } // namespace test #define FMT_SYSTEM(call) test::call diff --git a/test/util-test.cc b/test/util-test.cc index fd295525..8b8a20a1 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -699,9 +699,8 @@ void test_count_digits() { } TEST(UtilTest, StringRef) { - char space[100]; - std::strcpy(space, "some string"); - EXPECT_EQ(sizeof("some string") - 1, StringRef(space).size()); + char space[100] = "some string"; + EXPECT_EQ(std::strlen(space), StringRef(space).size()); } TEST(UtilTest, CountDigits) {