Add File::size and make File's ctor take StringRef.
This commit is contained in:
parent
f175591923
commit
e34e9fa0c7
39
posix.cc
39
posix.cc
@ -53,6 +53,20 @@
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#if FMT_GCC_VERSION >= 407
|
||||
# define FMT_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define FMT_UNUSED
|
||||
#endif
|
||||
|
||||
#if FMT_USE_STATIC_ASSERT
|
||||
# define FMT_STATIC_ASSERT(cond, message) static_assert(cond, message)
|
||||
#else
|
||||
# define FMT_CONCAT_(a, b) FMT_CONCAT(a, b)
|
||||
# define FMT_STATIC_ASSERT(cond, message) \
|
||||
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
// Return type of read and write functions.
|
||||
@ -98,13 +112,13 @@ int fmt::BufferedFile::fileno() const {
|
||||
return fd;
|
||||
}
|
||||
|
||||
fmt::File::File(const char *path, int oflag) {
|
||||
fmt::File::File(fmt::StringRef path, int oflag) {
|
||||
int mode = S_IRUSR | S_IWUSR;
|
||||
#ifdef _WIN32
|
||||
fd_ = -1;
|
||||
FMT_POSIX_CALL(sopen_s(&fd_, path, oflag, _SH_DENYNO, mode));
|
||||
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
|
||||
#else
|
||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path, oflag, mode)));
|
||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
|
||||
#endif
|
||||
if (fd_ == -1)
|
||||
throw SystemError(errno, "cannot open file {}", path);
|
||||
@ -128,6 +142,25 @@ void fmt::File::close() {
|
||||
throw SystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
fmt::LongLong fmt::File::size() const {
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER size = {};
|
||||
if (!GetFileSizeEx(_get_osfhandle(fd_), &size))
|
||||
throw WindowsError(GetLastError(), "cannot get file size");
|
||||
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(size.QuadPart),
|
||||
"return type of File::size is not large enough");
|
||||
return size.QuadPart;
|
||||
#else
|
||||
typedef struct stat Stat;
|
||||
Stat file_stat = Stat();
|
||||
if (fstat(fd_, &file_stat) == -1)
|
||||
throw SystemError(errno, "cannot get file attributes");
|
||||
FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
|
||||
"return type of File::size is not large enough");
|
||||
return file_stat.st_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::size_t fmt::File::read(void *buffer, std::size_t count) {
|
||||
RWResult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
||||
|
5
posix.h
5
posix.h
@ -206,7 +206,7 @@ class File {
|
||||
File() FMT_NOEXCEPT(true) : fd_(-1) {}
|
||||
|
||||
// Opens a file and constructs a File object representing this file.
|
||||
File(const char *path, int oflag);
|
||||
File(fmt::StringRef path, int oflag);
|
||||
|
||||
#if !FMT_USE_RVALUE_REFERENCES
|
||||
// Emulate a move constructor and a move assignment operator if rvalue
|
||||
@ -277,6 +277,9 @@ class File {
|
||||
// Closes the file.
|
||||
void close();
|
||||
|
||||
// Returns the file size.
|
||||
fmt::LongLong size() const;
|
||||
|
||||
// Attempts to read count bytes from the file into the specified buffer.
|
||||
std::size_t read(void *buffer, std::size_t count);
|
||||
|
||||
|
@ -194,6 +194,17 @@ TEST(FileTest, CloseNoRetry) {
|
||||
close_count = 0;
|
||||
}
|
||||
|
||||
TEST(FileTest, Size) {
|
||||
BufferedFile bf("test", "w");
|
||||
std::string content = "top secret, destroy before reading";
|
||||
bf.print(content);
|
||||
bf.close();
|
||||
File f("test", File::RDONLY);
|
||||
EXPECT_EQ(content.size(), f.size());
|
||||
// TODO: test if size can handle large file sizes
|
||||
// TODO: test FMT_STATIC_ASSERT
|
||||
}
|
||||
|
||||
TEST(FileTest, ReadRetry) {
|
||||
File read_end, write_end;
|
||||
File::pipe(read_end, write_end);
|
||||
|
Loading…
Reference in New Issue
Block a user