bfzgs 1 year ago
commit
4bfc469318

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+.idea
+.vscode

+ 26 - 0
core/Appendable.hpp

@@ -0,0 +1,26 @@
+// Appendable.hpp
+
+#ifndef BRYNHILD_CORE_APPENDABLE_HPP
+#define BRYNHILD_CORE_APPENDABLE_HPP
+
+#include <string>
+#include <stdexcept>
+
+namespace brynhild {
+namespace core {
+
+class Appendable {
+public:
+    virtual ~Appendable() {}
+
+    // Append a string or a part of it
+    virtual Appendable& append(const std::string& csq, int start = 0, int end = -1) = 0;
+
+    // Append a single character
+    virtual Appendable& append(char c) = 0;
+};
+
+} // namespace core
+} // namespace brynhild
+
+#endif // BRYNHILD_CORE_APPENDABLE_HPP

+ 35 - 0
core/AutoCloseable.hpp

@@ -0,0 +1,35 @@
+// AutoCloseable.hpp
+
+#ifndef BRYNHILD_CORE_AUTOCLOSEABLE_HPP
+#define BRYNHILD_CORE_AUTOCLOSEABLE_HPP
+
+namespace brynhild {
+    namespace core {
+
+        /**
+         * An object that may hold resources (such as file or socket handles)
+         * until it is closed. The close method of an AutoCloseable
+         * object should be called to release the resources.
+         *
+         * This is similar to Java's AutoCloseable interface.
+         */
+        class AutoCloseable {
+        public:
+            /**
+             * Virtual destructor. Subclasses should override this method
+             * to release any underlying resources.
+             */
+            virtual ~AutoCloseable() {}
+
+            /**
+             * Closes this resource, relinquishing any underlying resources.
+             * This method should be overridden by subclasses to perform
+             * resource release.
+             */
+            virtual void close() = 0;
+        };
+
+    } // namespace core
+} // namespace brynhild
+
+#endif // BRYNHILD_CORE_AUTOCLOSEABLE_HPP

+ 22 - 0
core/Flushable.hpp

@@ -0,0 +1,22 @@
+// Flushable.hpp
+
+#ifndef BRYNHILD_IO_FLUSHABLE_HPP
+#define BRYNHILD_IO_FLUSHABLE_HPP
+
+#include "IOException.hpp"
+
+namespace brynhild {
+namespace io {
+
+class Flushable {
+public:
+    virtual ~Flushable() {}
+
+    // Pure virtual function to flush the stream
+    virtual void flush() = 0;
+};
+
+} // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_FLUSHABLE_HPP

+ 39 - 0
core/Readable.hpp

@@ -0,0 +1,39 @@
+// Readable.hpp
+
+#ifndef BRYNHILD_CORE_READABLE_HPP
+#define BRYNHILD_CORE_READABLE_HPP
+
+#include <stdexcept>
+#include "../io/IOException.hpp"
+
+namespace brynhild {
+    namespace core {
+
+        /**
+         * A Readable is a source of characters. Characters from
+         * a Readable are made available to callers of the read
+         * method.
+         */
+        class Readable {
+        public:
+            // Virtual destructor
+            virtual ~Readable() {}
+
+            /**
+             * Attempts to read characters into the specified character array.
+             * The array is used as a repository of characters as-is: the only
+             * changes made are the results of a put operation.
+             *
+             * @param cbuf The character array to read characters into.
+             * @param len The number of characters to read.
+             * @return The number of char values added to the array,
+             *         or -1 if this source of characters is at its end.
+             * @throws IOException if an I/O error occurs.
+             */
+            virtual int read(char* cbuf, int len) = 0;
+        };
+
+    } // namespace core
+} // namespace brynhild
+
+#endif // BRYNHILD_CORE_READABLE_HPP

+ 7 - 0
core/fail_reason.hpp

@@ -0,0 +1,7 @@
+namespace brynhild {
+	namespace core {
+		enum FailReason {
+			NONE, FILE_EOF, TYPE_INCOMPATIABLE
+		};
+	}
+}

+ 287 - 0
core/file_reader.hpp

@@ -0,0 +1,287 @@
+#include<regex>
+#include"fail_reason.hpp"
+#include"tokenizer.hpp"
+using namespace std;
+namespace brynhild {
+    namespace core {
+        class FileReader {
+        private:
+            Tokenizer tokenizer;
+            bool validState;
+            bool strict;
+            FailReason reason;
+
+        public:
+            FileReader(const std::string& filename,bool strict=true)
+                : tokenizer(filename), validState(true),strict(strict),reason(NONE) {}
+
+            FileReader& operator>>(std::string& value) {
+                if (!validState) {
+                    if (strict) throw std::runtime_error("Read operation failed: Invalid state.");
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    value = word;
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) throw std::runtime_error("Read operation failed: No more data.");
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(int& value) {
+                if (!validState) {
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: Invalid state.");
+                    }
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    try {
+                        value = std::stoi(word);
+                    }
+                    catch (const std::exception& e) {
+                        validState = false;
+                        reason = TYPE_INCOMPATIABLE;
+                        if (strict) {
+                            throw e;
+                        }
+                    }
+                }
+                else {
+                    validState = false;
+                    reason = FILE_EOF;
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: No more data.");
+                    }
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(char& value) {
+                if (!validState) {
+                    if (strict) throw std::runtime_error("Read operation failed: Invalid state.");
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word) && word.length() == 1) {
+                    value = word[0];
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) throw std::runtime_error("Read operation failed: Expected a single character.");
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(short& value) {
+                if (!validState) {
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: Invalid state.");
+                    }
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    try {
+                        value = static_cast<short>(std::stoi(word));
+                    }
+                    catch (const std::exception& e) {
+                        reason = TYPE_INCOMPATIABLE;
+                        validState = false;
+                        if (strict) {
+                            throw e;
+                        }
+                    }
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: No more data.");
+                    }
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(float& value) {
+                if (!validState) {
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: Invalid state.");
+                    }
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    try {
+                        value = static_cast<float>(std::stof(word));
+                    }
+                    catch (const std::exception& e) {
+                        reason = TYPE_INCOMPATIABLE;
+                        validState = false;
+                        if (strict) {
+                            throw e;
+                        }
+                    }
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: No more data.");
+                    }
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(double& value) {
+                if (!validState) {
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: Invalid state.");
+                    }
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    try {
+                        value = static_cast<double>(std::stod(word));
+                    }
+                    catch (const std::exception& e) {
+                        reason = TYPE_INCOMPATIABLE;
+                        validState = false;
+                        if (strict) {
+                            throw e;
+                        }
+                    }
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: No more data.");
+                    }
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(long& value) {
+                if (!validState) {
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: Invalid state.");
+                    }
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    try {
+                        value = static_cast<long>(std::stol(word));
+                    }
+                    catch (const std::exception& e) {
+                        reason = TYPE_INCOMPATIABLE;
+                        validState = false;
+                        if (strict) {
+                            throw e;
+                        }
+                    }
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: No more data.");
+                    }
+                }
+                return *this;
+            }
+
+            FileReader& operator>>(long long& value) {
+                if (!validState) {
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: Invalid state.");
+                    }
+                    return *this;
+                }
+
+                std::string word;
+                if (tokenizer.getNextWord(word)) {
+                    try {
+                        value = static_cast<long long>(std::stoll(word));
+                    }
+                    catch (const std::exception& e) {
+                        reason = TYPE_INCOMPATIABLE;
+                        validState = false;
+                        if (strict) {
+                            throw e;
+                        }
+                    }
+                }
+                else {
+                    reason = FILE_EOF;
+                    validState = false;
+                    if (strict) {
+                        throw std::runtime_error("Read operation failed: No more data.");
+                    }
+                }
+                return *this;
+            }
+
+            size_t getCurrentLine() const {
+                if (tokenizer.isEOF) {
+                    return tokenizer.getCurrentLine() - 1;
+                }
+                else {
+                    return tokenizer.getCurrentLine();
+                }
+            }
+
+            size_t getCurrentOffset() const {
+                if (tokenizer.isEOF) {
+                    return tokenizer.lines[getCurrentLine() - 1].length() + 1;
+                }
+                return tokenizer.getCurrentOffset() - tokenizer.lastWord.length();
+            }
+
+            bool isValid() const {
+                return validState;
+            }
+
+            bool good() const {
+                return validState;
+            }
+
+            FailReason getReason() const{
+                return reason;
+            }
+
+            string getReasonString() const{
+                switch (reason)
+                {
+                case brynhild::core::NONE:
+                    return "NONE ERROR";
+                    break;
+                case brynhild::core::FILE_EOF:
+                    return "FILE_EOF";
+                    break;
+                case brynhild::core::TYPE_INCOMPATIABLE:
+                    return "TYPE_INCOMPATIABLE";
+                    break;
+                default:
+                    return "INVALID REASON";
+                    break;
+                }
+            }
+        };
+    }
+}

+ 64 - 0
core/tokenizer.hpp

@@ -0,0 +1,64 @@
+#include<iostream>
+#include<vector>
+#include<fstream>
+#include<cstring>
+#include<sstream>
+using namespace std;
+namespace brynhild {
+    namespace core {
+        class Tokenizer {
+        private:
+            size_t currentLine;
+            size_t currentPos;
+
+        public:
+            std::string lastWord;
+            std::vector<std::string> lines;
+            bool isEOF;
+            Tokenizer(const std::string& filename)
+                : currentLine(1), currentPos(1), isEOF(false) {
+                std::ifstream file(filename);
+                if (!file.is_open()) {
+                    throw std::runtime_error("Could not open file");
+                }
+                std::string line;
+                while (std::getline(file, line)) {
+                    lines.push_back(line);
+                }
+                file.close();
+            }
+
+            bool getNextWord(std::string& word) {
+                if (isEOF) return false;
+                while (currentLine <= lines.size()) {
+                    while (currentPos <= lines[currentLine - 1].length() && lines[currentLine - 1][currentPos - 1] == ' ') {
+                        currentPos++;
+                    }
+                    size_t startPos = currentPos;
+                    while (currentPos <= lines[currentLine - 1].length() && lines[currentLine - 1][currentPos - 1] != ' ') {
+                        currentPos++;
+                    }
+                    if (startPos < currentPos) {
+                        word = lines[currentLine - 1].substr(startPos - 1, currentPos - startPos);
+                        lastWord = word;
+                        return true;
+                    }
+                    currentLine++;
+                    currentPos = 1;
+                }
+                isEOF = true;
+                lastWord = "";
+                return false;
+            }
+
+
+            size_t getCurrentLine() const {
+                return currentLine;
+            }
+
+            size_t getCurrentOffset() const {
+                return currentPos;
+            }
+        };
+    }
+}

+ 40 - 0
io/Closeable.hpp

@@ -0,0 +1,40 @@
+// Closeable.hpp
+
+#ifndef BRYNHILD_IO_CLOSEABLE_HPP
+#define BRYNHILD_IO_CLOSEABLE_HPP
+
+#include "../core/AutoCloseable.hpp" // Assuming AutoCloseable is defined in a separate header
+
+namespace brynhild {
+    namespace io {
+
+        /**
+         * A Closeable is a source or destination of data that can be closed.
+         * The close method is invoked to release resources that the object is
+         * holding (such as open files).
+         */
+        class Closeable : public core::AutoCloseable {
+        public:
+            /**
+             * Virtual destructor. Ensures that derived classes can clean up resources.
+             */
+            virtual ~Closeable() {}
+
+            /**
+             * Closes this stream and releases any system resources associated
+             * with it. If the stream is already closed, then invoking this
+             * method has no effect.
+             *
+             * Subclasses should override this method to perform the actual
+             * resource release.
+             *
+             * @throws IOException if an I/O error occurs. In C++, this can be handled
+             * by throwing exceptions derived from std::exception.
+             */
+            virtual void close() override = 0; // Marking it as pure virtual
+        };
+
+    } // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_CLOSEABLE_HPP

+ 85 - 0
io/FileInputStream.hpp

@@ -0,0 +1,85 @@
+// FileInputStream.hpp
+
+#ifndef BRYNHILD_IO_FILEINPUTSTREAM_HPP
+#define BRYNHILD_IO_FILEINPUTSTREAM_HPP
+
+#include <fstream>
+#include <string>
+#include <memory>
+#include <mutex>
+#include "InputStream.hpp"
+#include "IOException.hpp"
+
+namespace brynhild {
+    namespace io {
+
+        class FileInputStream : public InputStream {
+        private:
+            std::unique_ptr<std::ifstream> fileStream;
+            std::string filePath;
+            std::mutex mutex;
+            std::streampos markPosition = 0;  // Position marker
+            bool isMarkSet = false;           // Flag to check if mark is set
+
+        public:
+            // Constructor with file path
+            explicit FileInputStream(const std::string& path)
+                : filePath(path), fileStream(std::make_unique<std::ifstream>(path, std::ios::binary)) {
+                if (!fileStream->is_open()) {
+                    throw IOException("File not found: " + path);
+                }
+            }
+
+            // Override read method from InputStream
+            int read() override {
+                std::lock_guard<std::mutex> lock(mutex); // Lock for thread safety
+                char ch;
+                fileStream->get(ch);
+                if (fileStream->eof()) {
+                    return -1;  // End of file
+                }
+                if (!fileStream->good()) {
+                    throw IOException("Read error");
+                }
+                return static_cast<unsigned char>(ch);  // Return byte as an unsigned char converted to int
+            }
+
+            // Override close method from InputStream
+            void close() override {
+                std::lock_guard<std::mutex> lock(mutex); // Lock for thread safety
+                if (fileStream && fileStream->is_open()) {
+                    fileStream->close();
+                }
+            }
+
+            // Mark the current position in the input stream
+            void mark(int readLimit) override {
+                std::lock_guard<std::mutex> lock(mutex); // Lock for thread safety
+                markPosition = fileStream->tellg();
+                isMarkSet = true;
+            }
+
+            // Reset the stream to the most recent mark
+            void reset() override {
+                std::lock_guard<std::mutex> lock(mutex); // Lock for thread safety
+                if (!isMarkSet) {
+                    throw IOException("Mark not set");
+                }
+                fileStream->seekg(markPosition);
+            }
+
+            // Check if mark and reset are supported
+            bool markSupported() const override {
+                return true;  // Mark and reset are supported
+            }
+
+            // Destructor
+            ~FileInputStream() {
+                close();
+            }
+        };
+
+    } // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_FILEINPUTSTREAM_HPP

+ 22 - 0
io/Flushable.hpp

@@ -0,0 +1,22 @@
+// Flushable.hpp
+
+#ifndef BRYNHILD_IO_FLUSHABLE_HPP
+#define BRYNHILD_IO_FLUSHABLE_HPP
+
+#include "IOException.hpp"
+
+namespace brynhild {
+namespace io {
+
+class Flushable {
+public:
+    virtual ~Flushable() {}
+
+    // Pure virtual function to flush the stream
+    virtual void flush() = 0;
+};
+
+} // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_FLUSHABLE_HPP

+ 45 - 0
io/IOException.hpp

@@ -0,0 +1,45 @@
+// IOException.hpp
+
+#ifndef BRYNHILD_IO_IOEXCEPTION_HPP
+#define BRYNHILD_IO_IOEXCEPTION_HPP
+
+#include <exception>
+#include <string>
+
+namespace brynhild {
+    namespace io {
+
+        /**
+         * Signals that an I/O exception of some sort has occurred. This
+         * class is the general class of exceptions produced by failed or
+         * interrupted I/O operations.
+         */
+        class IOException : public std::exception {
+        private:
+            std::string message;
+
+        public:
+            // Default constructor
+            IOException() : message("I/O error occurred") {}
+
+            // Constructor with a specific message
+            IOException(const std::string& msg) : message(msg) {}
+
+            // Constructor with a specific message and a cause
+            IOException(const std::string& msg, const std::exception& cause)
+                : message(msg + ": " + cause.what()) {}
+
+            // Constructor with a cause
+            IOException(const std::exception& cause)
+                : message("I/O error caused by: " + std::string(cause.what())) {}
+
+            // Override the what() method
+            virtual const char* what() const noexcept override {
+                return message.c_str();
+            }
+        };
+
+    } // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_IOEXCEPTION_HPP

+ 89 - 0
io/InputStream.hpp

@@ -0,0 +1,89 @@
+// InputStream.hpp
+
+#ifndef BRYNHILD_CORE_INPUTSTREAM_HPP
+#define BRYNHILD_CORE_INPUTSTREAM_HPP
+
+#include <iostream>
+#include "Closeable.hpp"
+#include "IOException.hpp"
+
+namespace brynhild {
+    namespace io {
+
+        class InputStream : public Closeable {
+        public:
+            // Virtual destructor to ensure proper cleanup in derived classes
+            virtual ~InputStream() {
+                close();
+            }
+
+            // Pure virtual function to read the next byte of data
+            virtual int read() = 0;
+
+            // Reads a sequence of bytes into a buffer
+            virtual int read(char* buffer, int offset, int length) {
+                if (buffer == nullptr) {
+                    throw IOException("Buffer is null");
+                }
+                if (offset < 0 || length < 0 || length > INT_MAX - offset) {
+                    throw IOException("Invalid offset or length");
+                }
+
+                int bytesRead = 0;
+                for (int i = 0; i < length; ++i) {
+                    int byte = read();
+                    if (byte == -1) {
+                        return bytesRead > 0 ? bytesRead : -1;
+                    }
+                    buffer[offset + i] = static_cast<char>(byte);
+                    bytesRead++;
+                }
+                return bytesRead;
+            }
+
+            // Skips over and discards n bytes of data
+            virtual long skip(long n) {
+                if (n <= 0) {
+                    return 0;
+                }
+
+                int skippedBytes = 0;
+                for (long i = 0; i < n; ++i) {
+                    if (read() == -1) {
+                        break;
+                    }
+                    skippedBytes++;
+                }
+                return skippedBytes;
+            }
+
+            // Returns an estimate of the number of bytes that can be read
+            virtual int available() const {
+                return 0;  // Default implementation, subclasses may override
+            }
+
+            // Closes this input stream
+            virtual void close() override {
+                // Implementation depends on the specific subclass
+            }
+
+            // Marks the current position in this input stream
+            virtual void mark(int readLimit) {
+                // Default implementation does nothing
+            }
+
+            // Repositions this stream to the position at the time the mark method was last called
+            virtual void reset() {
+                throw IOException("mark/reset not supported");
+            }
+
+            // Tests if this input stream supports the mark and reset methods
+            virtual bool markSupported() const {
+                return false;  // Default implementation
+            }
+        };
+
+    } // namespace core
+} // namespace brynhild
+
+#endif // BRYNHILD_CORE_INPUTSTREAM_HPP

+ 56 - 0
io/InputStreamReader.hpp

@@ -0,0 +1,56 @@
+// InputStreamReader.hpp
+
+#ifndef BRYNHILD_IO_INPUTSTREAMREADER_HPP
+#define BRYNHILD_IO_INPUTSTREAMREADER_HPP
+
+#include "Reader.hpp"
+#include "InputStream.hpp"
+#include "IOException.hpp"
+
+namespace brynhild {
+    namespace io {
+
+        /**
+         * InputStreamReader is a bridge from byte streams to character streams.
+         * It reads bytes from an InputStream and converts them into characters.
+         */
+        class InputStreamReader : public Reader {
+        private:
+            InputStream& inStream;  // Reference to the InputStream
+
+        public:
+            // Constructor with InputStream
+            explicit InputStreamReader(InputStream& in) : inStream(in) {}
+
+            // Override read methods from Reader
+            int read(char* cbuf, int off, int len) override {
+                if (cbuf == nullptr) {
+                    throw IOException("Buffer is null");
+                }
+                if (len <= 0 || off < 0) {
+                    return 0;
+                }
+
+                int bytesRead = 0, byteRead;
+                for (int i = 0; i < len; ++i) {
+                    byteRead = inStream.read();
+                    if (byteRead == -1) {
+                        break;
+                    }
+                    cbuf[off + i] = static_cast<char>(byteRead);
+                    bytesRead++;
+                }
+
+                return bytesRead == 0 && len > 0 ? -1 : bytesRead;
+            }
+
+            // Implement the close method
+            void close() override {
+                inStream.close();
+            }
+        };
+
+    } // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_INPUTSTREAMREADER_HPP

+ 73 - 0
io/Reader.hpp

@@ -0,0 +1,73 @@
+// Reader.hpp
+
+#ifndef BRYNHILD_IO_READER_HPP
+#define BRYNHILD_IO_READER_HPP
+
+#include <mutex>
+#include <stdexcept>
+#include "IOException.hpp"
+#include "../core/Readable.hpp"
+#include "Closeable.hpp"
+
+namespace brynhild {
+    namespace io {
+
+        class Reader : public core::Readable, public Closeable {
+        protected:
+            std::mutex lock; // Mutex used for synchronization within the class
+
+        public:
+            Reader() = default; // Default constructor
+            virtual ~Reader() = default; // Default destructor
+
+            // Pure virtual methods to be implemented by subclasses
+            virtual int read(char* cbuf, int off, int len) = 0;
+            virtual void close() = 0;
+
+            // Other virtual methods with default implementations
+            virtual int read(char* cbuf, int len) {
+                std::lock_guard<std::mutex> guard(lock); // Locking for thread safety
+                return read(cbuf, 0, len);
+            }
+            virtual int read() {
+                std::lock_guard<std::mutex> guard(lock); // Locking for thread safety
+                char cb[1];
+                int result = read(cb, 0, 1);
+                return (result == -1) ? -1 : static_cast<int>(cb[0]);
+            }
+            long skip(long n){
+                if (n <= 0) {
+                    return 0;
+                }
+
+                long skipped = 0;
+                for (long i = 0; i < n; ++i) {
+                    if (read() == -1) {
+                        break;
+                    }
+                    skipped++;
+                }
+                return skipped;
+            }
+            virtual bool ready() {
+                std::lock_guard<std::mutex> guard(lock); // Locking for thread safety
+                return false;
+            }
+            virtual bool markSupported() {
+                std::lock_guard<std::mutex> guard(lock); // Locking for thread safety
+                return false;
+            }
+            virtual void mark(int readAheadLimit) {
+                std::lock_guard<std::mutex> guard(lock); // Locking for thread safety
+                throw IOException("mark() not supported");
+            }
+            virtual void reset() {
+                std::lock_guard<std::mutex> guard(lock); // Locking for thread safety
+                throw IOException("reset() not supported");
+            }
+        };
+
+    } // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_READER_HPP

+ 43 - 0
io/SocketInputStream.hpp

@@ -0,0 +1,43 @@
+// SocketInputStream.hpp
+
+#ifndef BRYNHILD_IO_SOCKETINPUTSTREAM_HPP
+#define BRYNHILD_IO_SOCKETINPUTSTREAM_HPP
+
+#include "InputStream.hpp"
+#include "IOException.hpp"
+#include <string>
+#include <mutex>
+
+namespace brynhild {
+namespace io {
+
+class SocketInputStream : public InputStream {
+private:
+    std::string serverIP;
+    int dataPort;
+    int controlPort;
+    std::mutex mutex;
+
+public:
+    // Constructor with server IP/domain, data port, and control port
+    SocketInputStream(const std::string& serverIP, int dataPort, int controlPort)
+        : serverIP(serverIP), dataPort(dataPort), controlPort(controlPort) {
+        // Constructor logic (e.g., establishing socket connection)
+    }
+
+    // Override read method (abstract)
+    int read() override = 0;
+
+    // Override close method
+    void close() override {
+        std::lock_guard<std::mutex> lock(mutex); // Lock for thread safety
+        // Close logic for the socket stream
+    }
+
+    // Other InputStream methods remain abstract and should be implemented by derived classes
+};
+
+} // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_SOCKETINPUTSTREAM_HPP

+ 60 - 0
io/Writer.hpp

@@ -0,0 +1,60 @@
+// Writer.hpp
+
+#ifndef BRYNHILD_IO_WRITER_HPP
+#define BRYNHILD_IO_WRITER_HPP
+
+#include "../core/Appendable.hpp"
+#include "Flushable.hpp"
+#include "Closeable.hpp"
+#include <string>
+#include <mutex>
+#include <vector>
+#include <stdexcept>
+
+namespace brynhild {
+namespace io {
+
+class Writer : public core::Appendable, public Flushable, public Closeable {
+protected:
+    std::mutex lock;
+
+public:
+    Writer() = default;
+    virtual ~Writer() {}
+
+    // Pure virtual functions
+    virtual void write(const char* cbuf, size_t off, size_t len) = 0;
+    virtual void flush() = 0;
+    virtual void close() = 0;
+
+    // Write a single character
+    virtual void write(char c) {
+        std::lock_guard<std::mutex> guard(lock);
+        write(&c, 0, 1);
+    }
+
+    // Write a string
+    virtual void write(const std::string& str) {
+        write(str.c_str(), 0, str.size());
+    }
+
+    // Appendable interface methods
+    virtual Writer& append(const std::string& csq, int start = 0, int end = -1) override {
+        if (end == -1) end = csq.size();
+        if (start < 0 || start > end || end > static_cast<int>(csq.size())) {
+            throw std::out_of_range("Invalid start or end position");
+        }
+        write(csq.substr(start, end - start));
+        return *this;
+    }
+
+    virtual Writer& append(char c) override {
+        write(c);
+        return *this;
+    }
+};
+
+} // namespace io
+} // namespace brynhild
+
+#endif // BRYNHILD_IO_WRITER_HPP