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.

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