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.

299 lines
6.5 KiB

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