#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;
class cfilebuf : public streambuf {
private:
vector<char_type> buffer;
FILE *file;
protected:
virtual int underflow() override {
if (!file)
return traits_type::eof();
if (gptr() < egptr()) //если буфер не пуст, вернем текущий символ
return *gptr();
char_type *start = eback();
//читаем не больше символов, чем вмещает буфер
size_t rd = fread(start, sizeof(char_type), buffer.size(), file);
//указываем размер буфера не больше, чем было считано символов
setg(start, start, start + rd);
return rd > 0 ? *gptr() : traits_type::eof();
}
public:
cfilebuf(size_t _bufsize)
: buffer(_bufsize), file(nullptr)
{
char_type *start = buffer.data();
char_type *end = start + buffer.size();
setg(start, end, end); //устанавливаем eback = start, gptr = end, egptr = end
//т.к. gptr == egptr, буфер по факту пуст и будет заполнен при первой попытке чтения
}
~cfilebuf(){
close();
}
bool open(string fn){
close();
file = fopen(fn.c_str(), "r");
return file != nullptr;
}
void close(){
if (file){
fclose(file);
file = nullptr;
}
}
};
int main(int argc, char **argv){
cfilebuf buf(10);
istream in(&buf);
string line;
buf.open("file.txt");
while (getline(in, line)){
cout << line << endl;
}
return 0;
}