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.

468 lines
13 KiB

  1. /* File: C:\WACKER\xfer\cmprs1.c (Created: 20-Jan-1994)
  2. * created from HAWIN source file
  3. * cmprs1.c -- Routines to implement data compression
  4. *
  5. * Copyright 1989,1994 by Hilgraeve Inc. -- Monroe, MI
  6. * All rights reserved
  7. *
  8. * $Revision: 1 $
  9. * $Date: 10/05/98 1:16p $
  10. */
  11. #include <windows.h>
  12. #include <tdll\stdtyp.h>
  13. #if !defined(BYTE)
  14. #define BYTE unsigned char
  15. #endif
  16. #include "cmprs.h"
  17. #include "cmprs.hh"
  18. #if SHOW
  19. // #include <stdio.h>
  20. #endif
  21. unsigned int usPrefixCode = 0; /* code representing pattern matched so far */
  22. int mcK; /* character to be appended to prefix for
  23. next match */
  24. int (**ppfCmprsGetfunc)(void *) = NULL;
  25. /* pointer to the
  26. pointer to a function used by calling
  27. routine */
  28. int (*pfCmprsGetChar)(void *);
  29. /* pointer to the function used
  30. internally to get data to compress */
  31. void *pPsave;
  32. long *plCmprsLoadcnt;
  33. long lCmprsBegcnt;
  34. long lCmprsLimitcnt = 1L; // Initializing to one disables compression
  35. // shut-down unless changed
  36. struct s_cmprs_node *pstCmprsTbl; /* pointer to compression lookup table */
  37. #define NODE_CAST struct s_cmprs_node *
  38. int lookup_code(void);
  39. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  40. * compress_start
  41. *
  42. * DESCRIPTION
  43. * This function is called to begin data compression. The calling routine
  44. * should set up a pointer to a function through which it will make calls
  45. * to get characters of data. The pointer should be initialized to point
  46. * to the function that the compression routines should use to get raw
  47. * data for compression. The pointer is then modified by the compression
  48. * routines to point to the compressor. After compression is complete or
  49. * abandoned, the pointer is restored to its original value.
  50. * Example of calling sequence:
  51. * int (*xgetc)();
  52. * int fgetc();
  53. *
  54. * xgetc = fgetc;
  55. * if (compress_start(&xgetc))
  56. * ;
  57. * If fPauses is TRUE, the compressor will flush existing data through when
  58. * the input function returns an EOF but will not shutdown. Whenever the
  59. * next non-EOF is retrieved, compression will resume where it left off will
  60. * the pattern table still intact. The fPauses flag must be used by both
  61. * the compression and decompression routines to work. If fPauses is used,
  62. * the cmprs_stop() function must be used to shut compression down before
  63. * compress_disable() is called.
  64. *
  65. * RETURN VALUE
  66. * Returns TRUE if memory is available for table storage and at least one
  67. * character is available from input; FALSE otherwise.
  68. */
  69. int compress_start(int (**getfunc)(void *),
  70. void *pP,
  71. long *loadcnt,
  72. int fPauses)
  73. {
  74. #if FALSE
  75. #if !defined(LZTEST)
  76. long x;
  77. #endif
  78. #endif
  79. if (!compress_enable())
  80. return(FALSE);
  81. fFlushable = fPauses;
  82. fxLastBuildGood = FALSE; /* By setting this FALSE, we will cause
  83. * compression to shut down if the very first
  84. * table build indicates that compression is
  85. * not effective. Thereafter, it will take two
  86. * consecutive bad builds to shut it down.
  87. */
  88. if ((plCmprsLoadcnt = loadcnt) != NULL && !fFlushable)
  89. {
  90. lCmprsBegcnt = *plCmprsLoadcnt;
  91. /*
  92. * Compressability of files can be roughly measured by how many input
  93. * characters must be read before the pattern table fills up. The
  94. * lower the number, the less efficient compression is. This
  95. * calculation determines a cutoff point for any combination of
  96. * machine speed and transfer rate based on experimental trials.
  97. *
  98. * Note that this mechanism should not be used when the fPauses
  99. * parameter is TRUE because the decompressor would misinterpret
  100. * the data following the STOPCODE after compression shut down
  101. */
  102. #if FALSE
  103. #if !defined(LZTEST)
  104. if ((x = (cnfg.bit_rate / cpu_speed())) == 0L)
  105. lCmprsLimitcnt = 4300L;
  106. else
  107. lCmprsLimitcnt = max(x * 774L - 500L, 4300L);
  108. #else
  109. lCmprsLimitcnt = 4300L;
  110. #endif
  111. #endif
  112. lCmprsLimitcnt = 4300L;
  113. }
  114. pPsave = pP;
  115. ppfCmprsGetfunc = getfunc;
  116. pfCmprsGetChar = *ppfCmprsGetfunc;
  117. if ((mcK = (*pfCmprsGetChar)(pPsave)) != EOF)
  118. {
  119. *ppfCmprsGetfunc = cmprs_getc;
  120. cmprs_inittbl();
  121. ulHoldReg = 0L;
  122. ulHoldReg |= CLEARCODE;
  123. sBitsLeft = sCodeBits;
  124. usxCmprsStatus = COMPRESS_ACTIVE;
  125. #if SHOW
  126. printf("C %02X (starting, emit CLEARCODE)\n",
  127. mcK);
  128. printf("C -> %03X %08lX,%2d\n", CLEARCODE,
  129. ulHoldReg, sBitsLeft);
  130. #endif
  131. return(TRUE);
  132. }
  133. else
  134. {
  135. ppfCmprsGetfunc = NULL;
  136. return(FALSE);
  137. }
  138. }
  139. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  140. * compress_stop
  141. *
  142. * DESCRIPTION
  143. * If compression has been started, it is turned off.
  144. */
  145. void compress_stop(void)
  146. {
  147. #if SHOW
  148. printf("C Compress_stop\n");
  149. #endif
  150. if (ppfCmprsGetfunc != NULL)
  151. {
  152. *ppfCmprsGetfunc = pfCmprsGetChar;
  153. ppfCmprsGetfunc = NULL;
  154. }
  155. usxCmprsStatus = COMPRESS_IDLE;
  156. }
  157. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  158. * cmprs_inittbl
  159. *
  160. * DESCRIPTION
  161. * Used to initialize the lookup table used for compressing data.
  162. */
  163. void cmprs_inittbl(void)
  164. {
  165. register INT iCount;
  166. sCodeBits = 9;
  167. usMaxCode = 512;
  168. usFreeCode = FIRSTFREE;
  169. // pstCmprsTbl = (struct s_cmprs_node *)(OFFSETOF(compress_tblspace));
  170. pstCmprsTbl = (struct s_cmprs_node *)(compress_tblspace);
  171. for (iCount = 0; iCount < FIRSTFREE; ++iCount)
  172. pstCmprsTbl[iCount].first = pstCmprsTbl[iCount].next = NULL;
  173. }
  174. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  175. * cmprs_shutdown
  176. *
  177. * DESCRIPTION
  178. * This is the function that is installed by cmprs_getc when compression
  179. * is ending. It is installed after cmprs_getc encounters the end of the input
  180. * data. This function returns any remaining bytes, then returns EOF and
  181. * restores the original getc function
  182. *
  183. * RETURN VALUE
  184. * Returns the next code to be sent or EOF.
  185. */
  186. int cmprs_shutdown(void *pX)
  187. {
  188. int mcRetCode;
  189. // If we haven't sent all the data yet, do so
  190. if (sBitsLeft > 0)
  191. {
  192. mcRetCode = (int)(ulHoldReg & 0x00FF);
  193. ulHoldReg >>= 8;
  194. sBitsLeft -= 8;
  195. #if SHOW
  196. printf("C %02X %08lX,%2d Draining ulHoldReg\n",
  197. mcRetCode, ulHoldReg, sBitsLeft);
  198. #endif
  199. }
  200. else
  201. {
  202. // No more data waiting.
  203. mcRetCode = EOF;
  204. sBitsLeft = 0;
  205. if (!fFlushable)
  206. {
  207. // Not flushable, get compression out of the chain
  208. *ppfCmprsGetfunc = pfCmprsGetChar;
  209. ppfCmprsGetfunc = NULL;
  210. #if SHOW
  211. printf(" !fFlushable, outta here\n");
  212. #endif
  213. }
  214. else
  215. {
  216. // Flushable, see whether we should resume compression
  217. if ((mcK = (*pfCmprsGetChar)(pPsave)) != EOF)
  218. {
  219. #if SHOW
  220. printf("C %02X fFlushable TRUE, restarting\n",
  221. mcK);
  222. #endif
  223. *ppfCmprsGetfunc = cmprs_getc;
  224. mcRetCode = cmprs_getc(pPsave);
  225. }
  226. }
  227. }
  228. return(mcRetCode);
  229. }
  230. #if !USE_ASM
  231. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  232. * cmprs_getc
  233. *
  234. * DESCRIPTION
  235. * This is the function installed by compress_start to be used by any routine
  236. * that needs compressed data. It delivers bytes to the calling routine,
  237. * but may read several characters from the input to do so.
  238. *
  239. * RETURN VALUE
  240. * Returns next 8-bits of compressed data or EOF if no more is available.
  241. */
  242. int cmprs_getc(void *pX)
  243. {
  244. int mcRetCode;
  245. int fBuildGood;
  246. if (sBitsLeft < 8)
  247. {
  248. usPrefixCode = (unsigned int)mcK;
  249. do
  250. {
  251. if ((mcK = (*pfCmprsGetChar)(pPsave)) == EOF)
  252. {
  253. /* at end of file, send last code followed by STOPCODE */
  254. /* to stop decompression. Note that ulHoldReg may overflow */
  255. /* if the maximum code size is greater than 12 bits */
  256. ulHoldReg |= ((unsigned long)usPrefixCode << sBitsLeft);
  257. sBitsLeft += sCodeBits;
  258. #if SHOW
  259. printf("C -1 Shutdown,"
  260. " emit prefix and STOPCODE\n");
  261. printf("C -> %03X %08lX,%2d Codebits=%d\n",
  262. usPrefixCode, ulHoldReg, sBitsLeft, sCodeBits);
  263. #endif
  264. // If we're poised to switch to the next larger code size,
  265. // the decompressor will do so after the prior code, so
  266. // we should switch now too.
  267. if (usFreeCode >= usMaxCode && sCodeBits < MAXCODEBITS)
  268. {
  269. ++sCodeBits;
  270. usMaxCode *= 2;
  271. #if SHOW
  272. printf("C "
  273. "New sCodeBits = %d (anticipating)\n",
  274. sCodeBits);
  275. #endif
  276. }
  277. usPrefixCode = STOPCODE;
  278. *ppfCmprsGetfunc = cmprs_shutdown;
  279. usxCmprsStatus = COMPRESS_IDLE;
  280. break; /* let last code go out */
  281. }
  282. } while (lookup_code());
  283. ulHoldReg |= ((unsigned long)usPrefixCode << sBitsLeft);
  284. sBitsLeft += sCodeBits;
  285. #if SHOW
  286. printf("C -> %03X %08lX,%2d Codebits=%d\n", usPrefixCode,
  287. ulHoldReg, sBitsLeft, sCodeBits);
  288. #endif
  289. }
  290. mcRetCode = (int)(ulHoldReg & 0x00FF);
  291. ulHoldReg >>= 8;
  292. sBitsLeft -= 8;
  293. #if SHOW
  294. printf("C %02X %08lX,%2d\n", mcRetCode, ulHoldReg, sBitsLeft);
  295. #endif
  296. if (usFreeCode > usMaxCode)
  297. {
  298. /* We've used up all available codes at the current codesize */
  299. if (sCodeBits >= MAXCODEBITS)
  300. {
  301. /* We've filled the pattern table, either shut down or clear the
  302. * table and build a new one.
  303. */
  304. fBuildGood = TRUE;
  305. if (plCmprsLoadcnt &&
  306. (*plCmprsLoadcnt - lCmprsBegcnt) < lCmprsLimitcnt)
  307. fBuildGood = FALSE;
  308. #if SHOW
  309. printf("C Table full, fBuildGood = %d\n",
  310. fBuildGood);
  311. #endif
  312. /* if two ineffective builds in a row (or if the very first build
  313. * is ineffective, shut compression down.
  314. */
  315. if (!fBuildGood && !fxLastBuildGood)
  316. {
  317. /* compression is not effective, shut it down */
  318. ulHoldReg |= ((unsigned long)STOPCODE << sBitsLeft);
  319. sBitsLeft += sCodeBits;
  320. #if SHOW
  321. printf("C -> %03X %08lX,%2d Ineffective, emitting STOPCODE\n",
  322. STOPCODE, ulHoldReg, sBitsLeft);
  323. #endif
  324. *ppfCmprsGetfunc = cmprs_shutdown;
  325. usxCmprsStatus = COMPRESS_SHUTDOWN;
  326. }
  327. else
  328. {
  329. /* clear the table and build a new one in case the nature of
  330. * the data changes.
  331. */
  332. ulHoldReg |= ((unsigned long)CLEARCODE << sBitsLeft);
  333. sBitsLeft += sCodeBits;
  334. #if SHOW
  335. printf("C -> %03X %08lX,%2d New table, emiting CLEARCODE\n",
  336. CLEARCODE, ulHoldReg, sBitsLeft);
  337. #endif
  338. cmprs_inittbl();
  339. lCmprsBegcnt = *plCmprsLoadcnt;
  340. }
  341. fxLastBuildGood = fBuildGood;
  342. }
  343. else
  344. {
  345. /* code size hasn't maxed out yet, bump to next larger code size */
  346. ++sCodeBits;
  347. usMaxCode *= 2;
  348. #if SHOW
  349. printf("C New sCodeBits = %d, usMaxCode = %03X\n",
  350. sCodeBits, usMaxCode);
  351. #endif
  352. }
  353. }
  354. return(mcRetCode);
  355. }
  356. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  357. * lookup_code
  358. *
  359. * DESCRIPTION
  360. * This is a 'C' language version of the table lookup routine. It is used
  361. * when an internal lookup table is being used. An assembly language version
  362. * is used if an external lookup table is being used.
  363. * Given a current usPrefixCode and input character, this function
  364. * attempts to find a new usPrefixCode for the combined pattern in the table.
  365. * If so, it updates the usPrefixCode and returns TRUE. If the pattern is
  366. * not found, it adds the combination to the table and returns FALSE.
  367. *
  368. * RETURN VALUE
  369. * TRUE if usPrefixCode:mcK is found in the table. FALSE if not.
  370. */
  371. int lookup_code(void)
  372. {
  373. int firstflag;
  374. struct s_cmprs_node *tptr = (NODE_CAST)&pstCmprsTbl[usPrefixCode];
  375. struct s_cmprs_node *newptr;
  376. firstflag = TRUE;
  377. if (tptr->first != NULL)
  378. {
  379. firstflag = FALSE;
  380. tptr = tptr->first;
  381. for (;;)
  382. {
  383. if (tptr->cchar == (BYTE)mcK)
  384. {
  385. usPrefixCode = (unsigned int)(tptr - (NODE_CAST)(&pstCmprsTbl[0]));
  386. #if SHOW
  387. printf("C %02X ->(%03X)\n",
  388. mcK, usPrefixCode);
  389. #endif
  390. return(TRUE);
  391. }
  392. if (tptr->next == NULL)
  393. break;
  394. else
  395. tptr = tptr->next;
  396. }
  397. }
  398. if (usFreeCode < MAXNODES)
  399. {
  400. #if SHOW
  401. printf("C %02X Added %03X = %03X + %02X\n",
  402. mcK, usFreeCode, usPrefixCode, mcK);
  403. #endif
  404. newptr = (NODE_CAST)&pstCmprsTbl[usFreeCode++];
  405. if (firstflag)
  406. tptr->first = newptr;
  407. else
  408. tptr->next = newptr;
  409. newptr->first = newptr->next = NULL;
  410. newptr->cchar = (BYTE)mcK;
  411. }
  412. else
  413. ++usFreeCode; /* triggers clearing and rebuilding of table */
  414. return(FALSE);
  415. }
  416. #endif
  417. /* end of cmprs1.c */