zbuffer.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // MessagePack for C++ deflate buffer implementation
  3. //
  4. // Copyright (C) 2010-2016 FURUHASHI Sadayuki and KONDO Takatoshi
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef MSGPACK_V1_ZBUFFER_HPP
  11. #define MSGPACK_V1_ZBUFFER_HPP
  12. #include "msgpack/v1/zbuffer_decl.hpp"
  13. #include "msgpack/assert.hpp"
  14. #include <stdexcept>
  15. #include <zlib.h>
  16. namespace msgpack {
  17. /// @cond
  18. MSGPACK_API_VERSION_NAMESPACE(v1) {
  19. /// @endcond
  20. class zbuffer {
  21. public:
  22. zbuffer(int level = Z_DEFAULT_COMPRESSION,
  23. size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE)
  24. : m_data(MSGPACK_NULLPTR), m_init_size(init_size)
  25. {
  26. m_stream.zalloc = Z_NULL;
  27. m_stream.zfree = Z_NULL;
  28. m_stream.opaque = Z_NULL;
  29. m_stream.next_out = Z_NULL;
  30. m_stream.avail_out = 0;
  31. if(deflateInit(&m_stream, level) != Z_OK) {
  32. throw std::bad_alloc();
  33. }
  34. }
  35. ~zbuffer()
  36. {
  37. deflateEnd(&m_stream);
  38. ::free(m_data);
  39. }
  40. public:
  41. void write(const char* buf, size_t len)
  42. {
  43. MSGPACK_ASSERT(buf || len == 0);
  44. if (!buf) return;
  45. m_stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(buf));
  46. m_stream.avail_in = static_cast<uInt>(len);
  47. while(m_stream.avail_in > 0) {
  48. if(m_stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
  49. if(!expand()) {
  50. throw std::bad_alloc();
  51. }
  52. }
  53. if(deflate(&m_stream, Z_NO_FLUSH) != Z_OK) {
  54. throw std::bad_alloc();
  55. }
  56. }
  57. }
  58. char* flush()
  59. {
  60. while(true) {
  61. switch(deflate(&m_stream, Z_FINISH)) {
  62. case Z_STREAM_END:
  63. return m_data;
  64. case Z_OK:
  65. case Z_BUF_ERROR:
  66. if(!expand()) {
  67. throw std::bad_alloc();
  68. }
  69. break;
  70. default:
  71. throw std::bad_alloc();
  72. }
  73. }
  74. }
  75. char* data()
  76. {
  77. return m_data;
  78. }
  79. const char* data() const
  80. {
  81. return m_data;
  82. }
  83. size_t size() const
  84. {
  85. return static_cast<size_t>(reinterpret_cast<char*>(m_stream.next_out) - m_data);
  86. }
  87. void reset()
  88. {
  89. if(deflateReset(&m_stream) != Z_OK) {
  90. throw std::bad_alloc();
  91. }
  92. reset_buffer();
  93. }
  94. void reset_buffer()
  95. {
  96. m_stream.avail_out += static_cast<uInt>(reinterpret_cast<char*>(m_stream.next_out) - m_data);
  97. m_stream.next_out = reinterpret_cast<Bytef*>(m_data);
  98. }
  99. char* release_buffer()
  100. {
  101. char* tmp = m_data;
  102. m_data = MSGPACK_NULLPTR;
  103. m_stream.next_out = MSGPACK_NULLPTR;
  104. m_stream.avail_out = 0;
  105. return tmp;
  106. }
  107. private:
  108. bool expand()
  109. {
  110. size_t used = static_cast<size_t>(reinterpret_cast<char*>(m_stream.next_out) - m_data);
  111. size_t csize = used + m_stream.avail_out;
  112. size_t nsize = (csize == 0) ? m_init_size : csize * 2;
  113. char* tmp = static_cast<char*>(::realloc(m_data, nsize));
  114. if(tmp == MSGPACK_NULLPTR) {
  115. return false;
  116. }
  117. m_data = tmp;
  118. m_stream.next_out = reinterpret_cast<Bytef*>(tmp + used);
  119. m_stream.avail_out = static_cast<uInt>(nsize - used);
  120. return true;
  121. }
  122. #if defined(MSGPACK_USE_CPP03)
  123. private:
  124. zbuffer(const zbuffer&);
  125. zbuffer& operator=(const zbuffer&);
  126. #else // defined(MSGPACK_USE_CPP03)
  127. zbuffer(const zbuffer&) = delete;
  128. zbuffer& operator=(const zbuffer&) = delete;
  129. #endif // defined(MSGPACK_USE_CPP03)
  130. private:
  131. z_stream m_stream;
  132. char* m_data;
  133. size_t m_init_size;
  134. };
  135. /// @cond
  136. } // MSGPACK_API_VERSION_NAMESPACE(v1)
  137. /// @endcond
  138. } // namespace msgpack
  139. #endif // MSGPACK_V1_ZBUFFER_HPP