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.

1755 lines
38 KiB

  1. /* ------------------------------------------------------------------------ */
  2. /* */
  3. /* Copyright (c) Microsoft Corporation, 2000-2002. All rights reserved. */
  4. /* Copyright (c) Andrew Kadatch, 1991-2002. All rights reserved. */
  5. /* */
  6. /* Microsoft Confidential -- do not redistribute. */
  7. /* */
  8. /* ------------------------------------------------------------------------ */
  9. #include "xprs.h"
  10. #define MAX_CHAIN 9
  11. #define FILL_NULL 0 // fill q_hash buffer with NULLs or with &orig[0]
  12. // Zobrist hashing
  13. #define Z_HASH_SIZE_LOG (BUFF_SIZE_LOG - 1)
  14. #define Z_HASH_SIZE (1 << Z_HASH_SIZE_LOG)
  15. #define Z_HASH_SUM(b) (z_hash_map[0][b[0]] ^ z_hash_map[1][b[1]] ^ z_hash_map[2][b[2]])
  16. // quick hashing
  17. #define Q_HASH_SH1 3
  18. #define Q_HASH_SH2 (Q_HASH_SH1 >> 1)
  19. #define Q_HASH_SUM3(c1,c2,c3) (((c1) << Q_HASH_SH1) + ((c2) << Q_HASH_SH2) + (c3))
  20. #define Q_HASH_SUM(b) Q_HASH_SUM3 (b[0], b[1], b[2])
  21. #define Q_HASH_SIZE (Q_HASH_SUM3 (255, 255, 255) + 1)
  22. #define z_hash_t uint16
  23. #define z_index_t uint16
  24. #if CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  25. typedef struct huff_node_t huff_node;
  26. struct huff_node_t
  27. {
  28. huff_node *son[2];
  29. uxint freq;
  30. uint16 ch;
  31. uint16 bits;
  32. };
  33. typedef struct
  34. {
  35. huff_node buff[2 * HUFF_SIZE], *head[256], **link[256];
  36. } huff_info;
  37. #endif
  38. typedef struct
  39. {
  40. struct
  41. {
  42. #if CODING == CODING_BY_BIT
  43. xint bits;
  44. uchar *ptr;
  45. #elif CODING & (CODING_DIRECT | CODING_DIRECT2)
  46. uchar *ptr;
  47. #elif CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  48. uxint freq[HUFF_SIZE];
  49. uxint mask[HUFF_SIZE];
  50. uchar bits[HUFF_SIZE];
  51. huff_info info;
  52. uxint pointers;
  53. uxint extra;
  54. uxint masks;
  55. #endif /* CODING */
  56. } stat;
  57. xint chain;
  58. xint max_size;
  59. struct
  60. {
  61. uchar *beg;
  62. uchar *ptr;
  63. } comp;
  64. struct
  65. {
  66. uchar *beg;
  67. uchar *ptr;
  68. uchar *tag_ptr;
  69. tag_t tag_mask;
  70. xint chain;
  71. } temp;
  72. struct
  73. {
  74. xint len;
  75. xint pos;
  76. } match;
  77. struct
  78. {
  79. xint pos;
  80. xint size;
  81. xint stop;
  82. xint progress;
  83. const uchar *ptr;
  84. const uchar *end;
  85. const uchar *end_16;
  86. const uchar *end_3;
  87. const uchar *ptr_stop;
  88. } orig;
  89. } context;
  90. #define v p[-1].c
  91. typedef struct
  92. {
  93. union
  94. {
  95. z_index_t z_hash[Z_HASH_SIZE];
  96. z_index_t z_next[16];
  97. const uchar *q_last[16];
  98. } x;
  99. context c;
  100. } prs;
  101. #define MAGIC_ENCODE 0x53E7C0DE
  102. typedef struct
  103. {
  104. int magic;
  105. void *memory;
  106. prs *p;
  107. uchar *temp;
  108. unsigned max_size;
  109. int chain;
  110. int max_chain;
  111. } xpress_info;
  112. #if MAX_CHAIN >= 1
  113. static z_hash_t z_hash_map[MIN_MATCH][256];
  114. static int z_hash_map_initialized = 0;
  115. static void z_hash_map_init (void)
  116. {
  117. long v1, v2;
  118. z_hash_t *m;
  119. if (z_hash_map_initialized)
  120. return;
  121. v1 = 0x13579bdfL; v2 = 0x87654321L;
  122. for (m = z_hash_map[0]; m < z_hash_map[0] + sizeof (z_hash_map) / sizeof (z_hash_map[0][0]); ++m)
  123. {
  124. long vv1 = v2, vv2 = v1, d = 0;
  125. xint i = 32;
  126. do
  127. {
  128. d += 0x9e3779b9L; vv1 += d; vv2 += d;
  129. v1 += ((v2<<3) + vv1) ^ (v2 + d) ^ ((v2>>5) + vv2);
  130. v2 += ((v1<<3) + vv2) ^ (v1 + d) ^ ((v1>>5) + vv1);
  131. --i;
  132. }
  133. while (i);
  134. *m = (z_hash_t) ((v1 += v2) & (Z_HASH_SIZE - 1));
  135. }
  136. z_hash_map_initialized = 1;
  137. }
  138. static void z_hash_insert (prs *p)
  139. {
  140. const uchar *b, *e;
  141. xint n, h;
  142. e = v.orig.end - (MIN_MATCH-1);
  143. b = v.orig.ptr;
  144. n = 0;
  145. for (; b < e; ++b, ++n)
  146. {
  147. h = Z_HASH_SUM (b);
  148. p->x.z_next[n] = p[-1].x.z_hash[h];
  149. p[-1].x.z_hash[h] = (z_index_t) n;
  150. }
  151. e += MIN_MATCH-1;
  152. for (; b < e; ++b, ++n)
  153. p->x.z_next[n] = 0;
  154. }
  155. #endif
  156. #if CODING != CODING_BY_BIT
  157. static void tag_write_start (prs *p)
  158. {
  159. v.temp.tag_ptr = v.temp.ptr;
  160. v.temp.ptr += sizeof (v.temp.tag_mask);
  161. v.temp.tag_mask = 1;
  162. }
  163. #if CODING == CODING_HUFF_ALL
  164. #define INC_MASKS ++v.stat.masks
  165. #else
  166. #define INC_MASKS
  167. #endif
  168. #define tag_write(p,ptr,n) \
  169. { \
  170. tag_t __n = n | (v.temp.tag_mask << 1); \
  171. if (v.temp.tag_mask < 0) \
  172. { \
  173. *(__unaligned tag_t *) v.temp.tag_ptr = __n; \
  174. v.temp.tag_ptr = ptr; \
  175. ptr += sizeof (v.temp.tag_mask); \
  176. INC_MASKS; \
  177. __n = 1; \
  178. } \
  179. v.temp.tag_mask = __n; \
  180. }
  181. static void tag_write_finish (prs *p)
  182. {
  183. uchar *ptr = v.temp.ptr;
  184. do
  185. {
  186. tag_write (p, ptr, 1);
  187. }
  188. while (ptr == v.temp.ptr);
  189. }
  190. #elif CODING == CODING_BY_BIT
  191. static void tag_write_start (prs *p)
  192. {
  193. v.temp.tag_ptr = (uchar *) &v.temp.tag_mask;
  194. v.temp.tag_mask = 0;
  195. v.stat.bits = 0;
  196. }
  197. #define tag_write(p,ptr,n) do { \
  198. if (--v.stat.bits < 0) \
  199. { \
  200. *(__unaligned tag_t *)v.temp.tag_ptr = v.temp.tag_mask; \
  201. v.temp.tag_mask = n; \
  202. v.stat.bits = 8 * sizeof (v.temp.tag_mask) - 1; \
  203. v.temp.tag_ptr = ptr; \
  204. ptr += sizeof (v.temp.tag_mask); \
  205. } \
  206. v.temp.tag_mask = (v.temp.tag_mask << 1) + (n); \
  207. } while (0)
  208. #define tag_write_mask(p,ptr,n,b) do { \
  209. if ((v.stat.bits -= (b)) < 0) \
  210. { \
  211. *(__unaligned tag_t *)v.temp.tag_ptr = (v.temp.tag_mask << ((b) + v.stat.bits)) \
  212. + ((n) >> (-v.stat.bits)); \
  213. v.stat.bits += 8 * sizeof (v.temp.tag_mask); \
  214. v.temp.tag_mask = (n); \
  215. v.temp.tag_ptr = ptr; \
  216. ptr += sizeof (v.temp.tag_mask); \
  217. } \
  218. else \
  219. v.temp.tag_mask = (v.temp.tag_mask << (b)) + (n); \
  220. } while (0);
  221. static void tag_write_finish (prs *p)
  222. {
  223. do
  224. tag_write (p, v.temp.ptr, 1);
  225. while (v.stat.bits != 0);
  226. *(__unaligned tag_t *)v.temp.tag_ptr = v.temp.tag_mask;
  227. }
  228. #define write_lit(p,ptr,ch) do { \
  229. tag_write (p, ptr, 0); \
  230. *ptr++ = (ch); \
  231. } while (0)
  232. INLINE uchar *write_ptr (prs *p, uchar *ptr, xint offset, xint length)
  233. {
  234. uxint k;
  235. --offset;
  236. k = 2;
  237. if (offset > 255) k = 3;
  238. tag_write_mask (p, ptr, k, 2);
  239. *ptr++ = (uchar) offset;
  240. if (offset > 255) *ptr++ = (uchar) (offset >>= 8);
  241. if (length <= 8)
  242. {
  243. length -= MIN_MATCH - 1;
  244. tag_write_mask (p, ptr, 1, length);
  245. }
  246. else
  247. {
  248. tag_write_mask (p, ptr, 0, (9 - MIN_MATCH));
  249. if ((length -= 9) < 15)
  250. {
  251. if (v.stat.ptr == 0)
  252. {
  253. v.stat.ptr = ptr;
  254. *ptr++ = (uchar) length;
  255. }
  256. else
  257. {
  258. v.stat.ptr[0] |= length << 4;
  259. v.stat.ptr = 0;
  260. }
  261. }
  262. else
  263. {
  264. length -= 15;
  265. if (v.stat.ptr == 0)
  266. {
  267. v.stat.ptr = ptr;
  268. *ptr++ = 15;
  269. }
  270. else
  271. {
  272. v.stat.ptr[0] += 0xf0;
  273. v.stat.ptr = 0;
  274. }
  275. *ptr++ = (uchar) length;
  276. if (length >= 255)
  277. {
  278. ptr[-1] = 255;
  279. ptr[0] = (uchar) length;
  280. ptr[1] = (uchar) (length >>= 8);
  281. ptr += 2;
  282. }
  283. }
  284. }
  285. return (ptr);
  286. }
  287. #endif
  288. #if CODING & (CODING_DIRECT | CODING_DIRECT2)
  289. #define write_lit(p,ptr,ch) do { \
  290. *ptr++ = (ch); \
  291. tag_write (p, ptr, 0); \
  292. } while (0)
  293. #ifndef i386
  294. INLINE uchar *write_ptr (prs *p, uchar *ptr, int offset, int length)
  295. {
  296. length -= MIN_MATCH;
  297. --offset;
  298. #if CODING == CODING_DIRECT2
  299. offset <<= DIRECT2_LEN_LOG;
  300. if (length < DIRECT2_MAX_LEN)
  301. {
  302. offset |= length;
  303. ptr[0] = (uchar) offset;
  304. ptr[1] = (uchar) (offset >>= 8);
  305. ptr += 2;
  306. }
  307. else
  308. {
  309. offset |= DIRECT2_MAX_LEN;
  310. length -= DIRECT2_MAX_LEN;
  311. ptr[0] = (uchar) offset;
  312. ptr[1] = (uchar) (offset >>= 8);
  313. ptr += 2;
  314. if (v.stat.ptr == 0)
  315. {
  316. v.stat.ptr = ptr;
  317. *ptr++ = (uchar) (length < 15 ? length : 15);
  318. }
  319. else
  320. {
  321. v.stat.ptr[0] |= (uchar) ((length < 15 ? length : 15) << 4);
  322. v.stat.ptr = 0;
  323. }
  324. if ((length -= 15) >= 0)
  325. {
  326. *ptr++ = (uchar) length;
  327. if (length >= 255)
  328. {
  329. ptr[-1] = 255;
  330. length += DIRECT2_MAX_LEN + 15;
  331. ptr[0] = (uchar) length;
  332. ptr[1] = (uchar) (length >>= 8);
  333. ptr += 2;
  334. }
  335. }
  336. }
  337. #elif CODING == CODING_DIRECT
  338. if (v.stat.ptr == 0)
  339. {
  340. if (length < 7)
  341. {
  342. length <<= 5;
  343. v.stat.ptr = ptr;
  344. short_len:
  345. ptr[0] = (uchar) length;
  346. ptr[1] = (uchar) offset;
  347. ptr += 2;
  348. if (offset > 255)
  349. {
  350. ptr[0] = (uchar) (offset >>= 8);
  351. ptr[-2] = (uchar) (length += 16);
  352. ptr += 1;
  353. }
  354. }
  355. else if (length < 15 + 7)
  356. {
  357. length += (14 << 4) - 7;
  358. goto short_len;
  359. }
  360. else
  361. {
  362. if (offset > 255)
  363. ptr[0] = 0xff;
  364. else
  365. ptr[0] = 0xef;
  366. long_len:
  367. ptr[1] = (uchar) (length -= (7 + 15));
  368. ptr += 2;
  369. if (length >= 255)
  370. {
  371. length += 7 + 15;
  372. ptr[-1] = 255;
  373. ptr[0] = (uchar) (length);
  374. ptr[1] = (uchar) (length >>= 8);
  375. ptr += 2;
  376. }
  377. *ptr++ = (uchar) offset;
  378. if (offset > 255)
  379. *ptr++ = (uchar) (offset >>= 8);
  380. }
  381. }
  382. else
  383. {
  384. if (length < 7)
  385. {
  386. length |= v.stat.ptr[0];
  387. *ptr++ = (uchar) offset;
  388. if (offset > 255)
  389. {
  390. *ptr++ = (uchar) (offset >>= 8);
  391. length |= 8;
  392. }
  393. v.stat.ptr[0] = (uchar) length;
  394. v.stat.ptr = 0;
  395. }
  396. else if (length < 15 + 7)
  397. {
  398. length -= 7;
  399. ptr[1] = (uchar) offset;
  400. ptr[0] = (uchar) (length <<= 4);
  401. if (offset > 255)
  402. {
  403. v.stat.ptr[0] |= 15;
  404. v.stat.ptr = ptr;
  405. ptr[2] = (uchar) (offset >>= 8);
  406. ptr += 3;
  407. }
  408. else
  409. {
  410. v.stat.ptr[0] |= 7;
  411. v.stat.ptr = ptr;
  412. ptr += 2;
  413. }
  414. }
  415. else
  416. {
  417. if (offset > 255)
  418. v.stat.ptr[0] |= 15;
  419. else
  420. v.stat.ptr[0] |= 7;
  421. v.stat.ptr = ptr;
  422. ptr[0] = 15 << 4;
  423. goto long_len;
  424. }
  425. }
  426. #endif /* CODING */
  427. tag_write (p, ptr, 1);
  428. return (ptr);
  429. }
  430. #endif /* i386 */
  431. #elif CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  432. #if CODING == CODING_HUFF_ALL
  433. #define write_lit(p,ptr,ch) do { \
  434. ++v.stat.freq[*ptr++ = (ch)]; \
  435. tag_write (p, ptr, 0); \
  436. } while (0)
  437. #else
  438. #define write_lit(p,ptr,ch) do { \
  439. *ptr++ = (ch); \
  440. tag_write (p, ptr, 0); \
  441. } while (0)
  442. #endif
  443. #define BIOWR(mask,bits) { \
  444. assert (((mask) >> (bits)) == 0); \
  445. if ((Bits -= (bits)) < 0) \
  446. { \
  447. *(__unaligned bitmask2 *)Ptr1 = (bitmask2) ((Mask << (Bits + (bits))) \
  448. + ((mask) >> (-Bits))); \
  449. Mask = (mask); \
  450. Bits += sizeof (ubitmask2) * 8; \
  451. Ptr1 = Ptr2; \
  452. Ptr2 = (ubitmask2 *) ptr; \
  453. ptr += sizeof (ubitmask2); \
  454. } \
  455. else \
  456. Mask = (Mask << (bits)) + (mask); \
  457. }
  458. #if CODING == CODING_HUFF_LEN
  459. INLINE uchar *write_ptr (prs *p, uchar *ptr, int offset, int length)
  460. {
  461. xint k;
  462. ++v.stat.pointers;
  463. length -= MIN_MATCH;
  464. --offset;
  465. k = 0; if (offset > 255) k = 1;
  466. if (length < MAX_LENGTH - 1)
  467. ++v.stat.freq[*ptr++ = (uchar) (k |= length << 1)];
  468. else
  469. {
  470. length -= MAX_LENGTH - 1;
  471. ++v.stat.freq[ptr[0] = (uchar) (k |= (MAX_LENGTH - 1) << 1)];
  472. ptr[1] = (uchar) length;
  473. ptr += 2;
  474. if (length >= 255)
  475. {
  476. ptr[-1] = 255;
  477. length += MAX_LENGTH - 1;
  478. ptr[0] = (uchar) length;
  479. ptr[1] = (uchar) (length >>= 8);
  480. ptr += 2;
  481. }
  482. }
  483. *ptr++ = (uchar) offset;
  484. if (offset > 255)
  485. *ptr++ = (uchar) (offset >>= 8);
  486. tag_write (p, ptr, 1);
  487. return (ptr);
  488. }
  489. static void encode_pass2 (prs *p)
  490. {
  491. xint Bits;
  492. ubitmask4 Mask;
  493. ubitmask2 *Ptr1, *Ptr2;
  494. tag_t bmask;
  495. uchar *src = v.temp.beg;
  496. uchar *ptr = v.comp.ptr;
  497. uxint k;
  498. Ptr1 = (ubitmask2 *) ptr; ptr += sizeof (ubitmask2);
  499. Ptr2 = (ubitmask2 *) ptr; ptr += sizeof (ubitmask2);
  500. Mask = 0;
  501. Bits = 8 * sizeof (ubitmask2);
  502. bmask = 0;
  503. goto start;
  504. next:
  505. if (bmask >= 0)
  506. {
  507. bmask <<= 1;
  508. copy_byte:
  509. *ptr++ = *src++;
  510. goto next;
  511. }
  512. if ((bmask <<= 1) == 0)
  513. {
  514. start:
  515. *(__unaligned tag_t *)ptr = bmask = *(__unaligned tag_t *)src;
  516. src += sizeof (tag_t);
  517. ptr += sizeof (tag_t);
  518. if (bmask >= 0)
  519. {
  520. bmask = (bmask << 1) + 1;
  521. goto copy_byte;
  522. }
  523. bmask = (bmask << 1) + 1;
  524. }
  525. if (src >= v.temp.ptr)
  526. goto done;
  527. k = *src++;
  528. assert (k < HUFF_SIZE);
  529. BIOWR (v.stat.mask[k], v.stat.bits[k]);
  530. if (k >= ((MAX_LENGTH - 1) << 1))
  531. {
  532. if ((*ptr++ = *src++) == 255)
  533. {
  534. ptr[0] = src[0];
  535. ptr[1] = src[1];
  536. src += 2;
  537. ptr += 2;
  538. }
  539. }
  540. *ptr++ = *src++;
  541. if (k & 1) *ptr++ = *src++;
  542. goto next;
  543. done:
  544. *Ptr1 = (ubitmask2) (Mask <<= Bits);
  545. *Ptr2 = 0;
  546. v.comp.ptr = ptr;
  547. assert (src == v.temp.ptr);
  548. }
  549. #elif CODING & (CODING_HUFF_PTR | CODING_HUFF_ALL)
  550. #if CODING == CODING_HUFF_ALL
  551. #define CODING_ADJUST(n) (256 + (n))
  552. #else
  553. #define CODING_ADJUST(n) (n)
  554. #endif
  555. #if !defined (i386) || CODING != CODING_HUFF_ALL
  556. #define MAX_BITNO_LOG 8
  557. #define MAX_BITNO (1 << MAX_BITNO_LOG)
  558. static uchar bitno_table[MAX_BITNO];
  559. static int bitno_table_initialized = 0;
  560. static void bitno_init (void)
  561. {
  562. int i, k, n;
  563. if (bitno_table_initialized)
  564. return;
  565. bitno_table[0] = 255;
  566. for (i = 0; i < MAX_BITNO_LOG; ++i)
  567. {
  568. for (n = (k = 1<<i) << 1; k < n; ++k)
  569. bitno_table[k] = (uchar) i;
  570. }
  571. bitno_table_initialized = 1;
  572. }
  573. static int bitno (uxint n)
  574. {
  575. assert (n != 0 && (n >> (MAX_BITNO_LOG*2)) == 0);
  576. if (n >= MAX_BITNO)
  577. return (bitno_table[n >> MAX_BITNO_LOG] + MAX_BITNO_LOG);
  578. return (bitno_table[n]);
  579. }
  580. INLINE uchar *write_ptr (prs *p, uchar *ptr, int offset, int length)
  581. {
  582. xint k;
  583. k = bitno (offset);
  584. length -= MIN_MATCH;
  585. offset ^= 1 << k;
  586. v.stat.pointers += 2;
  587. v.stat.extra += k;
  588. k <<= MAX_LENGTH_LOG;
  589. if (length < MAX_LENGTH - 1)
  590. {
  591. k |= length;
  592. *ptr++ = (uchar) k;
  593. ++v.stat.freq[CODING_ADJUST (k)];
  594. }
  595. else
  596. {
  597. k |= MAX_LENGTH - 1;
  598. length -= MAX_LENGTH - 1;
  599. ptr[0] = (uchar) k;
  600. ++v.stat.freq[CODING_ADJUST (k)];
  601. ptr[1] = (uchar) length;
  602. ptr += 2;
  603. if (length >= 255)
  604. {
  605. length += MAX_LENGTH - 1;
  606. ptr[-1] = 255;
  607. ptr[0] = (uchar) length;
  608. ptr[1] = (uchar) (length >>= 8);
  609. ptr += 2;
  610. }
  611. }
  612. *ptr++ = (uchar) offset;
  613. if (k >= (9 << MAX_LENGTH_LOG))
  614. {
  615. v.stat.pointers += 1;
  616. *ptr++ = (uchar) (offset >>= 8);
  617. }
  618. tag_write (p, ptr, 1);
  619. return (ptr);
  620. }
  621. static void encode_pass2 (prs *p)
  622. {
  623. xint Bits;
  624. uxint Mask;
  625. ubitmask2 *Ptr1, *Ptr2;
  626. tag_t bmask;
  627. uchar *src = v.temp.beg;
  628. uchar *ptr = v.comp.ptr;
  629. uxint k;
  630. Ptr1 = (ubitmask2 *) ptr; ptr += sizeof (ubitmask2);
  631. Ptr2 = (ubitmask2 *) ptr; ptr += sizeof (ubitmask2);
  632. Mask = 0;
  633. Bits = 8 * sizeof (ubitmask2);
  634. bmask = 0;
  635. goto start;
  636. next:
  637. if (bmask >= 0)
  638. {
  639. bmask <<= 1;
  640. copy_byte:
  641. #if CODING == CODING_HUFF_ALL
  642. k = *src++;
  643. BIOWR (v.stat.mask[k], v.stat.bits[k]);
  644. #elif CODING == CODING_HUFF_PTR
  645. *ptr++ = *src++;
  646. #endif
  647. goto next;
  648. }
  649. if ((bmask <<= 1) == 0)
  650. {
  651. start:
  652. bmask = *(__unaligned tag_t *)src;
  653. src += sizeof (tag_t);
  654. #if CODING == CODING_HUFF_PTR
  655. *(__unaligned tag_t *)ptr = bmask;
  656. ptr += sizeof (tag_t);
  657. #endif
  658. if (bmask >= 0)
  659. {
  660. bmask = (bmask << 1) + 1;
  661. goto copy_byte;
  662. }
  663. bmask = (bmask << 1) + 1;
  664. }
  665. if (src >= v.temp.ptr)
  666. goto done;
  667. k = *src++;
  668. assert (k < HUFF_SIZE);
  669. BIOWR (v.stat.mask[CODING_ADJUST (k)], v.stat.bits[CODING_ADJUST (k)]);
  670. if ((k & (MAX_LENGTH - 1)) == MAX_LENGTH - 1)
  671. {
  672. if ((*ptr++ = *src++) == 255)
  673. {
  674. ptr[0] = src[0];
  675. ptr[1] = src[1];
  676. src += 2;
  677. ptr += 2;
  678. }
  679. }
  680. k >>= MAX_LENGTH_LOG;
  681. {
  682. uxint m = *src++;
  683. if (k > 8)
  684. m += *src++ << 8;
  685. BIOWR (m, k);
  686. }
  687. goto next;
  688. done:
  689. #if CODING == CODING_HUFF_ALL
  690. BIOWR (v.stat.mask[CODING_ADJUST(0)], v.stat.bits[CODING_ADJUST(0)]);
  691. #endif
  692. *(__unaligned bitmask2 *)Ptr1 = (ubitmask2) (Mask <<= Bits);
  693. *(__unaligned bitmask2 *)Ptr2 = 0;
  694. v.comp.ptr = ptr;
  695. assert (src == v.temp.ptr);
  696. }
  697. #else /* !defined (i386) || CODING != CODING_HUFF_ALL */
  698. #define TEMP eax
  699. #define TEMPB al
  700. #define PRS ebx
  701. #define V [PRS - SIZE prs] prs.c
  702. #define TAG edx
  703. #define TAGW dx
  704. #define TAGB dl
  705. #define PTR1 edi
  706. #define SRC esi
  707. #define MASK ebp
  708. #define MASKW bp
  709. #define PTR esp
  710. #define PTR2 esp + 4
  711. #define TAGS esp + 8
  712. static void encode_pass2 (prs *PrsPtr)
  713. {
  714. __asm
  715. {
  716. push ebp
  717. sub esp, 12
  718. /*
  719. uchar *src = v.temp.beg;
  720. uchar *ptr = v.comp.ptr;
  721. Ptr1 = (ubitmask2 *) ptr; ptr += sizeof (ubitmask2);
  722. Ptr2 = (ubitmask2 *) ptr; ptr += sizeof (ubitmask2);
  723. */
  724. mov PRS, PrsPtr
  725. mov PTR1, V.comp.ptr
  726. mov SRC, V.temp.beg
  727. lea TEMP, [PTR1 + 2]
  728. mov [PTR2], TEMP
  729. add TEMP, 2
  730. mov [PTR], TEMP
  731. /*
  732. Mask = 0;
  733. Bits = 8 * sizeof (ubitmask2);
  734. bmask = 0;
  735. */
  736. xor MASK, MASK
  737. mov ch, 16
  738. xor TAG, TAG
  739. jmp ReloadTag
  740. Literal:
  741. /*
  742. k = *src++;
  743. BIOWR (v.stat.mask[k], v.stat.bits[k]);
  744. */
  745. mov TEMP, V.stat.mask[TEMP*4]
  746. shl MASK, cl
  747. inc SRC
  748. add MASK, TEMP
  749. sub ch, cl
  750. jge BiowrDone_Literal
  751. mov cl, ch
  752. add ch, 16
  753. mov TEMP, [PTR]
  754. rol MASK, cl // attention! 286+ masks shift cound mod 32
  755. mov [PTR1], MASKW
  756. mov PTR1, [PTR2]
  757. ror MASK, cl
  758. mov [PTR2], TEMP
  759. add TEMP, 2
  760. mov [PTR], TEMP
  761. BiowrDone_Literal:
  762. movzx TEMP, byte ptr [SRC]
  763. add TAG, TAG
  764. mov cl, V.stat.bits[TEMP]
  765. jnc Literal
  766. jz ReloadTag
  767. Pointer:
  768. /*
  769. if (src >= v.temp.ptr)
  770. goto done;
  771. */
  772. mov cl, V.stat.bits[TEMP + 256]
  773. mov [TAGS], TAG
  774. cmp SRC, V.temp.ptr
  775. jae Done
  776. /*
  777. k = *src++;
  778. assert (k < HUFF_SIZE);
  779. BIOWR (v.stat.mask[CODING_ADJUST (k)], v.stat.bits[CODING_ADJUST (k)]);
  780. */
  781. shl MASK, cl
  782. mov TAGB, TEMPB
  783. add MASK, V.stat.mask[TEMP*4 + 256*4]
  784. mov TEMP, [PTR]
  785. sub ch, cl
  786. jge BiowrDone_Pointer
  787. mov cl, ch
  788. add ch, 16
  789. rol MASK, cl // attention! 286+ masks shift cound mod 32
  790. mov [PTR1], MASKW
  791. mov PTR1, [PTR2]
  792. ror MASK, cl
  793. mov [PTR2], TEMP
  794. add TEMP, 2
  795. BiowrDone_Pointer:
  796. mov cl, TAGB // release TEMP for LongLength
  797. and TAGB, MAX_LENGTH-1
  798. shr cl, MAX_LENGTH_LOG
  799. /*
  800. if ((k & (MAX_LENGTH - 1)) == MAX_LENGTH - 1)
  801. {
  802. if ((*ptr++ = *src++) == 255)
  803. {
  804. ptr[0] = src[0];
  805. ptr[1] = src[1];
  806. src += 2;
  807. ptr += 2;
  808. }
  809. }
  810. */
  811. cmp TAGB, MAX_LENGTH-1
  812. je LongLength
  813. LengthWritten:
  814. /*
  815. k >>= MAX_LENGTH_LOG;
  816. {
  817. uxint m = src[1];
  818. if (k > 8)
  819. {
  820. m += src[2] << 8;
  821. ++src;
  822. }
  823. BIOWR (m, k);
  824. }
  825. src += 2;
  826. */
  827. movzx TAG, byte ptr [SRC + 1]
  828. shl MASK, cl
  829. cmp cl, 8
  830. jbe GotOffset
  831. movzx TAG, word ptr [SRC + 1]
  832. inc SRC
  833. GotOffset:
  834. add MASK, TAG
  835. sub ch, cl
  836. jge BiowrDone_Offset
  837. mov cl, ch
  838. add ch, 16
  839. rol MASK, cl // attention! 286+ masks shift cound mod 32
  840. mov [PTR1], MASKW
  841. mov PTR1, [PTR2]
  842. ror MASK, cl
  843. mov [PTR2], TEMP
  844. add TEMP, 2
  845. BiowrDone_Offset:
  846. mov TAG, [TAGS]
  847. add SRC, 2
  848. mov [PTR], TEMP
  849. movzx TEMP, byte ptr [SRC]
  850. add TAG, TAG
  851. mov cl, V.stat.bits[TEMP]
  852. jnc Literal
  853. jnz Pointer
  854. jmp ReloadTag
  855. align 16
  856. ReloadTag:
  857. mov TAG, [SRC]
  858. movzx TEMP, byte ptr [SRC + 4]
  859. add SRC, 4
  860. test TAG, TAG
  861. mov cl, V.stat.bits[TEMP]
  862. lea TAG, [TAG*2 + 1]
  863. jge Literal
  864. jmp Pointer
  865. /*
  866. if ((*ptr++ = *++src) == 255)
  867. {
  868. ptr[0] = src[1];
  869. ptr[1] = src[2];
  870. src += 2;
  871. ptr += 2;
  872. }
  873. */
  874. #if _MSC_VER >= 1300
  875. align 16 // workaround bug in VC 6.0 back end (incorrect jump offset generation)
  876. #endif /* _MSC_VER >= 1300 */
  877. LongLength:
  878. mov TAGB, [SRC + 1]
  879. inc SRC
  880. mov [TEMP], TAGB
  881. inc TEMP
  882. cmp TAGB, 255
  883. jne LengthWritten
  884. mov TAGW, [SRC + 1]
  885. add TEMP, 2
  886. add SRC, 2
  887. mov [TEMP-2], TAGW
  888. jmp LengthWritten
  889. Done:
  890. /*
  891. BIOWR (v.stat.mask[CODING_ADJUST(0)], v.stat.bits[CODING_ADJUST(0)]);
  892. */
  893. mov cl, V.stat.bits[256]
  894. mov TEMP, [PTR]
  895. shl MASK, cl
  896. mov TAG, [PTR2]
  897. add MASK, V.stat.mask[256*4]
  898. sub ch, cl
  899. jge LastMaskWritten
  900. mov cl, ch
  901. neg cl
  902. add ch, 16
  903. ror MASK, cl
  904. mov [PTR1], MASKW
  905. mov PTR1, TAG
  906. rol MASK, cl
  907. mov TAG, TEMP
  908. add TEMP, 2
  909. /*
  910. *(__unaligned bitmask2 *)Ptr1 = (ubitmask2) (Mask <<= Bits);
  911. *(__unaligned bitmask2 *)Ptr2 = 0;
  912. v.comp.ptr = ptr;
  913. */
  914. LastMaskWritten:
  915. mov cl, ch
  916. shl MASK, cl
  917. mov word ptr [PTR1], MASKW
  918. mov word ptr [TAG], 0
  919. mov V.comp.ptr, TEMP
  920. #if DEBUG
  921. /*
  922. assert (src == v.temp.ptr);
  923. */
  924. cmp V.temp.ptr, SRC
  925. je RetOK
  926. int 3
  927. RetOK:
  928. #endif
  929. add esp, 12
  930. pop ebp
  931. } /* __asm */
  932. }
  933. #undef TEMP
  934. #undef PRS
  935. #undef V
  936. #undef TAG
  937. #undef TAGW
  938. #undef TAGB
  939. #undef PTR1
  940. #undef SRC
  941. #undef MASK
  942. #undef MASKW
  943. #undef PTR
  944. #undef PTR2
  945. #undef TAGS
  946. #endif /* !defined (i386) || CODING != CODING_HUFF_ALL */
  947. #endif /* CODING & (CODING_HUFF_PTR | CODING_HUFF_ALL) */
  948. /* ------------------ Create canonical Huffman code ------------------- */
  949. /* ----------------------------- */
  950. #define MAX_ALPHABET HUFF_SIZE
  951. static void huffman_create_codes (huff_info *info, uxint *freq, xint n, uxint *mask, uchar *length, uxint maxbits, uchar *encoded, uxint *total)
  952. {
  953. huff_node
  954. *p, *q, *r,
  955. *first_sorted, *first_free;
  956. xint i, k;
  957. assert ((uxint) (n-1) <= (MAX_ALPHABET-1));
  958. /* honestly it is easy enough to create Huffman code in-place */
  959. /* but the use of explicit data structures makes code simpler */
  960. /* clean everything up */
  961. memset (length, 0, sizeof (length[0]) * n);
  962. memset (encoded, 0, (n + 1) >> 1);
  963. if (mask != 0 && mask != freq)
  964. memset (mask, 0, sizeof (mask[0]) * n);
  965. /* store frequencies */
  966. p = info->buff;
  967. for (i = 0; i < n; ++i)
  968. {
  969. if ((p->freq = freq[i]) != 0)
  970. {
  971. p->son[0] = p+1; p->son[1] = 0;
  972. p->ch = (uint16) i;
  973. ++p;
  974. }
  975. }
  976. /* handle simple case */
  977. *total = 0;
  978. if (p <= info->buff + 1)
  979. {
  980. if (p == info->buff) /* if no symbols do nothing */
  981. return;
  982. i = p[-1].ch; /* single symbol code */
  983. mask[i] = 0;
  984. encoded[i >> 1] = 0x11; /* two symbols has 1-bit length */
  985. return;
  986. }
  987. first_free = p; /* store location of first unused node */
  988. p[-1].son[0] = 0; /* terminate the list */
  989. /* radix sort the list by frequency */
  990. p = info->buff; /* head of the list */
  991. /* initialize */
  992. for (n = 0; n < 256; ++n)
  993. *(info->link[n] = info->head + n) = 0;
  994. for (i = 0; i < (BUFF_SIZE_LOG <= 16 ? 16 : 32); i += 8)
  995. {
  996. /* link node to the end of respective bucket */
  997. do
  998. {
  999. n = (p->freq >> i) & 0xff;
  1000. info->link[n][0] = p; info->link[n] = p->son;
  1001. }
  1002. while ((p = p->son[0]) != 0);
  1003. /* merge buckets into single list */
  1004. n = 0;
  1005. while (info->head[n] == 0) ++n;
  1006. p = info->head[n]; info->head[k = n] = 0;
  1007. while (++n < 256)
  1008. {
  1009. if (info->head[n] == 0) continue;
  1010. info->link[k][0] = info->head[n]; info->link[k] = info->head + k; info->head[n] = 0;
  1011. k = n;
  1012. }
  1013. info->link[k][0] = 0; info->link[k] = info->head + k;
  1014. }
  1015. first_sorted = p; /* store head of sorted symbol's list */
  1016. restart:
  1017. assert (p == first_sorted);
  1018. q = first_free;
  1019. r = q - 1;
  1020. while (p != 0 || q != r)
  1021. {
  1022. ++r;
  1023. /* select left subtree */
  1024. assert (q <= r && (p != 0 || q != r));
  1025. if (p == 0 || (q != r && p->freq > q->freq))
  1026. {
  1027. r->son[0] = q; r->freq = q->freq; ++q;
  1028. }
  1029. else
  1030. {
  1031. r->son[0] = p; r->freq = p->freq; p = p->son[0];
  1032. }
  1033. /* select right subtree */
  1034. assert (q <= r && (p != 0 || q != r));
  1035. if (p == 0 || (q != r && p->freq > q->freq))
  1036. {
  1037. r->son[1] = q; r->freq += q->freq; ++q;
  1038. }
  1039. else
  1040. {
  1041. r->son[1] = p; r->freq += p->freq; p = p->son[0];
  1042. }
  1043. }
  1044. /* evaluate codewords' length */
  1045. i = -1; /* stack pointer */
  1046. n = 0; /* current tree depth */
  1047. p = r; /* current subtree root */
  1048. for (;;)
  1049. {
  1050. while (p->son[1] != 0)
  1051. {
  1052. /* put right son into stack and set up its depth */
  1053. (info->head[++i] = p->son[1])->bits = (uint16) (++n);
  1054. (p = p->son[0])->bits = (uint16) n;
  1055. }
  1056. length[p->ch] = (uchar) n;
  1057. if (i < 0) break; /* nothing's in stack */
  1058. n = (p = info->head[i--])->bits;
  1059. }
  1060. p = first_sorted;
  1061. #if DEBUG
  1062. for (q = p; (r = q->son[0]) != 0; q = r)
  1063. assert (q->bits >= r->bits);
  1064. #endif
  1065. if (p->bits > maxbits)
  1066. {
  1067. assert (p == first_sorted);
  1068. q = p;
  1069. do
  1070. q->freq = (q->freq + 1) >> 1;
  1071. while ((q = q->son[0]) != 0);
  1072. goto restart;
  1073. }
  1074. /* now sort symbols in a stable way by increasing codeword length */
  1075. /* initialize */
  1076. memset (info->head, 0, sizeof (info->head[0]) * 32);
  1077. for (n = 0; n < 32; ++n)
  1078. info->link[n] = info->head + n;
  1079. /* link node to the end of respective bucket */
  1080. p = info->buff;
  1081. do
  1082. {
  1083. n = p->bits;
  1084. info->link[n][0] = p; info->link[n] = p->son;
  1085. }
  1086. while (++p != first_free);
  1087. /* merge buckets into single list */
  1088. n = 0;
  1089. while (info->head[n] == 0) ++n;
  1090. p = info->head[n]; k = n;
  1091. while (++n < 32)
  1092. {
  1093. if (info->head[n] == 0) continue;
  1094. info->link[k][0] = info->head[n];
  1095. k = n;
  1096. }
  1097. info->link[k][0] = 0;
  1098. #if DEBUG
  1099. for (q = p; (r = q->son[0]) != 0; q = r)
  1100. assert (r->bits > q->bits || (r->bits == q->bits && r->ch > q->ch));
  1101. #endif
  1102. /* set up code masks */
  1103. if (mask == freq)
  1104. memset (mask, 0, sizeof (mask[0]) * n);
  1105. n = 0; /* mask */
  1106. i = 1; /* bit length */
  1107. k = 1; /* first index */
  1108. do
  1109. {
  1110. /* sum a[i] * b[i] may be evaluated without multiplications */
  1111. /* using O(B) memory and O(N+B) time if 0 <= b[i] < B */
  1112. *total += freq[p->ch] * p->bits;
  1113. encoded[p->ch >> 1] |= p->bits << (p->ch & 1 ? 4 : 0);
  1114. mask[p->ch] = (n <<= p->bits - i);
  1115. i = p->bits;
  1116. ++n;
  1117. }
  1118. while ((p = p->son[0]) != 0);
  1119. }
  1120. #endif /* CODING */
  1121. #define CHAIN 0
  1122. #define encode_pass1 encode0_pass1
  1123. #include "xencode.i"
  1124. #if MAX_CHAIN >= 1
  1125. #define CHAIN 1
  1126. #define encode_pass1 encode1_pass1
  1127. #define find_match find_match1
  1128. #include "xencode.i"
  1129. #endif
  1130. #if MAX_CHAIN >= 2
  1131. #define CHAIN 2
  1132. #define encode_pass1 encode2_pass1
  1133. #define find_match find_match2
  1134. #include "xencode.i"
  1135. #endif
  1136. #if MAX_CHAIN >= 3
  1137. #define CHAIN 3
  1138. #define encode_pass1 encodeN_pass1
  1139. #define find_match find_matchN
  1140. #include "xencode.i"
  1141. #endif
  1142. typedef void encode_pass1_proc (prs *p);
  1143. static void encode_pass1_progress (
  1144. prs *p,
  1145. encode_pass1_proc *encode_pass1,
  1146. XpressProgressFn *ProgressFn, // NULL or progress callback
  1147. void *ProgressContext, // user-defined context that will be passed to ProgressFn
  1148. int ProgressSize // call ProgressFn each time ProgressSize bytes processed
  1149. )
  1150. {
  1151. xint stop;
  1152. if (ProgressFn == 0)
  1153. {
  1154. encode_pass1 (p);
  1155. return;
  1156. }
  1157. stop = v.orig.stop;
  1158. for (;;)
  1159. {
  1160. if (v.orig.pos - v.orig.progress >= ProgressSize)
  1161. {
  1162. #if CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  1163. ProgressFn (ProgressContext, v.orig.pos);
  1164. #else
  1165. ProgressFn (ProgressContext, (v.orig.pos * 15) >> 4);
  1166. #endif
  1167. v.orig.progress = v.orig.pos;
  1168. }
  1169. v.orig.stop = stop;
  1170. if (v.orig.pos >= stop)
  1171. break;
  1172. if (stop - v.orig.progress > ProgressSize)
  1173. v.orig.stop = v.orig.progress + ProgressSize;
  1174. assert (v.orig.stop > v.orig.pos);
  1175. v.orig.ptr_stop = v.orig.stop + v.orig.ptr;
  1176. encode_pass1 (p);
  1177. }
  1178. }
  1179. #if !FILL_NULL
  1180. static
  1181. void
  1182. MemoryFillPtr (
  1183. const void **p,
  1184. const void *d,
  1185. int n
  1186. )
  1187. {
  1188. const void **e;
  1189. while (n & 7)
  1190. {
  1191. *p++ = d;
  1192. if (--n == 0)
  1193. return;
  1194. }
  1195. e = p + n;
  1196. do
  1197. {
  1198. p[0] = d;
  1199. p[1] = d;
  1200. p[2] = d;
  1201. p[3] = d;
  1202. p[4] = d;
  1203. p[5] = d;
  1204. p[6] = d;
  1205. p[7] = d;
  1206. p += 8;
  1207. }
  1208. while (p != e);
  1209. }
  1210. #endif /* !FILL_NULL */
  1211. XPRESS_EXPORT
  1212. int
  1213. XPRESS_CALL
  1214. XpressEncodeEx
  1215. (
  1216. XpressEncodeStream stream,
  1217. void *comp,
  1218. int comp_size,
  1219. const void *orig,
  1220. int orig_size,
  1221. XpressProgressFn *ProgressFn, // NULL or progress callback
  1222. void *ProgressContext, // user-defined context that will be passed to ProgressFn
  1223. int ProgressSize, // call ProgressFn each time ProgressSize bytes processed
  1224. int CompressionLevel
  1225. )
  1226. {
  1227. #if CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  1228. uchar huff_buff [HUFF_SIZE >> 1];
  1229. uxint huff_total;
  1230. #endif
  1231. uxint c_size;
  1232. prs *p;
  1233. xpress_info *info = (xpress_info *) stream;
  1234. encode_pass1_proc *encode_pass1;
  1235. if (info == 0 || info->magic != MAGIC_ENCODE)
  1236. return (0);
  1237. if ((unsigned) (orig_size-1) > info->max_size
  1238. || orig_size <= MIN_SIZE
  1239. || comp_size < MIN_SIZE
  1240. || comp == 0
  1241. || orig == 0)
  1242. {
  1243. return (orig_size);
  1244. }
  1245. p = info->p;
  1246. memset (&v, 0, sizeof (v));
  1247. if (CompressionLevel < 0)
  1248. CompressionLevel = 0;
  1249. else if (CompressionLevel > info->max_chain)
  1250. CompressionLevel = info->max_chain;
  1251. v.chain = CompressionLevel;
  1252. v.orig.end = (v.orig.ptr = orig) + (v.orig.size = v.orig.stop = orig_size);
  1253. v.orig.end_16 = v.orig.end - 16;
  1254. v.orig.end_3 = v.orig.end - MIN_MATCH;
  1255. v.comp.ptr = v.comp.beg = comp;
  1256. v.orig.pos = 0;
  1257. v.temp.beg = v.temp.ptr = info->temp;
  1258. #if CODING & (CODING_HUFF_PTR | CODING_HUFF_ALL) && !defined (i386)
  1259. // check initialization of static tables (in case somebody messed up with DLLs)
  1260. if (!bitno_table_initialized)
  1261. bitno_init ();
  1262. #endif
  1263. encode_pass1 = encode0_pass1;
  1264. if (v.chain <= 0)
  1265. {
  1266. #if FILL_NULL
  1267. memset ((void *) (&p->x.q_last[0]), 0, Q_HASH_SIZE * sizeof (p->x.q_last[0]));
  1268. #else
  1269. MemoryFillPtr ((const void **) (&p->x.q_last[0]), orig, Q_HASH_SIZE);
  1270. #endif /* FILL_NULL */
  1271. }
  1272. #if MAX_CHAIN >= 1
  1273. else
  1274. {
  1275. // check initialization of static tables (in case somebody messed up with DLLs)
  1276. if (!z_hash_map_initialized)
  1277. z_hash_map_init ();
  1278. if (v.chain == 1)
  1279. {
  1280. encode_pass1 = encode1_pass1;
  1281. memset ((void *) (&p->x.z_next[0]), 0, Z_HASH_SIZE * sizeof (p->x.z_next[0]));
  1282. }
  1283. #if MAX_CHAIN >= 2
  1284. else
  1285. {
  1286. encode_pass1 = encode2_pass1;
  1287. #if MAX_CHAIN >= 3
  1288. if (v.chain >= 3)
  1289. encode_pass1 = encodeN_pass1;
  1290. #endif /* MAX_CHAIN >= 3 */
  1291. memset (p[-1].x.z_hash, 0, sizeof (p[-1].x.z_hash));
  1292. z_hash_insert (p);
  1293. #if 0
  1294. {
  1295. int n = 0x1653;
  1296. int i, k;
  1297. i = 0; k = n;
  1298. do
  1299. {
  1300. k = p->x.z_next[k];
  1301. printf ("%2d: 0x%04x 0x%04x\n", i, k, n - k);
  1302. ++i;
  1303. }
  1304. while (k != 0);
  1305. }
  1306. #endif
  1307. }
  1308. #endif /* MAX_CHAIN >= 2 */
  1309. }
  1310. #endif /* MAX_CHAIN >= 1 */
  1311. if (ProgressSize <= 0 || ProgressSize > orig_size)
  1312. ProgressSize = orig_size;
  1313. if (ProgressFn != 0)
  1314. ProgressFn (ProgressContext, v.orig.progress = 0);
  1315. #if CODING & (CODING_DIRECT | CODING_DIRECT2 | CODING_BY_BIT)
  1316. v.temp.beg = v.temp.ptr = v.comp.ptr;
  1317. tag_write_start (p);
  1318. for (;;)
  1319. {
  1320. xint rest = comp_size - (xint) (v.temp.ptr - v.comp.beg) - 2 * sizeof (tag_t);
  1321. rest -= (rest + 7) >> 3;
  1322. if (rest <= (xint) (2 * sizeof (tag_t) + 8))
  1323. goto no_compression;
  1324. if (v.orig.pos >= v.orig.size)
  1325. break;
  1326. v.orig.stop = v.orig.pos + rest;
  1327. if (v.orig.stop > v.orig.size - 8)
  1328. {
  1329. v.orig.stop = v.orig.size - 8;
  1330. if (v.orig.pos >= v.orig.stop)
  1331. break;
  1332. }
  1333. encode_pass1_progress (p, encode_pass1, ProgressFn, ProgressContext, ProgressSize);
  1334. }
  1335. #else
  1336. v.orig.stop -= 7;
  1337. tag_write_start (p);
  1338. encode_pass1_progress (p, encode_pass1, ProgressFn, ProgressContext, ProgressSize);
  1339. #endif
  1340. while (v.orig.pos < v.orig.size)
  1341. {
  1342. write_lit (p, v.temp.ptr, v.orig.ptr[v.orig.pos]);
  1343. ++v.orig.pos;
  1344. }
  1345. tag_write_finish (p);
  1346. #if CODING & (CODING_DIRECT | CODING_DIRECT2 | CODING_BY_BIT)
  1347. c_size = (xint) (v.temp.ptr - v.temp.beg);
  1348. #elif CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  1349. if (v.stat.pointers == 0)
  1350. goto no_compression;
  1351. #if CODING == CODING_HUFF_ALL
  1352. ++v.stat.freq[CODING_ADJUST(0)];
  1353. #endif
  1354. huffman_create_codes (
  1355. &v.stat.info,
  1356. v.stat.freq, HUFF_SIZE,
  1357. v.stat.mask, v.stat.bits, 15, huff_buff, &huff_total
  1358. );
  1359. c_size = huff_total;
  1360. #if CODING & (CODING_HUFF_PTR | CODING_HUFF_ALL)
  1361. c_size += v.stat.extra;
  1362. #endif
  1363. if (c_size == 0) c_size = 1;
  1364. c_size = (((c_size - 1) & ~(sizeof (bitmask2) * 8 - 1)) >> 3);
  1365. c_size += (int) (v.temp.ptr - v.temp.beg) - v.stat.pointers + 4 + sizeof (huff_buff);
  1366. #if CODING == CODING_HUFF_ALL
  1367. for (huff_total = 0; huff_total < 256; ++huff_total)
  1368. c_size -= v.stat.freq[huff_total];
  1369. c_size -= v.stat.masks * sizeof (tag_t);
  1370. #endif
  1371. #endif /* CODING */
  1372. if (c_size >= (uxint) comp_size)
  1373. {
  1374. no_compression:
  1375. comp_size = orig_size;
  1376. }
  1377. else
  1378. {
  1379. #if CODING & (CODING_HUFF_LEN | CODING_HUFF_PTR | CODING_HUFF_ALL)
  1380. memcpy (v.comp.ptr, huff_buff, sizeof (huff_buff));
  1381. v.comp.ptr += sizeof (huff_buff);
  1382. #if 0
  1383. printf ("c_size = %d, temp_size = %d\n", c_size, v.temp.ptr - v.temp.beg);
  1384. {
  1385. FILE *fd = fopen (
  1386. #ifdef i386
  1387. "a.bad"
  1388. #else
  1389. "c.bad"
  1390. #endif
  1391. , "wb");
  1392. if (fd != 0)
  1393. {
  1394. fwrite (v.temp.beg, v.temp.ptr - v.temp.beg, 1, fd);
  1395. fclose (fd);
  1396. }
  1397. }
  1398. #endif
  1399. encode_pass2 (p);
  1400. #elif CODING & (CODING_BY_BIT | CODING_DIRECT | CODING_DIRECT2)
  1401. v.comp.ptr += c_size;
  1402. #else
  1403. #error Unknown CODING
  1404. #endif
  1405. comp_size = (int) (v.comp.ptr - v.comp.beg);
  1406. #if DEBUG
  1407. if (c_size != (uxint) comp_size)
  1408. printf ("error: c_size = %d, comp_size = %d\n", c_size, comp_size);
  1409. #endif
  1410. }
  1411. if (ProgressFn != 0)
  1412. ProgressFn (ProgressContext, orig_size);
  1413. return (comp_size);
  1414. }
  1415. XPRESS_EXPORT
  1416. int
  1417. XPRESS_CALL
  1418. XpressEncode
  1419. (
  1420. XpressEncodeStream stream,
  1421. void *comp,
  1422. int comp_size,
  1423. const void *orig,
  1424. int orig_size,
  1425. XpressProgressFn *ProgressFn, // NULL or progress callback
  1426. void *ProgressContext, // user-defined context that will be passed to ProgressFn
  1427. int ProgressSize // call ProgressFn each time ProgressSize bytes processed
  1428. )
  1429. {
  1430. xpress_info *info = (xpress_info *) stream;
  1431. if (info == 0 || info->magic != MAGIC_ENCODE)
  1432. return (0);
  1433. return (XpressEncodeEx (
  1434. stream,
  1435. comp,
  1436. comp_size,
  1437. orig,
  1438. orig_size,
  1439. ProgressFn,
  1440. ProgressContext,
  1441. ProgressSize,
  1442. info->chain
  1443. ));
  1444. }
  1445. #define MEM_ALIGN 256
  1446. XPRESS_EXPORT
  1447. XpressEncodeStream
  1448. XPRESS_CALL
  1449. XpressEncodeCreate (
  1450. int max_orig_size,
  1451. void *context,
  1452. XpressAllocFn *AllocFn,
  1453. int chain
  1454. )
  1455. {
  1456. xpress_info *info;
  1457. prs *p;
  1458. uchar *b;
  1459. int temp_size;
  1460. int alloc_size;
  1461. int max_chain;
  1462. if (AllocFn == 0 || (unsigned) (max_orig_size-1) > (BUFF_SIZE-1))
  1463. return (0);
  1464. #if CODING & (CODING_DIRECT | CODING_DIRECT2 | CODING_BY_BIT)
  1465. temp_size = 0;
  1466. #else
  1467. temp_size = max_orig_size + ((max_orig_size + 7) >> 3);
  1468. #endif
  1469. alloc_size = sizeof (p->x.q_last[0]) * Q_HASH_SIZE;
  1470. #if MAX_CHAIN <= 0
  1471. max_chain = chain = 0;
  1472. #else
  1473. if (chain > MAX_CHAIN)
  1474. chain = MAX_CHAIN;
  1475. max_chain = chain;
  1476. if (chain >= 1)
  1477. {
  1478. alloc_size = sizeof (p->x.z_next[0]) * Z_HASH_SIZE;
  1479. #if MAX_CHAIN >= 2
  1480. if (chain >= 2)
  1481. {
  1482. // data structures for (chain >= 2) are the same, enable deeper search
  1483. max_chain = MAX_CHAIN;
  1484. alloc_size = sizeof (p->x.z_next[0]) * max_orig_size;
  1485. if (temp_size < sizeof (p[-1].x.z_hash[0]) * Z_HASH_SIZE)
  1486. temp_size = sizeof (p[-1].x.z_hash[0]) * Z_HASH_SIZE;
  1487. }
  1488. #endif
  1489. }
  1490. #endif
  1491. temp_size = (temp_size + 256 + MEM_ALIGN-1 + sizeof (*p) - sizeof (p->x)) & ~(MEM_ALIGN-1);
  1492. alloc_size += temp_size + sizeof (*info) + MEM_ALIGN;
  1493. b = AllocFn (context, alloc_size);
  1494. if (b == 0)
  1495. return (0);
  1496. info = (xpress_info *) b;
  1497. info->max_size = max_orig_size - 1;
  1498. info->max_chain = max_chain;
  1499. info->chain = chain;
  1500. info->magic = MAGIC_ENCODE;
  1501. info->memory = b;
  1502. b = (uchar *) (info + 1);
  1503. b += MEM_ALIGN - (((__int64) b) & (MEM_ALIGN-1));
  1504. info->p = p = ((prs *) (b + temp_size));
  1505. info->temp = b;
  1506. #if MAX_CHAIN >= 1
  1507. if (!z_hash_map_initialized)
  1508. z_hash_map_init ();
  1509. #endif
  1510. #if CODING & (CODING_HUFF_PTR | CODING_HUFF_ALL) && !defined (i386)
  1511. if (!bitno_table_initialized)
  1512. bitno_init ();
  1513. #endif
  1514. return ((XpressEncodeStream) info);
  1515. }
  1516. XPRESS_EXPORT
  1517. void
  1518. XPRESS_CALL
  1519. XpressEncodeClose (
  1520. XpressEncodeStream stream,
  1521. void *context,
  1522. XpressFreeFn *FreeFn
  1523. )
  1524. {
  1525. xpress_info *info = (xpress_info *) stream;
  1526. if (info != 0 && FreeFn != 0 && info->magic == MAGIC_ENCODE)
  1527. {
  1528. info->magic = 0;
  1529. FreeFn (context, info->memory);
  1530. }
  1531. }
  1532. // returns MaxCompressionLevel or (-1) if stream was not initialized properly
  1533. XPRESS_EXPORT
  1534. int
  1535. XPRESS_CALL
  1536. XpressEncodeGetMaxCompressionLevel (
  1537. XpressEncodeStream EncodeStream // encoder's workspace
  1538. )
  1539. {
  1540. xpress_info *info = (xpress_info *) EncodeStream;
  1541. if (info != 0 && info->magic == MAGIC_ENCODE)
  1542. return (info->max_chain);
  1543. return (-1);
  1544. }