Leaked source code of windows server 2003
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.

1117 lines
34 KiB

  1. /*
  2. Decoding is splitted into two phases:
  3. 1. Fast decoding. Check bounds rarely (when loading new tag and after copying
  4. of a long string) and switch into Careful only when we are too close to the
  5. end of input or output buffer.
  6. 2. Careful decoding. Before performing any memory access all bounds are checked
  7. to make sure no buffer overrun or underrun will happen. Careful decoding is
  8. usually 1.5 times slower than Fast one, but only last several hundred bytes
  9. are decoded this way; all the rest is decoded Fast.
  10. As long as decoding code is essentially the same except for bounds checks that
  11. differ in Fast and Careful mode, in order to avoid code duplication this file
  12. is included twice with different setting of CAREFUL macro (first it is 0, then
  13. 1).
  14. Run "cl -EP xdecode.c >xdecode.pp" to see actual code.
  15. */
  16. #if _MSC_FULL_VER >= 13008827 && defined(_M_IX86)
  17. #pragma warning(disable:4731) // EBP modified with inline asm
  18. #endif
  19. #if CAREFUL
  20. #define LABEL(label) careful_##label
  21. #define CAREFUL_OK_IF(cond) if (cond) RET_OK
  22. #define CAREFUL_ERR_IF(cond) if (cond) RET_ERR
  23. #define CAREFUL_EOF_IF(cond) if (cond) goto ret_ok_eof;
  24. #define CAREFUL_IF(cond, label) label:
  25. #if CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  26. #define START careful_start:
  27. #else
  28. #define START
  29. #endif
  30. #else /* !CAREFUL */
  31. #define LABEL(label) label
  32. #define CAREFUL_OK_IF(cond)
  33. #define CAREFUL_ERR_IF(cond)
  34. #define CAREFUL_EOF_IF(cond)
  35. #define CAREFUL_IF(cond, label) if (cond) goto label
  36. #define START start:
  37. static void do_decode (decode_info *info)
  38. {
  39. #endif
  40. /* ----------------------- CODING_HUFF_ALL ------------------------ */
  41. /* --------------- */
  42. // C code: 26.3 MB/s, asm code: 32.3 MB/s at P3-500
  43. #if CODING == CODING_HUFF_ALL
  44. #ifndef i386
  45. #if !CAREFUL
  46. ubitmask4 Mask;
  47. bits_t Bits, bits;
  48. xint len;
  49. uxint ofs;
  50. uchar *dst = info->dst.beg;
  51. const uchar *src = info->src.beg;
  52. Mask = * (__unaligned ubitmask2 *) src; src += sizeof (ubitmask2);
  53. Mask <<= sizeof (ubitmask2) * 8;
  54. Mask += * (__unaligned ubitmask2 *) src; src += sizeof (ubitmask2);
  55. Bits = 8 * sizeof (ubitmask2);
  56. if (src >= info->src.careful || dst >= info->dst.careful)
  57. goto careful_next;
  58. goto LABEL(next);
  59. #endif /* CAREFUL */
  60. LABEL(decode_more):
  61. // too close to end of buffer? -- switch to careful mode...
  62. CAREFUL_IF (src >= info->src.careful, decode_more1);
  63. CAREFUL_IF (dst >= info->dst.careful, decode_more2);
  64. // input buffer ovverrun? -- corrupted compressed data
  65. CAREFUL_ERR_IF (src >= info->src.end_bitmask2);
  66. // read 16 bits more and update Mask&Bits respectively
  67. bits = Bits;
  68. ofs = * (__unaligned ubitmask2 *) src;
  69. bits = (bits_t) (-bits);
  70. src += sizeof (ubitmask2);
  71. ofs <<= bits;
  72. Bits += 8 * sizeof (ubitmask2);
  73. Mask += (ubitmask4) ofs;
  74. if ((len -= 256) >= 0)
  75. goto LABEL (pointer);
  76. for (;;)
  77. {
  78. CAREFUL_OK_IF (dst >= info->dst.stop);
  79. *dst = (uchar) len; // copy literal byte to output
  80. ofs = (uxint) (Mask >> (8 * sizeof (Mask) - DECODE_BITS));
  81. ++dst;
  82. len = ((int16 *) info->table)[ofs];
  83. bits = 15;
  84. if (len < 0)
  85. goto LABEL(long_codeword);
  86. // short codeword -- already decoded
  87. bits &= len; // bits = # of bit used in Mask
  88. len >>= 4; // len = token
  89. Mask <<= bits; // update Mask&Bits
  90. Bits = (bits_t) (Bits - bits); // read more bits if necessary
  91. if (Bits < 0)
  92. goto LABEL (decode_more);
  93. if ((len -= 256) < 0) // (len -= 256) < 0 ? literal : pointer
  94. continue;
  95. goto LABEL (pointer);
  96. LABEL(next): // decode next token via lookup table
  97. ofs = (uxint) (Mask >> (8 * sizeof (Mask) - DECODE_BITS));
  98. len = ((int16 *) info->table)[ofs];
  99. bits = 15;
  100. if (len >= 0)
  101. {
  102. // short codeword -- already decoded
  103. bits &= len; // bits = # of bit used in Mask
  104. len >>= 4; // len = token
  105. Mask <<= bits; // update Mask&Bits
  106. Bits = (bits_t) (Bits - bits); // read more bits if necessary
  107. if (Bits < 0)
  108. goto LABEL (decode_more);
  109. if ((len -= 256) < 0) // (len -= 256) < 0 ? literal : pointer
  110. continue;
  111. }
  112. else
  113. {
  114. LABEL (long_codeword):
  115. // long codeword -- decode bit by bit
  116. Mask <<= DECODE_BITS; // DECODE_BITS alreay parsed
  117. do
  118. {
  119. len += ((bitmask4) Mask) < 0; // len += MSB (Mask)
  120. Mask <<= 1; // 1 more bit was used
  121. len = ((int16 *) info->table)[len + 0x8000];
  122. }
  123. while (len < 0);
  124. bits &= len; // bits = # of bit used in Mask
  125. len >>= 4; // len = token
  126. Bits = (bits_t) (Bits - bits); // read more bits if necessary
  127. if (Bits < 0)
  128. goto LABEL (decode_more);
  129. if ((len -= 256) < 0) // (len -= 256) < 0 ? literal : pointer
  130. continue;
  131. }
  132. LABEL(pointer):
  133. CAREFUL_EOF_IF (dst >= info->dst.stop);
  134. bits = (bits_t) (len >> MAX_LENGTH_LOG); // # of bits in offset
  135. ofs = (uxint) ((Mask >> 1) | (((ubitmask4) 1) << (8 * sizeof (Mask) - 1)));
  136. Mask <<= bits; // update Mask and Bits
  137. Bits = (bits_t) (Bits - bits);
  138. bits ^= 8 * sizeof (ofs) - 1; // bits = 31 - bits
  139. len &= MAX_LENGTH - 1; // run length - MIN_MATCH
  140. ofs >>= bits; // ofs = (1<<bits) | (Mask<<(32-bits))
  141. info->src.last = src; // save src
  142. ofs = (uxint) (- (xint) ofs); // ofs = real negative offset
  143. #if !CAREFUL && 8-MIN_MATCH < MAX_LENGTH-1
  144. if (len <= 8-MIN_MATCH)
  145. {
  146. src = dst + ofs; // src = beginning of string
  147. #ifdef _M_IX86 // unligned access is faster only on x86
  148. if (ofs < ~2)
  149. {
  150. if (src < info->dst.beg) // buffer underrun? -- corrupted data
  151. RET_ERR;
  152. ofs = ((__unaligned uint32 *) src)[0]; // copy 8 bytes
  153. ((__unaligned uint32 *) dst)[0] = ofs;
  154. ofs = ((__unaligned uint32 *) src)[1];
  155. ((__unaligned uint32 *) dst)[1] = ofs;
  156. src = info->src.last; // restore src
  157. dst = dst + len + MIN_MATCH; // dst = next output position
  158. if (Bits >= 0) // have enough Bits in Mask? -- proceed further
  159. goto LABEL (next);
  160. goto LABEL (mask_more); // otherwise, read more bits
  161. }
  162. #endif
  163. if (src < info->dst.beg) // buffer underrun? -- corrupted data
  164. RET_ERR;
  165. COPY_8_BYTES (dst, src); // copy 8 bytes one by one
  166. // NB: dst & src may overlap
  167. src = info->src.last; // restore src
  168. dst = dst + len + MIN_MATCH; // dst = next output position
  169. if (Bits >= 0) // have enough Bits in Mask? -- proceed further
  170. goto LABEL (next);
  171. goto LABEL (mask_more); // otherwise, read more bits
  172. }
  173. #endif /* CAREFUL */
  174. if (len == MAX_LENGTH - 1) // long length? -- decode it
  175. {
  176. // if input data overrun then compressed data corrupted
  177. CAREFUL_ERR_IF (src >= info->src.end);
  178. len = *src++ + (MAX_LENGTH-1);
  179. if (len == 255 + MAX_LENGTH-1)
  180. {
  181. CAREFUL_ERR_IF (src >= info->src.end_1);
  182. len = * (__unaligned uint16 *) src;
  183. src += 2;
  184. if (len < 255 + MAX_LENGTH-1) // length should be large enough
  185. RET_ERR;
  186. }
  187. info->src.last = src; // save input buffer pointer
  188. }
  189. len += MIN_MATCH; // len = actual length
  190. src = dst + ofs; // src = pointer to the beginning of string
  191. dst += len; // dst = last output position
  192. if (src < info->dst.beg) // buffer underrun? -- corrupted data
  193. RET_ERR;
  194. #if !CAREFUL
  195. if (dst >= info->dst.careful)
  196. goto careful_check_overrun;
  197. #else
  198. careful_check_overrun:
  199. if (dst > info->dst.stop) // more to copy than necessary?
  200. {
  201. dst -= len; // dst = first output position
  202. len = info->dst.stop - dst; // len = max length to copy
  203. COPY_BLOCK_SLOW (dst, src, len); // copy last run
  204. src = info->src.last; // restore input buffer pointer
  205. RET_OK; // OK but no EOF mark was found
  206. }
  207. #endif
  208. dst -= len; // dst = first output position
  209. COPY_BLOCK_SLOW (dst, src, len); // input & output may overlap -- copy byte by byte
  210. src = info->src.last; // restore input buffer pointer
  211. CAREFUL_IF (dst >= info->dst.careful, copy1);
  212. if (Bits >= 0) // enough Bits in Mask?
  213. goto LABEL (next); // decode next token
  214. #if !CAREFUL && 8-MIN_MATCH < MAX_LENGTH-1
  215. LABEL(mask_more):
  216. #endif
  217. // have 2 more bytes in input buffer?
  218. CAREFUL_ERR_IF (src >= info->src.end_bitmask2);
  219. // read 16 bits more and update Mask&Bits respectively
  220. bits = Bits;
  221. ofs = * (__unaligned ubitmask2 *) src;
  222. bits = (bits_t) (-bits);
  223. src += sizeof (ubitmask2);
  224. ofs <<= bits;
  225. Bits += 8 * sizeof (ubitmask2);
  226. Mask += (ubitmask4) ofs;
  227. goto LABEL (next); // decode next token
  228. } /* of for(;;) */
  229. #if CAREFUL
  230. ret_ok_eof:
  231. if (dst == info->dst.end && len == 0)
  232. info->eof = 1;
  233. ret_ok:
  234. info->src.last = src;
  235. info->dst.last = dst;
  236. info->result = 1;
  237. return;
  238. ret_err:
  239. info->result = 0;
  240. return;
  241. #endif /* CAREFUL */
  242. #else /* ---------------------- defined i386 --------------------- */
  243. #if !CAREFUL
  244. __asm
  245. {
  246. mov eax,info ; save info
  247. push esi ; save registers
  248. push edi
  249. push edx
  250. push ecx
  251. push ebx
  252. push ebp
  253. mov ebp,eax ; (ebp) = info
  254. mov ebx,[ebp].src.beg ; (ebx) = src
  255. mov edi,[ebp].dst.beg ; (edx) = dst
  256. xor esi,esi ; initialize Mask
  257. mov si,[ebx]
  258. shl esi,16
  259. mov si,[ebx+2]
  260. add ebx,4
  261. mov ch,16 ; (ch) = Bits = 16
  262. cmp ebx,[ebp].src.careful ; too close to the end of src buffer?
  263. jae careful_next ; yes, be careful...
  264. cmp edi,[ebp].dst.careful ; too close to the end of dst buffer?
  265. jae careful_next ; yes, be careful...
  266. jmp LABEL (next)
  267. #endif /* CAREFUL */
  268. LABEL(literal):
  269. #if CAREFUL
  270. cmp edi,[ebp].dst.stop ; decoded as much as asked?
  271. jae ret_ok ; done, but no EOF mark
  272. #endif
  273. mov edx,esi ; (edx) = Mask
  274. mov [edi],al ; store literal byte
  275. shr edx,32-DECODE_BITS
  276. inc edi ; (edi) = next output position
  277. movsx eax,word ptr [ebp+edx*2].table ; (eax) = respective decode table entry
  278. mov cl,15 ; (cl) = 15
  279. test eax,eax ; need further decoding? (= codelen > DECODE_BITS?)
  280. jl LABEL(long_code) ; yes, do it
  281. and cl,al ; (cl) = # of bits used in mask
  282. shr eax,4 ; (eax) = token
  283. shl esi,cl ; (esi) = resulting mask
  284. sub ch,cl ; (ch) = # of available bits left in dx
  285. jl LABEL(decode_more) ; if ch < 0 need to read more bits
  286. sub eax,256 ; (eax) = token - 256
  287. jl LABEL(literal) ; if < 0 then al = code of literal
  288. jmp LABEL(pointer) ; otherwise it's pointer
  289. LABEL(next):
  290. mov edx,esi ; (edx) = Mask
  291. mov cl,15 ; (cl) = 15
  292. shr edx,32-DECODE_BITS ; (edx) = DECODE_BITS most significant bits of Mask
  293. movsx eax,word ptr [ebp+edx*2].table ; (eax) = respective decode table entry
  294. test eax,eax ; need further decoding?
  295. jl LABEL(long_code) ; yes, continue
  296. and cl,al ; (cl) = # of bits used in mask
  297. shr eax,4 ; (eax) = current token
  298. shl esi,cl ; (esi) = resulting mask
  299. sub ch,cl ; (ch) = # of available bits left in dx
  300. jl LABEL(decode_more) ; if ch < 0 need to read more bits
  301. sub eax,256 ; (eax) = token - 256
  302. jl LABEL(literal) ; if < 0 then al = code of literal
  303. jmp LABEL(pointer) ; otherwise it's pointer
  304. LABEL(long_code):
  305. shl esi, DECODE_BITS ; DECODE_BITS were used; remove them
  306. LABEL(next_bit):
  307. add esi,esi ; Mask <<= 1 (and get carry)
  308. adc eax,0 ; eax += (old Mask < 0)
  309. movsx eax,word ptr [ebp+eax*2+0x10000].table ; (eax) = token
  310. test eax,eax ; need further decoding?
  311. jl LABEL(next_bit) ; yes, continue
  312. and cl,al ; (cl) = # of bits used in mask
  313. shr eax,4 ; (eax) = token
  314. sub ch,cl ; (ch) = # of available bits left in Mask
  315. jl LABEL(decode_more) ; if ch < 0 need to read more bits
  316. sub eax,256 ; (eax) = token - 256
  317. jl LABEL(literal) ; if < 0 then al = code of literal
  318. jmp LABEL(pointer) ; otherwise it's pointer
  319. LABEL(decode_more):
  320. #if !CAREFUL
  321. cmp ebx,[ebp].src.careful ; too close to the end of src buffer?
  322. jae careful_decode_more ; yes, be careful...
  323. cmp edi,[ebp].dst.careful ; too close to the end of dst buffer?
  324. jae careful_decode_more ; yes, be careful...
  325. #else
  326. cmp ebx,[ebp].src.end_bitmask2 ; buffer overrun?
  327. jae error ; yes, error...
  328. #endif
  329. mov cl,ch ; (cl) = (# of have - # of used)
  330. xor edx,edx
  331. mov dx,[ebx] ; (edx) = next 16 bits
  332. neg cl ; (cl) = # unused bits in Mask
  333. add ebx,2 ; (ebx) = ptr to next token
  334. shl edx,cl ; (edx) = 16 aligned on required boundary
  335. add ch,16 ; (ch) = # of free bits in Mask
  336. add esi,edx ; (esi) = Mask + next 16 bits
  337. sub eax,256 ; (eax) = token - 256
  338. jl LABEL(literal) ; if < 0 then al = code of literal
  339. LABEL(pointer):
  340. #if CAREFUL
  341. cmp edi,[ebp].dst.stop ; reached end of buffer?
  342. jae ret_ok_eof ; yes, done, and probably EOF (check later)
  343. #endif
  344. mov cl,al ; prepare to obtain # of bits in offset
  345. mov edx,esi ; (edx) = mask
  346. shr cl,MAX_LENGTH_LOG ; (cl) = # of bits in offset
  347. or edx,1 ; set less significant bit
  348. shl esi,cl ; (esi) = (Mask << cl)
  349. sub ch,cl ; (ch) = # of bits left in mask
  350. ror edx,1 ; (edx) = (Mask >> 1) | 0x80000000
  351. xor cl,31 ; (cl) = 31 - (# of bits in mask)
  352. and eax,MAX_LENGTH-1 ; (eax) = length - MIN_MATCH
  353. shr edx,cl ; (edx) = (1 << #) + (Mask >> (32-#)) = offset
  354. push esi ; save mask
  355. neg edx ; (edx) = negative offset
  356. #if !CAREFUL && 8-MIN_MATCH < MAX_LENGTH-1
  357. cmp eax,8-MIN_MATCH ; length > 8?
  358. ja LABEL(long_string)
  359. lea esi, [edi+edx] ; esi = beginning of string
  360. cmp edx,-3 ; offset < 4?
  361. jae LABEL(copy_by_one) ; yes, copy byte by byte
  362. cmp esi, [ebp].dst.beg ; output buffer underrun?
  363. jb error_pop ; yes, corrupted data
  364. mov edx,[esi] ; get first 4 bytes
  365. mov [edi],edx ; store them
  366. mov edx,[esi+4] ; get next 4 byte
  367. mov [edi+4],edx ; store them
  368. pop esi ; restore mask
  369. lea edi,[edi+eax+MIN_MATCH] ; (edi) = next output location
  370. test ch,ch ; have enough bits in Mask?
  371. jge LABEL(next) ; yes, proceed further
  372. jmp LABEL(mask_more) ; no, need to read in more bits
  373. LABEL(copy_by_one):
  374. cmp esi, [ebp].dst.beg ; output buffer underrun?
  375. jb error_pop ; yes, corrupted data
  376. mov dl,[esi] ; copy 8 bytes by one
  377. mov [edi],dl ; NB: no readahead is allowed here
  378. mov dl,[esi+1] ; because source and destination
  379. mov [edi+1],dl ; may overlap
  380. mov dl,[esi+2]
  381. mov [edi+2],dl
  382. mov dl,[esi+3]
  383. mov [edi+3],dl
  384. mov dl,[esi+4]
  385. mov [edi+4],dl
  386. mov dl,[esi+5]
  387. mov [edi+5],dl
  388. mov dl,[esi+6]
  389. mov [edi+6],dl
  390. mov dl,[esi+7]
  391. mov [edi+7],dl
  392. pop esi ; restore mask
  393. lea edi,[edi+eax+MIN_MATCH] ; (edi) = next output location
  394. test ch,ch ; have enough bits in Mask?
  395. jge LABEL(next) ; yes, proceed further
  396. jmp LABEL(mask_more) ; no, need to read in more bits
  397. LABEL(long_string):
  398. #endif /* CAREFUL */
  399. cmp eax,MAX_LENGTH-1 ; long length?
  400. je LABEL(long_length) ; yes, decode it
  401. LABEL(long_length_done):
  402. lea esi,[edi+edx] ; (esi) = source pointer
  403. add eax,MIN_MATCH ; (edx) = length
  404. lea edx,[esi+eax] ; (eax) = last output position
  405. cmp esi,[ebp].dst.beg ; output buffer underrun?
  406. jb error_pop ; yes, corrupted data
  407. xchg eax,ecx ; (ecx) = length, (ah) = bit counter
  408. #if !CAREFUL
  409. cmp edx,[ebp].dst.careful ; too close to the end of buffer?
  410. jae careful_check_overrun ; yes, be careful
  411. #else
  412. careful_check_overrun:
  413. cmp edx,[ebp].dst.stop ; too much to output?
  414. jbe careful_no_overrun ; yes, adjust length
  415. sub edx,[ebp].dst.stop ; (edx) = excess
  416. sub ecx,edx ; (ecx) = exact length
  417. rep movsb ; copy bytes
  418. pop esi ; restore mask
  419. jmp ret_ok ; OK, but not EOF
  420. careful_no_overrun:
  421. #endif
  422. rep movsb ; copy bytes
  423. mov ch,ah ; restore byte counter
  424. pop esi ; restore Mask
  425. #if !CAREFUL
  426. cmp edi,[ebp].dst.careful ; too close to the end of input buffer?
  427. jae careful_copy ; yes, switch into careful mode
  428. #else
  429. careful_copy:
  430. #endif
  431. test ch,ch ; have enough bits in Mask?
  432. jge LABEL(next) ; yes, proceed further
  433. #if CAREFUL
  434. cmp ebx,[ebp].src.end_bitmask2 ; input buffer overrun?
  435. jae error
  436. #else
  437. LABEL(mask_more):
  438. #endif
  439. mov cl,ch ; (cl) = (# of have - # of used)
  440. xor edx,edx
  441. mov dx,[ebx] ; (edx) = next 16 bits
  442. neg cl ; (cl) = # unused bits in Mask
  443. add ebx,2 ; (ebx) = ptr to next token
  444. shl edx,cl ; (edx) = 16 aligned on required boundary
  445. add ch,16 ; (ch) = # of free bits in Mask
  446. add esi,edx ; (esi) = Mask + next 16 bits
  447. jmp LABEL(next) ; decode next token
  448. LABEL(long_length):
  449. #if CAREFUL
  450. cmp ebx,[ebp].src.end ; input buffer overrun?
  451. jae error_pop ; yes, corrupted data
  452. #endif
  453. xor eax,eax
  454. mov al,[ebx] ; (eax) = next byte
  455. inc ebx ; (ebx) = ptr to next token
  456. cmp al,255 ; (eax) == 255?
  457. lea eax,[eax+MAX_LENGTH-1] ; (eax) = next byte + MAX_LENGTH-1
  458. jne LABEL(long_length_done) ; no, length decoded
  459. #if CAREFUL
  460. cmp ebx,[ebp].src.end_1 ; input buffer overrun?
  461. jae error_pop ; yes, corrupted data
  462. #endif
  463. xor eax,eax
  464. mov ax,[ebx] ; (eax) = next word
  465. add ebx,2 ; (ebx) = ptr to next token
  466. cmp ax,255+MAX_LENGTH-1 ; length should be long enough
  467. jae LABEL(long_length_done)
  468. jmp error
  469. #if CAREFUL
  470. error_pop:
  471. pop eax ; pop Mask saved on stack
  472. error:
  473. xor eax,eax ; decode error: return 0
  474. jmp ret_common
  475. ret_ok_eof:
  476. cmp edi,[ebp].dst.end
  477. jne ret_ok
  478. test eax,eax
  479. jne ret_ok ; eof iff eax == 0
  480. mov eax,1
  481. mov [ebp].eof,eax
  482. ret_ok:
  483. mov eax,1 ; no [obvious] error: return 0
  484. ret_common:
  485. mov [ebp].result, eax ; store result
  486. mov [ebp].src.last,ebx ; save last value of source ptr
  487. mov [ebp].dst.last,edi ; save last value of destination ptr
  488. pop ebp ; restore registers we used
  489. pop ebx
  490. pop ecx
  491. pop edx
  492. pop edi
  493. pop esi ; and return
  494. } /* end of __asm */
  495. #endif /* CAREFUL */
  496. #endif /* i386 */
  497. #endif /* -------------------- CODING_HUFF_ALL ------------------ */
  498. /* ----------------------- CODING_DIRECT2 ------------------------ */
  499. /* -------------- */
  500. #if CODING == CODING_DIRECT2
  501. #ifndef i386
  502. // C code: 73 MB/s at P3-500; asm code 80.5 MB/s
  503. /*
  504. Pseudocode:
  505. ----------
  506. length = NextWord ();
  507. offset = length >> DIRECT2_LEN_LOG;
  508. length &= DIRECT2_MAX_LEN;
  509. if (length == DIRECT2_MAX_LEN)
  510. {
  511. length = NextQuad ();
  512. if (length == 15)
  513. {
  514. length = NextByte ();
  515. if (length == 255)
  516. length = NextWord () - 15 - DIRECT2_MAX_LEN;
  517. length += 15;
  518. }
  519. length += DIRECT2_MAX_LEN;
  520. }
  521. length += MIN_MATCH;
  522. ++offset;
  523. memcpy (dst, dst - offset, length);
  524. dst += length;
  525. */
  526. #if !CAREFUL
  527. tag_t bmask = 0;
  528. xint ofs, len;
  529. const uchar *ptr = 0;
  530. uchar *dst = info->dst.beg;
  531. const uchar *src = info->src.beg;
  532. goto start;
  533. #endif /* !CAREFUL */
  534. LABEL (next):
  535. if (bmask >= 0) do // while MSB(bmask) == 0
  536. {
  537. bmask <<= 1;
  538. LABEL (copy_byte):
  539. CAREFUL_OK_IF (dst >= info->dst.stop);
  540. CAREFUL_ERR_IF (src >= info->src.end);
  541. *dst++ = *src++; // copy next byte
  542. } while (bmask >= 0);
  543. if ((bmask <<= 1) == 0) // if bmask == 0 reload it
  544. {
  545. START;
  546. CAREFUL_IF (src >= info->src.careful || dst >= info->dst.careful, restart);
  547. CAREFUL_ERR_IF (src >= info->src.end_tag);
  548. bmask = * (__unaligned tag_t *) src;
  549. src += sizeof (tag_t);
  550. if (bmask >= 0)
  551. {
  552. bmask = (bmask << 1) + 1;
  553. goto LABEL (copy_byte);
  554. }
  555. bmask = (bmask << 1) + 1;
  556. }
  557. #if !CAREFUL
  558. assert (dst < info->dst.end - 8);
  559. #endif
  560. CAREFUL_EOF_IF (dst >= info->dst.stop);
  561. CAREFUL_ERR_IF (src >= info->src.end_1);
  562. ofs = * (__unaligned uint16 *) src;
  563. src += 2;
  564. len = ofs;
  565. ofs >>= DIRECT2_LEN_LOG;
  566. len &= DIRECT2_MAX_LEN;
  567. ofs = ~ofs;
  568. #if !CAREFUL && (8 - MIN_MATCH < DIRECT2_MAX_LEN)
  569. if (len <= 8 - MIN_MATCH)
  570. {
  571. const uchar *src1 = dst + ofs;
  572. #ifdef _M_IX86 // unaligned access is faster only on x86
  573. if (ofs < ~2)
  574. {
  575. if (src1 < info->dst.beg) RET_ERR; // check for buffer underrun
  576. ofs = ((__unaligned uint32 *) src1)[0]; // quickly copy 8 bytes
  577. ((__unaligned uint32 *) dst)[0] = ofs;
  578. ofs = ((__unaligned uint32 *) src1)[1];
  579. ((__unaligned uint32 *) dst)[1] = ofs;
  580. dst += len + MIN_MATCH; // dst = next output position
  581. goto LABEL (next); // decode next token
  582. }
  583. #endif
  584. if (src1 < info->dst.beg) RET_ERR; // check for buffer overrun
  585. COPY_8_BYTES (dst, src1);
  586. dst += len + MIN_MATCH;
  587. goto LABEL (next);
  588. }
  589. #endif
  590. if (len == DIRECT2_MAX_LEN) // decode long length
  591. {
  592. if (ptr == 0)
  593. {
  594. CAREFUL_ERR_IF (src >= info->src.end);
  595. ptr = src;
  596. len = *src++ & 15;
  597. }
  598. else
  599. {
  600. len = *ptr >> 4;
  601. ptr = 0;
  602. }
  603. if (len == 15)
  604. {
  605. CAREFUL_ERR_IF (src >= info->src.end);
  606. len = *src++;
  607. if (len == 255)
  608. {
  609. CAREFUL_ERR_IF (src >= info->src.end_1);
  610. len = * (__unaligned uint16 *) src;
  611. src += 2;
  612. if (len < 255 + 15 + DIRECT2_MAX_LEN) RET_ERR;
  613. len += MIN_MATCH;
  614. goto LABEL (done_len);
  615. }
  616. len += 15;
  617. }
  618. len += DIRECT2_MAX_LEN + MIN_MATCH;
  619. goto LABEL (done_len);
  620. }
  621. len += MIN_MATCH;
  622. LABEL (done_len):
  623. info->src.last = src;
  624. src = dst + ofs;
  625. #if !CAREFUL
  626. if (dst + len >= info->dst.careful)
  627. goto careful_copy_tail;
  628. #else
  629. careful_copy_tail:
  630. if (dst + len > info->dst.stop)
  631. {
  632. if (src < info->dst.beg) RET_ERR;
  633. len = (xint) (info->dst.stop - dst);
  634. assert (len >= 0);
  635. COPY_BLOCK_SLOW (dst, src, len);
  636. src = info->src.last;
  637. RET_OK;
  638. }
  639. #endif /* !CAREFUL */
  640. if (src < info->dst.beg) RET_ERR;
  641. COPY_BLOCK_SLOW (dst, src, len); // copy block
  642. src = info->src.last; // restore input buffer ptr
  643. goto LABEL (next);
  644. #if CAREFUL
  645. ret_ok_eof:
  646. if (dst == info->dst.end)
  647. info->eof = 1;
  648. ret_ok:
  649. info->src.last = src;
  650. info->dst.last = dst;
  651. info->result = 1;
  652. return;
  653. ret_err:
  654. info->result = 0;
  655. return;
  656. #endif /* CAREFUL */
  657. #else /* ------------------------- i386 ---------------------------- */
  658. #if !CAREFUL
  659. __asm
  660. {
  661. mov eax,info // save info
  662. push ebx // save registers
  663. push ecx
  664. push edx
  665. push esi
  666. push edi
  667. push ebp
  668. #define PTR dword ptr [esp]
  669. #define DST_STOP dword ptr [esp+4*1]
  670. #define DST_CAREFUL dword ptr [esp+4*2]
  671. #define SRC_CAREFUL dword ptr [esp+4*3]
  672. #define SRC_END dword ptr [esp+4*4]
  673. #define SRC_END_1 dword ptr [esp+4*5]
  674. #define SRC_END_TAG dword ptr [esp+4*6]
  675. #define INFO dword ptr [esp+4*7]
  676. #define LOCALS 8
  677. sub esp,4*LOCALS // make room for locals
  678. mov edx,[eax].dst.stop
  679. mov DST_STOP,edx
  680. mov edx,[eax].dst.careful
  681. mov DST_CAREFUL,edx
  682. mov edx,[eax].src.careful
  683. mov SRC_CAREFUL,edx
  684. mov edx,[eax].src.end
  685. mov SRC_END,edx
  686. mov edx,[eax].src.end_1
  687. mov SRC_END_1,edx
  688. mov edx,[eax].src.end_tag
  689. mov SRC_END_TAG,edx
  690. xor edx,edx // ptr = 0
  691. mov PTR,edx
  692. mov INFO,eax
  693. mov edx,[eax].dst.beg
  694. mov ebp,edx
  695. mov edi,[eax].dst.beg
  696. mov ebx,[eax].src.beg
  697. xor eax,eax // bmask = 0
  698. jmp start
  699. #endif /* !CAREFUL */
  700. align 16
  701. LABEL (literal_1):
  702. mov [edi-1],cl
  703. LABEL (literal):
  704. #if CAREFUL
  705. cmp edi,DST_STOP
  706. jae ret_ok // recoded everything?
  707. cmp ebx,SRC_END
  708. jae ret_err
  709. #endif
  710. inc edi
  711. mov cl,[ebx] // copy next byte
  712. inc ebx
  713. add eax,eax // check most significant bit
  714. jnc LABEL (literal_1)
  715. mov [edi-1],cl
  716. jz LABEL (start) // need reloading?
  717. LABEL (pointer):
  718. #if CAREFUL
  719. cmp edi,DST_STOP // decoded all the stuff? -- done
  720. jae ret_ok_eof
  721. cmp ebx,SRC_END_1
  722. jae ret_err
  723. #endif
  724. xor edx,edx
  725. mov dx,[ebx]
  726. mov ecx,edx
  727. shr edx,DIRECT2_LEN_LOG
  728. add ebx,2
  729. not edx // edx = -offset
  730. and ecx,DIRECT2_MAX_LEN // ecx = length - MIN_LENGTH
  731. lea esi,[edi+edx]
  732. #if !CAREFUL && (8 - MIN_MATCH < DIRECT2_MAX_LEN)
  733. cmp cl,8 - MIN_MATCH // length > 8?
  734. ja LABEL (long_length)
  735. cmp esi,ebp // output buffer underrun?
  736. jb ret_err
  737. cmp edx,-3
  738. mov edx,[esi]
  739. jae LABEL (byte_by_byte)
  740. mov [edi],edx
  741. mov edx,[esi+4]
  742. mov [edi+4],edx
  743. lea edi,[edi+ecx+MIN_MATCH]
  744. add eax,eax
  745. jnc LABEL (literal)
  746. jnz LABEL (pointer)
  747. jmp LABEL (start)
  748. LABEL (byte_by_byte):
  749. add ecx,MIN_MATCH
  750. rep movsb
  751. add eax,eax
  752. jnc LABEL (literal)
  753. jnz LABEL (pointer)
  754. jmp LABEL (start)
  755. LABEL (long_length):
  756. #endif /* !CAREFUL && (8 - MIN_MATCH < DIRECT2_MAX_LEN) */
  757. cmp esi,ebp // output buffer underrun?
  758. jb ret_err
  759. mov edx,PTR
  760. cmp cl,DIRECT2_MAX_LEN
  761. jne LABEL (done_len)
  762. test edx,edx
  763. je LABEL (ptr_zero)
  764. xor ecx,ecx
  765. mov cl,[edx]
  766. xor edx,edx
  767. shr ecx,4
  768. jmp LABEL(done_quad)
  769. LABEL (ptr_zero):
  770. #if CAREFUL
  771. cmp ebx,SRC_END
  772. jae ret_err
  773. #endif
  774. xor ecx,ecx
  775. mov cl,[ebx]
  776. mov edx,ebx
  777. and ecx,15
  778. inc ebx
  779. LABEL(done_quad):
  780. mov PTR,edx
  781. cmp cl,15
  782. lea ecx,[ecx+DIRECT2_MAX_LEN]
  783. je LABEL(len255)
  784. LABEL(done_len):
  785. lea edx,[edi+ecx+MIN_MATCH] // edx = end of copy
  786. add ecx,MIN_MATCH
  787. #if !CAREFUL
  788. cmp edx,DST_CAREFUL // too close to end of buffer?
  789. jae careful_copy_tail
  790. #else
  791. careful_copy_tail:
  792. cmp edx,DST_STOP // ahead of output buffer?
  793. jbe LABEL (checked_eob)
  794. mov ecx,DST_STOP
  795. sub ecx,edi // ecx = corrected length
  796. rep movsb // copy substring
  797. jmp ret_ok // no errors, no EOF mark
  798. LABEL (checked_eob):
  799. #endif
  800. rep movsb // copy substring
  801. add eax,eax
  802. jnc LABEL (literal)
  803. jnz LABEL (pointer)
  804. align 16
  805. LABEL (start):
  806. #if !CAREFUL
  807. cmp ebx,SRC_CAREFUL // too close to end of buffer(s)?
  808. jae careful_start // be careful if so
  809. cmp edi,DST_CAREFUL
  810. jae careful_start
  811. #else
  812. cmp ebx,SRC_END_TAG // input buffer overrun? -- corrupted data
  813. jae ret_err
  814. #endif
  815. mov eax,[ebx]
  816. add ebx,4
  817. test eax,eax
  818. lea eax,[eax+eax+1]
  819. jns LABEL (literal)
  820. jmp LABEL (pointer)
  821. LABEL(len255):
  822. #if CAREFUL
  823. cmp ebx,SRC_END
  824. jae ret_err
  825. #endif
  826. xor ecx,ecx
  827. mov cl,[ebx]
  828. inc ebx
  829. cmp cl,255
  830. lea ecx,[ecx+15+DIRECT2_MAX_LEN]
  831. jne LABEL(done_len)
  832. #if CAREFUL
  833. cmp ebx,SRC_END_1
  834. jae ret_err
  835. #endif
  836. xor ecx,ecx
  837. mov cx,[ebx]
  838. add ebx,2
  839. cmp ecx,255 + 15 + DIRECT2_MAX_LEN
  840. jae LABEL (done_len)
  841. #if CAREFUL
  842. ret_err:
  843. xor eax,eax
  844. jmp ret_common
  845. ret_ok_eof:
  846. mov ebx,INFO
  847. mov eax,1
  848. cmp edi,[ebx].dst.end
  849. jne ret_ok
  850. mov [ebx].eof,eax
  851. ret_ok:
  852. mov eax,1
  853. mov ebx,INFO
  854. mov [ebx].src.last,ebx
  855. mov [ebx].dst.last,edi
  856. ret_common:
  857. MOV ebx,INFO
  858. mov [ebx].result,eax
  859. add esp,4*LOCALS
  860. pop ebp
  861. pop edi
  862. pop esi
  863. pop edx
  864. pop ecx
  865. pop ebx
  866. } /* __asm */
  867. #endif /* CAREFUL */
  868. #endif /* i386 */
  869. #endif /* ----------------- CODING == CODING_DIRECT2 --------------- */
  870. /* --------------------------- End of code ------------------------- */
  871. /* ----------- */
  872. #if CAREFUL
  873. } /* end of "do_decode" */
  874. #endif /* CAREFUL */
  875. #undef CAREFUL
  876. #undef LABEL
  877. #undef CAREFUL_LABEL
  878. #undef CAREFUL_OK_IF
  879. #undef CAREFUL_ERR_IF
  880. #undef CAREFUL_EOF_IF
  881. #undef CAREFUL_IF
  882. #undef START
  883. #undef FAST_COPY_DONE