zbuffer.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 <stdexcept>
  14. #include <zlib.h>
  15. namespace msgpack {
  16. /// @cond
  17. MSGPACK_API_VERSION_NAMESPACE(v1) {
  18. /// @endcond
  19. class zbuffer {
  20. public:
  21. zbuffer(int level = Z_DEFAULT_COMPRESSION,
  22. size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE)
  23. : m_data(MSGPACK_NULLPTR), m_init_size(init_size)
  24. {
  25. m_stream.zalloc = Z_NULL;
  26. m_stream.zfree = Z_NULL;
  27. m_stream.opaque = Z_NULL;
  28. m_stream.next_out = Z_NULL;
  29. m_stream.avail_out = 0;
  30. if(deflateInit(&m_stream, level) != Z_OK) {
  31. throw std::bad_alloc();
  32. }
  33. }
  34. ~zbuffer()
  35. {
  36. deflateEnd(&m_stream);
  37. ::free(m_data);
  38. }
  39. public:
  40. void write(const char* buf, size_t len)
  41. {
  42. m_stream.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(buf));
  43. m_stream.avail_in = len;
  44. while(m_stream.avail_in > 0) {
  45. if(m_stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
  46. if(!expand()) {
  47. throw std::bad_alloc();
  48. }
  49. }
  50. if(deflate(&m_stream, Z_NO_FLUSH) != Z_OK) {
  51. throw std::bad_alloc();
  52. }
  53. }
  54. }
  55. char* flush()
  56. {
  57. while(true) {
  58. switch(deflate(&m_stream, Z_FINISH)) {
  59. case Z_STREAM_END:
  60. return m_data;
  61. case Z_OK:
  62. if(!expand()) {
  63. throw std::bad_alloc();
  64. }
  65. break;
  66. default:
  67. throw std::bad_alloc();
  68. }
  69. }
  70. }
  71. char* data()
  72. {
  73. return m_data;
  74. }
  75. const char* data() const
  76. {
  77. return m_data;
  78. }
  79. size_t size() const
  80. {
  81. return reinterpret_cast<char*>(m_stream.next_out) - m_data;
  82. }
  83. void reset()
  84. {
  85. if(deflateReset(&m_stream) != Z_OK) {
  86. throw std::bad_alloc();
  87. }
  88. reset_buffer();
  89. }
  90. void reset_buffer()
  91. {
  92. m_stream.avail_out += reinterpret_cast<char*>(m_stream.next_out) - m_data;
  93. m_stream.next_out = reinterpret_cast<Bytef*>(m_data);
  94. }
  95. char* release_buffer()
  96. {
  97. char* tmp = m_data;
  98. m_data = MSGPACK_NULLPTR;
  99. m_stream.next_out = MSGPACK_NULLPTR;
  100. m_stream.avail_out = 0;
  101. return tmp;
  102. }
  103. private:
  104. bool expand()
  105. {
  106. size_t used = reinterpret_cast<char*>(m_stream.next_out) - m_data;
  107. size_t csize = used + m_stream.avail_out;
  108. size_t nsize = (csize == 0) ? m_init_size : csize * 2;
  109. char* tmp = static_cast<char*>(::realloc(m_data, nsize));
  110. if(tmp == MSGPACK_NULLPTR) {
  111. return false;
  112. }
  113. m_data = tmp;
  114. m_stream.next_out = reinterpret_cast<Bytef*>(tmp + used);
  115. m_stream.avail_out = nsize - used;
  116. return true;
  117. }
  118. #if defined(MSGPACK_USE_CPP03)
  119. private:
  120. zbuffer(const zbuffer&);
  121. zbuffer& operator=(const zbuffer&);
  122. #else // defined(MSGPACK_USE_CPP03)
  123. zbuffer(const zbuffer&) = delete;
  124. zbuffer& operator=(const zbuffer&) = delete;
  125. #endif // defined(MSGPACK_USE_CPP03)
  126. private:
  127. z_stream m_stream;
  128. char* m_data;
  129. size_t m_init_size;
  130. };
  131. /// @cond
  132. } // MSGPACK_API_VERSION_NAMESPACE(v1)
  133. /// @endcond
  134. } // namespace msgpack
  135. #endif // MSGPACK_V1_ZBUFFER_HPP