Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
7.6 KiB

  1. /*
  2. * decverb.c
  3. *
  4. * Decoding verbatim-bit blocks
  5. */
  6. #include "decoder.h"
  7. static long special_decode_verbatim_block(
  8. t_decoder_context *context,
  9. long BufPos,
  10. int amount_to_decode
  11. )
  12. {
  13. ulong match_pos;
  14. long bufpos_end;
  15. int match_length;
  16. int c;
  17. ulong dec_bitbuf;
  18. byte *dec_input_curpos;
  19. byte *dec_end_input_pos;
  20. byte *dec_mem_window;
  21. char dec_bitcount;
  22. char m;
  23. /*
  24. * Store commonly used variables locally
  25. */
  26. dec_bitcount = context->dec_bitcount;
  27. dec_bitbuf = context->dec_bitbuf;
  28. dec_input_curpos = context->dec_input_curpos;
  29. dec_end_input_pos = context->dec_end_input_pos;
  30. dec_mem_window = context->dec_mem_window;
  31. bufpos_end = BufPos + amount_to_decode;
  32. /*
  33. * We may overflow by up to MAX_MATCH
  34. */
  35. while (BufPos < bufpos_end)
  36. {
  37. /* decode an item from the main tree */
  38. DECODE_MAIN_TREE(c);
  39. if ((c -= NUM_CHARS) < 0)
  40. {
  41. /* it's a character */
  42. /* note: c - 256 == c if c is a byte */
  43. context->dec_mem_window[BufPos] = (byte) c;
  44. /* we know BufPos < bufpos_end here, so no need to check for overflow */
  45. context->dec_mem_window[context->dec_window_size+BufPos] = (byte) c;
  46. BufPos++;
  47. }
  48. else
  49. {
  50. /* get match length header */
  51. if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
  52. {
  53. /* get match length footer if necessary */
  54. DECODE_LEN_TREE_NOEOFCHECK(match_length);
  55. }
  56. /* get match position slot */
  57. m = c >> NL_SHIFT;
  58. /* read any extra bits for the match position */
  59. if (m > 2)
  60. {
  61. if (m > 3) /* dec_extra_bits[m] != 0 */
  62. {
  63. GET_BITS17_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
  64. match_pos += MP_POS_minus2[m];
  65. }
  66. else
  67. {
  68. match_pos = 1; // MP_POS_minus2[3];
  69. }
  70. /*
  71. * Add match base to "extra bits". Our match base
  72. * table has 2 subtracted from all the elements.
  73. *
  74. * This is because encoded positions 0,1,2 denote
  75. * repeated offsets. Encoded position 3 denotes
  76. * a match 1 character away, 4 encodes 2 away, etc.
  77. * Hence the subtraction of 2, which has been
  78. * incorporated into the table.
  79. */
  80. /* update LRU repeated offset list */
  81. context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
  82. context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
  83. context->dec_last_matchpos_offset[0] = match_pos;
  84. }
  85. else
  86. {
  87. /* positions 0, 1, 2 denote repeated offsets */
  88. match_pos = context->dec_last_matchpos_offset[m];
  89. if (m)
  90. {
  91. context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
  92. context->dec_last_matchpos_offset[0] = match_pos;
  93. }
  94. }
  95. /* match lengths range from 2...257 */
  96. match_length += MIN_MATCH;
  97. /* copy match data */
  98. do
  99. {
  100. context->dec_mem_window[BufPos] = context->dec_mem_window[(BufPos-match_pos) & context->dec_window_mask];
  101. /* replicate bytes */
  102. if (BufPos < MAX_MATCH)
  103. context->dec_mem_window[context->dec_window_size+BufPos] = context->dec_mem_window[BufPos];
  104. BufPos++;
  105. } while (--match_length > 0);
  106. }
  107. }
  108. context->dec_bitcount = dec_bitcount;
  109. context->dec_bitbuf = dec_bitbuf;
  110. context->dec_input_curpos = dec_input_curpos;
  111. return BufPos;
  112. }
  113. #ifdef ASM_DECODE_VERBATIM_BLOCK
  114. long fast_decode_verbatim_block(
  115. t_decoder_context *context,
  116. long BufPos,
  117. int amount_to_decode
  118. );
  119. #else /* !ASM_DECODE_VERBATIM_BLOCK */
  120. long fast_decode_verbatim_block(t_decoder_context *context, long BufPos, int amount_to_decode)
  121. {
  122. ulong match_pos;
  123. ulong match_ptr;
  124. long bufpos_end;
  125. long decode_residue;
  126. int match_length;
  127. int c;
  128. ulong dec_bitbuf;
  129. byte *dec_input_curpos;
  130. byte *dec_end_input_pos;
  131. byte *dec_mem_window;
  132. char dec_bitcount;
  133. char m;
  134. /*
  135. * Store commonly used variables locally
  136. */
  137. dec_bitcount = context->dec_bitcount;
  138. dec_bitbuf = context->dec_bitbuf;
  139. dec_input_curpos = context->dec_input_curpos;
  140. dec_end_input_pos = context->dec_end_input_pos;
  141. dec_mem_window = context->dec_mem_window;
  142. bufpos_end = BufPos + amount_to_decode;
  143. while (BufPos < bufpos_end)
  144. {
  145. /* decode an item from the main tree */
  146. DECODE_MAIN_TREE(c);
  147. if ((c -= NUM_CHARS) < 0)
  148. {
  149. /* it's a character */
  150. /* note: c - 256 == c if c is a byte */
  151. context->dec_mem_window[BufPos++] = (byte) c;
  152. }
  153. else
  154. {
  155. /* get match length header */
  156. if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
  157. {
  158. /* get match length footer if necessary */
  159. DECODE_LEN_TREE_NOEOFCHECK(match_length);
  160. }
  161. /* get match position slot */
  162. m = c >> NL_SHIFT;
  163. /* read any extra bits for the match position */
  164. if (m > 2)
  165. {
  166. if (m > 3) /* dec_extra_bits[m] != 0 */
  167. {
  168. GET_BITS17_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
  169. match_pos += MP_POS_minus2[m];
  170. }
  171. else
  172. {
  173. match_pos = MP_POS_minus2[3];
  174. }
  175. /*
  176. * Add match base to "extra bits". Our match base
  177. * table has 2 subtracted from all the elements.
  178. *
  179. * This is because encoded positions 0,1,2 denote
  180. * repeated offsets. Encoded position 3 denotes
  181. * a match 1 character away, 4 encodes 2 away, etc.
  182. * Hence the subtraction of 2, which has been
  183. * incorporated into the table.
  184. */
  185. /* update LRU repeated offset list */
  186. context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
  187. context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
  188. context->dec_last_matchpos_offset[0] = match_pos;
  189. }
  190. else
  191. {
  192. /* positions 0, 1, 2 denote repeated offsets */
  193. match_pos = context->dec_last_matchpos_offset[m];
  194. if (m)
  195. {
  196. context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
  197. context->dec_last_matchpos_offset[0] = match_pos;
  198. }
  199. }
  200. /* match lengths range from 2...257 */
  201. match_length += MIN_MATCH;
  202. match_ptr = (BufPos - match_pos) & context->dec_window_mask;
  203. /* copy match data */
  204. do
  205. {
  206. context->dec_mem_window[BufPos++] = context->dec_mem_window[match_ptr++];
  207. } while (--match_length > 0);
  208. }
  209. }
  210. context->dec_bitcount = dec_bitcount;
  211. context->dec_bitbuf = dec_bitbuf;
  212. context->dec_input_curpos = dec_input_curpos;
  213. /* should be zero */
  214. decode_residue = BufPos - bufpos_end;
  215. BufPos &= context->dec_window_mask;
  216. context->dec_bufpos = BufPos;
  217. return decode_residue;
  218. }
  219. #endif /* ASM_DECODE_VERBATIM_BLOCK */
  220. int decode_verbatim_block(t_decoder_context *context, long BufPos, int amount_to_decode)
  221. {
  222. /*
  223. * Special case code when BufPos is near the beginning of the window;
  224. * we must properly update our MAX_MATCH wrapper bytes.
  225. */
  226. if (BufPos < MAX_MATCH)
  227. {
  228. long new_bufpos;
  229. long amount_to_slowly_decode;
  230. amount_to_slowly_decode = (((MAX_MATCH-BufPos) < (amount_to_decode)) ? (MAX_MATCH-BufPos) : (amount_to_decode));
  231. /*
  232. * It's ok to end up decoding more than we wanted if we
  233. * restricted it to decoding only MAX_MATCH; there's
  234. * no guarantee a match doesn't straddle MAX_MATCH
  235. */
  236. new_bufpos = special_decode_verbatim_block(
  237. context,
  238. BufPos,
  239. amount_to_slowly_decode
  240. );
  241. amount_to_decode -= (new_bufpos-BufPos);
  242. context->dec_bufpos = BufPos = new_bufpos;
  243. /*
  244. * Note: if amount_to_decode < 0 then we're in trouble
  245. */
  246. if (amount_to_decode <= 0)
  247. return amount_to_decode;
  248. }
  249. return fast_decode_verbatim_block(context, BufPos, amount_to_decode);
  250. }