1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
#ifndef SHRINKWRAP_ISTREAM_HPP
#define SHRINKWRAP_ISTREAM_HPP
#include "stdio.hpp"
#include "xz.hpp"
#include "gz.hpp"
#include "zstd.hpp"
#include <streambuf>
#include <memory>
namespace shrinkwrap
{
namespace detail
{
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
class istream : public std::istream
{
public:
istream(const std::string& file_path)
:
std::istream(nullptr)
{
FILE* fp = fopen(file_path.c_str(), "rb");
int first_byte = fgetc(fp);
ungetc(first_byte, fp);
switch (char(first_byte))
{
case '\x1F':
sbuf_ = detail::make_unique<::shrinkwrap::bgzf::ibuf>(fp);
break;
case char('\xFD'):
sbuf_ = detail::make_unique<::shrinkwrap::xz::ibuf>(fp);
break;
case '\x28':
sbuf_ = detail::make_unique<::shrinkwrap::zstd::ibuf>(fp);
break;
default:
sbuf_ = detail::make_unique<::shrinkwrap::stdio::filebuf>(fp);
}
this->rdbuf(sbuf_.get());
}
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
istream(istream&& src)
:
std::istream(src.sbuf_.get()),
sbuf_(std::move(src.sbuf_))
{
}
istream& operator=(istream&& src)
{
if (&src != this)
{
std::istream::operator=(std::move(src));
sbuf_ = std::move(src.sbuf_);
}
return *this;
}
#endif
private:
std::unique_ptr<std::streambuf> sbuf_;
};
}
#endif //SHRINKWRAP_ISTREAM_HPP
|