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.

451 lines
14 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. ulong 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. #ifdef TRACING
  38. TracingLiteral(bufpos, (byte) c);
  39. #endif
  40. dec_mem_window[bufpos] = (byte) c;
  41. dec_mem_window[context->dec_window_size + bufpos] = (byte) c;
  42. bufpos++;
  43. }
  44. else
  45. {
  46. /*
  47. * Get match length slot
  48. */
  49. if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
  50. {
  51. DECODE_LEN_TREE_NOEOFCHECK(match_length);
  52. }
  53. /*
  54. * Get match position slot
  55. */
  56. m = c >> NL_SHIFT;
  57. if (m > 2)
  58. {
  59. if (dec_extra_bits[ m ] >= 3)
  60. {
  61. if (dec_extra_bits[m]-3)
  62. {
  63. /* no need to getbits17 */
  64. GET_BITS_NOEOFCHECK(dec_extra_bits[ m ] - 3, temp_pos);
  65. }
  66. else
  67. {
  68. temp_pos = 0;
  69. }
  70. match_pos = MP_POS_minus2[m] + (temp_pos << 3);
  71. DECODE_ALIGNED_NOEOFCHECK(temp_pos);
  72. match_pos += temp_pos;
  73. }
  74. else
  75. {
  76. if (dec_extra_bits[m])
  77. {
  78. GET_BITS_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
  79. match_pos += MP_POS_minus2[m];
  80. }
  81. else
  82. {
  83. match_pos = 1; // MP_POS_minus2[m==3];
  84. }
  85. }
  86. context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
  87. context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
  88. context->dec_last_matchpos_offset[0] = match_pos;
  89. }
  90. else
  91. {
  92. match_pos = context->dec_last_matchpos_offset[m];
  93. if (m)
  94. {
  95. context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
  96. context->dec_last_matchpos_offset[0] = match_pos;
  97. }
  98. }
  99. match_length += MIN_MATCH;
  100. #ifdef EXTRALONGMATCHES
  101. if ( match_length == MAX_MATCH ) {
  102. //
  103. // Fetch extra match length in addition to MAX_MATCH, which
  104. // is encoded like this:
  105. //
  106. // 0xxxxxxxx (8-bit value)
  107. // 10xxxxxxxxxx (10-bit value plus 2^8)
  108. // 110xxxxxxxxxxxx (12-bit value plus 2^8 plus 2^10)
  109. // 111xxxxxxxxxxxxxxx (15-bit value)
  110. //
  111. // 15 bits is the largest possible because a match cannot
  112. // span a 32K boundary.
  113. //
  114. // We know we'll read at least 9 bits, so read 9 bits first
  115. // and then determine how many additional to read based on
  116. // the first 3 bits of that.
  117. //
  118. ULONG ExtraMatchLength;
  119. ULONG ExtraMatchLengthResidue;
  120. GET_BITS_NOEOFCHECK( 9, ExtraMatchLength );
  121. if ( ExtraMatchLength & ( 1 << 8 )) {
  122. if ( ExtraMatchLength & ( 1 << 7 )) {
  123. if ( ExtraMatchLength & ( 1 << 6 )) {
  124. //
  125. // First 3 bits are '111', so that means remaining
  126. // 6 bits are the first 6 bits of the 15 bit value
  127. // meaning we must read 9 more bits.
  128. //
  129. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 9;
  130. GET_BITS_NOEOFCHECK( 9, ExtraMatchLengthResidue );
  131. ExtraMatchLength |= ExtraMatchLengthResidue;
  132. }
  133. else {
  134. //
  135. // First 3 bits are '110', so that means remaining
  136. // 6 bits are the first 6 bits of the 12 bit value
  137. // meaning we must read 6 more bits. Then we add
  138. // 2^8 plus 2^10 to the value.
  139. //
  140. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 6;
  141. GET_BITS_NOEOFCHECK( 6, ExtraMatchLengthResidue );
  142. ExtraMatchLength |= ExtraMatchLengthResidue;
  143. ExtraMatchLength += ( 1 << 8 ) + ( 1 << 10 );
  144. }
  145. }
  146. else {
  147. //
  148. // First 2 bits are '10', so that means remaining
  149. // 7 bits are the first 7 bits of the 10 bit value
  150. // meaning we must read 3 more bits. Then we add
  151. // 2^8 to the value.
  152. //
  153. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 7 ) - 1 )) << 3;
  154. GET_BITS_NOEOFCHECK( 3, ExtraMatchLengthResidue );
  155. ExtraMatchLength |= ExtraMatchLengthResidue;
  156. ExtraMatchLength += ( 1 << 8 );
  157. }
  158. }
  159. else {
  160. //
  161. // First bit is a '0', so that means remaining 8 bits are
  162. // the 8 bit value to add to the match length. No need to
  163. // mask off the leading '0'.
  164. //
  165. }
  166. match_length += ExtraMatchLength;
  167. }
  168. #endif
  169. #ifdef TRACING
  170. TracingMatch(bufpos,
  171. bufpos-match_pos,
  172. context->dec_window_size,
  173. match_length,
  174. m);
  175. #endif
  176. do
  177. {
  178. dec_mem_window[bufpos] = dec_mem_window[(bufpos-match_pos) & context->dec_window_mask];
  179. if (bufpos < MAX_MATCH)
  180. dec_mem_window[context->dec_window_size+bufpos] = dec_mem_window[bufpos];
  181. bufpos++;
  182. } while (--match_length > 0);
  183. }
  184. }
  185. context->dec_bitcount = dec_bitcount;
  186. context->dec_bitbuf = dec_bitbuf;
  187. context->dec_input_curpos = dec_input_curpos;
  188. return bufpos;
  189. }
  190. #ifndef ASM_DECODE_ALIGNED_OFFSET_BLOCK
  191. long fast_decode_aligned_offset_block(t_decoder_context *context, long bufpos, int amount_to_decode)
  192. {
  193. ulong match_pos;
  194. ulong temp_pos;
  195. long bufpos_end;
  196. long decode_residue;
  197. int match_length;
  198. int c;
  199. ulong dec_bitbuf;
  200. char dec_bitcount;
  201. byte *dec_input_curpos;
  202. byte *dec_end_input_pos;
  203. byte *dec_mem_window;
  204. ulong match_ptr;
  205. ulong m;
  206. /*
  207. * Store commonly used variables locally
  208. */
  209. dec_bitcount = context->dec_bitcount;
  210. dec_bitbuf = context->dec_bitbuf;
  211. dec_input_curpos = context->dec_input_curpos;
  212. dec_end_input_pos = context->dec_end_input_pos;
  213. dec_mem_window = context->dec_mem_window;
  214. bufpos_end = bufpos + amount_to_decode;
  215. while (bufpos < bufpos_end)
  216. {
  217. /*
  218. * Decode an item
  219. */
  220. DECODE_MAIN_TREE(c);
  221. if ((c -= NUM_CHARS) < 0)
  222. {
  223. #ifdef TRACING
  224. TracingLiteral(bufpos, (byte) c);
  225. #endif
  226. dec_mem_window[bufpos++] = (byte) c;
  227. }
  228. else
  229. {
  230. /*
  231. * Get match length slot
  232. */
  233. if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
  234. {
  235. DECODE_LEN_TREE_NOEOFCHECK(match_length);
  236. }
  237. /*
  238. * Get match position slot
  239. */
  240. m = c >> NL_SHIFT;
  241. if (m > 2)
  242. {
  243. if (dec_extra_bits[ m ] >= 3)
  244. {
  245. if (dec_extra_bits[m]-3)
  246. {
  247. /* no need to getbits17 */
  248. GET_BITS_NOEOFCHECK(dec_extra_bits[ m ] - 3, temp_pos);
  249. }
  250. else
  251. {
  252. temp_pos = 0;
  253. }
  254. match_pos = MP_POS_minus2[m] + (temp_pos << 3);
  255. DECODE_ALIGNED_NOEOFCHECK(temp_pos);
  256. match_pos += temp_pos;
  257. }
  258. else
  259. {
  260. if (dec_extra_bits[m])
  261. {
  262. GET_BITS_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
  263. match_pos += MP_POS_minus2[m];
  264. }
  265. else
  266. {
  267. match_pos = MP_POS_minus2[m];
  268. }
  269. }
  270. context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
  271. context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
  272. context->dec_last_matchpos_offset[0] = match_pos;
  273. }
  274. else
  275. {
  276. match_pos = context->dec_last_matchpos_offset[m];
  277. if (m)
  278. {
  279. context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
  280. context->dec_last_matchpos_offset[0] = match_pos;
  281. }
  282. }
  283. match_length += MIN_MATCH;
  284. match_ptr = (bufpos - match_pos) & context->dec_window_mask;
  285. #ifdef EXTRALONGMATCHES
  286. if ( match_length == MAX_MATCH ) {
  287. //
  288. // See detailed explanation above.
  289. //
  290. ULONG ExtraMatchLength, ExtraMatchLengthResidue;
  291. GET_BITS_NOEOFCHECK( 9, ExtraMatchLength );
  292. if ( ExtraMatchLength & ( 1 << 8 )) {
  293. if ( ExtraMatchLength & ( 1 << 7 )) {
  294. if ( ExtraMatchLength & ( 1 << 6 )) {
  295. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 9;
  296. GET_BITS_NOEOFCHECK( 9, ExtraMatchLengthResidue );
  297. ExtraMatchLength |= ExtraMatchLengthResidue;
  298. }
  299. else {
  300. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 6 ) - 1 )) << 6;
  301. GET_BITS_NOEOFCHECK( 6, ExtraMatchLengthResidue );
  302. ExtraMatchLength |= ExtraMatchLengthResidue;
  303. ExtraMatchLength += ( 1 << 8 ) + ( 1 << 10 );
  304. }
  305. }
  306. else {
  307. ExtraMatchLength = ( ExtraMatchLength & (( 1 << 7 ) - 1 )) << 3;
  308. GET_BITS_NOEOFCHECK( 3, ExtraMatchLengthResidue );
  309. ExtraMatchLength |= ExtraMatchLengthResidue;
  310. ExtraMatchLength += ( 1 << 8 );
  311. }
  312. }
  313. match_length += ExtraMatchLength;
  314. }
  315. #endif
  316. #ifdef TRACING
  317. TracingMatch(bufpos,
  318. bufpos - match_pos,
  319. context->dec_window_size,
  320. match_length,
  321. m);
  322. #endif
  323. do
  324. {
  325. dec_mem_window[bufpos++] = dec_mem_window[match_ptr++];
  326. } while (--match_length > 0);
  327. }
  328. }
  329. context->dec_bitcount = dec_bitcount;
  330. context->dec_bitbuf = dec_bitbuf;
  331. context->dec_input_curpos = dec_input_curpos;
  332. /* should be zero */
  333. decode_residue = bufpos - bufpos_end;
  334. bufpos &= context->dec_window_mask;
  335. context->dec_bufpos = bufpos;
  336. return decode_residue;
  337. }
  338. #endif
  339. int decode_aligned_offset_block(
  340. t_decoder_context * context,
  341. long BufPos,
  342. int amount_to_decode
  343. )
  344. {
  345. /*
  346. * Special case code when BufPos is near the beginning of the window;
  347. * we must properly update our MAX_MATCH wrapper bytes.
  348. */
  349. if (BufPos < MAX_MATCH)
  350. {
  351. long new_bufpos;
  352. long amount_to_slowly_decode;
  353. amount_to_slowly_decode = min(MAX_MATCH-BufPos, amount_to_decode);
  354. /*
  355. * It's ok to end up decoding more than we wanted if we
  356. * restricted it to decoding only MAX_MATCH; there's
  357. * no guarantee a match doesn't straddle MAX_MATCH
  358. */
  359. new_bufpos = special_decode_aligned_block(
  360. context,
  361. BufPos,
  362. amount_to_slowly_decode
  363. );
  364. amount_to_decode -= (new_bufpos-BufPos);
  365. context->dec_bufpos = BufPos = new_bufpos;
  366. /*
  367. * Note: if amount_to_decode < 0 then we're in trouble
  368. */
  369. if (amount_to_decode <= 0)
  370. return amount_to_decode;
  371. }
  372. return fast_decode_aligned_offset_block(context, BufPos, amount_to_decode);
  373. }