| 87 | } |
| 88 | |
| 89 | class TBZipCompress::TImpl: public TAdditionalStorage<TImpl> { |
| 90 | public: |
| 91 | inline TImpl(IOutputStream* stream, size_t level) |
| 92 | : Stream_(stream) |
| 93 | { |
| 94 | Zero(BzStream_); |
| 95 | |
| 96 | if (BZ2_bzCompressInit(&BzStream_, level, 0, 0) != BZ_OK) { |
| 97 | ythrow TBZipCompressError() << "can not init bzip engine"; |
| 98 | } |
| 99 | |
| 100 | BzStream_.next_out = TmpBuf(); |
| 101 | BzStream_.avail_out = TmpBufLen(); |
| 102 | } |
| 103 | |
| 104 | inline ~TImpl() { |
| 105 | BZ2_bzCompressEnd(&BzStream_); |
| 106 | } |
| 107 | |
| 108 | inline void Write(const void* buf, size_t size) { |
| 109 | BzStream_.next_in = (char*)buf; |
| 110 | BzStream_.avail_in = size; |
| 111 | |
| 112 | Y_DEFER { |
| 113 | BzStream_.next_in = 0; |
| 114 | BzStream_.avail_in = 0; |
| 115 | }; |
| 116 | |
| 117 | while (BzStream_.avail_in) { |
| 118 | const int ret = BZ2_bzCompress(&BzStream_, BZ_RUN); |
| 119 | |
| 120 | switch (ret) { |
| 121 | case BZ_RUN_OK: |
| 122 | continue; |
| 123 | |
| 124 | case BZ_PARAM_ERROR: |
| 125 | case BZ_OUTBUFF_FULL: |
| 126 | Stream_->Write(TmpBuf(), TmpBufLen() - BzStream_.avail_out); |
| 127 | BzStream_.next_out = TmpBuf(); |
| 128 | BzStream_.avail_out = TmpBufLen(); |
| 129 | |
| 130 | break; |
| 131 | |
| 132 | default: |
| 133 | ythrow TBZipCompressError() << "bzip error(" << ret << ", " << BzStream_.avail_out << ")"; |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | inline void Flush() { |
| 139 | /* |