summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--include/fud_c_file.hpp48
-rw-r--r--source/fud_c_file.cpp91
3 files changed, 137 insertions, 7 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d3e399..d5ebb4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,9 +50,12 @@ if (FUD_DOC)
REQUIRED dot
OPTIONAL_COMPONENTS mscgen dia)
- doxygen_add_docs(docs
+ set(DOXYGEN_GENERATE_HTML YES)
+ set(DOXYGEN_GENERATE_MAN YES)
+ doxygen_add_docs(fudDocs
include
# CONFIG_FILE "Doxyfile"
+ Comment "Generate man pages and html"
)
endif()
diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp
index 281d216..b48e8a0 100644
--- a/include/fud_c_file.hpp
+++ b/include/fud_c_file.hpp
@@ -26,6 +26,7 @@
namespace fud {
+/** \brief Access Modes for */
enum class CFileMode : uint8_t
{
ReadOnly,
@@ -76,12 +77,35 @@ constexpr const char* CTextFileModeFromFlags(CFileMode mode)
}
}
-enum class FileResult
+enum class FileStatus
{
Success,
+ InvalidName,
+ InvalidArgument,
+ InvalidState,
+ NullPointer,
Error,
};
+static inline const char* FileStatusToString(FileStatus status) {
+ switch (status) {
+ case FileStatus::Success:
+ return "Success";
+ case FileStatus::InvalidName:
+ return "InvalidName";
+ case FileStatus::InvalidArgument:
+ return "InvalidArgument";
+ case FileStatus::InvalidState:
+ return "InvalidState";
+ case FileStatus::NullPointer:
+ return "NullPointer";
+ case FileStatus::Error:
+ return "Error";
+ default:
+ return "Unknown";
+ }
+}
+
class CBinaryFile {
public:
CBinaryFile(const String& filename, CFileMode mode);
@@ -89,13 +113,29 @@ class CBinaryFile {
CBinaryFile(const CBinaryFile& rhs) = delete;
~CBinaryFile();
CBinaryFile& operator=(const CBinaryFile& rhs) = delete;
- FileResult open();
+ FileStatus open();
void close();
const FILE* file() const;
- FILE* file();
+ [[nodiscard]] FILE* file();
+
+ [[nodiscard]] bool isOpen() const;
+
+ [[nodiscard]] Result<size_t, FileStatus> size() const;
+
+ template <typename T>
+ [[nodiscard]] FileStatus read(T& destination, size_t length);
+
+ template <typename T>
+ [[nodiscard]] FileStatus read(T& destination, size_t length, size_t offset);
+
+ [[nodiscard]] FileStatus read(void* destination, size_t destinationSize, size_t length);
+
+ [[nodiscard]] FileStatus read(void* destination, size_t destinationSize, size_t length, size_t offset);
private:
- String m_filename;
+ FileStatus reset() const;
+
+ const String m_filename;
String m_extraFlags{};
String m_mode;
CFileMode m_modeFlags;
diff --git a/source/fud_c_file.cpp b/source/fud_c_file.cpp
index 24186bf..3d15431 100644
--- a/source/fud_c_file.cpp
+++ b/source/fud_c_file.cpp
@@ -38,10 +38,13 @@ CBinaryFile::~CBinaryFile() {
close();
}
-FileResult CBinaryFile::open()
+FileStatus CBinaryFile::open()
{
+ if (!m_filename.valid()) {
+ return FileStatus::InvalidName;
+ }
m_file = fopen(m_filename.c_str(), m_mode.c_str());
- return m_file != nullptr ? FileResult::Success : FileResult::Error;
+ return m_file != nullptr ? FileStatus::Success : FileStatus::Error;
}
void CBinaryFile::close()
@@ -62,4 +65,88 @@ FILE* CBinaryFile::file()
return m_file;
}
+bool CBinaryFile::isOpen() const
+{
+ return m_file != nullptr;
+}
+
+Result<size_t, FileStatus> CBinaryFile::size() const
+{
+ using RetType = Result<size_t, FileStatus>;
+ if (!isOpen()) {
+ return RetType::error(FileStatus::InvalidState);
+ }
+
+ auto seekStatus = fseek(m_file, 0, SEEK_END);
+ if (seekStatus != 0) {
+ return RetType::error(FileStatus::Error);
+ }
+
+ auto fileSizeResult = ftell(m_file);
+ if (fileSizeResult < 0) {
+ return RetType::error(FileStatus::Error);
+ }
+
+ auto fileSize = static_cast<size_t>(fileSizeResult);
+
+ auto resetStatus = reset();
+ if (resetStatus != FileStatus::Success) {
+ return RetType::error(resetStatus);
+ }
+
+ return RetType::okay(fileSize);
+}
+
+FileStatus CBinaryFile::read(void* destination, size_t destinationSize, size_t length)
+{
+ return read(destination, destinationSize, length, 0);
+}
+
+FileStatus CBinaryFile::read(void* destination, size_t destinationSize, size_t length, size_t offset)
+{
+ if (length == 0) {
+ return FileStatus::Success;
+ }
+
+ if (destination == nullptr) {
+ return FileStatus::NullPointer;
+ }
+
+ if (offset > LONG_MAX || SIZE_MAX - offset < length || destinationSize < length) {
+ return FileStatus::InvalidArgument;
+ }
+
+ auto fileSizeResult = size();
+ if (fileSizeResult.isError()) {
+ return fileSizeResult.getError();
+ }
+
+ auto fileSize = fileSizeResult.getOkay();
+ if (offset + length > fileSize) {
+ return FileStatus::InvalidArgument;
+ }
+
+ auto seekResult = fseek(m_file, static_cast<long>(offset), SEEK_SET);
+ if (seekResult != 0) {
+ return FileStatus::Error;
+ }
+
+ auto* destPtr = static_cast<char*>(destination);
+ auto readResult = fread(destPtr, length, 1, m_file);
+ if (readResult != 1) {
+ static_cast<void>(reset());
+ return FileStatus::Error;
+ }
+
+ return FileStatus::Success;
+}
+
+FileStatus CBinaryFile::reset() const {
+ if (!isOpen()) {
+ return FileStatus::InvalidState;
+ }
+ auto result = fseek(m_file, 0, SEEK_SET);
+ return result == 0 ? FileStatus::Success : FileStatus::Error;
+}
+
} // namespace fud