factory.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include "factory.h"
  2. #include <library/cpp/streams/bzip2/bzip2.h>
  3. #include <library/cpp/streams/factory/open_common/factory.h>
  4. #include <util/stream/holder.h>
  5. #include <util/stream/file.h>
  6. #include <library/cpp/streams/lz/lz.h>
  7. #include <util/stream/str.h>
  8. #include <util/stream/zlib.h>
  9. #include <util/stream/multi.h>
  10. #include <util/generic/ptr.h>
  11. #include <util/generic/string.h>
  12. namespace {
  13. template <class T>
  14. struct TInputHolderX: public T {
  15. inline decltype(T().Get()) Set(T t) noexcept {
  16. t.Swap(*this);
  17. return this->Get();
  18. }
  19. };
  20. template <class T>
  21. struct TInputHolderX<T*> {
  22. static inline T* Set(T* t) noexcept {
  23. return t;
  24. }
  25. };
  26. template <class TInput>
  27. struct TStringMultiInput: private TInputHolderX<TInput>, private TString, private THolder<IInputStream>, public TMultiInput {
  28. TStringMultiInput(const TString& head, TInput tail)
  29. : TString(head)
  30. , THolder<IInputStream>(new TStringInput(*this))
  31. , TMultiInput(THolder<IInputStream>::Get(), this->Set(tail))
  32. {
  33. }
  34. ~TStringMultiInput() override {
  35. }
  36. };
  37. }
  38. template <class TInput>
  39. THolder<IInputStream> OpenMaybeCompressedInputX(TInput input) {
  40. const size_t MAX_SIGNATURE_SIZE = 4;
  41. char buffer[MAX_SIGNATURE_SIZE];
  42. TString header(buffer, input->Load(buffer, MAX_SIGNATURE_SIZE));
  43. if (header.size() == MAX_SIGNATURE_SIZE) {
  44. // any lz
  45. THolder<IInputStream> lz = TryOpenOwnedLzDecompressor(new TStringMultiInput<TInput>(header, input));
  46. if (lz.Get()) {
  47. return lz;
  48. }
  49. }
  50. THolder<IInputStream> multi(new TStringMultiInput<TInput>(header, input));
  51. // gzip
  52. const TStringBuf GZIP = "\x1F\x8B";
  53. const TStringBuf ZLIB = "\x78\x9C";
  54. if (header.StartsWith(GZIP) || header.StartsWith(ZLIB)) {
  55. return MakeHolder<THoldingStream<TBufferedZLibDecompress>>(std::move(multi));
  56. }
  57. // bzip2
  58. constexpr TStringBuf BZIP2 = "BZ";
  59. if (header.StartsWith(BZIP2)) {
  60. return MakeHolder<THoldingStream<TBZipDecompress>>(std::move(multi));
  61. }
  62. return multi;
  63. }
  64. THolder<IInputStream> OpenMaybeCompressedInput(IInputStream* input) {
  65. return OpenMaybeCompressedInputX(input);
  66. }
  67. THolder<IInputStream> OpenOwnedMaybeCompressedInput(THolder<IInputStream> input) {
  68. return OpenMaybeCompressedInputX(TAtomicSharedPtr<IInputStream>(input));
  69. }
  70. THolder<IInputStream> OpenMaybeCompressedInput(const TString& path) {
  71. if (!path || path == TStringBuf("-")) {
  72. return OpenOwnedMaybeCompressedInput(OpenStdin());
  73. }
  74. return OpenOwnedMaybeCompressedInput(MakeHolder<TFileInput>(path));
  75. }
  76. THolder<IInputStream> OpenMaybeCompressedInput(const TString& path, ui32 bufSize) {
  77. if (!path || path == TStringBuf("-")) {
  78. return OpenOwnedMaybeCompressedInput(OpenStdin(bufSize));
  79. }
  80. return OpenOwnedMaybeCompressedInput(MakeHolder<TFileInput>(path, bufSize));
  81. }