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.

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