From 6be111209176dddb8326c02eb5189539f5cb08c7 Mon Sep 17 00:00:00 2001 From: bronku Date: Thu, 13 Nov 2025 17:51:51 +0100 Subject: [PATCH] buffered reader and writer --- .clangd | 2 ++ main.cpp | 1 + makefile | 2 +- reader.hpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ writer.hpp | 55 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 .clangd create mode 100644 reader.hpp create mode 100644 writer.hpp diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..c7a47fe --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Add: [-std=c++17] diff --git a/main.cpp b/main.cpp index 1403137..c3a72c6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,5 @@ #include "config.hpp" +#include "reader.hpp" #include "record.hpp" #include #include diff --git a/makefile b/makefile index 437aecf..6f37da3 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -CFLAGS = -g -lc++ +CFLAGS = -g -lc++ -std=c++17 build/main: main.cpp build clang $(CFLAGS) main.cpp -o build/main diff --git a/reader.hpp b/reader.hpp new file mode 100644 index 0000000..c9432fb --- /dev/null +++ b/reader.hpp @@ -0,0 +1,78 @@ +#pragma once +#include "record.hpp" +#include +#include +#include + +class Reader { +private: + std::vector read_buffer; + std::istream& input_stream; + size_t buffer_size; + size_t total_reads_count; + int last_element_idx; // last valid element in buffer + int current_idx; // current reading position + + // returns true if at least one record was returned + bool refill_buffer() + { + last_element_idx = -1; + current_idx = 0; + + for (size_t i = 0; i < buffer_size; i++) { + if (!(input_stream >> read_buffer[i])) { + break; + } + last_element_idx = static_cast(i); + } + + return last_element_idx >= 0; + } + +public: + explicit Reader(std::istream& input_stream, size_t buffer_size = 8) + : read_buffer(buffer_size) + , input_stream(input_stream) + , buffer_size(buffer_size) + , total_reads_count(0) + , last_element_idx(-1) + , current_idx(0) + { + } + + std::optional read() + { + if (current_idx > last_element_idx) { + bool read_new_items = refill_buffer(); + if (!read_new_items) { + return std::nullopt; + } + } + + Record record = read_buffer[current_idx]; + current_idx++; + total_reads_count++; + + return record; + } + + size_t total_reads() const + { + return total_reads_count; + } + + // #todo remove if not used in the end + // bool has_more() const + // { + // return current_idx <= last_element_idx || !input_stream.eof(); + // } + + // void reset() + // { + // input_stream.clear(); + // input_stream.seekg(0); + // last_element_idx = -1; + // current_idx = 0; + // total_reads_count = 0; + // } +}; diff --git a/writer.hpp b/writer.hpp new file mode 100644 index 0000000..99dbb84 --- /dev/null +++ b/writer.hpp @@ -0,0 +1,55 @@ +#pragma once +#include "record.hpp" +#include +#include + +class Writer { +private: + std::vector write_buffer; + std::ostream& output_stream; + size_t buffer_size; + size_t total_writes_count; + size_t current_idx; // Current position in buffer + + // returns true on success + // doesn't really flush for performace reasons + // could be changed to really flush to monitor the impac of amount of writes + bool flush_buffer() + { + for (size_t i = 0; i < current_idx; ++i) { + if (!(output_stream << write_buffer[i])) { + return false; + } + } + + return true; + } + +public: + explicit Writer(std::ostream& output_stream, size_t buffer_size = 8) + : write_buffer(buffer_size) + , output_stream(output_stream) + , buffer_size(buffer_size) + , total_writes_count(0) + , current_idx(0) + { + } + + bool write(const Record& record) + { + write_buffer[current_idx] = record; + current_idx++; + total_writes_count++; + + if (current_idx >= buffer_size) { + return flush_buffer(); + } + + return true; + } + + size_t total_writes() const + { + return total_writes_count; + } +};