aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2023-07-05 01:54:08 +0800
committercrupest <crupest@outlook.com>2023-07-05 01:54:08 +0800
commitbcfd51a7fabf7adf5f134247ca1020fac98b24b5 (patch)
tree41471cee6af6a7e49140e50ba818366b316c8ea7 /src
parentaa9bc6bb7c11e810745c80548dd5ed5b2cb08740 (diff)
downloadcru-bcfd51a7fabf7adf5f134247ca1020fac98b24b5.tar.gz
cru-bcfd51a7fabf7adf5f134247ca1020fac98b24b5.tar.bz2
cru-bcfd51a7fabf7adf5f134247ca1020fac98b24b5.zip
Add CFileStream. Move ErrnoException.
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/Exception.cpp11
-rw-r--r--src/common/io/CFileStream.cpp132
-rw-r--r--src/common/platform/unix/ErrnoException.cpp11
4 files changed, 145 insertions, 10 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index fb2dd471..2c7f28e0 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -6,6 +6,7 @@ add_library(CruBase
String.cpp
StringToNumberConverter.cpp
StringUtil.cpp
+ io/CFileStream.cpp
io/Stream.cpp
io/Resource.cpp
io/MemoryStream.cpp
diff --git a/src/common/Exception.cpp b/src/common/Exception.cpp
index 86816720..b0053bac 100644
--- a/src/common/Exception.cpp
+++ b/src/common/Exception.cpp
@@ -1,5 +1,9 @@
#include "cru/common/Exception.h"
+#include "cru/common/Format.h"
+
+#include <cerrno>
+
namespace cru {
Exception::Exception() {}
@@ -14,4 +18,11 @@ const char* Exception::what() const noexcept {
return utf8_message_.c_str();
}
+
+ErrnoException::ErrnoException(const String& message)
+ : ErrnoException(message, errno) {}
+
+ErrnoException::ErrnoException(const String& message, int errno_code)
+ : Exception(Format(u"{}. Errno is {}.", message, errno_code)),
+ errno_code_(errno_code) {}
} // namespace cru
diff --git a/src/common/io/CFileStream.cpp b/src/common/io/CFileStream.cpp
new file mode 100644
index 00000000..de195538
--- /dev/null
+++ b/src/common/io/CFileStream.cpp
@@ -0,0 +1,132 @@
+#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)
+ : file_(std::fopen(path, mode)),
+ readable_(ModeCanRead(mode)),
+ writable_(ModeCanWrite(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)
+ : file_(file),
+ readable_(readable),
+ writable_(writable),
+ auto_close_(auto_close) {
+ if (file_ == nullptr) {
+ throw Exception(u"File is NULL.");
+ }
+}
+
+CFileStream::~CFileStream() {
+ if (auto_close_ && file_ != nullptr) {
+ std::fclose(file_);
+ }
+}
+
+bool CFileStream::CanSeek() {
+ CheckClosed();
+ return true;
+}
+
+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::Seek(Index offset, SeekOrigin origin) {
+ CheckClosed();
+ if (std::fseek(file_, offset, ConvertOriginFlag(origin))) {
+ throw ErrnoException(u"Seek failed.");
+ }
+ return Tell();
+}
+
+Index CFileStream::Tell() {
+ CheckClosed();
+ long position = std::ftell(file_);
+ if (position == -1) {
+ throw ErrnoException(u"Tell failed.");
+ }
+ return position;
+}
+
+void CFileStream::Rewind() {
+ CheckClosed();
+ std::rewind(file_);
+}
+
+bool CFileStream::CanRead() {
+ CheckClosed();
+ return readable_;
+}
+
+Index CFileStream::Read(std::byte* buffer, Index offset, Index size) {
+ CheckClosed();
+ auto count = std::fread(buffer + offset, 1, size, file_);
+ return count;
+}
+
+bool CFileStream::CanWrite() {
+ CheckClosed();
+ return writable_;
+}
+
+Index CFileStream::Write(const std::byte* buffer, Index offset, Index size) {
+ CheckClosed();
+ auto count = std::fwrite(buffer + offset, 1, size, file_);
+ return count;
+}
+
+void CFileStream::Flush() {
+ CheckClosed();
+ std::fflush(file_);
+}
+
+void CFileStream::Close() {
+ if (file_ != nullptr) {
+ std::fclose(file_);
+ file_ = nullptr;
+ }
+}
+
+void CFileStream::CheckClosed() {
+ if (file_ == nullptr) {
+ throw StreamAlreadyClosedException(u"File is closed.");
+ }
+}
+} // namespace cru::io
diff --git a/src/common/platform/unix/ErrnoException.cpp b/src/common/platform/unix/ErrnoException.cpp
index f2171943..06c42ff6 100644
--- a/src/common/platform/unix/ErrnoException.cpp
+++ b/src/common/platform/unix/ErrnoException.cpp
@@ -1,14 +1,5 @@
#include "cru/common/platform/unix/ErrnoException.h"
-#include "cru/common/Format.h"
-
-#include <errno.h>
-
namespace cru::platform::unix {
-ErrnoException::ErrnoException(const String& message)
- : ErrnoException(message, errno) {}
-
-ErrnoException::ErrnoException(const String& message, int errno_code)
- : PlatformException(Format(u"{}. Errno is {}.", message, errno_code)),
- errno_code_(errno_code) {}
+// Moved to Exception.cpp
} // namespace cru::platform::unix