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