diff options
Diffstat (limited to 'third_party/msgpack/include/msgpack/v1/zbuffer.hpp')
-rw-r--r-- | third_party/msgpack/include/msgpack/v1/zbuffer.hpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/third_party/msgpack/include/msgpack/v1/zbuffer.hpp b/third_party/msgpack/include/msgpack/v1/zbuffer.hpp new file mode 100644 index 0000000000..e34b48ed71 --- /dev/null +++ b/third_party/msgpack/include/msgpack/v1/zbuffer.hpp @@ -0,0 +1,159 @@ +// +// MessagePack for C++ deflate buffer implementation +// +// Copyright (C) 2010-2016 FURUHASHI Sadayuki and KONDO Takatoshi +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef MSGPACK_V1_ZBUFFER_HPP +#define MSGPACK_V1_ZBUFFER_HPP + +#include "msgpack/v1/zbuffer_decl.hpp" + +#include <stdexcept> +#include <zlib.h> + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +class zbuffer { +public: + zbuffer(int level = Z_DEFAULT_COMPRESSION, + size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE) + : m_data(MSGPACK_NULLPTR), m_init_size(init_size) + { + m_stream.zalloc = Z_NULL; + m_stream.zfree = Z_NULL; + m_stream.opaque = Z_NULL; + m_stream.next_out = Z_NULL; + m_stream.avail_out = 0; + if(deflateInit(&m_stream, level) != Z_OK) { + throw std::bad_alloc(); + } + } + + ~zbuffer() + { + deflateEnd(&m_stream); + ::free(m_data); + } + +public: + void write(const char* buf, size_t len) + { + m_stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(buf)); + m_stream.avail_in = len; + + while(m_stream.avail_in > 0) { + if(m_stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) { + if(!expand()) { + throw std::bad_alloc(); + } + } + + if(deflate(&m_stream, Z_NO_FLUSH) != Z_OK) { + throw std::bad_alloc(); + } + } + } + + char* flush() + { + while(true) { + switch(deflate(&m_stream, Z_FINISH)) { + case Z_STREAM_END: + return m_data; + case Z_OK: + if(!expand()) { + throw std::bad_alloc(); + } + break; + default: + throw std::bad_alloc(); + } + } + } + + char* data() + { + return m_data; + } + + const char* data() const + { + return m_data; + } + + size_t size() const + { + return reinterpret_cast<char*>(m_stream.next_out) - m_data; + } + + void reset() + { + if(deflateReset(&m_stream) != Z_OK) { + throw std::bad_alloc(); + } + reset_buffer(); + } + + void reset_buffer() + { + m_stream.avail_out += reinterpret_cast<char*>(m_stream.next_out) - m_data; + m_stream.next_out = reinterpret_cast<Bytef*>(m_data); + } + + char* release_buffer() + { + char* tmp = m_data; + m_data = MSGPACK_NULLPTR; + m_stream.next_out = MSGPACK_NULLPTR; + m_stream.avail_out = 0; + return tmp; + } + +private: + bool expand() + { + size_t used = reinterpret_cast<char*>(m_stream.next_out) - m_data; + size_t csize = used + m_stream.avail_out; + size_t nsize = (csize == 0) ? m_init_size : csize * 2; + + char* tmp = static_cast<char*>(::realloc(m_data, nsize)); + if(tmp == MSGPACK_NULLPTR) { + return false; + } + + m_data = tmp; + m_stream.next_out = reinterpret_cast<Bytef*>(tmp + used); + m_stream.avail_out = nsize - used; + + return true; + } +#if defined(MSGPACK_USE_CPP03) +private: + zbuffer(const zbuffer&); + zbuffer& operator=(const zbuffer&); +#else // defined(MSGPACK_USE_CPP03) + zbuffer(const zbuffer&) = delete; + zbuffer& operator=(const zbuffer&) = delete; +#endif // defined(MSGPACK_USE_CPP03) + +private: + z_stream m_stream; + char* m_data; + size_t m_init_size; +}; + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif // MSGPACK_V1_ZBUFFER_HPP |