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.

399 lines
13 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. ulong 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. #ifdef TRACING
  44. TracingLiteral(BufPos, (byte) c);
  45. #endif
  46. context->dec_mem_window[BufPos] = (byte) c;
  47. /* we know BufPos < bufpos_end here, so no need to check for overflow */
  48. context->dec_mem_window[context->dec_window_size+BufPos] = (byte) c;
  49. BufPos++;
  50. }
  51. else
  52. {
  53. /* get match length header */
  54. if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
  55. {
  56. /* get match length footer if necessary */
  57. DECODE_LEN_TREE_NOEOFCHECK(match_length);
  58. }
  59. /* get match position slot */
  60. m = c >> NL_SHIFT;
  61. /* read any extra bits for the match position */
  62. if (m > 2)
  63. {
  64. if (m > 3) /* dec_extra_bits[m] != 0 */
  65. {
  66. GET_BITS17_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
  67. match_pos += MP_POS_minus2[m];
  68. }
  69. else
  70. {
  71. match_pos = 1; // MP_POS_minus2[3];
  72. }
  73. /*
  74. * Add match base to "extra bits". Our match base
  75. * table has 2 subtracted from all the elements.
  76. *
  77. * This is because encoded positions 0,1,2 denote
  78. * repeated offsets. Encoded position 3 denotes
  79. * a match 1 character away, 4 encodes 2 away, etc.
  80. * Hence the subtraction of 2, which has been
  81. * incorporated into the table.
  82. */
  83. /* update LRU repeated offset list */
  84. context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
  85. context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
  86. context->dec_last_matchpos_offset[0] = match_pos;
  87. }
  88. else
  89. {
  90. /* positions 0, 1, 2 denote repeated offsets */
  91. match_pos = context->dec_last_matchpos_offset[m];
  92. if (m)
  93. {
  94. context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
  95. context->dec_last_matchpos_offset[0] = match_pos;
  96. }
  97. }
  98. /* match lengths range from 2...257 */
  99. match_length += MIN_MATCH;
  100. #ifdef EXTRALONGMATCHES
  101. if ( match_length == MAX_MATCH ) {
  102. //
  103. // See detailed explanation in decalign.c
  104. //
  105. ULONG ExtraMatchLength, ExtraMatchLengthResidue;
  106. GET_BITS_NOEOFCHECK( 9, ExtraMatchLength );
  107. if ( ExtraMatchLength & ( 1 << 8 )) {
  108. if ( ExtraMatchLength & ( 1 << 7 )) {
  109. if ( ExtraMatchLength & ( 1 << 6 )) {
  110. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 9;
  111. GET_BITS_NOEOFCHECK( 9, ExtraMatchLengthResidue );
  112. ExtraMatchLength |= ExtraMatchLengthResidue;
  113. }
  114. else {
  115. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 6;
  116. GET_BITS_NOEOFCHECK( 6, ExtraMatchLengthResidue );
  117. ExtraMatchLength |= ExtraMatchLengthResidue;
  118. ExtraMatchLength += ( 1 << 8 ) + ( 1 << 10 );
  119. }
  120. }
  121. else {
  122. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 7 ) - 1 )) << 3;
  123. GET_BITS_NOEOFCHECK( 3, ExtraMatchLengthResidue );
  124. ExtraMatchLength |= ExtraMatchLengthResidue;
  125. ExtraMatchLength += ( 1 << 8 );
  126. }
  127. }
  128. match_length += ExtraMatchLength;
  129. }
  130. #endif
  131. #ifdef TRACING
  132. TracingMatch(BufPos,
  133. BufPos - match_pos,
  134. context->dec_window_size,
  135. match_length,
  136. m);
  137. #endif
  138. /* copy match data */
  139. do
  140. {
  141. context->dec_mem_window[BufPos] = context->dec_mem_window[(BufPos-match_pos) & context->dec_window_mask];
  142. /* replicate bytes */
  143. if (BufPos < MAX_MATCH) // what does this do? Does it need to be more than MAX_MATCH now?
  144. context->dec_mem_window[context->dec_window_size+BufPos] = context->dec_mem_window[BufPos];
  145. BufPos++;
  146. } while (--match_length > 0);
  147. }
  148. }
  149. context->dec_bitcount = dec_bitcount;
  150. context->dec_bitbuf = dec_bitbuf;
  151. context->dec_input_curpos = dec_input_curpos;
  152. return BufPos;
  153. }
  154. #ifdef ASM_DECODE_VERBATIM_BLOCK
  155. long __cdecl fast_decode_verbatim_block(
  156. t_decoder_context *context,
  157. long BufPos,
  158. int amount_to_decode
  159. );
  160. #else /* !ASM_DECODE_VERBATIM_BLOCK */
  161. long fast_decode_verbatim_block(t_decoder_context *context, long BufPos, int amount_to_decode)
  162. {
  163. ulong match_pos;
  164. ulong match_ptr;
  165. long bufpos_end;
  166. long decode_residue;
  167. int match_length;
  168. int c;
  169. ulong dec_bitbuf;
  170. byte *dec_input_curpos;
  171. byte *dec_end_input_pos;
  172. byte *dec_mem_window;
  173. char dec_bitcount;
  174. ulong m;
  175. /*
  176. * Store commonly used variables locally
  177. */
  178. dec_bitcount = context->dec_bitcount;
  179. dec_bitbuf = context->dec_bitbuf;
  180. dec_input_curpos = context->dec_input_curpos;
  181. dec_end_input_pos = context->dec_end_input_pos;
  182. dec_mem_window = context->dec_mem_window;
  183. bufpos_end = BufPos + amount_to_decode;
  184. while (BufPos < bufpos_end)
  185. {
  186. /* decode an item from the main tree */
  187. DECODE_MAIN_TREE(c);
  188. if ((c -= NUM_CHARS) < 0)
  189. {
  190. /* it's a character */
  191. /* note: c - 256 == c if c is a byte */
  192. #ifdef TRACING
  193. TracingLiteral(BufPos, (byte) c);
  194. #endif
  195. context->dec_mem_window[BufPos++] = (byte) c;
  196. }
  197. else
  198. {
  199. /* get match length header */
  200. if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
  201. {
  202. /* get match length footer if necessary */
  203. DECODE_LEN_TREE_NOEOFCHECK(match_length);
  204. }
  205. /* get match position slot */
  206. m = c >> NL_SHIFT;
  207. /* read any extra bits for the match position */
  208. if (m > 2)
  209. {
  210. if (m > 3) /* dec_extra_bits[m] != 0 */
  211. {
  212. GET_BITS17_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
  213. match_pos += MP_POS_minus2[m];
  214. }
  215. else
  216. {
  217. match_pos = MP_POS_minus2[3];
  218. }
  219. /*
  220. * Add match base to "extra bits". Our match base
  221. * table has 2 subtracted from all the elements.
  222. *
  223. * This is because encoded positions 0,1,2 denote
  224. * repeated offsets. Encoded position 3 denotes
  225. * a match 1 character away, 4 encodes 2 away, etc.
  226. * Hence the subtraction of 2, which has been
  227. * incorporated into the table.
  228. */
  229. /* update LRU repeated offset list */
  230. context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
  231. context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
  232. context->dec_last_matchpos_offset[0] = match_pos;
  233. }
  234. else
  235. {
  236. /* positions 0, 1, 2 denote repeated offsets */
  237. match_pos = context->dec_last_matchpos_offset[m];
  238. if (m)
  239. {
  240. context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
  241. context->dec_last_matchpos_offset[0] = match_pos;
  242. }
  243. }
  244. /* match lengths range from 2...257 */
  245. match_length += MIN_MATCH;
  246. #ifdef EXTRALONGMATCHES
  247. if ( match_length == MAX_MATCH ) {
  248. //
  249. // See detailed explanation in decalign.c
  250. //
  251. ULONG ExtraMatchLength, ExtraMatchLengthResidue;
  252. GET_BITS_NOEOFCHECK( 9, ExtraMatchLength );
  253. if ( ExtraMatchLength & ( 1 << 8 )) {
  254. if ( ExtraMatchLength & ( 1 << 7 )) {
  255. if ( ExtraMatchLength & ( 1 << 6 )) {
  256. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 9;
  257. GET_BITS_NOEOFCHECK( 9, ExtraMatchLengthResidue );
  258. ExtraMatchLength |= ExtraMatchLengthResidue;
  259. }
  260. else {
  261. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 6;
  262. GET_BITS_NOEOFCHECK( 6, ExtraMatchLengthResidue );
  263. ExtraMatchLength |= ExtraMatchLengthResidue;
  264. ExtraMatchLength += ( 1 << 8 ) + ( 1 << 10 );
  265. }
  266. }
  267. else {
  268. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 7 ) - 1 )) << 3;
  269. GET_BITS_NOEOFCHECK( 3, ExtraMatchLengthResidue );
  270. ExtraMatchLength |= ExtraMatchLengthResidue;
  271. ExtraMatchLength += ( 1 << 8 );
  272. }
  273. }
  274. match_length += ExtraMatchLength;
  275. }
  276. #endif
  277. match_ptr = (BufPos - match_pos) & context->dec_window_mask;
  278. #ifdef TRACING
  279. TracingMatch(BufPos,
  280. BufPos - match_pos,
  281. context->dec_window_size,
  282. match_length,
  283. m);
  284. #endif
  285. /* copy match data */
  286. do
  287. {
  288. context->dec_mem_window[BufPos++] = context->dec_mem_window[match_ptr++];
  289. } while (--match_length > 0);
  290. }
  291. }
  292. context->dec_bitcount = dec_bitcount;
  293. context->dec_bitbuf = dec_bitbuf;
  294. context->dec_input_curpos = dec_input_curpos;
  295. /* should be zero */
  296. decode_residue = BufPos - bufpos_end;
  297. BufPos &= context->dec_window_mask;
  298. context->dec_bufpos = BufPos;
  299. return decode_residue;
  300. }
  301. #endif /* ASM_DECODE_VERBATIM_BLOCK */
  302. int decode_verbatim_block(t_decoder_context *context, long BufPos, int amount_to_decode)
  303. {
  304. /*
  305. * Special case code when BufPos is near the beginning of the window;
  306. * we must properly update our MAX_MATCH wrapper bytes.
  307. */
  308. if (BufPos < MAX_MATCH)
  309. {
  310. long new_bufpos;
  311. long amount_to_slowly_decode;
  312. amount_to_slowly_decode = min(MAX_MATCH-BufPos, amount_to_decode);
  313. /*
  314. * It's ok to end up decoding more than we wanted if we
  315. * restricted it to decoding only MAX_MATCH; there's
  316. * no guarantee a match doesn't straddle MAX_MATCH
  317. */
  318. new_bufpos = special_decode_verbatim_block(
  319. context,
  320. BufPos,
  321. amount_to_slowly_decode
  322. );
  323. amount_to_decode -= (new_bufpos-BufPos);
  324. context->dec_bufpos = BufPos = new_bufpos;
  325. /*
  326. * Note: if amount_to_decode < 0 then we're in trouble
  327. */
  328. if (amount_to_decode <= 0)
  329. return amount_to_decode;
  330. }
  331. return fast_decode_verbatim_block(context, BufPos, amount_to_decode);
  332. }