aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/Exception.h3
-rw-r--r--include/cru/common/io/FileNotExistException.h19
-rw-r--r--include/cru/common/io/OpenFileFlag.h12
-rw-r--r--src/common/Base.cpp2
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/io/CFileStream.cpp25
-rw-r--r--src/common/io/FileNotExistException.cpp12
-rw-r--r--src/common/io/OpenFileFlag.cpp19
8 files changed, 88 insertions, 5 deletions
diff --git a/include/cru/common/Exception.h b/include/cru/common/Exception.h
index 6f458d35..d7e32a5a 100644
--- a/include/cru/common/Exception.h
+++ b/include/cru/common/Exception.h
@@ -20,6 +20,9 @@ class CRU_BASE_API Exception : public std::exception {
const char* what() const noexcept override;
+ protected:
+ void SetMessage(String message) { message_ = std::move(message); }
+
private:
String message_;
mutable std::string utf8_message_;
diff --git a/include/cru/common/io/FileNotExistException.h b/include/cru/common/io/FileNotExistException.h
new file mode 100644
index 00000000..f49271b1
--- /dev/null
+++ b/include/cru/common/io/FileNotExistException.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "../Base.h"
+#include "../Exception.h"
+
+namespace cru::io {
+ class CRU_BASE_API FileNotExistException : public Exception {
+ public:
+ FileNotExistException(String path);
+
+ CRU_DEFAULT_COPY(FileNotExistException)
+ CRU_DEFAULT_MOVE(FileNotExistException)
+
+ ~FileNotExistException() override = default;
+
+ private:
+ String path_;
+ };
+}
diff --git a/include/cru/common/io/OpenFileFlag.h b/include/cru/common/io/OpenFileFlag.h
index fd8b6e2c..4a5789fb 100644
--- a/include/cru/common/io/OpenFileFlag.h
+++ b/include/cru/common/io/OpenFileFlag.h
@@ -11,11 +11,14 @@ using OpenFileFlag = Bitmask<details::OpenFileFlagTag>;
struct OpenFileFlags {
/**
* \brief for reading
+ * If the file does not exist, FileNotExistException should be thrown.
*/
static constexpr OpenFileFlag Read{0x1};
/**
* \brief for writing
+ * If the file does not exist and Create is not specified,
+ * FileNotExistException should be thrown.
*/
static constexpr OpenFileFlag Write{0x2};
@@ -34,7 +37,8 @@ struct OpenFileFlags {
/**
* \brief when writing, if the file does not exist, create one
- * Only effective for writing.
+ * Only effective for writing. When file does not exist, FileNotExistException
+ * will NOT be thrown and a new file will be created.
*/
static constexpr OpenFileFlag Create{0x10};
@@ -43,4 +47,10 @@ struct OpenFileFlags {
*/
static constexpr OpenFileFlag Exclusive{0x20};
};
+
+/**
+ * Append, Truncate, Create must be used with Write.
+ * Append and Truncate must not be used together.
+ */
+bool CheckOpenFileFlag(OpenFileFlag flags);
} // namespace cru::io
diff --git a/src/common/Base.cpp b/src/common/Base.cpp
index b6d39fef..ba4077b4 100644
--- a/src/common/Base.cpp
+++ b/src/common/Base.cpp
@@ -1,6 +1,6 @@
#include "cru/common/Base.h"
-#include <stdexcept>
+#include <exception>
namespace cru {
void UnreachableCode() { std::terminate(); }
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 2c7f28e0..6541f156 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -7,6 +7,7 @@ add_library(CruBase
StringToNumberConverter.cpp
StringUtil.cpp
io/CFileStream.cpp
+ io/FileNotExistException.cpp
io/Stream.cpp
io/Resource.cpp
io/MemoryStream.cpp
diff --git a/src/common/io/CFileStream.cpp b/src/common/io/CFileStream.cpp
index 68fb137d..133cd8f6 100644
--- a/src/common/io/CFileStream.cpp
+++ b/src/common/io/CFileStream.cpp
@@ -46,22 +46,41 @@ CFileStream::CFileStream(std::FILE* file, bool readable, bool writable,
}
namespace {
-std::string ConvertOpenFileFlagToCFileFlag(OpenFileFlag flags) {
+/**
+ * Generally the fopen will return a NULL ptr if the file does not exist. Then
+ * we must throw FileNotExistException. However, there are cases we have to
+ * check existence explicitly before. The case is OpenFileFlags::Write is
+ * specified but OpenFileFlags::Create is not, in which fopen usually create a
+ * new file automatically but we want a FileNotExistException to be thrown.
+ */
+std::string ConvertOpenFileFlagToCFileFlag(OpenFileFlag flags,
+ bool* explicit_check_exist) {
+ *explicit_check_exist = false;
+
std::string result;
+
bool need_read = flags & OpenFileFlags::Read;
bool need_write = flags & OpenFileFlags::Write;
- bool append = flags & OpenFileFlags::Append;
if (!need_write) {
// No need to write? The simplest
+ // Note even OpenFileFlags::Create is set, we still have to check exist.
return "r";
}
// Now we need writing.
- if (!need_read) {
+ bool create = OpenFileFlags::Create;
+
+ if (!create) {
+ *explicit_check_exist = true;
}
+ bool append = flags & OpenFileFlags::Append;
+
+ if (!need_read) {
+ return "w";
+ }
}
} // namespace
diff --git a/src/common/io/FileNotExistException.cpp b/src/common/io/FileNotExistException.cpp
new file mode 100644
index 00000000..a2e1fdb1
--- /dev/null
+++ b/src/common/io/FileNotExistException.cpp
@@ -0,0 +1,12 @@
+#include "cru/common/io/FileNotExistException.h"
+
+#include "cru/common/Exception.h"
+#include "cru/common/Format.h"
+
+#include <utility>
+
+namespace cru::io {
+ FileNotExistException::FileNotExistException(String path): Exception(), path_(std::move(path)) {
+ SetMessage(Format(u"File {} does not exist.", path_));
+ }
+}
diff --git a/src/common/io/OpenFileFlag.cpp b/src/common/io/OpenFileFlag.cpp
new file mode 100644
index 00000000..6b9957fe
--- /dev/null
+++ b/src/common/io/OpenFileFlag.cpp
@@ -0,0 +1,19 @@
+#include "cru/common/io/OpenFileFlag.h"
+
+namespace cru::io {
+bool CheckOpenFileFlag(OpenFileFlag flags) {
+ auto has = [flags](OpenFileFlag flag) { return flags & flag; };
+
+ if ((has(OpenFileFlags::Append) || has(OpenFileFlags::Truncate) ||
+ has(OpenFileFlags::Create)) &&
+ !has(OpenFileFlags::Write)) {
+ return false;
+ }
+
+ if (has(OpenFileFlags::Truncate) && has(OpenFileFlags::Append)) {
+ return false;
+ }
+
+ return true;
+}
+} // namespace cru::io