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.

1103 lines
34 KiB

  1. /*
  2. * Microsoft Confidential
  3. * Copyright (c) 1994 Microsoft Corporation
  4. * All Rights Reserved.
  5. *
  6. * MRCICODE.C
  7. *
  8. * MRCI 1 & MRCI 2 maxcompress and decompress functions
  9. */
  10. #include "mrcicode.h" /* prototype verification */
  11. //#define NDEBUG /* turn off assertions */
  12. #include <assert.h> /* use NDEBUG to inhibit */
  13. #include <setjmp.h> /* fast overflow recovery */
  14. #define LOGCHASH (13) /* Log of max. no. of hash buckets */
  15. #define CHASH (1U << LOGCHASH) /* Reasonably large table */
  16. #define hash(w) ((w) & (CHASH - 1))
  17. /* Simply toss the high-order bits */
  18. #define word(p) ((p)[0] + (((p)[1]) << 8))
  19. /* Return word at location */
  20. #define BITMASK(x) ((1 << x) - 1) /* returns lower 'x' bits set */
  21. #define LOGDISPSMALL (6) /* Number of bits in small disp */
  22. #define LOGDISPMED (8) /* Number of bits in medium disp */
  23. #define LOGDISPBIG (12) /* Number of bits in big displacement */
  24. #define MAXDISPSMALL ((1 << LOGDISPSMALL) - 1)
  25. /* Maximum small displacement */
  26. #define MAXDISPMED ((1 << LOGDISPMED) + MAXDISPSMALL)
  27. /* Maximum medium displacement */
  28. #define MAXDISPBIG ((1 << LOGDISPBIG) + MAXDISPMED)
  29. /* Maximum big displacement */
  30. #define MINDISPSMALL (0) /* Minimum small displacement */
  31. #define MINDISPMED (MAXDISPSMALL + 1)
  32. /* Minimum medium displacement */
  33. #define MINDISPBIG (MAXDISPMED + 1)/* Minimum big displacement */
  34. #define DISPMAX (MAXDISPBIG - 1)/* MAXDISPBIG is our end marker */
  35. #define MINMATCH1 (2) /* Minimum match length for MRCI1 */
  36. #define MINMATCH2 (3) /* Minimum match length for MRCI2 */
  37. #define MAXMATCH (512) /* Maximum match length */
  38. #define EOB (0) /* length used to mean end of block */
  39. #define SECTOR (512) /* blocking factor */
  40. #define SIG_SIZE (4) /* # of block type prefix bytes */
  41. /* local variables */
  42. #ifdef BIT16
  43. #define FARBSS _far
  44. #else
  45. #define FARBSS
  46. #endif
  47. static unsigned abits; /* Array of bits */
  48. static unsigned cbitsleft; /* Number of bits in abits */
  49. static unsigned char FAR *pCompressed; /* pointer into compressed data */
  50. static unsigned cCompressed; /* # bytes remaining @ pCompressed */
  51. static jmp_buf bailout; /* longjmp if cCompressed exceeded */
  52. static unsigned FARBSS ahash[CHASH]; /* Hash table */
  53. static unsigned FARBSS alink[MAXDISPBIG]; /* Links */
  54. /* compression internal functions */
  55. #ifdef BIT16
  56. #define FAST _near _pascal /* speed up local calls */
  57. #else
  58. #define FAST
  59. #endif
  60. static void FAST inithash(void);
  61. static void FAST charbuf(unsigned c);
  62. static void FAST putbits(unsigned bits,unsigned cbits);
  63. static void FAST outlength(unsigned cb);
  64. static void FAST mrci1outsingle(unsigned ch);
  65. static void FAST mrci1outstring(unsigned disp,unsigned cb);
  66. static void FAST mrci2outsingle(unsigned ch);
  67. static void FAST mrci2outstring(unsigned disp,unsigned cb);
  68. /* decompression internal functions */
  69. static unsigned FAST getbit(void);
  70. static unsigned FAST getbits(unsigned cbits);
  71. static void FAST expandstring(unsigned char FAR **ppchout,unsigned disp,
  72. unsigned cb);
  73. /*
  74. * (compress) Reset the hash tables between blocks.
  75. */
  76. static void FAST inithash(void)
  77. {
  78. unsigned FAR *entry;
  79. int i;
  80. entry = ahash;
  81. i = CHASH;
  82. do
  83. {
  84. *entry++ = (unsigned) -1; /* Mark all entries as empty */
  85. } while (--i);
  86. }
  87. /*
  88. * (compress) Add a character to compressed output buffer.
  89. */
  90. static void FAST charbuf(unsigned c)
  91. {
  92. if (cCompressed-- == 0) /* make sure there's room */
  93. {
  94. longjmp(bailout,1); /* Data expanding! */
  95. }
  96. *pCompressed++ = (unsigned char) c; /* Put character into buffer */
  97. }
  98. /*
  99. * (compress) Write n bits to the compressed bitstream.
  100. */
  101. static void FAST putbits(unsigned ab,unsigned cbits)
  102. {
  103. do /* Loop to emit bits */
  104. {
  105. if (cbits > cbitsleft) /* if not enough space */
  106. {
  107. cbits -= cbitsleft; /* doing partial */
  108. abits |= (ab << (8 - cbitsleft));
  109. /* Put bits in output buffer */
  110. ab >>= cbitsleft; /* clip sent bits */
  111. charbuf(abits); /* Emit the buffer */
  112. cbitsleft = 8; /* Reset buffer count */
  113. abits = 0; /* Reset buffer */
  114. }
  115. else /* can do all in one pass */
  116. {
  117. abits |= ((ab & BITMASK(cbits)) << (8 - cbitsleft));
  118. /* Put bits in output buffer */
  119. cbitsleft -= cbits; /* used up some buffer */
  120. if (cbitsleft == 0) /* If buffer full */
  121. {
  122. charbuf(abits); /* Emit the buffer */
  123. cbitsleft = 8; /* Reset buffer count */
  124. abits = 0; /* Reset buffer */
  125. }
  126. break; /* we've done all cbits */
  127. }
  128. } while (cbits); /* repeat until done */
  129. }
  130. /*
  131. * (compress) Encode a length into the compressed stream.
  132. */
  133. static void FAST outlength(unsigned cb)
  134. {
  135. unsigned alogbits, clogbits;
  136. unsigned avaluebits, cvaluebits;
  137. assert(cb >= 2); /* Length must be at least two */
  138. assert(cb <= MAXMATCH);
  139. if (cb <= 2)
  140. {
  141. alogbits = 1;
  142. clogbits = 1;
  143. cvaluebits = 0;
  144. }
  145. else if (cb <= 4)
  146. {
  147. alogbits = 1 << 1;
  148. clogbits = 2;
  149. avaluebits = cb - 3;
  150. cvaluebits = 1;
  151. }
  152. else if (cb <= 8)
  153. {
  154. alogbits = 1 << 2;
  155. clogbits = 3;
  156. avaluebits = cb - 5;
  157. cvaluebits = 2;
  158. }
  159. else if (cb <= 16)
  160. {
  161. alogbits = 1 << 3;
  162. clogbits = 4;
  163. avaluebits = cb - 9;
  164. cvaluebits = 3;
  165. }
  166. else if (cb <= 32)
  167. {
  168. alogbits = 1 << 4;
  169. clogbits = 5;
  170. avaluebits = cb - 17;
  171. cvaluebits = 4;
  172. }
  173. else if (cb <= 64)
  174. {
  175. alogbits = 1 << 5;
  176. clogbits = 6;
  177. avaluebits = cb - 33;
  178. cvaluebits = 5;
  179. }
  180. else if (cb <= 128)
  181. {
  182. alogbits = 1 << 6;
  183. clogbits = 7;
  184. avaluebits = cb - 65;
  185. cvaluebits = 6;
  186. }
  187. else if (cb <= 256)
  188. {
  189. alogbits = 1 << 7;
  190. clogbits = 8;
  191. avaluebits = cb - 129;
  192. cvaluebits = 7;
  193. }
  194. else /* (cb <= 512) */
  195. {
  196. alogbits = 1 << 8;
  197. clogbits = 9;
  198. avaluebits = cb - 257;
  199. cvaluebits = 8;
  200. }
  201. putbits(alogbits,clogbits);
  202. if (cvaluebits)
  203. {
  204. putbits(avaluebits,cvaluebits);
  205. }
  206. }
  207. /*
  208. * (MRCI1 compress) Encode a literal into the compressed stream.
  209. */
  210. static void FAST mrci1outsingle(unsigned ch)
  211. {
  212. ch = (ch << 2) | ((ch & 0x80) ? 1 : 2);
  213. putbits(ch,9);
  214. }
  215. /*
  216. * (MRCI2 compress) Encode a literal into the compressed stream.
  217. */
  218. static void FAST mrci2outsingle(unsigned ch)
  219. {
  220. if (ch & 0x80)
  221. {
  222. putbits((ch << 2) | 3,9);
  223. }
  224. else
  225. {
  226. putbits(ch << 1,8);
  227. }
  228. }
  229. /*
  230. * (MRCI1 compress) Encode a match into the compressed stream.
  231. */
  232. static void FAST mrci1outstring(unsigned disp,unsigned cb)
  233. {
  234. assert(((cb >= MINMATCH1) && (disp != 0) && (disp < MAXDISPBIG)) ||
  235. ((cb == EOB) && (disp == MAXDISPBIG)));
  236. if (disp <= MAXDISPSMALL)
  237. {
  238. putbits(((disp - MINDISPSMALL) << 2),LOGDISPSMALL + 2);
  239. /* Put small displacement */
  240. }
  241. else if (disp <= MAXDISPMED)
  242. {
  243. putbits(((disp - MINDISPMED) << 3) | 3,LOGDISPMED + 3);
  244. /* Put medium displacement */
  245. }
  246. else
  247. {
  248. putbits(((disp - MINDISPBIG) << 3) | 7,LOGDISPBIG + 3);
  249. /* Put big displacement */
  250. }
  251. if (cb != EOB) /* If not an end marker */
  252. {
  253. outlength(cb); /* Emit the match length */
  254. }
  255. }
  256. /*
  257. * (MRCI2 compress) Encode a match into the compressed stream.
  258. */
  259. static void FAST mrci2outstring(unsigned disp,unsigned cb)
  260. {
  261. assert(((cb >= MINMATCH2) && (disp != 0) && (disp < MAXDISPBIG)) ||
  262. ((cb == EOB) && (disp == MAXDISPBIG)));
  263. if (disp <= MAXDISPSMALL)
  264. {
  265. putbits(((disp - MINDISPSMALL) << 3) | 1,LOGDISPSMALL + 3);
  266. /* Put small displacement */
  267. }
  268. else if (disp <= MAXDISPMED)
  269. {
  270. putbits(((disp - MINDISPMED) << 4) | 5,LOGDISPMED + 4);
  271. /* Put medium displacement */
  272. }
  273. else
  274. {
  275. putbits(((disp - MINDISPBIG) << 4) | 13,LOGDISPBIG + 4);
  276. /* Put big displacement */
  277. }
  278. if (cb != EOB) /* If not an end marker */
  279. {
  280. outlength(cb - 1); /* Emit the match length */
  281. }
  282. }
  283. /*
  284. * (MRCI1) MaxCompress
  285. */
  286. unsigned Mrci1MaxCompress(unsigned char FAR *pchbase,unsigned cchunc,
  287. unsigned char FAR *pchcmpBase,unsigned cchcmpMax)
  288. {
  289. unsigned cchbest; /* Length of best match */
  290. unsigned cchmatch; /* Length of this match */
  291. unsigned ibest; /* Position of best match */
  292. unsigned icur; /* Current position */
  293. unsigned ihash; /* Hash table index */
  294. unsigned ilink; /* Link index */
  295. unsigned char FAR *pch; /* Char pointer */
  296. unsigned char FAR *pch2; /* Char pointer */
  297. unsigned char FAR *pchend; /* End of input (-> last valid) */
  298. unsigned cch; /* per-pass limit */
  299. cbitsleft = 8; /* Buffer is empty */
  300. abits = 0;
  301. pCompressed = pchcmpBase; /* Initialize pointer */
  302. if (cchunc < cchcmpMax)
  303. {
  304. cCompressed = cchunc; /* limit to source size */
  305. }
  306. else
  307. {
  308. cCompressed = cchcmpMax; /* limit to max size offered */
  309. }
  310. if (cCompressed < SIG_SIZE)
  311. {
  312. return((unsigned) -1);
  313. }
  314. *pCompressed++ = 'D';
  315. *pCompressed++ = 'S';
  316. *pCompressed++ = '\x00';
  317. *pCompressed++ = '\x01';
  318. cCompressed -= SIG_SIZE;
  319. pch = pchbase; /* Initialize */
  320. if (cchunc-- == 0)
  321. {
  322. return(0); /* Do nothing to empty buffer */
  323. }
  324. inithash(); /* Initialize tables */
  325. if (setjmp(bailout) != 0) /* If failure */
  326. {
  327. return((unsigned) -1); /* Data expanded */
  328. }
  329. cchbest = 0; /* no match yet */
  330. icur = 0; /* Initialize */
  331. for (cch = SECTOR - 1; cch <= (cchunc + SECTOR - 1); cch += SECTOR)
  332. {
  333. assert(cchbest == 0); /* must always start with no match */
  334. if (cch > cchunc)
  335. {
  336. cch = cchunc; /* limit to exact req count */
  337. }
  338. pchend = &pchbase[cch]; /* Remember end of buffer */
  339. while (icur < cch) /* While at least two chars left */
  340. {
  341. /* update hash tables for this character */
  342. ihash = hash(word(&pchbase[icur]));
  343. /* Get hash index */
  344. ilink = ahash[ihash]; /* Get link index */
  345. ahash[ihash] = icur; /* Remember position */
  346. alink[icur % MAXDISPBIG] = ilink;
  347. /* Chain on rest of list */
  348. /* walk hash chain looking for matches */
  349. while (ilink < icur && icur - ilink <= DISPMAX)
  350. { /* While link is valid and in range */
  351. pch = &pchbase[icur]; /* Point at first byte */
  352. pch2 = &pchbase[ilink]; /* Point at first byte */
  353. if (pch[cchbest] == pch2[cchbest] && word(pch) == word(pch2))
  354. { /* If we have a possible best match */
  355. pch += 2; /* Skip first pair */
  356. pch2 += 2; /* Skip first pair */
  357. while (pch <= pchend) /* Loop to find end of match */
  358. {
  359. if (*pch != *pch2++)
  360. {
  361. break; /* Break if mismatch */
  362. }
  363. pch++; /* Skip matching character */
  364. }
  365. if ((cchmatch = (unsigned)(pch - pchbase) - icur) > cchbest)
  366. { /* If new best match */
  367. cchbest = cchmatch; /* Remember length */
  368. ibest = ilink; /* Remember position */
  369. assert((pch-1) <= pchend);
  370. if (pch > pchend)
  371. {
  372. break; /* Break if we can't do any better */
  373. }
  374. }
  375. }
  376. assert((alink[ilink % MAXDISPBIG] == (unsigned) -1) ||
  377. (alink[ilink % MAXDISPBIG] < ilink));
  378. ilink = alink[ilink % MAXDISPBIG];
  379. /* Get next link */
  380. } /* until end of hash chain reached */
  381. if (cchbest >= MINMATCH1) /* If we have a string match */
  382. {
  383. mrci1outstring(icur - ibest,cchbest);
  384. /* Describe matching string */
  385. #ifdef VXD
  386. if (icur + cchbest >= cch ) /* If end of sector reached */
  387. #else
  388. if (icur + cchbest >= cchunc) /* If end of buffer reached */
  389. #endif
  390. {
  391. icur += cchbest; /* Advance the index */
  392. cchbest = 0; /* reset for next match */
  393. break; /* Done if buffer exhausted */
  394. }
  395. icur++; /* Skip to first unhashed pair */
  396. #ifdef VXD
  397. /* avoid re-seeding all of a big match */
  398. if (cchbest > MAXDISPSMALL)
  399. { /* If big match */
  400. icur += cchbest - MAXDISPSMALL - 1;
  401. /* Skip ahead */
  402. cchbest = MAXDISPSMALL + 1;
  403. /* Use shorter length */
  404. }
  405. #endif
  406. /* update hash tables for each add't char in string */
  407. ibest = icur % MAXDISPBIG; /* Get current link table index */
  408. while (--cchbest != 0) /* Loop to reseed link table */
  409. {
  410. ihash = hash(word(&pchbase[icur]));
  411. /* Get hash index */
  412. ilink = ahash[ihash]; /* Get link index */
  413. ahash[ihash] = icur++; /* Remember position */
  414. alink[ibest] = ilink; /* Chain on rest of list */
  415. if (++ibest < MAXDISPBIG)
  416. {
  417. continue; /* Loop if we haven't wrapped yet */
  418. }
  419. ibest = 0; /* Wrap to zero */
  420. }
  421. assert(cchbest == 0); /* Counter must be 0 */
  422. }
  423. else
  424. {
  425. mrci1outsingle(pchbase[icur++]);
  426. /* Else output single character */
  427. cchbest = 0; /* Reset counter */
  428. }
  429. }
  430. assert(icur == cch || icur == cch + 1);
  431. /* Must be at or past last character */
  432. if (icur == cch)
  433. {
  434. #ifndef VXD
  435. ihash = hash(word(&pchbase[icur]));
  436. /* Get hash index */
  437. ilink = ahash[ihash]; /* Get link index */
  438. ahash[ihash] = icur; /* Remember position */
  439. alink[icur % MAXDISPBIG] = ilink;
  440. /* Chain on rest of list */
  441. #endif
  442. mrci1outsingle(pchbase[icur++]); /* Output last character */
  443. }
  444. assert(icur == cch + 1); /* Must be past last character */
  445. mrci1outstring(MAXDISPBIG,EOB); /* Put out an end marker */
  446. }
  447. if (cbitsleft != 8)
  448. {
  449. charbuf(abits); /* Flush bit buffer */
  450. }
  451. if ((unsigned) (pCompressed - pchcmpBase) > cchunc)
  452. {
  453. return((unsigned) -1); /* data expanded or not smaller */
  454. }
  455. return (unsigned)(pCompressed - pchcmpBase); /* Return compressed size */
  456. }
  457. /*
  458. * (MRCI2) MaxCompress
  459. */
  460. unsigned Mrci2MaxCompress(unsigned char FAR *pchbase,unsigned cchunc,
  461. unsigned char FAR *pchcmpBase,unsigned cchcmpMax)
  462. {
  463. unsigned cchbest; /* Length of best match */
  464. unsigned cchmatch; /* Length of this match */
  465. unsigned ibest; /* Position of best match */
  466. unsigned icur; /* Current position */
  467. unsigned ihash; /* Hash table index */
  468. unsigned ilink; /* Link index */
  469. unsigned char FAR *pch; /* Char pointer */
  470. unsigned char FAR *pch2; /* Char pointer */
  471. unsigned char FAR *pchend; /* End of input (-> last valid) */
  472. unsigned cch; /* per-pass limit */
  473. cbitsleft = 8; /* Buffer is empty */
  474. abits = 0;
  475. pCompressed = pchcmpBase; /* Initialize pointer */
  476. if (cchunc < cchcmpMax)
  477. {
  478. cCompressed = cchunc; /* limit to source size */
  479. }
  480. else
  481. {
  482. cCompressed = cchcmpMax; /* limit to max size offered */
  483. }
  484. if (cCompressed < SIG_SIZE)
  485. {
  486. return((unsigned) -1);
  487. }
  488. *pCompressed++ = 'J';
  489. *pCompressed++ = 'M';
  490. *pCompressed++ = '\x00';
  491. *pCompressed++ = '\x01';
  492. cCompressed -= SIG_SIZE;
  493. pch = pchbase; /* Initialize */
  494. if (cchunc-- == 0)
  495. {
  496. return(0); /* Do nothing to empty buffer */
  497. }
  498. inithash(); /* Initialize tables */
  499. if (setjmp(bailout) != 0) /* If failure */
  500. {
  501. return((unsigned) -1); /* Data expanded */
  502. }
  503. cchbest = 0; /* no match yet */
  504. icur = 0; /* Initialize */
  505. for (cch = SECTOR - 1; cch <= (cchunc + SECTOR - 1); cch += SECTOR)
  506. {
  507. assert(cchbest == 0); /* must always start with no match */
  508. if (cch > cchunc)
  509. {
  510. cch = cchunc; /* limit to exact req count */
  511. }
  512. pchend = &pchbase[cch]; /* Remember end of buffer */
  513. while (icur < cch) /* While at least two chars left */
  514. {
  515. /* update hash tables for this character */
  516. ihash = hash(word(&pchbase[icur]));
  517. /* Get hash index */
  518. ilink = ahash[ihash]; /* Get link index */
  519. ahash[ihash] = icur; /* Remember position */
  520. alink[icur % MAXDISPBIG] = ilink;
  521. /* Chain on rest of list */
  522. /* walk hash chain looking for matches */
  523. while (ilink < icur && icur - ilink <= DISPMAX)
  524. { /* While link is valid and in range */
  525. pch = &pchbase[icur]; /* Point at first byte */
  526. pch2 = &pchbase[ilink]; /* Point at first byte */
  527. if (pch[cchbest] == pch2[cchbest] && word(pch) == word(pch2))
  528. { /* If we have a possible best match */
  529. pch += 2; /* Skip first pair */
  530. pch2 += 2; /* Skip first pair */
  531. while (pch <= pchend) /* Loop to find end of match */
  532. {
  533. if (*pch != *pch2++)
  534. {
  535. break; /* Break if mismatch */
  536. }
  537. pch++; /* Skip matching character */
  538. }
  539. if ((cchmatch = (unsigned)(pch - pchbase) - icur) > cchbest)
  540. { /* If new best match */
  541. cchbest = cchmatch; /* Remember length */
  542. ibest = ilink; /* Remember position */
  543. assert((pch-1) <= pchend);
  544. if (pch > pchend)
  545. {
  546. break; /* Break if we can't do any better */
  547. }
  548. }
  549. }
  550. assert((alink[ilink % MAXDISPBIG] == (unsigned) -1) ||
  551. (alink[ilink % MAXDISPBIG] < ilink));
  552. ilink = alink[ilink % MAXDISPBIG];
  553. /* Get next link */
  554. } /* until end of hash chain reached */
  555. if (cchbest >= MINMATCH2) /* If we have a string match */
  556. {
  557. mrci2outstring(icur - ibest,cchbest);
  558. /* Describe matching string */
  559. #ifdef VXD
  560. if (icur + cchbest >= cch ) /* If end of sector reached */
  561. #else
  562. if (icur + cchbest >= cchunc) /* If end of buffer reached */
  563. #endif
  564. {
  565. icur += cchbest; /* Advance the index */
  566. cchbest = 0; /* reset for next match */
  567. break; /* Done if buffer exhausted */
  568. }
  569. icur++; /* Skip to first unhashed pair */
  570. #ifdef VXD
  571. /* avoid re-seeding all of a big match */
  572. if (cchbest > MAXDISPSMALL)
  573. { /* If big match */
  574. icur += cchbest - MAXDISPSMALL - 1;
  575. /* Skip ahead */
  576. cchbest = MAXDISPSMALL + 1;
  577. /* Use shorter length */
  578. }
  579. #endif
  580. /* update hash tables for each add't char in string */
  581. ibest = icur % MAXDISPBIG; /* Get current link table index */
  582. while (--cchbest != 0) /* Loop to reseed link table */
  583. {
  584. ihash = hash(word(&pchbase[icur]));
  585. /* Get hash index */
  586. ilink = ahash[ihash]; /* Get link index */
  587. ahash[ihash] = icur++; /* Remember position */
  588. alink[ibest] = ilink; /* Chain on rest of list */
  589. if (++ibest < MAXDISPBIG)
  590. {
  591. continue; /* Loop if we haven't wrapped yet */
  592. }
  593. ibest = 0; /* Wrap to zero */
  594. }
  595. assert(cchbest == 0); /* Counter must be 0 */
  596. }
  597. else
  598. {
  599. mrci2outsingle(pchbase[icur++]);
  600. /* Else output single character */
  601. cchbest = 0; /* Reset counter */
  602. }
  603. }
  604. assert(icur == cch || icur == cch + 1);
  605. /* Must be at or past last character */
  606. if (icur == cch)
  607. {
  608. #ifndef VXD
  609. ihash = hash(word(&pchbase[icur]));
  610. /* Get hash index */
  611. ilink = ahash[ihash]; /* Get link index */
  612. ahash[ihash] = icur; /* Remember position */
  613. alink[icur % MAXDISPBIG] = ilink;
  614. /* Chain on rest of list */
  615. #endif
  616. mrci2outsingle(pchbase[icur++]); /* Output last character */
  617. }
  618. assert(icur == cch + 1); /* Must be past last character */
  619. mrci2outstring(MAXDISPBIG,EOB); /* Put out an end marker */
  620. }
  621. if (cbitsleft != 8)
  622. {
  623. charbuf(abits); /* Flush bit buffer */
  624. }
  625. if ((unsigned) (pCompressed - pchcmpBase) > cchunc)
  626. {
  627. return((unsigned) -1); /* data expanded or not smaller */
  628. }
  629. return (unsigned)(pCompressed - pchcmpBase); /* Return compressed size */
  630. }
  631. /*
  632. * (decompress) Get a single bit from the compressed input stream.
  633. */
  634. static unsigned FAST getbit(void)
  635. {
  636. unsigned bit; /* Bit */
  637. if (cbitsleft) /* If bits available */
  638. {
  639. cbitsleft--; /* Decrement bit count */
  640. bit = abits & 1; /* Get a bit */
  641. abits >>= 1; /* Remove it */
  642. }
  643. else /* no bits available */
  644. {
  645. if (cCompressed-- == 0) /* If buffer empty */
  646. {
  647. longjmp(bailout,1); /* input overrun */
  648. }
  649. cbitsleft = 7; /* Reset count */
  650. abits = *pCompressed++; /* Get a byte */
  651. bit = abits & 1; /* Get a bit */
  652. abits >>= 1; /* Remove it */
  653. }
  654. return(bit); /* Return the bit */
  655. }
  656. /*
  657. * (decompress) Get multiple bits from the compressed input stream.
  658. */
  659. static unsigned FAST getbits(unsigned cbits)
  660. {
  661. unsigned bits; /* Bits to return */
  662. unsigned cbitsdone; /* number of bits added so far */
  663. unsigned cbitsneeded; /* number of bits still needed */
  664. if (cbits <= cbitsleft) /* If we have enough bits */
  665. {
  666. bits = abits; /* Get the bits */
  667. cbitsleft -= cbits; /* Decrement bit count */
  668. abits >>= cbits; /* Remove used bits */
  669. }
  670. else /* If we'll need to read more bits */
  671. {
  672. bits = 0; /* No bits set yet */
  673. cbitsdone = 0; /* no bits added yet */
  674. cbitsneeded = cbits; /* bits needed */
  675. do
  676. {
  677. if (cbitsleft == 0) /* If no bits ready */
  678. {
  679. if (cCompressed-- == 0) /* count down used */
  680. {
  681. longjmp(bailout,1); /* if input overrun */
  682. }
  683. cbitsleft = 8; /* Reset count */
  684. abits = *pCompressed++; /* Get 8 new bits */
  685. }
  686. bits |= (abits << cbitsdone); /* copy bits for output */
  687. if (cbitsleft >= cbitsneeded) /* if enough now */
  688. {
  689. cbitsleft -= cbitsneeded; /* reduce bits remaining available */
  690. abits >>= cbitsneeded; /* discard used bits */
  691. break; /* got them */
  692. }
  693. else /* if not enough yet */
  694. {
  695. cbitsneeded -= cbitsleft; /* reduce bits still needed */
  696. cbitsdone += cbitsleft; /* increase shift for future bits */
  697. cbitsleft = 0; /* reduce bits remaining available */
  698. }
  699. } while (cbitsneeded); /* go back if more bits needed */
  700. }
  701. return(bits & BITMASK(cbits)); /* Return the bits */
  702. }
  703. /*
  704. * (decompress) Expand a match.
  705. *
  706. * Note: source overwrite is required (so we can't memcpy or memmove)
  707. */
  708. static void FAST expandstring(unsigned char FAR **ppchout,unsigned disp,
  709. unsigned cb)
  710. {
  711. unsigned char FAR *source;
  712. unsigned char FAR *target;
  713. assert(cb != 0);
  714. target = *ppchout; /* where the bytes go */
  715. source = target - disp; /* where the bytes come from */
  716. *ppchout += cb; /* Update the output pointer */
  717. while (cb--)
  718. {
  719. *target++ = *source++;
  720. }
  721. }
  722. /*
  723. * (MRCI1) Decompress
  724. */
  725. unsigned Mrci1Decompress(unsigned char FAR *pchin,unsigned cchin,
  726. unsigned char FAR *pchdecBase,unsigned cchdecMax)
  727. {
  728. unsigned b; /* A byte */
  729. unsigned length; /* Length of match */
  730. unsigned disp; /* Displacement */
  731. unsigned char FAR *pchout; /* Output buffer pointer */
  732. abits = 0; /* Bit buffer is empty */
  733. cbitsleft = 0; /* No bits read yet */
  734. pCompressed = pchin; /* setup source pointer */
  735. cCompressed = cchin; /* setup source counter */
  736. if ((cCompressed <= SIG_SIZE) || /* must have a signature */
  737. (*pCompressed++ != 'D') || (*pCompressed++ != 'S'))
  738. {
  739. return((unsigned) -1); /* Data corrupted */
  740. }
  741. pCompressed += 2; /* ignore flags */
  742. cCompressed -= SIG_SIZE;
  743. pchout = pchdecBase; /* Point at output buffer */
  744. if (setjmp(bailout) != 0) /* If failure */
  745. {
  746. return((unsigned) -1); /* Data corrupted */
  747. }
  748. for (;;)
  749. {
  750. b = getbits(2); /* get two bits */
  751. if (b == 1) /* If single byte 128..255 */
  752. { /* Get the rest of byte */
  753. *pchout++ = (unsigned char) (getbits(7) | 0x80);
  754. continue; /* Next token */
  755. }
  756. if (b == 2) /* If single byte 0..127 */
  757. { /* Get the rest of byte */
  758. *pchout++ = (unsigned char) getbits(7);
  759. continue; /* Next token */
  760. }
  761. if (b == 0)
  762. {
  763. disp = getbits(6) + MINDISPSMALL;
  764. }
  765. else /* b == 3 */
  766. {
  767. if (getbit() == 0)
  768. {
  769. disp = getbits(8) + MINDISPMED;
  770. }
  771. else
  772. {
  773. disp = getbits(12) + MINDISPBIG;
  774. }
  775. }
  776. if (disp == MAXDISPBIG)
  777. {
  778. if ((unsigned) (pchout - pchdecBase) >= cchdecMax)
  779. {
  780. break; /* End marker found */
  781. }
  782. else
  783. {
  784. continue; /* End sector found */
  785. }
  786. }
  787. length = 0; /* Initialize */
  788. while (getbit() == 0)
  789. {
  790. length++; /* Count the leading zeroes */
  791. }
  792. assert(b <= 15); /* Cannot be too big */
  793. if (length)
  794. {
  795. length = getbits(length) + (1 << length) + 1;
  796. }
  797. else
  798. {
  799. length = 2;
  800. }
  801. expandstring(&pchout,disp,length); /* Copy the match */
  802. }
  803. return (unsigned)((pchout - pchdecBase)); /* Return decompressed size */
  804. }
  805. /*
  806. * (MRCI2) Decompress
  807. */
  808. unsigned Mrci2Decompress(unsigned char FAR *pchin,unsigned cchin,
  809. unsigned char FAR *pchdecBase,unsigned cchdecMax)
  810. {
  811. unsigned length; /* Length of match */
  812. unsigned disp; /* Displacement */
  813. unsigned char FAR *pchout; /* Output buffer pointer */
  814. abits = 0; /* Bit buffer is empty */
  815. cbitsleft = 0; /* No bits read yet */
  816. pCompressed = pchin; /* setup source pointer */
  817. cCompressed = cchin; /* setup source counter */
  818. if ((cCompressed <= SIG_SIZE) || /* must have a signature */
  819. (*pCompressed++ != 'J') || (*pCompressed++ != 'M'))
  820. {
  821. return((unsigned) -1); /* Data corrupted */
  822. }
  823. pCompressed += 2; /* ignore flags */
  824. cCompressed -= SIG_SIZE;
  825. pchout = pchdecBase; /* Point at output buffer */
  826. if (setjmp(bailout) != 0) /* If failure */
  827. {
  828. return((unsigned) -1); /* Data corrupted */
  829. }
  830. for (;;)
  831. {
  832. if (getbit() == 0) /* literal 00..7F */
  833. {
  834. *pchout++ = (unsigned char) getbits(7);
  835. continue; /* Next token */
  836. }
  837. if (getbit() == 1) /* literal 80..FF */
  838. {
  839. *pchout++ = (unsigned char)(getbits(7) | 0x80);
  840. continue; /* Next token */
  841. }
  842. if (getbit() == 0)
  843. {
  844. disp = getbits(6) + MINDISPSMALL;
  845. }
  846. else
  847. {
  848. if (getbit() == 0)
  849. {
  850. disp = getbits(8) + MINDISPMED;
  851. }
  852. else
  853. {
  854. disp = getbits(12) + MINDISPBIG;
  855. }
  856. }
  857. if (disp == MAXDISPBIG)
  858. {
  859. if ((unsigned) (pchout - pchdecBase) >= cchdecMax)
  860. {
  861. break; /* End marker found */
  862. }
  863. else
  864. {
  865. continue; /* End sector found */
  866. }
  867. }
  868. length = 0; /* Initialize */
  869. while (getbit() == 0)
  870. {
  871. length++; /* Count the leading zeroes */
  872. }
  873. assert(length <= 15); /* Cannot be too big */
  874. if (length)
  875. {
  876. length = getbits(length) + (1 << length) + 1;
  877. }
  878. else
  879. {
  880. length = 2;
  881. }
  882. expandstring(&pchout,disp,length + 1); /* Copy the match */
  883. }
  884. return (unsigned)((pchout - pchdecBase)); /* Return decompressed size */
  885. }