zbuffer.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. * MessagePack for C deflate buffer implementation
  3. *
  4. * Copyright (C) 2010 FURUHASHI Sadayuki
  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_ZBUFFER_H
  11. #define MSGPACK_ZBUFFER_H
  12. #include "sysdep.h"
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <zlib.h>
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif
  19. /**
  20. * @defgroup msgpack_zbuffer Compressed buffer
  21. * @ingroup msgpack_buffer
  22. * @{
  23. */
  24. typedef struct msgpack_zbuffer {
  25. z_stream stream;
  26. char* data;
  27. size_t init_size;
  28. } msgpack_zbuffer;
  29. #ifndef MSGPACK_ZBUFFER_INIT_SIZE
  30. #define MSGPACK_ZBUFFER_INIT_SIZE 8192
  31. #endif
  32. static inline bool msgpack_zbuffer_init(
  33. msgpack_zbuffer* zbuf, int level, size_t init_size);
  34. static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
  35. static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size);
  36. static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf);
  37. static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
  38. static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
  39. static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
  40. static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
  41. static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
  42. static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
  43. #ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
  44. #define MSGPACK_ZBUFFER_RESERVE_SIZE 512
  45. #endif
  46. static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len);
  47. static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
  48. static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
  49. int level, size_t init_size)
  50. {
  51. memset(zbuf, 0, sizeof(msgpack_zbuffer));
  52. zbuf->init_size = init_size;
  53. if(deflateInit(&zbuf->stream, level) != Z_OK) {
  54. free(zbuf->data);
  55. return false;
  56. }
  57. return true;
  58. }
  59. static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
  60. {
  61. deflateEnd(&zbuf->stream);
  62. free(zbuf->data);
  63. }
  64. static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
  65. {
  66. msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
  67. if (zbuf == NULL) return NULL;
  68. if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
  69. free(zbuf);
  70. return NULL;
  71. }
  72. return zbuf;
  73. }
  74. static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
  75. {
  76. if(zbuf == NULL) { return; }
  77. msgpack_zbuffer_destroy(zbuf);
  78. free(zbuf);
  79. }
  80. static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
  81. {
  82. size_t used = (char*)zbuf->stream.next_out - zbuf->data;
  83. size_t csize = used + zbuf->stream.avail_out;
  84. size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
  85. char* tmp = (char*)realloc(zbuf->data, nsize);
  86. if(tmp == NULL) {
  87. return false;
  88. }
  89. zbuf->data = tmp;
  90. zbuf->stream.next_out = (Bytef*)(tmp + used);
  91. zbuf->stream.avail_out = nsize - used;
  92. return true;
  93. }
  94. static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
  95. {
  96. msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
  97. zbuf->stream.next_in = (Bytef*)buf;
  98. zbuf->stream.avail_in = len;
  99. while(zbuf->stream.avail_in > 0) {
  100. if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
  101. if(!msgpack_zbuffer_expand(zbuf)) {
  102. return -1;
  103. }
  104. }
  105. if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
  106. return -1;
  107. }
  108. }
  109. return 0;
  110. }
  111. static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
  112. {
  113. while(true) {
  114. switch(deflate(&zbuf->stream, Z_FINISH)) {
  115. case Z_STREAM_END:
  116. return zbuf->data;
  117. case Z_OK:
  118. if(!msgpack_zbuffer_expand(zbuf)) {
  119. return NULL;
  120. }
  121. break;
  122. default:
  123. return NULL;
  124. }
  125. }
  126. }
  127. static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
  128. {
  129. return zbuf->data;
  130. }
  131. static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
  132. {
  133. return (char*)zbuf->stream.next_out - zbuf->data;
  134. }
  135. static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
  136. {
  137. zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data;
  138. zbuf->stream.next_out = (Bytef*)zbuf->data;
  139. }
  140. static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
  141. {
  142. if(deflateReset(&zbuf->stream) != Z_OK) {
  143. return false;
  144. }
  145. msgpack_zbuffer_reset_buffer(zbuf);
  146. return true;
  147. }
  148. static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
  149. {
  150. char* tmp = zbuf->data;
  151. zbuf->data = NULL;
  152. zbuf->stream.next_out = NULL;
  153. zbuf->stream.avail_out = 0;
  154. return tmp;
  155. }
  156. /** @} */
  157. #ifdef __cplusplus
  158. }
  159. #endif
  160. #endif /* msgpack/zbuffer.h */