Commit eaa89e23 authored by Victor Zverovich's avatar Victor Zverovich

Put File, BufferedFile & ErrorCode in the fmt namespace.

parent b692ab58
...@@ -46,7 +46,18 @@ if (FMT_SHARED) ...@@ -46,7 +46,18 @@ if (FMT_SHARED)
set(shared SHARED) set(shared SHARED)
endif () endif ()
add_library(format ${shared} format.cc format.h) include(CheckSymbolExists)
if (WIN32)
check_symbol_exists(open io.h HAVE_OPEN)
else ()
check_symbol_exists(open fcntl.h HAVE_OPEN)
endif ()
if (HAVE_OPEN)
add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1)
set(FMT_POSIX_SRC posix.cc posix.h)
endif ()
add_library(format ${shared} format.cc format.h ${FMT_POSIX_SRC})
if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(format PROPERTIES COMPILE_FLAGS set_target_properties(format PROPERTIES COMPILE_FLAGS
"-Wall -Wextra -pedantic") "-Wall -Wextra -pedantic")
...@@ -55,7 +66,7 @@ if (CPP11_FLAG AND FMT_EXTRA_TESTS) ...@@ -55,7 +66,7 @@ if (CPP11_FLAG AND FMT_EXTRA_TESTS)
set_target_properties(format PROPERTIES COMPILE_FLAGS ${CPP11_FLAG}) set_target_properties(format PROPERTIES COMPILE_FLAGS ${CPP11_FLAG})
# Test compilation with default flags. # Test compilation with default flags.
file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h) file(GLOB src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cc test/*.h)
add_library(testformat format.cc ${src}) add_library(testformat format.cc ${FMT_POSIX_SRC} ${src})
endif () endif ()
add_subdirectory(doc) add_subdirectory(doc)
...@@ -77,16 +88,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") ...@@ -77,16 +88,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=1) add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=1)
endif () endif ()
include(CheckSymbolExists)
if (WIN32)
check_symbol_exists(open io.h HAVE_OPEN)
else ()
check_symbol_exists(open fcntl.h HAVE_OPEN)
endif ()
if (HAVE_OPEN)
add_definitions(-DFMT_USE_FILE_DESCRIPTORS=1)
endif ()
enable_testing() enable_testing()
include_directories(.) include_directories(.)
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "posix.h" #include "posix.h"
#include <errno.h>
#include <limits.h> #include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -44,16 +43,6 @@ ...@@ -44,16 +43,6 @@
#endif // _WIN32 #endif // _WIN32
// Retries the expression while it evaluates to -1 and error equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY(result, expression) \
do { \
result = (expression); \
} while (result == -1 && errno == EINTR)
#else
# define FMT_RETRY(result, expression) result = (expression)
#endif
namespace { namespace {
#ifdef _WIN32 #ifdef _WIN32
// On Windows the count argument to read and write is unsigned, so convert // On Windows the count argument to read and write is unsigned, so convert
...@@ -66,12 +55,12 @@ inline std::size_t ConvertRWCount(std::size_t count) { return count; } ...@@ -66,12 +55,12 @@ inline std::size_t ConvertRWCount(std::size_t count) { return count; }
#endif #endif
} }
BufferedFile::~BufferedFile() FMT_NOEXCEPT(true) { fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT(true) {
if (file_ && FMT_SYSTEM(fclose(file_)) != 0) if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
fmt::ReportSystemError(errno, "cannot close file"); fmt::ReportSystemError(errno, "cannot close file");
} }
void BufferedFile::close() { void fmt::BufferedFile::close() {
if (!file_) if (!file_)
return; return;
int result = FMT_SYSTEM(fclose(file_)); int result = FMT_SYSTEM(fclose(file_));
...@@ -80,14 +69,14 @@ void BufferedFile::close() { ...@@ -80,14 +69,14 @@ void BufferedFile::close() {
fmt::ThrowSystemError(errno, "cannot close file"); fmt::ThrowSystemError(errno, "cannot close file");
} }
int BufferedFile::fileno() const { int fmt::BufferedFile::fileno() const {
int fd = FMT_POSIX_CALL(fileno(file_)); int fd = FMT_POSIX_CALL(fileno(file_));
if (fd == -1) if (fd == -1)
fmt::ThrowSystemError(errno, "cannot get file descriptor"); fmt::ThrowSystemError(errno, "cannot get file descriptor");
return fd; return fd;
} }
File::File(const char *path, int oflag) { fmt::File::File(const char *path, int oflag) {
int mode = S_IRUSR | S_IWUSR; int mode = S_IRUSR | S_IWUSR;
#ifdef _WIN32 #ifdef _WIN32
fd_ = -1; fd_ = -1;
...@@ -99,14 +88,14 @@ File::File(const char *path, int oflag) { ...@@ -99,14 +88,14 @@ File::File(const char *path, int oflag) {
fmt::ThrowSystemError(errno, "cannot open file {}") << path; fmt::ThrowSystemError(errno, "cannot open file {}") << path;
} }
File::~File() FMT_NOEXCEPT(true) { fmt::File::~File() FMT_NOEXCEPT(true) {
// Don't retry close in case of EINTR! // Don't retry close in case of EINTR!
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0) if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
fmt::ReportSystemError(errno, "cannot close file"); fmt::ReportSystemError(errno, "cannot close file");
} }
void File::close() { void fmt::File::close() {
if (fd_ == -1) if (fd_ == -1)
return; return;
// Don't retry close in case of EINTR! // Don't retry close in case of EINTR!
...@@ -117,7 +106,7 @@ void File::close() { ...@@ -117,7 +106,7 @@ void File::close() {
fmt::ThrowSystemError(errno, "cannot close file"); fmt::ThrowSystemError(errno, "cannot close file");
} }
std::streamsize File::read(void *buffer, std::size_t count) { std::streamsize fmt::File::read(void *buffer, std::size_t count) {
std::streamsize result = 0; std::streamsize result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, ConvertRWCount(count)))); FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, ConvertRWCount(count))));
if (result == -1) if (result == -1)
...@@ -125,7 +114,7 @@ std::streamsize File::read(void *buffer, std::size_t count) { ...@@ -125,7 +114,7 @@ std::streamsize File::read(void *buffer, std::size_t count) {
return result; return result;
} }
std::streamsize File::write(const void *buffer, std::size_t count) { std::streamsize fmt::File::write(const void *buffer, std::size_t count) {
std::streamsize result = 0; std::streamsize result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, ConvertRWCount(count)))); FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, ConvertRWCount(count))));
if (result == -1) if (result == -1)
...@@ -133,7 +122,7 @@ std::streamsize File::write(const void *buffer, std::size_t count) { ...@@ -133,7 +122,7 @@ std::streamsize File::write(const void *buffer, std::size_t count) {
return result; return result;
} }
File File::dup(int fd) { fmt::File fmt::File::dup(int fd) {
// Don't retry as dup doesn't return EINTR. // Don't retry as dup doesn't return EINTR.
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
int new_fd = FMT_POSIX_CALL(dup(fd)); int new_fd = FMT_POSIX_CALL(dup(fd));
...@@ -142,7 +131,7 @@ File File::dup(int fd) { ...@@ -142,7 +131,7 @@ File File::dup(int fd) {
return File(new_fd); return File(new_fd);
} }
void File::dup2(int fd) { void fmt::File::dup2(int fd) {
int result = 0; int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) { if (result == -1) {
...@@ -151,14 +140,14 @@ void File::dup2(int fd) { ...@@ -151,14 +140,14 @@ void File::dup2(int fd) {
} }
} }
void File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT(true) { void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT(true) {
int result = 0; int result = 0;
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
if (result == -1) if (result == -1)
ec = ErrorCode(errno); ec = ErrorCode(errno);
} }
void File::pipe(File &read_end, File &write_end) { void fmt::File::pipe(File &read_end, File &write_end) {
// Close the descriptors first to make sure that assignments don't throw // Close the descriptors first to make sure that assignments don't throw
// and there are no leaks. // and there are no leaks.
read_end.close(); read_end.close();
...@@ -181,7 +170,7 @@ void File::pipe(File &read_end, File &write_end) { ...@@ -181,7 +170,7 @@ void File::pipe(File &read_end, File &write_end) {
write_end = File(fds[1]); write_end = File(fds[1]);
} }
BufferedFile File::fdopen(const char *mode) { fmt::BufferedFile fmt::File::fdopen(const char *mode) {
// Don't retry as fdopen doesn't return EINTR. // Don't retry as fdopen doesn't return EINTR.
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
if (!f) { if (!f) {
......
...@@ -28,12 +28,15 @@ ...@@ -28,12 +28,15 @@
#ifndef FMT_POSIX_H #ifndef FMT_POSIX_H
#define FMT_POSIX_H #define FMT_POSIX_H
#include <stdio.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h>
#include <cstddef> #include <cstddef>
#include <ios> #include <ios>
#include "format.h"
#ifndef FMT_POSIX #ifndef FMT_POSIX
# ifdef _WIN32 # ifdef _WIN32
// Fix warnings about deprecated symbols. // Fix warnings about deprecated symbols.
...@@ -56,29 +59,41 @@ ...@@ -56,29 +59,41 @@
# endif # endif
#endif #endif
// Retries the expression while it evaluates to -1 and error equals to EINTR.
#ifndef _WIN32
# define FMT_RETRY(result, expression) \
do { \
result = (expression); \
} while (result == -1 && errno == EINTR)
#else
# define FMT_RETRY(result, expression) result = (expression)
#endif
namespace fmt {
// An error code. // An error code.
class ErrorCode { class ErrorCode {
private: private:
int value_; int value_;
public: public:
explicit ErrorCode(int value = 0) FMT_NOEXCEPT(true) : value_(value) {} explicit ErrorCode(int value = 0) FMT_NOEXCEPT(true) : value_(value) { }
int get() const FMT_NOEXCEPT(true) { return value_; } int get() const FMT_NOEXCEPT(true) { return value_; }
}; };
// A buffered file. // A buffered file.
class BufferedFile { class BufferedFile {
private: private:
FILE *file_; FILE *file_;
friend class File; friend class File;
explicit BufferedFile(FILE *f) : file_(f) {} explicit BufferedFile(FILE *f) : file_(f) { }
public: public:
// Constructs a BufferedFile object which doesn't represent any file. // Constructs a BufferedFile object which doesn't represent any file.
BufferedFile() FMT_NOEXCEPT(true) : file_(0) {} BufferedFile() FMT_NOEXCEPT(true) : file_(0) { }
// Destroys the object closing the file it represents if any. // Destroys the object closing the file it represents if any.
~BufferedFile() FMT_NOEXCEPT(true); ~BufferedFile() FMT_NOEXCEPT(true);
...@@ -87,16 +102,16 @@ class BufferedFile { ...@@ -87,16 +102,16 @@ class BufferedFile {
// Emulate a move constructor and a move assignment operator if rvalue // Emulate a move constructor and a move assignment operator if rvalue
// references are not supported. // references are not supported.
private: private:
// A proxy object to emulate a move constructor. // A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly. // It is private to make it impossible call operator Proxy directly.
struct Proxy { struct Proxy {
FILE *file; FILE *file;
}; };
public: public:
// A "move constructor" for moving from a temporary. // A "move constructor" for moving from a temporary.
BufferedFile(Proxy p) FMT_NOEXCEPT(true) : file_(p.file) {} BufferedFile(Proxy p) FMT_NOEXCEPT(true) : file_(p.file) { }
// A "move constructor" for for moving from an lvalue. // A "move constructor" for for moving from an lvalue.
BufferedFile(BufferedFile &f) FMT_NOEXCEPT(true) : file_(f.file_) { BufferedFile(BufferedFile &f) FMT_NOEXCEPT(true) : file_(f.file_) {
...@@ -125,6 +140,7 @@ class BufferedFile { ...@@ -125,6 +140,7 @@ class BufferedFile {
file_ = 0; file_ = 0;
return p; return p;
} }
#else #else
private: private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(BufferedFile); GTEST_DISALLOW_COPY_AND_ASSIGN_(BufferedFile);
...@@ -158,13 +174,13 @@ class BufferedFile { ...@@ -158,13 +174,13 @@ class BufferedFile {
// than an exception. You can get standard behavior by overriding the // than an exception. You can get standard behavior by overriding the
// invalid parameter handler with _set_invalid_parameter_handler. // invalid parameter handler with _set_invalid_parameter_handler.
class File { class File {
private: private:
int fd_; // File descriptor. int fd_; // File descriptor.
// Constructs a File object with a given descriptor. // Constructs a File object with a given descriptor.
explicit File(int fd) : fd_(fd) {} explicit File(int fd) : fd_(fd) { }
public: public:
// Possible values for the oflag argument to the constructor. // Possible values for the oflag argument to the constructor.
enum { enum {
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only. RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
...@@ -173,7 +189,7 @@ class File { ...@@ -173,7 +189,7 @@ class File {
}; };
// Constructs a File object which doesn't represent any file. // Constructs a File object which doesn't represent any file.
File() FMT_NOEXCEPT(true) : fd_(-1) {} File() FMT_NOEXCEPT(true) : fd_(-1) { }
// Opens a file and constructs a File object representing this file. // Opens a file and constructs a File object representing this file.
File(const char *path, int oflag); File(const char *path, int oflag);
...@@ -182,16 +198,16 @@ class File { ...@@ -182,16 +198,16 @@ class File {
// Emulate a move constructor and a move assignment operator if rvalue // Emulate a move constructor and a move assignment operator if rvalue
// references are not supported. // references are not supported.
private: private:
// A proxy object to emulate a move constructor. // A proxy object to emulate a move constructor.
// It is private to make it impossible call operator Proxy directly. // It is private to make it impossible call operator Proxy directly.
struct Proxy { struct Proxy {
int fd; int fd;
}; };
public: public:
// A "move constructor" for moving from a temporary. // A "move constructor" for moving from a temporary.
File(Proxy p) FMT_NOEXCEPT(true) : fd_(p.fd) {} File(Proxy p) FMT_NOEXCEPT(true) : fd_(p.fd) { }
// A "move constructor" for for moving from an lvalue. // A "move constructor" for for moving from an lvalue.
File(File &other) FMT_NOEXCEPT(true) : fd_(other.fd_) { File(File &other) FMT_NOEXCEPT(true) : fd_(other.fd_) {
...@@ -220,6 +236,7 @@ class File { ...@@ -220,6 +236,7 @@ class File {
fd_ = -1; fd_ = -1;
return p; return p;
} }
#else #else
private: private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(File); GTEST_DISALLOW_COPY_AND_ASSIGN_(File);
...@@ -273,11 +290,13 @@ class File { ...@@ -273,11 +290,13 @@ class File {
BufferedFile fdopen(const char *mode); BufferedFile fdopen(const char *mode);
}; };
}
#if !FMT_USE_RVALUE_REFERENCES #if !FMT_USE_RVALUE_REFERENCES
namespace std { namespace std {
// For compatibility with C++98. // For compatibility with C++98.
inline BufferedFile &move(BufferedFile &f) { return f; } inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
inline File &move(File &f) { return f; } inline fmt::File &move(fmt::File &f) { return f; }
} }
#endif #endif
......
...@@ -1466,6 +1466,9 @@ TEST(FormatterTest, OutputNotWrittenOnError) { ...@@ -1466,6 +1466,9 @@ TEST(FormatterTest, OutputNotWrittenOnError) {
#if FMT_USE_FILE_DESCRIPTORS #if FMT_USE_FILE_DESCRIPTORS
using fmt::BufferedFile;
using fmt::File;
TEST(FormatterTest, FileSink) { TEST(FormatterTest, FileSink) {
File read_end, write_end; File read_end, write_end;
File::pipe(read_end, write_end); File::pipe(read_end, write_end);
......
...@@ -356,6 +356,10 @@ TEST(UtilTest, FormatSystemErrorMessage) { ...@@ -356,6 +356,10 @@ TEST(UtilTest, FormatSystemErrorMessage) {
#if FMT_USE_FILE_DESCRIPTORS #if FMT_USE_FILE_DESCRIPTORS
using fmt::BufferedFile;
using fmt::ErrorCode;
using fmt::File;
// Checks if the file is open by reading one character from it. // Checks if the file is open by reading one character from it.
bool IsOpen(int fd) { bool IsOpen(int fd) {
char buffer; char buffer;
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#if FMT_USE_FILE_DESCRIPTORS #if FMT_USE_FILE_DESCRIPTORS
#include "posix.cc" using fmt::File;
void OutputRedirect::Flush() { void OutputRedirect::Flush() {
#if EOF != -1 #if EOF != -1
......
...@@ -99,8 +99,8 @@ std::string FormatSystemErrorMessage(int error_code, fmt::StringRef message); ...@@ -99,8 +99,8 @@ std::string FormatSystemErrorMessage(int error_code, fmt::StringRef message);
class OutputRedirect { class OutputRedirect {
private: private:
FILE *file_; FILE *file_;
File original_; // Original file passed to redirector. fmt::File original_; // Original file passed to redirector.
File read_end_; // Read end of the pipe where the output is redirected. fmt::File read_end_; // Read end of the pipe where the output is redirected.
GTEST_DISALLOW_COPY_AND_ASSIGN_(OutputRedirect); GTEST_DISALLOW_COPY_AND_ASSIGN_(OutputRedirect);
......
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
#include "gtest-extra.h" #include "gtest-extra.h"
using fmt::BufferedFile;
using fmt::ErrorCode;
using fmt::File;
namespace { namespace {
int open_count; int open_count;
int close_count; int close_count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment