Browse Source

File reader

Kajetan Johannes Hammerle 10 months ago
parent
commit
2835837be2

+ 0 - 8
io/File.cpp

@@ -1,8 +0,0 @@
-#include "io/File.h"
-
-#include <stdio.h>
-
-Core::File::File() {
-    // file = fopen("fsdf", "r");
-    // int i = fgetc(file);
-}

+ 3 - 7
io/File.h

@@ -1,16 +1,12 @@
 #ifndef CORE_FILE_H
 #define CORE_FILE_H
 
-#include "math/Vector.h"
+#include <limits.h>
+
 #include "utils/ArrayString.h"
 
 namespace Core {
-    class File final {
-        void* file;
-
-    public:
-        File();
-    };
+    using Path = String8<PATH_MAX>;
 }
 
 #endif

+ 74 - 0
io/FileReader.cpp

@@ -0,0 +1,74 @@
+#include "io/FileReader.h"
+
+#include <stdio.h>
+
+#include "utils/Logger.h"
+
+Core::FileReader::FileReader() : file(nullptr) {
+}
+
+Core::FileReader::FileReader(FileReader&& other) : FileReader() {
+    swap(other);
+}
+
+Core::FileReader::~FileReader() {
+    if(file != nullptr) {
+        int r = fclose(static_cast<FILE*>(file));
+        if(r != 0) {
+            CORE_LOG_WARNING("Cannot close file #: #", path, r);
+        }
+        file = nullptr;
+    }
+}
+
+Core::FileReader& Core::FileReader::operator=(FileReader&& other) {
+    swap(other);
+    return *this;
+}
+
+const Core::Path& Core::FileReader::getPath() const {
+    return path;
+}
+
+Core::Error Core::FileReader::open(const Path& p) {
+    if(file != nullptr) {
+        return Error::INVALID_STATE;
+    }
+    path = p;
+    file = fopen(path, "rb");
+    return file != nullptr ? Error::NONE : Error::CANNOT_OPEN_FILE;
+}
+
+Core::Error Core::FileReader::open(const char* p) {
+    if(file != nullptr) {
+        return Error::INVALID_STATE;
+    }
+    CORE_RETURN_ERROR(path.append(p));
+    file = fopen(path, "rb");
+    return file != nullptr ? Error::NONE : Error::CANNOT_OPEN_FILE;
+}
+
+Core::Error Core::FileReader::readChar(int& c) {
+    if(file == nullptr) {
+        return Error::INVALID_STATE;
+    }
+    c = fgetc(static_cast<FILE*>(file));
+    return c == EOF ? Error::END_OF_FILE : Error::NONE;
+}
+
+Core::Error Core::FileReader::readChars(char* buffer, int bufferSize) {
+    if(file == nullptr) {
+        return Error::INVALID_STATE;
+    } else if(bufferSize <= 0) {
+        return Error::INVALID_ARGUMENT;
+    }
+    size_t size = static_cast<size_t>(bufferSize - 1);
+    size_t readBytes = fread(buffer, 1, size, static_cast<FILE*>(file));
+    buffer[readBytes] = '\0';
+    return readBytes != size ? Error::END_OF_FILE : Error::NONE;
+}
+
+void Core::FileReader::swap(FileReader& other) {
+    Core::swap(file, other.file);
+    Core::swap(path, other.path);
+}

+ 32 - 0
io/FileReader.h

@@ -0,0 +1,32 @@
+#ifndef CORE_FILE_READER_H
+#define CORE_FILE_READER_H
+
+#include "io/File.h"
+
+namespace Core {
+    using Path = String8<PATH_MAX>;
+
+    class FileReader final {
+        void* file;
+        Path path;
+
+    public:
+        FileReader();
+        FileReader(const FileReader& other) = delete;
+        FileReader(FileReader&& other);
+        ~FileReader();
+        FileReader& operator=(const FileReader& other) = delete;
+        FileReader& operator=(FileReader&& other);
+
+        const Path& getPath() const;
+
+        Error open(const Path& path);
+        Error open(const char* path);
+        Error readChar(int& c);
+        Error readChars(char* buffer, int bufferSize);
+
+        void swap(FileReader& other);
+    };
+}
+
+#endif

+ 2 - 2
meson.build

@@ -16,7 +16,7 @@ src = [
     'math/Frustum.cpp',
     'math/View.cpp',
     'thread/Thread.cpp',
-    'io/File.cpp',
+    'io/FileReader.cpp',
 ]
 
 src_tests = [
@@ -50,7 +50,7 @@ src_tests = [
     'tests/ClockTests.cpp',
     'tests/RandomTests.cpp',
     'tests/ThreadTests.cpp',
-    'tests/FileTests.cpp',
+    'tests/FileReaderTests.cpp',
 ]
 
 src_performance = [

+ 2 - 0
test/Main.cpp

@@ -9,6 +9,7 @@
 #include "tests/ClockTests.h"
 #include "tests/ColorTests.h"
 #include "tests/ComponentsTests.h"
+#include "tests/FileReaderTests.h"
 #include "tests/FrustumTests.h"
 #include "tests/HashMapTests.h"
 #include "tests/LinkedListTests.h"
@@ -50,6 +51,7 @@ int main() {
     Core::ClockTests::test();
     Core::ColorTests::test();
     Core::ComponentsTests::test();
+    Core::FileReaderTests::test();
     Core::FrustumTests::test();
     Core::HashMapTests::test();
     Core::LinkedListTests::test();

+ 72 - 0
tests/FileReaderTests.cpp

@@ -0,0 +1,72 @@
+#include "tests/FileReaderTests.h"
+
+#include "io/FileReader.h"
+#include "test/Test.h"
+
+static constexpr const char* TEST_FILE = "../src/tests/resources/test";
+
+static void testReadChar() {
+    Core::FileReader r;
+    CORE_TEST_ERROR(r.open(TEST_FILE));
+    Core::String8<128> s;
+    while(true) {
+        int c = 0;
+        if(r.readChar(c) != Core::Error::NONE) {
+            break;
+        }
+        CORE_TEST_ERROR(s.append(static_cast<c32>(c)));
+    }
+    CORE_TEST_STRING("abc\nBaum\n", s);
+}
+
+static void testReadChars() {
+    Core::FileReader r;
+    CORE_TEST_ERROR(r.open(TEST_FILE));
+    char buffer[128];
+    CORE_TEST_EQUAL(Core::Error::END_OF_FILE,
+                    r.readChars(buffer, sizeof(buffer)));
+    CORE_TEST_STRING("abc\nBaum\n", buffer);
+}
+
+static void testReadCharsOverflow() {
+    Core::FileReader r;
+    CORE_TEST_ERROR(r.open(TEST_FILE));
+    char buffer[6];
+    CORE_TEST_ERROR(r.readChars(buffer, sizeof(buffer)));
+    CORE_TEST_STRING("abc\nB", buffer);
+}
+
+static void testMoveConstruct() {
+    Core::FileReader r;
+    CORE_TEST_ERROR(r.open(TEST_FILE));
+    Core::FileReader r2 = Core::move(r);
+    CORE_TEST_STRING("", r.getPath());
+    CORE_TEST_STRING(TEST_FILE, r2.getPath());
+
+    int c = 0;
+    CORE_TEST_EQUAL(Core::Error::INVALID_STATE, r.readChar(c));
+    CORE_TEST_ERROR(r2.readChar(c));
+    CORE_TEST_EQUAL('a', c);
+}
+
+static void testMoveAssignment() {
+    Core::FileReader r;
+    CORE_TEST_ERROR(r.open(TEST_FILE));
+    Core::FileReader r2;
+    r2 = Core::move(r);
+    CORE_TEST_STRING("", r.getPath());
+    CORE_TEST_STRING(TEST_FILE, r2.getPath());
+
+    int c = 0;
+    CORE_TEST_EQUAL(Core::Error::INVALID_STATE, r.readChar(c));
+    CORE_TEST_ERROR(r2.readChar(c));
+    CORE_TEST_EQUAL('a', c);
+}
+
+void Core::FileReaderTests::test() {
+    testReadChar();
+    testReadChars();
+    testReadCharsOverflow();
+    testMoveConstruct();
+    testMoveAssignment();
+}

+ 8 - 0
tests/FileReaderTests.h

@@ -0,0 +1,8 @@
+#ifndef CORE_FILE_READER_TESTS_H
+#define CORE_FILE_READER_TESTS_H
+
+namespace Core::FileReaderTests {
+    void test();
+}
+
+#endif

+ 0 - 11
tests/FileTests.cpp

@@ -1,11 +0,0 @@
-#include "tests/FileTests.h"
-
-#include "io/File.h"
-#include "test/Test.h"
-
-static void testAdd() {
-}
-
-void Core::FileTests::test() {
-    testAdd();
-}

+ 0 - 8
tests/FileTests.h

@@ -1,8 +0,0 @@
-#ifndef CORE_FILE_TESTS_H
-#define CORE_FILE_TESTS_H
-
-namespace Core::FileTests {
-    void test();
-}
-
-#endif

+ 1 - 1
tests/ProbingHashMapTests.cpp

@@ -148,7 +148,7 @@ static void testToString1() {
     CORE_TEST_ERROR(map.add(1, 3));
     CORE_TEST_ERROR(map.add(2, 4));
     CORE_TEST_ERROR(map.add(3, 5));
-    CORE_TEST_STRING("[1 = 3, 2 = 4, 3 = 5]", map);
+    CORE_TEST_STRING("[2 = 4, 1 = 3, 3 = 5]", map);
 }
 
 static void testToString2() {

+ 2 - 0
tests/resources/test

@@ -0,0 +1,2 @@
+abc
+Baum

+ 1 - 2
utils/Logger.h

@@ -1,9 +1,8 @@
 #ifndef CORE_LOGGER_H
 #define CORE_LOGGER_H
 
-#include <stdio.h>
-
 #include "utils/ArrayString.h"
+
 namespace Core::Logger {
     enum class Level { ERROR, WARNING, INFO, DEBUG };
     extern Level level;

+ 2 - 0
utils/Utility.cpp

@@ -24,6 +24,8 @@ const char* Core::getErrorName(Error e) {
         case Error::THREAD_ERROR: return "THREAD_ERROR";
         case Error::INVALID_ID: return "INVALID_ID";
         case Error::EXISTING_KEY: return "EXISTING_KEY";
+        case Error::CANNOT_OPEN_FILE: return "CANNOT_OPEN_FILE";
+        case Error::END_OF_FILE: return "END_OF_FILE";
     }
     return "?";
 }

+ 3 - 1
utils/Utility.h

@@ -21,7 +21,9 @@ namespace Core {
         SLEEP_INTERRUPTED,
         THREAD_ERROR,
         INVALID_ID,
-        EXISTING_KEY
+        EXISTING_KEY,
+        CANNOT_OPEN_FILE,
+        END_OF_FILE
     };
     const char* getErrorName(Error e);