xdelta3-second.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /* xdelta3 - delta compression tools and library
  2. Copyright 2016 Joshua MacDonald
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. #ifndef _XDELTA3_SECOND_H_
  14. #define _XDELTA3_SECOND_H_
  15. static inline void xd3_bit_state_encode_init (bit_state *bits)
  16. {
  17. bits->cur_byte = 0;
  18. bits->cur_mask = 1;
  19. }
  20. static inline int xd3_decode_bits (xd3_stream *stream,
  21. bit_state *bits,
  22. const uint8_t **input,
  23. const uint8_t *input_max,
  24. usize_t nbits,
  25. usize_t *valuep)
  26. {
  27. usize_t value = 0;
  28. usize_t vmask = 1 << nbits;
  29. if (bits->cur_mask == 0x100) { goto next_byte; }
  30. for (;;)
  31. {
  32. do
  33. {
  34. vmask >>= 1;
  35. if (bits->cur_byte & bits->cur_mask)
  36. {
  37. value |= vmask;
  38. }
  39. bits->cur_mask <<= 1;
  40. if (vmask == 1) { goto done; }
  41. }
  42. while (bits->cur_mask != 0x100);
  43. next_byte:
  44. if (*input == input_max)
  45. {
  46. stream->msg = "secondary decoder end of input";
  47. return XD3_INTERNAL;
  48. }
  49. bits->cur_byte = *(*input)++;
  50. bits->cur_mask = 1;
  51. }
  52. done:
  53. IF_DEBUG2 (DP(RINT "(d) %"W"u ", value));
  54. (*valuep) = value;
  55. return 0;
  56. }
  57. #if REGRESSION_TEST
  58. /* There may be extra bits at the end of secondary decompression, this macro
  59. * checks for non-zero bits. This is overly strict, but helps pass the
  60. * single-bit-error regression test. */
  61. static int
  62. xd3_test_clean_bits (xd3_stream *stream, bit_state *bits)
  63. {
  64. for (; bits->cur_mask != 0x100; bits->cur_mask <<= 1)
  65. {
  66. if (bits->cur_byte & bits->cur_mask)
  67. {
  68. stream->msg = "secondary decoder garbage";
  69. return XD3_INTERNAL;
  70. }
  71. }
  72. return 0;
  73. }
  74. #endif
  75. static int
  76. xd3_get_secondary (xd3_stream *stream, xd3_sec_stream **sec_streamp,
  77. int is_encode)
  78. {
  79. if (*sec_streamp == NULL)
  80. {
  81. int ret;
  82. if ((*sec_streamp = stream->sec_type->alloc (stream)) == NULL)
  83. {
  84. stream->msg = "error initializing secondary stream";
  85. return XD3_INVALID;
  86. }
  87. if ((ret = stream->sec_type->init (stream, *sec_streamp, is_encode)) != 0)
  88. {
  89. return ret;
  90. }
  91. }
  92. return 0;
  93. }
  94. static int
  95. xd3_decode_secondary (xd3_stream *stream,
  96. xd3_desect *sect,
  97. xd3_sec_stream **sec_streamp)
  98. {
  99. usize_t dec_size;
  100. uint8_t *out_used;
  101. int ret;
  102. if ((ret = xd3_get_secondary (stream, sec_streamp, 0)) != 0)
  103. {
  104. return ret;
  105. }
  106. /* Decode the size, allocate the buffer. */
  107. if ((ret = xd3_read_size (stream, & sect->buf,
  108. sect->buf_max, & dec_size)) ||
  109. (ret = xd3_decode_allocate (stream, dec_size,
  110. & sect->copied2, & sect->alloc2)))
  111. {
  112. return ret;
  113. }
  114. if (dec_size == 0)
  115. {
  116. stream->msg = "secondary decoder invalid output size";
  117. return XD3_INVALID_INPUT;
  118. }
  119. out_used = sect->copied2;
  120. if ((ret = stream->sec_type->decode (stream, *sec_streamp,
  121. & sect->buf, sect->buf_max,
  122. & out_used, out_used + dec_size)))
  123. {
  124. return ret;
  125. }
  126. if (sect->buf != sect->buf_max)
  127. {
  128. stream->msg = "secondary decoder finished with unused input";
  129. return XD3_INTERNAL;
  130. }
  131. if (out_used != sect->copied2 + dec_size)
  132. {
  133. stream->msg = "secondary decoder short output";
  134. return XD3_INTERNAL;
  135. }
  136. sect->buf = sect->copied2;
  137. sect->buf_max = sect->copied2 + dec_size;
  138. sect->size = dec_size;
  139. return 0;
  140. }
  141. #if XD3_ENCODER
  142. static inline int xd3_encode_bit (xd3_stream *stream,
  143. xd3_output **output,
  144. bit_state *bits,
  145. usize_t bit)
  146. {
  147. int ret;
  148. if (bit)
  149. {
  150. bits->cur_byte |= bits->cur_mask;
  151. }
  152. /* OPT: Might help to buffer more than 8 bits at once. */
  153. if (bits->cur_mask == 0x80)
  154. {
  155. if ((ret = xd3_emit_byte (stream, output, bits->cur_byte)) != 0)
  156. {
  157. return ret;
  158. }
  159. bits->cur_mask = 1;
  160. bits->cur_byte = 0;
  161. }
  162. else
  163. {
  164. bits->cur_mask <<= 1;
  165. }
  166. return 0;
  167. }
  168. static inline int xd3_flush_bits (xd3_stream *stream,
  169. xd3_output **output,
  170. bit_state *bits)
  171. {
  172. return (bits->cur_mask == 1) ? 0 :
  173. xd3_emit_byte (stream, output, bits->cur_byte);
  174. }
  175. static inline int xd3_encode_bits (xd3_stream *stream,
  176. xd3_output **output,
  177. bit_state *bits,
  178. usize_t nbits,
  179. usize_t value)
  180. {
  181. int ret;
  182. usize_t mask = 1 << nbits;
  183. XD3_ASSERT (nbits > 0);
  184. XD3_ASSERT (nbits < sizeof (usize_t) * 8);
  185. XD3_ASSERT (value < mask);
  186. do
  187. {
  188. mask >>= 1;
  189. if ((ret = xd3_encode_bit (stream, output, bits, value & mask)))
  190. {
  191. return ret;
  192. }
  193. }
  194. while (mask != 1);
  195. IF_DEBUG2 (DP(RINT "(e) %"W"u ", value));
  196. return 0;
  197. }
  198. static int
  199. xd3_encode_secondary (xd3_stream *stream,
  200. xd3_output **head,
  201. xd3_output **tail,
  202. xd3_sec_stream **sec_streamp,
  203. xd3_sec_cfg *cfg,
  204. int *did_it)
  205. {
  206. xd3_output *tmp_head;
  207. xd3_output *tmp_tail;
  208. usize_t comp_size;
  209. usize_t orig_size;
  210. int ret;
  211. orig_size = xd3_sizeof_output (*head);
  212. if (orig_size < SECONDARY_MIN_INPUT) { return 0; }
  213. if ((ret = xd3_get_secondary (stream, sec_streamp, 1)) != 0)
  214. {
  215. return ret;
  216. }
  217. tmp_head = xd3_alloc_output (stream, NULL);
  218. /* Encode the size, encode the data. Encoding the size makes it
  219. * simpler, but is a little gross. Should not need the entire
  220. * section in contiguous memory, but it is much easier this way. */
  221. if ((ret = xd3_emit_size (stream, & tmp_head, orig_size)) ||
  222. (ret = stream->sec_type->encode (stream, *sec_streamp, *head,
  223. tmp_head, cfg)))
  224. {
  225. goto getout;
  226. }
  227. /* If the secondary compressor determines it's no good, it returns
  228. * XD3_NOSECOND. */
  229. /* Setup tmp_tail, comp_size */
  230. tmp_tail = tmp_head;
  231. comp_size = tmp_head->next;
  232. while (tmp_tail->next_page != NULL)
  233. {
  234. tmp_tail = tmp_tail->next_page;
  235. comp_size += tmp_tail->next;
  236. }
  237. XD3_ASSERT (comp_size == xd3_sizeof_output (tmp_head));
  238. XD3_ASSERT (tmp_tail != NULL);
  239. if (comp_size < (orig_size - SECONDARY_MIN_SAVINGS) || cfg->inefficient)
  240. {
  241. if (comp_size < orig_size)
  242. {
  243. IF_DEBUG1(DP(RINT "[encode_secondary] saved %"W"u bytes: %"W"u -> %"W"u (%0.2f%%)\n",
  244. orig_size - comp_size, orig_size, comp_size,
  245. 100.0 * (double) comp_size / (double) orig_size));
  246. }
  247. xd3_free_output (stream, *head);
  248. *head = tmp_head;
  249. *tail = tmp_tail;
  250. *did_it = 1;
  251. }
  252. else
  253. {
  254. getout:
  255. if (ret == XD3_NOSECOND) { ret = 0; }
  256. xd3_free_output (stream, tmp_head);
  257. }
  258. return ret;
  259. }
  260. #endif /* XD3_ENCODER */
  261. #endif /* _XDELTA3_SECOND_H_ */