1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
#include "cru/common/io/CFileStream.h"
#include "cru/common/Exception.h"
#include "cru/common/io/Stream.h"
#include <cstdio>
namespace cru::io {
static bool ModeCanRead(const char* mode) {
for (const char* p = mode; *p != '\0'; p++) {
if (*p == 'r' || *p == '+') {
return true;
}
}
return false;
}
static bool ModeCanWrite(const char* mode) {
for (const char* p = mode; *p != '\0'; p++) {
if (*p == 'w' || *p == 'a' || *p == '+') {
return true;
}
}
return false;
}
CFileStream::CFileStream(const char* path, const char* mode)
: Stream(true, ModeCanRead(mode), ModeCanWrite(mode)),
file_(std::fopen(path, mode)),
auto_close_(true) {
if (file_ == nullptr) {
throw ErrnoException(u"Cannot open file.");
}
}
CFileStream::CFileStream(std::FILE* file, bool readable, bool writable,
bool auto_close)
: Stream(true, readable, writable), file_(file), auto_close_(auto_close) {
if (file_ == nullptr) {
throw Exception(u"File is NULL.");
}
}
CFileStream::~CFileStream() {
if (auto_close_ && file_ != nullptr) {
std::fclose(file_);
}
}
static int ConvertOriginFlag(Stream::SeekOrigin origin) {
switch (origin) {
case Stream::SeekOrigin::Begin:
return SEEK_SET;
case Stream::SeekOrigin::Current:
return SEEK_CUR;
case Stream::SeekOrigin::End:
return SEEK_END;
default:
throw Exception(u"Unknown seek origin.");
}
}
Index CFileStream::DoSeek(Index offset, SeekOrigin origin) {
if (std::fseek(file_, offset, ConvertOriginFlag(origin))) {
throw ErrnoException(u"Seek failed.");
}
return DoTell();
}
Index CFileStream::DoTell() {
long position = std::ftell(file_);
if (position == -1) {
throw ErrnoException(u"Tell failed.");
}
return position;
}
void CFileStream::DoRewind() { std::rewind(file_); }
Index CFileStream::DoRead(std::byte* buffer, Index offset, Index size) {
auto count = std::fread(buffer + offset, 1, size, file_);
return count;
}
Index CFileStream::DoWrite(const std::byte* buffer, Index offset, Index size) {
auto count = std::fwrite(buffer + offset, 1, size, file_);
return count;
}
void CFileStream::DoFlush() { std::fflush(file_); }
void CFileStream::DoClose() {
CRU_STREAM_BEGIN_CLOSE
std::fclose(file_);
file_ = nullptr;
}
} // namespace cru::io
|