├── .gitignore ├── test ├── Makefile ├── big_endian │ ├── build.sh │ ├── run_test.sh │ ├── README.md │ └── powerpc_sysroot_setup.sh ├── input_test.cpp ├── output_test.cpp ├── nocompression_test.cpp ├── buffer_test.cpp └── CMakeLists.txt ├── Readme.md ├── zstream_common.hpp ├── .github └── workflows │ └── cmake-multi-platform.yml ├── ozstream_impl.hpp ├── izstream_impl.hpp ├── izstream.hpp └── ozstream.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ -I.. -o output_test output_test.cpp -lz 3 | -------------------------------------------------------------------------------- /test/big_endian/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | SYSROOT=${HOME}/powerpc_sysroot 5 | 6 | sudo cp -r ../../../zstream-cpp ${SYSROOT} 7 | sudo chroot ${SYSROOT} /bin/bash -c "cd zstream-cpp/test && make" 8 | -------------------------------------------------------------------------------- /test/big_endian/run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | SYSROOT=${HOME}/powerpc_sysroot 5 | TEST_FILE=${SYSROOT}/test.txt 6 | 7 | sudo rm -f ${TEST_FILE} ${SYSROOT}/test.txt.gz 8 | sudo chroot ${SYSROOT} ./zstream-cpp/test/output_test 9 | sudo chroot ${SYSROOT} gunzip ./test.txt.gz 10 | -------------------------------------------------------------------------------- /test/input_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "izstream.hpp" 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | using namespace zstream; 10 | 11 | int main(void) { 12 | ifstream is("test.txt.gz"); 13 | igzstream gz(is); 14 | double d = 0; 15 | while (gz >> d) { 16 | cout << d << endl; 17 | } 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /test/output_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ozstream.hpp" 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | using namespace zstream; 10 | 11 | int main(void) { 12 | ofstream os("test.txt.gz"); 13 | ogzstream gz(os); 14 | for (size_t i = 0; i < 2000; i++) { 15 | gz << drand48() << endl; 16 | } 17 | cout << gz.get_zerr() << endl; 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /test/big_endian/README.md: -------------------------------------------------------------------------------- 1 | # Setup Big Endian Environment 2 | 3 | These steps have been test on Ubuntu 22.04. 4 | 5 | * ./powerpc_sysroot_setup.sh 6 | * This setups up a big endian build and run environment 7 | * Uses Debian Jesse distribution that supported powerpc big endian architectures 8 | * ./build.sh 9 | * build output_test under big endian envirionment 10 | * ./run_test.sh 11 | * runs output_test under big endian envirionment 12 | -------------------------------------------------------------------------------- /test/big_endian/powerpc_sysroot_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Setups up powerpc sysroot on Ubuntu 22.04 4 | # 5 | set -e 6 | 7 | sudo apt install -y qemu-user-static debootstrap 8 | SYSROOT=${HOME}/powerpc_sysroot 9 | mkdir -p ${SYSROOT} 10 | sudo debootstrap --arch=powerpc --foreign \ 11 | jessie ${SYSROOT} \ 12 | http://archive.debian.org/debian 13 | sudo cp /usr/bin/qemu-ppc-static ${SYSROOT}/usr/bin/ 14 | sudo chroot ${SYSROOT} /debootstrap/debootstrap --second-stage 15 | 16 | sudo chroot ${SYSROOT} /bin/bash -c "apt update && apt install -y --force-yes zlib1g-dev build-essential vim file" 17 | -------------------------------------------------------------------------------- /test/nocompression_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "zstream.hpp" 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | using namespace zstream; 11 | 12 | int main(void) 13 | { 14 | string input = "Hello world \n"; 15 | ostringstream buffer; 16 | { 17 | ozstream zipper(buffer, 0); 18 | zipper << input; 19 | } 20 | string zstr = buffer.str(); 21 | 22 | istringstream ibuffer(zstr); 23 | izstream izstream(ibuffer); 24 | izstream.unsetf(ios_base::skipws); 25 | 26 | string output = std::string((std::istream_iterator(izstream)), 27 | std::istream_iterator()); 28 | 29 | if (output != input) 30 | { 31 | cout << "compare failed" << endl; 32 | return 1; 33 | } 34 | else 35 | { 36 | cout << "compare succeeded" << endl; 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/buffer_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "izstream.hpp" 5 | #include "ozstream.hpp" 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | using namespace zstream; 12 | 13 | int main(void) { 14 | string input = "Hello world \n"; 15 | ostringstream buffer; 16 | { 17 | ozstream zipper(buffer); 18 | zipper << input; 19 | } 20 | string zstr = buffer.str(); 21 | 22 | istringstream ibuffer(zstr); 23 | izstream izstream(ibuffer); 24 | izstream.unsetf(ios_base::skipws); 25 | 26 | string output = std::string((std::istream_iterator(izstream)), 27 | std::istream_iterator()); 28 | 29 | if (output != input) { 30 | cout << "compare failed" << endl; 31 | return 1; 32 | } else { 33 | cout << "compare succeeded" << endl; 34 | return 0; 35 | } 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | STL iostream implementation using the library zlib. This means that you can easily manipulate zipped streams like any other STL ostream/istream. 5 | 6 | To give you an idea, consider following snippet that prints "Hello World": 7 | 8 | ostringstream output_buffer; 9 | // writing data 10 | output_buffer << "Hello world" << endl ; 11 | 12 | Now, the same snippet but with zipped output using zlib: 13 | 14 | // zip_ostream uses output_buffer as output buffer :) 15 | ozstream zipper( output_buffer ); 16 | 17 | // writing data as usual 18 | zipper << "Hello world" << endl; 19 | 20 | Or, to create gzipped files: 21 | 22 | ofstream file("hello_world.txt.gz"); 23 | ogzstream gzfile(file); 24 | gzfile << "Hello world " << endl; 25 | 26 | As you can see adding zipped buffers into your existing applications is quite straightforward. To summarize, let's see some quick facts about zstream: 27 | 28 | * STL compliant, 29 | * any-stream-to-any-stream support, 30 | * char, wchar_t support, 31 | * fining tuning of compression properties, 32 | * support custom allocators (New!) 33 | 34 | 35 | Based on the work of Jonathan de Halleux, published on CodeProject http://www.codeproject.com/Articles/4457/zipstream-bzip-stream-iostream-wrappers-for-the-zl 36 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(zstream-cpp) 3 | 4 | find_package(ZLIB REQUIRED) 5 | 6 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++11") 7 | 8 | include_directories("${CMAKE_SOURCE_DIR}/..") 9 | include_directories(${ZLIB_INCLUDE_DIRS}) 10 | 11 | add_executable(output_test output_test.cpp) 12 | target_link_libraries(output_test ${ZLIB_LIBRARIES}) 13 | 14 | add_executable(input_test input_test.cpp) 15 | target_link_libraries(input_test ${ZLIB_LIBRARIES}) 16 | 17 | add_executable(buffer_test buffer_test.cpp) 18 | target_link_libraries(buffer_test ${ZLIB_LIBRARIES}) 19 | 20 | add_executable(nocompression_test nocompression_test.cpp) 21 | target_link_libraries(nocompression_test ${ZLIB_LIBRARIES}) 22 | 23 | # CREATE single header file 24 | 25 | file(READ "${CMAKE_SOURCE_DIR}/../zstream_common.hpp" COMMON_CONTENT) 26 | file(READ "${CMAKE_SOURCE_DIR}/../izstream.hpp" IZSTREAM_CONTENT) 27 | file(READ "${CMAKE_SOURCE_DIR}/../izstream_impl.hpp" IZSTREAM_IMPL_CONTENT) 28 | file(READ "${CMAKE_SOURCE_DIR}/../ozstream.hpp" OZSTREAM_CONTENT) 29 | file(READ "${CMAKE_SOURCE_DIR}/../ozstream_impl.hpp" OZSTREAM_IMPL_CONTENT) 30 | 31 | string(REPLACE "#include \"" "//#include \"" CONTENT "${COMMON_CONTENT} ${OZSTREAM_CONTENT} ${OZSTREAM_IMPL_CONTENT} ${IZSTREAM_CONTENT} ${IZSTREAM_IMPL_CONTENT}") 32 | 33 | file(WRITE "${CMAKE_BINARY_DIR}/zstream.hpp" "${CONTENT}") 34 | -------------------------------------------------------------------------------- /zstream_common.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | zstream-cpp Library License: 3 | -------------------------- 4 | 5 | The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. 6 | 7 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | 15 | 3. This notice may not be removed or altered from any source distribution 16 | 17 | Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 18 | Gero Mueller, post@geromueller.de, 2015 19 | */ 20 | 21 | #ifndef ZIP_STREAM_COMMON_HPP 22 | #define ZIP_STREAM_COMMON_HPP 23 | 24 | #include 25 | 26 | namespace zstream { 27 | 28 | /// Compression strategy, see zlib doc. 29 | enum EStrategy { 30 | StrategyFiltered = 1, StrategyHuffmanOnly = 2, DefaultStrategy = 0 31 | }; 32 | 33 | namespace detail { 34 | /// default gzip buffer size, 35 | /// change this to suite your needs 36 | const size_t default_buffer_size = 4096; 37 | 38 | const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */ 39 | 40 | /* gzip flag byte */ 41 | const int gz_ascii_flag = 0x01; /* bit 0 set: file probably ascii text */ 42 | const int gz_head_crc = 0x02; /* bit 1 set: header CRC present */ 43 | const int gz_extra_field = 0x04; /* bit 2 set: extra field present */ 44 | const int gz_orig_name = 0x08; /* bit 3 set: original file name present */ 45 | const int gz_comment = 0x10; /* bit 4 set: file comment present */ 46 | const int gz_reserved = 0xE0; /* bits 5..7: reserved */ 47 | 48 | } // detail 49 | } // zstream 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /.github/workflows/cmake-multi-platform.yml: -------------------------------------------------------------------------------- 1 | # This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. 2 | # See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml 3 | name: CMake on multiple platforms 4 | 5 | on: 6 | push: 7 | branches: [ "master" ] 8 | pull_request: 9 | branches: [ "master" ] 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. 17 | fail-fast: false 18 | 19 | # Set up a matrix to run the following 3 configurations: 20 | # 1. 21 | # 2. 22 | # 3. 23 | # 24 | # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. 25 | matrix: 26 | os: [ubuntu-latest, windows-latest] 27 | build_type: [Release] 28 | c_compiler: [gcc, clang, cl] 29 | include: 30 | - os: windows-latest 31 | c_compiler: cl 32 | cpp_compiler: cl 33 | - os: ubuntu-latest 34 | c_compiler: gcc 35 | cpp_compiler: g++ 36 | - os: ubuntu-latest 37 | c_compiler: clang 38 | cpp_compiler: clang++ 39 | exclude: 40 | - os: windows-latest 41 | c_compiler: gcc 42 | - os: windows-latest 43 | c_compiler: clang 44 | - os: ubuntu-latest 45 | c_compiler: cl 46 | 47 | steps: 48 | - uses: actions/checkout@v4 49 | 50 | - name: Set reusable strings 51 | # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. 52 | id: strings 53 | shell: bash 54 | run: | 55 | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" 56 | 57 | - name: Configure CMake 58 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 59 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 60 | run: > 61 | cmake -B ${{ steps.strings.outputs.build-output-dir }} 62 | -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} 63 | -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} 64 | -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} 65 | -S ${{ github.workspace }}/test 66 | 67 | - name: Build 68 | # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). 69 | run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} 70 | 71 | - name: Test 72 | working-directory: ${{ steps.strings.outputs.build-output-dir }} 73 | # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). 74 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 75 | run: ctest --build-config ${{ matrix.build_type }} 76 | -------------------------------------------------------------------------------- /ozstream_impl.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | zstream-cpp Library License: 3 | -------------------------- 4 | 5 | The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. 6 | 7 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | 15 | 3. This notice may not be removed or altered from any source distribution 16 | 17 | Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 18 | Gero Mueller, post@geromueller.de, 2015 19 | */ 20 | 21 | #ifndef OUTPUT_ZIP_STREAM_IMPL_HPP 22 | #define OUTPUT_ZIP_STREAM_IMPL_HPP 23 | 24 | #include "ozstream.hpp" 25 | #include "zlib.h" 26 | #include 27 | #include 28 | 29 | #ifndef OS_CODE 30 | # define OS_CODE 0x03 /* assume Unix */ 31 | #endif 32 | 33 | namespace zstream { 34 | 35 | template 37 | basic_zip_streambuf::basic_zip_streambuf( 38 | ostream_reference ostream_, size_t level_, EStrategy strategy_, 39 | size_t window_size_, size_t memory_level_, size_t buffer_size_) : 40 | m_ostream(ostream_), m_output_buffer(buffer_size_, 0), m_buffer( 41 | buffer_size_, 0), m_crc(0) { 42 | m_zip_stream.zalloc = (alloc_func) 0; 43 | m_zip_stream.zfree = (free_func) 0; 44 | 45 | m_zip_stream.next_in = NULL; 46 | m_zip_stream.avail_in = 0; 47 | m_zip_stream.avail_out = 0; 48 | m_zip_stream.next_out = NULL; 49 | 50 | m_err = deflateInit2(&m_zip_stream, std::min(9, static_cast(level_)), 51 | Z_DEFLATED, 52 | -static_cast(window_size_), // <-- changed 53 | std::min(9, static_cast(memory_level_)), 54 | static_cast(strategy_)); 55 | 56 | m_zip_stream.avail_out = static_cast(m_output_buffer.size()); 57 | m_zip_stream.next_out = &(m_output_buffer[0]); 58 | 59 | char_type *p = &(m_buffer[0]); 60 | this->setp(p, p + buffer_size_); 61 | } 62 | 63 | template 65 | basic_zip_streambuf::~basic_zip_streambuf() { 66 | } 67 | 68 | template 70 | int basic_zip_streambuf::sync() { 71 | int c = overflow(EOF); 72 | if (c == EOF) 73 | return -1; 74 | else 75 | return 0; 76 | } 77 | 78 | template 80 | typename basic_zip_streambuf::int_type basic_zip_streambuf< 81 | Elem, Tr, ElemA, ByteT, ByteAT>::overflow( 82 | typename basic_zip_streambuf::int_type c) { 83 | // buffer full, zip it.. 84 | int w = static_cast(this->pptr() - this->pbase()); 85 | if (w > 0) { 86 | if (zip_to_stream(this->pbase(), w)) { 87 | this->setp(this->pbase(), this->epptr()); 88 | } else { 89 | return EOF; 90 | } 91 | } 92 | 93 | // write c if not EOF 94 | if (c != EOF) { 95 | *this->pptr() = c; 96 | this->pbump(1); 97 | return c; 98 | } else { 99 | return 0; 100 | } 101 | 102 | } 103 | 104 | template 106 | std::streamsize basic_zip_streambuf::zip_write( 107 | int flag) { 108 | std::streamsize total_written_byte_size = 0; 109 | 110 | m_err = ::deflate(&m_zip_stream, flag); 111 | 112 | if (m_err == Z_OK || m_err == Z_STREAM_END) { 113 | std::streamsize written_byte_size = 114 | static_cast(m_output_buffer.size()) 115 | - m_zip_stream.avail_out; 116 | if (written_byte_size > 0) { 117 | total_written_byte_size += written_byte_size; 118 | // ouput buffer is full, dumping to ostream 119 | m_ostream.write((const char_type*) &(m_output_buffer[0]), 120 | static_cast(written_byte_size 121 | / sizeof(char_type))); 122 | 123 | // checking if some bytes were not written. 124 | size_t remainder = written_byte_size % sizeof(char_type); 125 | if (remainder != 0) { 126 | // copy to the beginning of the stream 127 | memcpy(&(m_output_buffer[0]), 128 | &(m_output_buffer[written_byte_size - remainder]), 129 | remainder); 130 | 131 | } 132 | 133 | m_zip_stream.avail_out = static_cast(m_output_buffer.size() 134 | - remainder); 135 | m_zip_stream.next_out = &m_output_buffer[remainder]; 136 | } 137 | } 138 | 139 | return total_written_byte_size; 140 | } 141 | 142 | template 144 | bool basic_zip_streambuf::zip_to_stream( 145 | typename basic_zip_streambuf::char_type* buffer_, 146 | std::streamsize buffer_size_) { 147 | 148 | m_zip_stream.next_in = (byte_buffer_type) buffer_; 149 | m_zip_stream.avail_in = static_cast(buffer_size_ * sizeof(char_type)); 150 | 151 | // updating crc 152 | m_crc = ::crc32(m_crc, m_zip_stream.next_in, m_zip_stream.avail_in); 153 | 154 | do { 155 | zip_write(0); 156 | } while (m_zip_stream.avail_in != 0 && m_err == Z_OK); 157 | 158 | return m_err == Z_OK; 159 | } 160 | 161 | template 163 | std::streamsize basic_zip_streambuf::zfinish() { 164 | std::streamsize total_written_byte_size = 0; 165 | 166 | this->sync(); 167 | 168 | // updating crc 169 | m_crc = crc32(m_crc, m_zip_stream.next_in, m_zip_stream.avail_in); 170 | 171 | do { 172 | total_written_byte_size += zip_write(Z_FINISH); 173 | } while (m_err == Z_OK); 174 | 175 | m_ostream.flush(); 176 | 177 | m_err = deflateEnd(&m_zip_stream); 178 | 179 | return total_written_byte_size; 180 | } 181 | 182 | template 184 | void basic_gzip_ostream::put_long( 185 | typename basic_gzip_ostream::ostream_reference out_, 186 | unsigned int x_) { 187 | static const int size_ul = sizeof(unsigned int); 188 | static const int size_c = sizeof(char_type); 189 | static const int n_end = size_ul / size_c; 190 | out_.write(reinterpret_cast(&x_), n_end); 191 | } 192 | 193 | template 195 | void basic_gzip_ostream::add_header() { 196 | char_type zero = 0; 197 | 198 | this->rdbuf()->get_ostream().put( 199 | static_cast(detail::gz_magic[0])).put( 200 | static_cast(detail::gz_magic[1])).put( 201 | static_cast(Z_DEFLATED)).put(zero) //flags 202 | .put(zero).put(zero).put(zero).put(zero) // time 203 | .put(zero) //xflags 204 | .put(static_cast(OS_CODE)); 205 | } 206 | 207 | template 209 | void basic_gzip_ostream::add_footer() { 210 | put_long(this->rdbuf()->get_ostream(), htole32(this->rdbuf()->get_crc())); 211 | put_long(this->rdbuf()->get_ostream(), htole32(this->rdbuf()->get_in_size())); 212 | } 213 | 214 | } // zstream 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /izstream_impl.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | zstream-cpp Library License: 3 | -------------------------- 4 | 5 | The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. 6 | 7 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | 15 | 3. This notice may not be removed or altered from any source distribution 16 | 17 | Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 18 | Gero Mueller, post@geromueller.de, 2015 19 | */ 20 | 21 | #ifndef INPUT_ZIP_STREAM_IMPL_HPP 22 | #define INPUT_ZIP_STREAM_IMPL_HPP 23 | 24 | #include "izstream.hpp" 25 | #include 26 | #include 27 | 28 | namespace zstream { 29 | 30 | template 32 | basic_unzip_streambuf::basic_unzip_streambuf( 33 | istream_reference istream_, size_t window_size_, 34 | size_t read_buffer_size_, size_t input_buffer_size_) : 35 | m_istream(istream_), m_input_buffer(input_buffer_size_), m_buffer( 36 | read_buffer_size_), m_crc(0) { 37 | // setting zalloc, zfree and opaque 38 | m_zip_stream.zalloc = (alloc_func) 0; 39 | m_zip_stream.zfree = (free_func) 0; 40 | 41 | m_zip_stream.next_in = NULL; 42 | m_zip_stream.avail_in = 0; 43 | m_zip_stream.avail_out = 0; 44 | m_zip_stream.next_out = NULL; 45 | 46 | m_err = inflateInit2(&m_zip_stream, -static_cast(window_size_)); 47 | 48 | this->setg(&(m_buffer[0]) + 4, // beginning of putback area 49 | &(m_buffer[0]) + 4, // read position 50 | &(m_buffer[0]) + 4); // end position 51 | } 52 | 53 | template 55 | size_t basic_unzip_streambuf::fill_input_buffer() { 56 | m_zip_stream.next_in = &(m_input_buffer[0]); 57 | m_istream.read((char_type*) (&(m_input_buffer[0])), 58 | static_cast(m_input_buffer.size() 59 | / sizeof(char_type))); 60 | return m_zip_stream.avail_in = m_istream.gcount() * sizeof(char_type); 61 | } 62 | 63 | template 65 | basic_unzip_streambuf::~basic_unzip_streambuf() { 66 | inflateEnd(&m_zip_stream); 67 | } 68 | 69 | template 71 | typename basic_unzip_streambuf::int_type basic_unzip_streambuf< 72 | Elem, Tr, ElemA, ByteT, ByteAT>::underflow() { 73 | if (this->gptr() && (this->gptr() < this->egptr())) 74 | return *reinterpret_cast(this->gptr()); 75 | 76 | int n_putback = static_cast(this->gptr() - this->eback()); 77 | if (n_putback > 4) 78 | n_putback = 4; 79 | memcpy(&(m_buffer[0]) + (4 - n_putback), this->gptr() - n_putback, 80 | n_putback * sizeof(char_type)); 81 | 82 | int num = unzip_from_stream(&(m_buffer[0]) + 4, 83 | static_cast((m_buffer.size() - 4) 84 | * sizeof(char_type))); 85 | if (num <= 0) // ERROR or EOF 86 | return EOF; 87 | 88 | // reset buffer pointers 89 | this->setg(&(m_buffer[0]) + (4 - n_putback), // beginning of putback area 90 | &(m_buffer[0]) + 4, // read position 91 | &(m_buffer[0]) + 4 + num); // end of buffer 92 | 93 | // return next character 94 | return *reinterpret_cast(this->gptr()); 95 | } 96 | 97 | template 99 | std::streamsize basic_unzip_streambuf::unzip_from_stream( 100 | char_type* buffer_, std::streamsize buffer_size_) { 101 | m_zip_stream.next_out = (byte_buffer_type) buffer_; 102 | m_zip_stream.avail_out = 103 | static_cast(buffer_size_ * sizeof(char_type)); 104 | size_t count = m_zip_stream.avail_in; 105 | 106 | do { 107 | if (m_zip_stream.avail_in == 0) 108 | count = fill_input_buffer(); 109 | 110 | if (m_zip_stream.avail_in) { 111 | m_err = inflate(&m_zip_stream, Z_SYNC_FLUSH); 112 | } 113 | } while (m_err == Z_OK && m_zip_stream.avail_out != 0 && count != 0); 114 | 115 | // updating crc 116 | m_crc = crc32(m_crc, (byte_buffer_type) buffer_, 117 | buffer_size_ - m_zip_stream.avail_out / sizeof(char_type)); 118 | std::streamsize n_read = buffer_size_ 119 | - m_zip_stream.avail_out / sizeof(char_type); 120 | 121 | // check if it is the end 122 | if (m_err == Z_STREAM_END) 123 | put_back_from_zip_stream(); 124 | 125 | return n_read; 126 | } 127 | 128 | template 130 | void basic_unzip_streambuf::put_back_from_zip_stream() { 131 | if (m_zip_stream.avail_in == 0) 132 | return; 133 | 134 | m_istream.clear(std::ios::goodbit); 135 | m_istream.seekg(-static_cast(m_zip_stream.avail_in), 136 | std::ios_base::cur); 137 | 138 | m_zip_stream.avail_in = 0; 139 | } 140 | 141 | template 143 | int basic_gzip_istream::check_header() { 144 | int method; /* method byte */ 145 | int flags; /* flags byte */ 146 | uInt len; 147 | int c; 148 | int err = 0; 149 | z_stream& zip_stream = this->rdbuf()->get_zip_stream(); 150 | 151 | /* Check the gzip magic header */ 152 | for (len = 0; len < 2; len++) { 153 | c = (int) this->rdbuf()->get_istream().get(); 154 | if (c != detail::gz_magic[len]) { 155 | if (len != 0) 156 | this->rdbuf()->get_istream().unget(); 157 | if (c != EOF) { 158 | this->rdbuf()->get_istream().unget(); 159 | } 160 | 161 | err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END; 162 | return err; 163 | } 164 | } 165 | 166 | method = (int) this->rdbuf()->get_istream().get(); 167 | flags = (int) this->rdbuf()->get_istream().get(); 168 | if (method != Z_DEFLATED || (flags & detail::gz_reserved) != 0) { 169 | err = Z_DATA_ERROR; 170 | return err; 171 | } 172 | 173 | /* Discard time, xflags and OS code: */ 174 | for (len = 0; len < 6; len++) 175 | this->rdbuf()->get_istream().get(); 176 | 177 | if ((flags & detail::gz_extra_field) != 0) { 178 | /* skip the extra field */ 179 | len = (uInt) this->rdbuf()->get_istream().get(); 180 | len += ((uInt) this->rdbuf()->get_istream().get()) << 8; 181 | /* len is garbage if EOF but the loop below will quit anyway */ 182 | while (len-- != 0 && this->rdbuf()->get_istream().get() != EOF) 183 | ; 184 | } 185 | if ((flags & detail::gz_orig_name) != 0) { 186 | /* skip the original file name */ 187 | while ((c = this->rdbuf()->get_istream().get()) != 0 && c != EOF) 188 | ; 189 | } 190 | if ((flags & detail::gz_comment) != 0) { 191 | /* skip the .gz file comment */ 192 | while ((c = this->rdbuf()->get_istream().get()) != 0 && c != EOF) 193 | ; 194 | } 195 | if ((flags & detail::gz_head_crc) != 0) { /* skip the header crc */ 196 | for (len = 0; len < 2; len++) 197 | this->rdbuf()->get_istream().get(); 198 | } 199 | err = this->rdbuf()->get_istream().eof() ? Z_DATA_ERROR : Z_OK; 200 | 201 | return err; 202 | } 203 | 204 | template 206 | void basic_gzip_istream::read_footer() { 207 | read_long(this->rdbuf()->get_istream(), m_gzip_crc); 208 | read_long(this->rdbuf()->get_istream(), m_gzip_data_size); 209 | } 210 | 211 | template 213 | void basic_gzip_istream::read_long( 214 | istream_reference in_, unsigned int& x_) { 215 | static const int size_ul = sizeof(unsigned int); 216 | static const int size_c = sizeof(char_type); 217 | static const int n_end = size_ul / size_c; 218 | in_.read(reinterpret_cast(&x_), n_end); 219 | } 220 | 221 | } // zstream 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /izstream.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | zstream-cpp Library License: 3 | -------------------------- 4 | 5 | The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. 6 | 7 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | 15 | 3. This notice may not be removed or altered from any source distribution 16 | 17 | Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 18 | Gero Mueller, post@geromueller.de, 2015 19 | */ 20 | 21 | #ifndef INPUT_ZIP_STREAM_HPP 22 | #define INPUT_ZIP_STREAM_HPP 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "zstream_common.hpp" 31 | 32 | namespace zstream { 33 | 34 | /** \brief A stream decorator that takes compressed input and unzips it to a istream. 35 | 36 | The class wraps up the deflate method of the zlib library 1.1.4 http://www.gzip.org/zlib/ 37 | */ 38 | template, 39 | typename ElemA = std::allocator, typename ByteT = unsigned char, 40 | typename ByteAT = std::allocator > 41 | class basic_unzip_streambuf: public std::basic_streambuf { 42 | public: 43 | typedef std::basic_istream& istream_reference; 44 | typedef ElemA char_allocator_type; 45 | typedef ByteT byte_type; 46 | typedef ByteAT byte_allocator_type; 47 | typedef byte_type* byte_buffer_type; 48 | typedef typename std::basic_streambuf::char_type char_type; 49 | typedef typename std::basic_streambuf::int_type int_type; 50 | typedef std::vector byte_vector_type; 51 | typedef std::vector char_vector_type; 52 | 53 | /** Construct a unzip stream 54 | * More info on the following parameters can be found in the zlib documentation. 55 | */ 56 | basic_unzip_streambuf(istream_reference istream_, size_t window_size_, 57 | size_t read_buffer_size_, size_t input_buffer_size_); 58 | 59 | ~basic_unzip_streambuf(); 60 | 61 | int_type underflow(); 62 | 63 | /// returns the compressed input istream 64 | istream_reference get_istream() { 65 | return m_istream; 66 | } 67 | 68 | /// returns the zlib stream structure 69 | z_stream& get_zip_stream() { 70 | return m_zip_stream; 71 | } 72 | 73 | /// returns the latest zlib error state 74 | int get_zerr() const { 75 | return m_err; 76 | } 77 | 78 | /// returns the crc of the uncompressed data so far 79 | unsigned int get_crc() const { 80 | return m_crc; 81 | } 82 | 83 | /// returns the number of uncompressed bytes 84 | unsigned int get_out_size() const { 85 | return m_zip_stream.total_out; 86 | } 87 | 88 | /// returns the number of read compressed bytes 89 | unsigned long get_in_size() const { 90 | return m_zip_stream.total_in; 91 | } 92 | 93 | private: 94 | void put_back_from_zip_stream(); 95 | std::streamsize unzip_from_stream(char_type*, std::streamsize); 96 | 97 | size_t fill_input_buffer(); 98 | 99 | istream_reference m_istream; 100 | z_stream m_zip_stream; 101 | int m_err; 102 | byte_vector_type m_input_buffer; 103 | char_vector_type m_buffer; 104 | long m_crc; 105 | }; 106 | 107 | /*! \brief Base class for unzip istreams 108 | 109 | Contains a basic_unzip_streambuf. 110 | */ 111 | template, 112 | typename ElemA = std::allocator, typename ByteT = unsigned char, 113 | typename ByteAT = std::allocator > 114 | class basic_zip_istreambase: virtual public std::basic_ios { 115 | public: 116 | typedef std::basic_istream& istream_reference; 117 | typedef basic_unzip_streambuf unzip_streambuf_type; 118 | 119 | basic_zip_istreambase(istream_reference ostream_, size_t window_size_, 120 | size_t read_buffer_size_, size_t input_buffer_size_) : 121 | m_buf(ostream_, window_size_, read_buffer_size_, input_buffer_size_) { 122 | this->init(&m_buf); 123 | } 124 | 125 | /// returns the underlying unzip istream object 126 | unzip_streambuf_type* rdbuf() { 127 | return &m_buf; 128 | } 129 | 130 | /// returns the zlib error state 131 | int get_zerr() const { 132 | return m_buf.get_zerr(); 133 | } 134 | 135 | /// returns the uncompressed data crc 136 | long get_crc() const { 137 | return m_buf.get_crc(); 138 | } 139 | 140 | /// returns the uncompressed data size 141 | long get_out_size() const { 142 | return m_buf.get_out_size(); 143 | } 144 | 145 | /// returns the compressed data size 146 | unsigned long get_in_size() const { 147 | return m_buf.get_in_size(); 148 | } 149 | 150 | private: 151 | unzip_streambuf_type m_buf; 152 | }; 153 | 154 | /*! \brief A zipper istream 155 | 156 | This class is a istream decorator that behaves 'almost' like any other ostream. 157 | 158 | At construction, it takes any istream that shall be used to input of the compressed data. 159 | 160 | Simlpe example: 161 | \code 162 | // create a stream on zip string 163 | istringstream istringstream_( ostringstream_.str()); 164 | // create unzipper istream 165 | zip_istream unzipper( istringstream_); 166 | 167 | // read and unzip 168 | unzipper>>f_r>>d_r>>ui_r>>ul_r>>us_r>>c_r>>dum_r; 169 | \endcode 170 | */ 171 | template, 172 | typename ElemA = std::allocator, typename ByteT = unsigned char, 173 | typename ByteAT = std::allocator > 174 | class basic_gzip_istream: public basic_zip_istreambase, public std::basic_istream { 176 | public: 177 | typedef typename std::basic_istream::char_type char_type; 178 | typedef std::basic_istream& istream_reference; 179 | typedef basic_zip_istreambase zip_istreambase_type; 180 | typedef std::basic_istream istream_type; 181 | typedef unsigned char byte_type; 182 | 183 | /** Construct a unzipper stream 184 | * 185 | * \param istream_ input buffer 186 | * \param window_size_ 187 | * \param read_buffer_size_ 188 | * \param input_buffer_size_ 189 | */ 190 | basic_gzip_istream(istream_reference istream_, size_t window_size_ = 15, 191 | size_t read_buffer_size_ = detail::default_buffer_size, 192 | size_t input_buffer_size_ = detail::default_buffer_size) : 193 | zip_istreambase_type(istream_, window_size_, read_buffer_size_, 194 | input_buffer_size_), istream_type(this->rdbuf()), m_gzip_crc( 195 | 0), m_gzip_data_size(0) { 196 | if (this->rdbuf()->get_zerr() == Z_OK) 197 | check_header(); 198 | } 199 | 200 | /// reads the gzip header 201 | void read_footer(); 202 | /** return crc check result 203 | 204 | When you have finished reading the compressed data, call read_footer to read the uncompressed data crc. 205 | This method compares it to the crc of the uncompressed data. 206 | 207 | \return true if crc check is succesful 208 | */ 209 | bool check_crc() const { 210 | return this->get_crc() == m_gzip_crc; 211 | } 212 | 213 | /// return data size check 214 | bool check_data_size() const { 215 | return this->get_out_size() == m_gzip_data_size; 216 | } 217 | 218 | /// return the crc value in the file 219 | unsigned int get_gzip_crc() const { 220 | return m_gzip_crc; 221 | } 222 | 223 | /// return the data size in the file 224 | unsigned int get_gzip_data_size() const { 225 | return m_gzip_data_size; 226 | } 227 | 228 | protected: 229 | static void read_long(istream_reference in_, unsigned int& x_); 230 | int check_header(); 231 | unsigned int m_gzip_crc; 232 | unsigned int m_gzip_data_size; 233 | }; 234 | 235 | template, 236 | typename ElemA = std::allocator, typename ByteT = unsigned char, 237 | typename ByteAT = std::allocator > 238 | class basic_zip_istream: public basic_zip_istreambase, public std::basic_istream { 240 | public: 241 | typedef typename std::basic_istream::char_type char_type; 242 | typedef std::basic_istream& istream_reference; 243 | typedef basic_zip_istreambase zip_istreambase_type; 244 | typedef std::basic_istream istream_type; 245 | typedef unsigned char byte_type; 246 | 247 | /** Construct a unzipper stream 248 | * 249 | * \param istream_ input buffer 250 | * \param window_size_ 251 | * \param read_buffer_size_ 252 | * \param input_buffer_size_ 253 | */ 254 | basic_zip_istream(istream_reference istream_, size_t window_size_ = 15, 255 | size_t read_buffer_size_ = detail::default_buffer_size, 256 | size_t input_buffer_size_ = detail::default_buffer_size) : 257 | zip_istreambase_type(istream_, window_size_, read_buffer_size_, 258 | input_buffer_size_), istream_type(this->rdbuf()) { 259 | } 260 | }; 261 | 262 | /// A typedef for basic_zip_istream 263 | typedef basic_gzip_istream igzstream; 264 | /// A typedef for basic_zip_istream 265 | typedef basic_gzip_istream wigzstream; 266 | 267 | /// A typedef for basic_zip_istream 268 | typedef basic_zip_istream izstream; 269 | /// A typedef for basic_zip_istream 270 | typedef basic_zip_istream wizstream; 271 | 272 | } // zstream 273 | 274 | #include "izstream_impl.hpp" 275 | 276 | #endif 277 | 278 | -------------------------------------------------------------------------------- /ozstream.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | zstream-cpp Library License: 3 | -------------------------- 4 | 5 | The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. 6 | 7 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 14 | 15 | 3. This notice may not be removed or altered from any source distribution 16 | 17 | Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 18 | Gero Mueller, post@geromueller.de, 2015 19 | */ 20 | 21 | #ifndef OUTPUT_ZIP_STREAM_HPP 22 | #define OUTPUT_ZIP_STREAM_HPP 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "zstream_common.hpp" 31 | 32 | namespace zstream { 33 | 34 | /** \brief A stream decorator that takes raw input and zips it to a ostream. 35 | 36 | The class wraps up the inflate method of the zlib library 37 | */ 38 | template, 39 | typename ElemA = std::allocator, typename ByteT = unsigned char, 40 | typename ByteAT = std::allocator > 41 | class basic_zip_streambuf: public std::basic_streambuf { 42 | public: 43 | typedef std::basic_ostream& ostream_reference; 44 | typedef ElemA char_allocator_type; 45 | typedef ByteT byte_type; 46 | typedef ByteAT byte_allocator_type; 47 | typedef byte_type* byte_buffer_type; 48 | typedef typename std::basic_streambuf::char_type char_type; 49 | typedef typename std::basic_streambuf::int_type int_type; 50 | typedef std::vector byte_vector_type; 51 | typedef std::vector char_vector_type; 52 | 53 | /** Construct a zip stream 54 | * More info on the following parameters can be found in the zlib documentation. 55 | */ 56 | basic_zip_streambuf(ostream_reference ostream_, size_t level_, 57 | EStrategy strategy_, size_t window_size_, size_t memory_level_, 58 | size_t buffer_size_); 59 | 60 | ~basic_zip_streambuf(); 61 | 62 | int sync(); 63 | int_type overflow(int_type c); 64 | 65 | /** flushes the zip buffer and output buffer. 66 | 67 | This method should be called at the end of the compression. Calling flush multiple times, will lower the 68 | compression ratio. 69 | */ 70 | std::streamsize zfinish(); 71 | 72 | /// returns a reference to the output stream 73 | ostream_reference get_ostream() const { 74 | return m_ostream; 75 | } 76 | 77 | /// returns the latest zlib error status 78 | int get_zerr() const { 79 | return m_err; 80 | } 81 | 82 | /// returns the crc of the input data compressed so far. 83 | long get_crc() const { 84 | return m_crc; 85 | } 86 | 87 | /// returns the size (bytes) of the input data compressed so far. 88 | long get_in_size() const { 89 | return m_zip_stream.total_in; 90 | } 91 | 92 | /// returns the size (bytes) of the compressed data so far. 93 | long get_out_size() const { 94 | return m_zip_stream.total_out; 95 | } 96 | 97 | private: 98 | bool zip_to_stream(char_type*, std::streamsize); 99 | std::streamsize zip_write(int flag); 100 | 101 | ostream_reference m_ostream; 102 | z_stream m_zip_stream; 103 | int m_err; 104 | byte_vector_type m_output_buffer; 105 | char_vector_type m_buffer; 106 | long m_crc; 107 | }; 108 | 109 | /*! \brief Base class for zip ostreams 110 | 111 | Contains a basic_zip_streambuf. 112 | */ 113 | template, 114 | typename ElemA = std::allocator, typename ByteT = unsigned char, 115 | typename ByteAT = std::allocator > 116 | class basic_zip_ostreambase: virtual public std::basic_ios { 117 | public: 118 | typedef std::basic_ostream& ostream_reference; 119 | typedef basic_zip_streambuf zip_streambuf_type; 120 | 121 | /** Construct a zip stream 122 | * More info on the following parameters can be found in the zlib documentation. 123 | */ 124 | basic_zip_ostreambase(ostream_reference ostream_, size_t level_, 125 | EStrategy strategy_, size_t window_size_, size_t memory_level_, 126 | size_t buffer_size_) : 127 | m_buf(ostream_, level_, strategy_, window_size_, memory_level_, 128 | buffer_size_) { 129 | this->init(&m_buf); 130 | } 131 | 132 | /// returns the underlying zip ostream object 133 | zip_streambuf_type* rdbuf() { 134 | return &m_buf; 135 | } 136 | 137 | /// returns the zlib error state 138 | int get_zerr() const { 139 | return m_buf.get_zerr(); 140 | } 141 | 142 | /// returns the uncompressed data crc 143 | long get_crc() const { 144 | return m_buf.get_crc(); 145 | } 146 | 147 | /// returns the compressed data size 148 | long get_out_size() const { 149 | return m_buf.get_out_size(); 150 | } 151 | 152 | /// returns the uncompressed data size 153 | long get_in_size() const { 154 | return m_buf.get_in_size(); 155 | } 156 | 157 | private: 158 | zip_streambuf_type m_buf; 159 | }; 160 | 161 | /*! \brief A zipper ostream 162 | 163 | This class is a ostream decorator that behaves 'almost' like any other ostream. 164 | 165 | At construction, it takes any ostream that shall be used to output of the compressed data. 166 | 167 | When finished, you need to call the special method close or call the destructor 168 | to flush all the intermidiate streams. 169 | 170 | Example: 171 | \code 172 | // creating the target zip string, could be a fstream 173 | ostringstream ostringstream_; 174 | // creating the zip layer 175 | zip_ostream zipper(ostringstream_); 176 | 177 | 178 | // writing data 179 | zipper<, 185 | typename ElemA = std::allocator, typename ByteT = unsigned char, 186 | typename ByteAT = std::allocator > 187 | class basic_gzip_ostream: public basic_zip_ostreambase, public std::basic_ostream { 189 | public: 190 | typedef typename std::basic_ostream::char_type char_type; 191 | typedef std::basic_ostream& ostream_reference; 192 | typedef basic_zip_ostreambase zip_ostreambase_type; 193 | typedef std::basic_ostream ostream_type; 194 | 195 | /** Constructs a zipper ostream decorator 196 | * 197 | * \param ostream_ ostream where the compressed output is written 198 | * \param is_gzip_ true if gzip header and footer have to be added 199 | * \param level_ level of compression 0, bad and fast, 9, good and slower, 200 | * \param strategy_ compression strategy 201 | * \param window_size_ see zlib doc 202 | * \param memory_level_ see zlib doc 203 | * \param buffer_size_ the buffer size used to zip data 204 | 205 | When is_gzip_ is true, a gzip header and footer is automatically added. 206 | */ 207 | basic_gzip_ostream(ostream_reference ostream_, 208 | size_t level_ = Z_DEFAULT_COMPRESSION, EStrategy strategy_ = 209 | DefaultStrategy, size_t window_size_ = 15, 210 | size_t memory_level_ = 8, size_t buffer_size_ = detail::default_buffer_size) : 211 | zip_ostreambase_type(ostream_, level_, strategy_, window_size_, 212 | memory_level_, buffer_size_), ostream_type(this->rdbuf()), 213 | m_closed(false) { 214 | add_header(); 215 | } 216 | 217 | ~basic_gzip_ostream() { 218 | close(); 219 | } 220 | 221 | void close() { 222 | if (m_closed) 223 | return; 224 | this->flush(); 225 | this->rdbuf()->zfinish(); 226 | add_footer(); 227 | m_closed = true; 228 | } 229 | 230 | private: 231 | static void put_long(ostream_reference out_, unsigned int x_); 232 | void add_header(); 233 | void add_footer(); 234 | bool m_closed; 235 | }; 236 | 237 | template, 238 | typename ElemA = std::allocator, typename ByteT = unsigned char, 239 | typename ByteAT = std::allocator > 240 | class basic_zip_ostream: public basic_zip_ostreambase, public std::basic_ostream { 242 | public: 243 | typedef typename std::basic_ostream::char_type char_type; 244 | typedef std::basic_ostream& ostream_reference; 245 | typedef basic_zip_ostreambase zip_ostreambase_type; 246 | typedef std::basic_ostream ostream_type; 247 | 248 | /** Constructs a zipper ostream decorator 249 | * 250 | * \param ostream_ ostream where the compressed output is written 251 | * \param is_gzip_ true if gzip header and footer have to be added 252 | * \param level_ level of compression 0, bad and fast, 9, good and slower, 253 | * \param strategy_ compression strategy 254 | * \param window_size_ see zlib doc 255 | * \param memory_level_ see zlib doc 256 | * \param buffer_size_ the buffer size used to zip data 257 | 258 | When is_gzip_ is true, a gzip header and footer is automatically added. 259 | */ 260 | basic_zip_ostream(ostream_reference ostream_, 261 | size_t level_ = Z_DEFAULT_COMPRESSION, EStrategy strategy_ = 262 | DefaultStrategy, size_t window_size_ = 15, 263 | size_t memory_level_ = 8, size_t buffer_size_ = detail::default_buffer_size) : 264 | zip_ostreambase_type(ostream_, level_, strategy_, window_size_, 265 | memory_level_, buffer_size_), ostream_type(this->rdbuf()), 266 | m_closed(false) { 267 | } 268 | 269 | ~basic_zip_ostream() { 270 | close(); 271 | } 272 | 273 | void close() { 274 | if (m_closed) 275 | return; 276 | this->flush(); 277 | this->rdbuf()->zfinish(); 278 | m_closed = true; 279 | } 280 | 281 | private: 282 | bool m_closed; 283 | }; 284 | 285 | /// A typedef for basic_zip_ostream 286 | typedef basic_gzip_ostream ogzstream; 287 | /// A typedef for basic_zip_ostream 288 | typedef basic_gzip_ostream wgzostream; 289 | /// A typedef for basic_zip_ostream 290 | typedef basic_zip_ostream ozstream; 291 | /// A typedef for basic_zip_ostream 292 | typedef basic_zip_ostream wzostream; 293 | 294 | } // zstream 295 | 296 | #include "ozstream_impl.hpp" 297 | 298 | #endif 299 | 300 | --------------------------------------------------------------------------------