[iostreams] replacement of std::ifstream, review request
Hi, I made a library which gets an std::ifstream and read a certain file format. Now I would like to support also gzip compressed input files, but it should also support not compressed files. I used boost::iostreams to implement a new stream class which should replace the std::ifstream in my library. Following functions are called from std::ifstream: - std::ifstream(const char*) - read(...) - seek(...) - close(...) My question is, is everything done correctly or is there a more elegant way to implement this? I'm not a stream expert, so I doubt if I do it in a good way :-). Would be great if someone from the experts can have a look to it and review it. Thanks in advance, Sascha I derived my class from boost::iostreams::filtering_istream, here is my implementation: #ifndef PAT_INPUTSTREAM_H #define PAT_INPUTSTREAM_H #include <boost/iostreams/device/file.hpp> #include <boost/iostreams/filter/gzip.hpp> #include <boost/iostreams/filtering_stream.hpp> #include <string> namespace my { namespace io = boost::iostreams; /*! Check if a given file is a (gzipped-)compressed format It is using functions from zlib */ bool isCompressed(const char* p_name); /*! \class ifstream Special input stream to handle compressed files. After opening an my::ifstream, it should be checked with is_open() if it is openend correctly. */ class ifstream : public io::filtering_istream { private: std::string _name; // the filename is needed for re-opening in seek() public: ifstream(const char* p_name) : _name(p_name) { if (isCompressed(p_name)) { io::filtering_istream::push(io::gzip_decompressor()); io::filtering_istream::push(io::file_source(p_name, std::ios::binary)); } else { io::filtering_istream::push(io::file_source(p_name)); } } bool open(const char* p_name) { if (!is_open()) { _name = p_name; if (isCompressed(p_name)) { io::filtering_istream::push(io::gzip_decompressor()); io::filtering_istream::push(io::file_source(p_name, std::ios::binary)); } else { io::filtering_istream::push(io::file_source(p_name)); } } return is_open(); } void close() { if (is_open()) { while (io::filtering_istream::size()) { io::filtering_istream::pop(); } } } bool is_open() { if (io::filtering_istream::size()) { // the last components is the file device io::file_source* device = io::filtering_istream::component<io::file_source>(io::filtering_istream::size()-1); if (device) return device->is_open(); } return false; } ifstream& seekg(std::streampos p_pos) { // seek means close the stream // and read until position is reached were we // want to be if (is_open()) { close(); if (open(_name.c_str())) { const std::streampos PAT_BLOCK_SIZE = 1024; char* buf = new char[PAT_BLOCK_SIZE]; while (p_pos) { if (p_pos / PAT_BLOCK_SIZE) { read(buf, PAT_BLOCK_SIZE); p_pos -= PAT_BLOCK_SIZE; } else { read(buf, p_pos % PAT_BLOCK_SIZE); p_pos -= (p_pos % PAT_BLOCK_SIZE); } } delete [] buf; } } return *this; } }; } // end of namespace pat #endif
participants (1)
-
Sascha Ochsenknecht