#include "factory.h" #include #include #include #include #include #include #include #include #include #include namespace { template struct TInputHolderX: public T { inline decltype(T().Get()) Set(T t) noexcept { t.Swap(*this); return this->Get(); } }; template struct TInputHolderX { static inline T* Set(T* t) noexcept { return t; } }; template struct TStringMultiInput: private TInputHolderX, private TString, private THolder, public TMultiInput { TStringMultiInput(const TString& head, TInput tail) : TString(head) , THolder(new TStringInput(*this)) , TMultiInput(THolder::Get(), this->Set(tail)) { } ~TStringMultiInput() override { } }; } template THolder OpenMaybeCompressedInputX(TInput input) { const size_t MAX_SIGNATURE_SIZE = 4; char buffer[MAX_SIGNATURE_SIZE]; TString header(buffer, input->Load(buffer, MAX_SIGNATURE_SIZE)); if (header.size() == MAX_SIGNATURE_SIZE) { // any lz THolder lz = TryOpenOwnedLzDecompressor(new TStringMultiInput(header, input)); if (lz.Get()) { return lz; } } THolder multi(new TStringMultiInput(header, input)); // gzip const TStringBuf GZIP = "\x1F\x8B"; const TStringBuf ZLIB = "\x78\x9C"; if (header.StartsWith(GZIP) || header.StartsWith(ZLIB)) { return MakeHolder>(std::move(multi)); } // bzip2 constexpr TStringBuf BZIP2 = "BZ"; if (header.StartsWith(BZIP2)) { return MakeHolder>(std::move(multi)); } return multi; } THolder OpenMaybeCompressedInput(IInputStream* input) { return OpenMaybeCompressedInputX(input); } THolder OpenOwnedMaybeCompressedInput(THolder input) { return OpenMaybeCompressedInputX(TAtomicSharedPtr(input)); } THolder OpenMaybeCompressedInput(const TString& path) { if (!path || path == TStringBuf("-")) { return OpenOwnedMaybeCompressedInput(OpenStdin()); } return OpenOwnedMaybeCompressedInput(MakeHolder(path)); } THolder OpenMaybeCompressedInput(const TString& path, ui32 bufSize) { if (!path || path == TStringBuf("-")) { return OpenOwnedMaybeCompressedInput(OpenStdin(bufSize)); } return OpenOwnedMaybeCompressedInput(MakeHolder(path, bufSize)); }