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.

1060 lines
28 KiB

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