What you need to do is provide a type that inherits from std::basic_streambuf. There are many mysterious virtualmember functions, relevant ones are for you showmanyc(), underflow(), uflow()and xsgetn(). You will want to reload them by overflowing, automatically open the next file in your list (if any).
Here is an example implementation. We act std::filebufjust like we save the deque<string>following files that we need to read:
class multifilebuf : public std::filebuf
{
public:
multifilebuf(std::initializer_list<std::string> filenames)
: next_filenames(filenames.begin() + 1, filenames.end())
{
open(*filenames.begin(), std::ios::in);
}
protected:
std::streambuf::int_type underflow() override
{
for (;;) {
auto res = std::filebuf::underflow();
if (res == traits_type::eof()) {
if (next_filenames.empty()) {
return res;
}
else {
close();
open(next_filenames.front(), std::ios::in);
next_filenames.pop_front();
continue;
}
}
else {
return res;
}
}
}
private:
std::deque<std::string> next_filenames;
};
This way you can make everything transparent to your end user:
multifilebuf mfb{"file1", "file2", "file3"};
std::istream is(&mfb);
std::string word;
while (is >> word) {
}
Barry source
share