Вам дан класс Writer
, который умеет писать данные на экран, в файл или в память – в общем, неважно куда.
У этого класса есть виртуальная функция Write
, принимающая на вход указатель на байты памяти и их количество.
Функция пытается записать эти байты в нужное место.
Выглядит этот класс примерно так:
class Writer {
public:
virtual void Write(const char * data, size_t len) {
// Какой-то вывод в файл, на экран или в память
}
};
Однако операция вывода имеет накладные расходы, и частые вызовы Write
с маленькими размерами данных могут замедлять программу.
Вам надо написать класс-наследник BufferedWriter
, который осуществлял бы буферизованный вывод.
Конструктор этого класса должен принимать параметр типа size_t
– размер буфера.
Переопределенная в этом классе функция Write
должна сначала дописывать данные в этот внутренний буфер, и только когда он заполнится – вызывать Write
базового класса с данными этого буфера.
В конце использования класса оставшиеся в буфере данные также должны быть записаны через вызов функции Write
базового класса.
Максимально возможный размер буфера, переданный в конструкторе, в процессе работы не должен изменяться.
Начните свою программу с #include "writer.h"
– эта директива подключит нашу версию базового класса Writer
.
Далее напишите только код класса-наследника BufferedWriter
.
Будем в качестве буфера использовать vector<char>
.
В конструкторе установим зарезервированную ёмкость вектора равной размеру буфера, и не будем дальше её менять.
Функция Write
будет помещать в конец вектора очередной кусок данных, лишь бы он поместился в вектор.
Если вектор заполнился, вызовем вспомогательную функцию Flush
, обращающуюся к функции Write
базового класса.
Важно не забыть вызвать Flush
в деструкторе нашего класса, так как в буфере могли остаться какие-то данные.
#include "writer.h"
#include <algorithm> // for std::min
#include <vector>
class BufferedWriter: public Writer {
private:
std::vector<char> buffer;
public:
BufferedWriter(size_t bufsize) {
buffer.reserve(bufsize);
}
void Write(const char* data, size_t len) override {
size_t pos = 0;
while (pos != len) {
auto chunk = std::min(len - pos, buffer.capacity() - buffer.size());
buffer.insert(buffer.end(), data + pos, data + pos + chunk);
pos += chunk;
if (buffer.size() == buffer.capacity()) {
Flush();
}
}
}
void Flush() {
Writer::Write(buffer.data(), buffer.size());
buffer.clear();
}
~BufferedWriter() {
Flush();
}
};