├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── appveyor.yml ├── include └── lz4_stream.h ├── lz4_compress.cpp ├── lz4_decompress.cpp ├── test ├── CMakeLists.txt ├── lz4_stream_test.cpp └── main.cpp └── thirdparty ├── catch2 └── CMakeLists.txt └── lz4 └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: xenial 3 | 4 | sudo: false 5 | 6 | matrix: 7 | include: 8 | - compiler: gcc 9 | env: BUILD_TYPE=Coverage 10 | - compiler: gcc 11 | env: BUILD_TYPE=Debug 12 | - compiler: gcc 13 | env: BUILD_TYPE=Release 14 | - compiler: clang 15 | env: BUILD_TYPE=Debug 16 | 17 | addons: 18 | apt: 19 | update: true 20 | packages: 21 | - liblz4-dev 22 | homebrew: 23 | update: true 24 | packages: 25 | - lz4 26 | 27 | os: 28 | - linux 29 | - osx 30 | 31 | before_script: 32 | - mkdir build 33 | - cd build 34 | - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} .. 35 | - make 36 | 37 | script: 38 | - ctest -V 39 | 40 | after_success: 41 | - if [ "${BUILD_TYPE}" == "Coverage" ]; then bash <(curl -s https://codecov.io/bash); fi 42 | 43 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | project(lz4_stream LANGUAGES CXX) 4 | 5 | include(ExternalProject) 6 | 7 | option(LZ4_STREAM_UseBundledLz4 "Use bundled static LZ4 library" OFF) 8 | option(LZ4_STREAM_BuildTests "Build unittests" ON) 9 | 10 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 11 | 12 | set(LZ4_STREAM_LIBRARY_NAME ${PROJECT_NAME}) 13 | set(LZ4_STREAM_LIBRARY_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include/") 14 | 15 | # TODO: Probably shouldn't be set like this 16 | set(CMAKE_CXX_STANDARD 11) 17 | if(MSVC) 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX /EHsc") 19 | else() 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") 21 | endif() 22 | 23 | # TODO: Probably shouldn't be set like this 24 | set(CMAKE_CXX_FLAGS_COVERAGE 25 | "${GCC_DEBUG_FLAGS} -fprofile-arcs -ftest-coverage" 26 | CACHE STRING "Flags used by the C++ compiler during coverage builds." 27 | FORCE) 28 | set(CMAKE_EXE_LINKER_FLAGS_COVERAGE 29 | "${CMAKE_EXE_LINKER_FLAGS} --coverage" 30 | CACHE STRING "Flags used for linking binaries during coverage builds." 31 | FORCE) 32 | mark_as_advanced( 33 | CMAKE_CXX_FLAGS_COVERAGE 34 | CMAKE_EXE_LINKER_FLAGS_COVERAGE) 35 | 36 | # Create lz4_stream library 37 | add_library(${LZ4_STREAM_LIBRARY_NAME} INTERFACE) 38 | target_include_directories(${LZ4_STREAM_LIBRARY_NAME} INTERFACE ${LZ4_STREAM_LIBRARY_INCLUDE_DIR}) 39 | 40 | if(LZ4_STREAM_UseBundledLz4) 41 | message(STATUS "Using bundled LZ4 library") 42 | add_subdirectory("thirdparty/lz4") 43 | target_link_libraries(${LZ4_STREAM_LIBRARY_NAME} INTERFACE lz4) 44 | target_include_directories(${LZ4_STREAM_LIBRARY_NAME} INTERFACE lz4) 45 | else() 46 | find_package(PkgConfig REQUIRED) 47 | pkg_check_modules(LZ4 REQUIRED liblz4) 48 | target_include_directories(${LZ4_STREAM_LIBRARY_NAME} INTERFACE ${LZ4_INCLUDE_DIR}) 49 | target_link_libraries(${LZ4_STREAM_LIBRARY_NAME} INTERFACE ${LZ4_LIBRARIES}) 50 | endif() 51 | 52 | if(LZ4_STREAM_BuildTests) 53 | enable_testing() 54 | add_subdirectory("thirdparty/catch2") 55 | add_subdirectory("test") 56 | endif() 57 | 58 | # Create example executables 59 | # TODO: Move to own directory 60 | add_executable(lz4_compress lz4_compress.cpp) 61 | target_link_libraries(lz4_compress ${LZ4_STREAM_LIBRARY_NAME}) 62 | 63 | add_executable(lz4_decompress lz4_decompress.cpp) 64 | target_link_libraries(lz4_decompress ${LZ4_STREAM_LIBRARY_NAME}) 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Kasper Laudrup 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lz4_stream - A C++ stream using LZ4 (de)compression 2 | =================================================== 3 | 4 | lz4_stream is a simple wrapper that uses C++ streams for compressing and decompressing data using the [LZ4 compression library] 5 | 6 | Usage 7 | ----- 8 | 9 | Look at lz4\_compress.cpp and lz4\_decompress.cpp for example command line programs that can compress and decompress using this stream library. 10 | 11 | Building 12 | -------- 13 | 14 | ``` 15 | mkdir build 16 | cd build 17 | cmake .. 18 | make 19 | ``` 20 | 21 | Requirements 22 | ------------ 23 | 24 | The [LZ4 compression library] is required to use this library. 25 | 26 | Build status 27 | ------------ 28 | 29 | Ubuntu and OSX (GCC/Clang): 30 | 31 | [![Build Status](https://travis-ci.org/laudrup/lz4_stream.png)](https://travis-ci.org/laudrup/lz4_stream) 32 | 33 | Windows (MS C++): 34 | 35 | [![Build status](https://ci.appveyor.com/api/projects/status/xrp8bjf9217broom?svg=true)](https://ci.appveyor.com/project/laudrup/lz4-stream) 36 | 37 | Code coverage (codecov.io): 38 | 39 | [![codecov](https://codecov.io/gh/laudrup/lz4_stream/branch/master/graph/badge.svg)](https://codecov.io/gh/laudrup/lz4_stream) 40 | 41 | License 42 | ------- 43 | 44 | Standard BSD 3-Clause License as used by the LZ4 library. 45 | 46 | [LZ4 compression library]: https://github.com/lz4/lz4 47 | [cmake]: http://cmake.org 48 | [Google Test Framework]: https://github.com/google/googletest 49 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | environment: 4 | matrix: 5 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 6 | platform: x86 7 | GENERATOR: Visual Studio 14 2015 8 | CONFIG: Release 9 | 10 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 11 | platform: x86 12 | GENERATOR: Visual Studio 14 2015 13 | CONFIG: Debug 14 | 15 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 16 | platform: x86 17 | GENERATOR: Visual Studio 15 2017 18 | CONFIG: Release 19 | 20 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 21 | platform: x86 22 | GENERATOR: Visual Studio 15 2017 23 | CONFIG: Debug 24 | 25 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 26 | platform: x64 27 | GENERATOR: Visual Studio 14 2015 Win64 28 | CONFIG: Release 29 | 30 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 31 | platform: x64 32 | GENERATOR: Visual Studio 14 2015 Win64 33 | CONFIG: Debug 34 | 35 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 36 | platform: x64 37 | GENERATOR: Visual Studio 15 2017 Win64 38 | CONFIG: Release 39 | 40 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 41 | platform: x64 42 | GENERATOR: Visual Studio 15 2017 Win64 43 | CONFIG: Debug 44 | 45 | before_build: 46 | - cmake . -G "%GENERATOR%" -DLZ4_STREAM_UseBundledLz4=ON 47 | 48 | build_script: 49 | - cmake --build . --config "%CONFIG%" 50 | 51 | test_script: 52 | - ctest -C "%CONFIG%" -V -j 53 | -------------------------------------------------------------------------------- /include/lz4_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef LZ4_STREAM 2 | #define LZ4_STREAM 3 | 4 | // LZ4 Headers 5 | #include 6 | 7 | // Standard headers 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace lz4_stream { 17 | /** 18 | * @brief An output stream that will LZ4 compress the input data. 19 | * 20 | * An output stream that will wrap another output stream and LZ4 21 | * compress its input data to that stream. 22 | * 23 | */ 24 | template 25 | class basic_ostream : public std::ostream 26 | { 27 | public: 28 | /** 29 | * @brief Constructs an LZ4 compression output stream 30 | * 31 | * @param sink The stream to write compressed data to 32 | */ 33 | basic_ostream(std::ostream& sink) 34 | : std::ostream(new output_buffer(sink)), 35 | buffer_(dynamic_cast(rdbuf())) { 36 | assert(buffer_); 37 | } 38 | 39 | /** 40 | * @brief Destroys the LZ4 output stream. Calls close() if not already called. 41 | */ 42 | ~basic_ostream() { 43 | close(); 44 | delete buffer_; 45 | } 46 | 47 | /** 48 | * @brief Flushes and writes LZ4 footer data to the LZ4 output stream. 49 | * 50 | * After calling this function no more data should be written to the stream. 51 | */ 52 | void close() { 53 | buffer_->close(); 54 | } 55 | 56 | private: 57 | class output_buffer : public std::streambuf { 58 | public: 59 | output_buffer(const output_buffer &) = delete; 60 | output_buffer& operator= (const output_buffer &) = delete; 61 | 62 | output_buffer(std::ostream &sink) 63 | : sink_(sink), 64 | // TODO: No need to recalculate the dest_buf_ size on each construction 65 | dest_buf_(LZ4F_compressBound(src_buf_.size(), nullptr)), 66 | ctx_(nullptr), 67 | closed_(false) { 68 | char* base = &src_buf_.front(); 69 | setp(base, base + src_buf_.size() - 1); 70 | 71 | size_t ret = LZ4F_createCompressionContext(&ctx_, LZ4F_VERSION); 72 | if (LZ4F_isError(ret) != 0) { 73 | throw std::runtime_error(std::string("Failed to create LZ4 compression context: ") 74 | + LZ4F_getErrorName(ret)); 75 | } 76 | write_header(); 77 | } 78 | 79 | ~output_buffer() { 80 | close(); 81 | } 82 | 83 | void close() { 84 | if (closed_) { 85 | return; 86 | } 87 | sync(); 88 | write_footer(); 89 | LZ4F_freeCompressionContext(ctx_); 90 | closed_ = true; 91 | } 92 | 93 | private: 94 | int_type overflow(int_type ch) override { 95 | assert(std::less_equal()(pptr(), epptr())); 96 | 97 | *pptr() = static_cast(ch); 98 | pbump(1); 99 | compress_and_write(); 100 | 101 | return ch; 102 | } 103 | 104 | int_type sync() override { 105 | compress_and_write(); 106 | return 0; 107 | } 108 | 109 | void compress_and_write() { 110 | // TODO: Throw exception instead or set badbit 111 | assert(!closed_); 112 | int orig_size = static_cast(pptr() - pbase()); 113 | pbump(-orig_size); 114 | size_t ret = LZ4F_compressUpdate(ctx_, &dest_buf_.front(), dest_buf_.capacity(), 115 | pbase(), orig_size, nullptr); 116 | if (LZ4F_isError(ret) != 0) { 117 | throw std::runtime_error(std::string("LZ4 compression failed: ") 118 | + LZ4F_getErrorName(ret)); 119 | } 120 | sink_.write(&dest_buf_.front(), ret); 121 | } 122 | 123 | void write_header() { 124 | // TODO: Throw exception instead or set badbit 125 | assert(!closed_); 126 | size_t ret = LZ4F_compressBegin(ctx_, &dest_buf_.front(), dest_buf_.capacity(), nullptr); 127 | if (LZ4F_isError(ret) != 0) { 128 | throw std::runtime_error(std::string("Failed to start LZ4 compression: ") 129 | + LZ4F_getErrorName(ret)); 130 | } 131 | sink_.write(&dest_buf_.front(), ret); 132 | } 133 | 134 | void write_footer() { 135 | assert(!closed_); 136 | size_t ret = LZ4F_compressEnd(ctx_, &dest_buf_.front(), dest_buf_.capacity(), nullptr); 137 | if (LZ4F_isError(ret) != 0) { 138 | throw std::runtime_error(std::string("Failed to end LZ4 compression: ") 139 | + LZ4F_getErrorName(ret)); 140 | } 141 | sink_.write(&dest_buf_.front(), ret); 142 | } 143 | 144 | std::ostream& sink_; 145 | std::array src_buf_; 146 | std::vector dest_buf_; 147 | LZ4F_compressionContext_t ctx_; 148 | bool closed_; 149 | }; 150 | 151 | output_buffer* buffer_; 152 | }; 153 | 154 | /** 155 | * @brief An input stream that will LZ4 decompress output data. 156 | * 157 | * An input stream that will wrap another input stream and LZ4 158 | * decompress its output data to that stream. 159 | * 160 | */ 161 | template 162 | class basic_istream : public std::istream 163 | { 164 | public: 165 | /** 166 | * @brief Constructs an LZ4 decompression input stream 167 | * 168 | * @param source The stream to read LZ4 compressed data from 169 | */ 170 | basic_istream(std::istream& source) 171 | : std::istream(new input_buffer(source)), 172 | buffer_(dynamic_cast(rdbuf())) { 173 | assert(buffer_); 174 | } 175 | 176 | /** 177 | * @brief Destroys the LZ4 output stream. 178 | */ 179 | ~basic_istream() { 180 | delete buffer_; 181 | } 182 | 183 | private: 184 | class input_buffer : public std::streambuf { 185 | public: 186 | input_buffer(std::istream &source) 187 | : source_(source), 188 | offset_(0), 189 | src_buf_size_(0), 190 | ctx_(nullptr) { 191 | size_t ret = LZ4F_createDecompressionContext(&ctx_, LZ4F_VERSION); 192 | if (LZ4F_isError(ret) != 0) { 193 | throw std::runtime_error(std::string("Failed to create LZ4 decompression context: ") 194 | + LZ4F_getErrorName(ret)); 195 | } 196 | setg(&src_buf_.front(), &src_buf_.front(), &src_buf_.front()); 197 | } 198 | 199 | ~input_buffer() { 200 | LZ4F_freeDecompressionContext(ctx_); 201 | } 202 | 203 | int_type underflow() override { 204 | size_t written_size = 0; 205 | while (written_size == 0) { 206 | if (offset_ == src_buf_size_) { 207 | source_.read(&src_buf_.front(), src_buf_.size()); 208 | src_buf_size_ = static_cast(source_.gcount()); 209 | offset_ = 0; 210 | } 211 | 212 | if (src_buf_size_ == 0) { 213 | return traits_type::eof(); 214 | } 215 | 216 | size_t src_size = src_buf_size_ - offset_; 217 | size_t dest_size = dest_buf_.size(); 218 | size_t ret = LZ4F_decompress(ctx_, &dest_buf_.front(), &dest_size, 219 | &src_buf_.front() + offset_, &src_size, nullptr); 220 | if (LZ4F_isError(ret) != 0) { 221 | throw std::runtime_error(std::string("LZ4 decompression failed: ") 222 | + LZ4F_getErrorName(ret)); 223 | } 224 | written_size = dest_size; 225 | offset_ += src_size; 226 | } 227 | setg(&dest_buf_.front(), &dest_buf_.front(), &dest_buf_.front() + written_size); 228 | return traits_type::to_int_type(*gptr()); 229 | } 230 | 231 | input_buffer(const input_buffer&) = delete; 232 | input_buffer& operator= (const input_buffer&) = delete; 233 | private: 234 | std::istream& source_; 235 | std::array src_buf_; 236 | std::array dest_buf_; 237 | size_t offset_; 238 | size_t src_buf_size_; 239 | LZ4F_decompressionContext_t ctx_; 240 | }; 241 | 242 | input_buffer* buffer_; 243 | }; 244 | 245 | using ostream = basic_ostream<>; 246 | using istream = basic_istream<>; 247 | 248 | } 249 | #endif // LZ4_STREAM 250 | -------------------------------------------------------------------------------- /lz4_compress.cpp: -------------------------------------------------------------------------------- 1 | // Own headers 2 | #include "lz4_stream.h" 3 | 4 | // Standard headers 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | if (argc != 3) 12 | { 13 | std::cerr << "Usage: " << argv[0] << " inputfile outputfile" << std::endl; 14 | return 1; 15 | } 16 | std::ifstream in_file(argv[1]); 17 | std::ofstream out_file(argv[2]); 18 | 19 | lz4_stream::ostream lz4_stream(out_file); 20 | 21 | std::copy(std::istreambuf_iterator(in_file), 22 | std::istreambuf_iterator(), 23 | std::ostreambuf_iterator(lz4_stream)); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /lz4_decompress.cpp: -------------------------------------------------------------------------------- 1 | // Own headers 2 | #include "lz4_stream.h" 3 | 4 | // Standard headers 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | if (argc != 3) 12 | { 13 | std::cerr << "Usage: " << argv[0] << " inputfile outputfile" << std::endl; 14 | return 1; 15 | } 16 | std::ifstream in_file(argv[1]); 17 | std::ofstream out_file(argv[2]); 18 | 19 | lz4_stream::istream lz4_stream(in_file); 20 | 21 | std::copy(std::istreambuf_iterator(lz4_stream), 22 | std::istreambuf_iterator(), 23 | std::ostreambuf_iterator(out_file)); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(lz4_stream_test main.cpp lz4_stream_test.cpp) 2 | target_link_libraries(lz4_stream_test ${LZ4_STREAM_LIBRARY_NAME} catch2) 3 | add_test(lz4_stream_test lz4_stream_test) 4 | -------------------------------------------------------------------------------- /test/lz4_stream_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "catch.hpp" 5 | 6 | #include "lz4_stream.h" 7 | 8 | TEST_CASE("Lz4Stream") { 9 | std::stringstream compressed_stream; 10 | 11 | lz4_stream::ostream lz4_out_stream(compressed_stream); 12 | lz4_stream::istream lz4_in_stream(compressed_stream); 13 | 14 | std::string test_string = 15 | "Three Rings for the Elven-kings under the sky,\n" 16 | "Seven for the Dwarf-lords in their halls of stone,\n" 17 | "Nine for Mortal Men doomed to die,\n" 18 | "One for the Dark Lord on his dark throne\n" 19 | "In the Land of Mordor where the Shadows lie.\n" 20 | "One Ring to rule them all, One Ring to find them,\n" 21 | "One Ring to bring them all, and in the darkness bind them,\n" 22 | "In the Land of Mordor where the Shadows lie.\n"; 23 | 24 | SECTION("Default compression/decompression") { 25 | lz4_out_stream << test_string; 26 | lz4_out_stream.close(); 27 | 28 | CHECK(std::string(std::istreambuf_iterator(lz4_in_stream), {}) == test_string); 29 | } 30 | 31 | SECTION("Empty data") { 32 | lz4_out_stream.close(); 33 | 34 | CHECK(std::string(std::istreambuf_iterator(lz4_in_stream), {}).empty()); 35 | } 36 | 37 | SECTION("All zeroes") { 38 | lz4_out_stream << std::string(1024, '\0'); 39 | lz4_out_stream.close(); 40 | 41 | CHECK(std::string(std::istreambuf_iterator(lz4_in_stream), {}) == std::string(1024, '\0')); 42 | } 43 | 44 | SECTION("Small output buffer") { 45 | std::stringstream compressed_stream; 46 | lz4_stream::basic_ostream<8> lz4_out_stream(compressed_stream); 47 | lz4_stream::istream lz4_in_stream(compressed_stream); 48 | lz4_out_stream << test_string; 49 | lz4_out_stream.close(); 50 | 51 | CHECK(std::string(std::istreambuf_iterator(lz4_in_stream), {}) == test_string); 52 | } 53 | 54 | SECTION("Small input buffer") { 55 | lz4_stream::basic_istream<8, 8> lz4_in_stream(compressed_stream); 56 | lz4_out_stream << test_string; 57 | lz4_out_stream.close(); 58 | 59 | CHECK(std::string(std::istreambuf_iterator(lz4_in_stream), {}) == test_string); 60 | } 61 | 62 | SECTION("Small input and ouput buffer") { 63 | std::stringstream compressed_stream; 64 | lz4_stream::basic_istream<8, 8> lz4_in_stream(compressed_stream); 65 | lz4_stream::basic_ostream<8> lz4_out_stream(compressed_stream); 66 | lz4_out_stream << test_string; 67 | lz4_out_stream.close(); 68 | 69 | CHECK(std::string(std::istreambuf_iterator(lz4_in_stream), {}) == test_string); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "catch.hpp" 3 | -------------------------------------------------------------------------------- /thirdparty/catch2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ExternalProject_Add( 2 | Catch2 3 | GIT_REPOSITORY https://github.com/catchorg/Catch2 4 | GIT_TAG v2.6.0 5 | CONFIGURE_COMMAND "" 6 | BUILD_COMMAND "" 7 | INSTALL_COMMAND "" 8 | ) 9 | 10 | ExternalProject_Get_property(Catch2 SOURCE_DIR) 11 | 12 | add_library(catch2 INTERFACE) 13 | target_include_directories(catch2 INTERFACE ${SOURCE_DIR}/single_include/catch2) 14 | add_dependencies(catch2 Catch2) 15 | -------------------------------------------------------------------------------- /thirdparty/lz4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(MSVC) 2 | set(BUILD_COMMAND ${CMAKE_VS_MSBUILD_COMMAND} /property:PlatformToolset=${CMAKE_VS_PLATFORM_TOOLSET} /p:Configuration=$ /p:Platform=${CMAKE_VS_PLATFORM_NAME} "visual/VS2010/lz4.sln") 3 | else() 4 | set(BUILD_COMMAND make) 5 | endif() 6 | 7 | ExternalProject_Add( 8 | LibLz4 9 | GIT_REPOSITORY https://github.com/lz4/lz4.git 10 | GIT_TAG v1.8.3 11 | BUILD_COMMAND ${BUILD_COMMAND} 12 | BUILD_IN_SOURCE 1 13 | INSTALL_COMMAND "" 14 | CONFIGURE_COMMAND "" 15 | ) 16 | 17 | ExternalProject_Get_property(LibLz4 SOURCE_DIR) 18 | ExternalProject_Get_property(LibLz4 BINARY_DIR) 19 | 20 | add_library(lz4 INTERFACE) 21 | 22 | if(MSVC) 23 | target_link_libraries(lz4 INTERFACE ${BINARY_DIR}/visual/VS2010/bin/${CMAKE_VS_PLATFORM_NAME}_$/liblz4_static.lib) 24 | else() 25 | target_link_libraries(lz4 INTERFACE ${BINARY_DIR}/lib/liblz4.a) 26 | endif() 27 | 28 | target_include_directories(lz4 INTERFACE ${SOURCE_DIR}/lib) 29 | 30 | add_dependencies(lz4 LibLz4) 31 | --------------------------------------------------------------------------------