decompress.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: decompress.c /main/4 1995/10/26 12:36:44 rswiston $ */
  24. /*
  25. * decompress - cat a compressed file
  26. *
  27. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  28. * (c) Copyright 1993, 1994 International Business Machines Corp.
  29. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  30. * (c) Copyright 1993, 1994 Novell, Inc.
  31. */
  32. /* #include "fontmisc.h" */
  33. #include <unistd.h>
  34. #include <fcntl.h>
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <sys/stat.h>
  38. #include "bufioI.h"
  39. #define BITS 16
  40. /*
  41. * a code_int must be able to hold 2**BITS values of type int, and also -1
  42. */
  43. #if BITS > 15
  44. typedef long int code_int;
  45. #else
  46. typedef int code_int;
  47. #endif
  48. typedef long int count_int;
  49. #ifdef NO_UCHAR
  50. typedef char char_type;
  51. #else
  52. typedef unsigned char char_type;
  53. #endif /* UCHAR */
  54. static int magic_header[] = { 0x1F, 0x9D };
  55. /* Defines for third byte of header */
  56. #define BIT_MASK 0x1f
  57. #define BLOCK_MASK 0x80
  58. /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
  59. a fourth header byte (for expansion).
  60. */
  61. #define INIT_BITS 9 /* initial number of bits/code */
  62. #ifdef COMPATIBLE /* But wrong! */
  63. # define MAXCODE(n_bits) (1 << (n_bits) - 1)
  64. #else
  65. # define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
  66. #endif /* COMPATIBLE */
  67. static code_int getcode();
  68. /*
  69. * the next two codes should not be changed lightly, as they must not
  70. * lie within the contiguous general code space.
  71. */
  72. #define FIRST 257 /* first free entry */
  73. #define CLEAR 256 /* table clear output code */
  74. #define STACK_SIZE 8192
  75. typedef struct _compressedFILE {
  76. BufFilePtr file;
  77. char_type *stackp;
  78. code_int oldcode;
  79. char_type finchar;
  80. int block_compress;
  81. int maxbits;
  82. code_int maxcode, maxmaxcode;
  83. code_int free_ent;
  84. int clear_flg;
  85. int n_bits;
  86. /* bit buffer */
  87. int offset, size;
  88. char_type buf[BITS];
  89. char_type de_stack[STACK_SIZE];
  90. char_type *tab_suffix;
  91. unsigned short *tab_prefix;
  92. } CompressedFile;
  93. static int hsize_table[] = {
  94. 5003, /* 12 bits - 80% occupancy */
  95. 9001, /* 13 bits - 91% occupancy */
  96. 18013, /* 14 bits - 91% occupancy */
  97. 35023, /* 15 bits - 94% occupancy */
  98. 69001 /* 16 bits - 95% occupancy */
  99. };
  100. static int BufCompressedFill(), BufCompressedSkip(), BufCompressedClose();
  101. BufFilePtr
  102. _DtHelpCeBufFilePushZ (BufFilePtr f)
  103. {
  104. int code;
  105. int maxbits;
  106. int hsize;
  107. CompressedFile *file;
  108. int extra;
  109. if ((BufFileGet(f) != magic_header[0]) ||
  110. (BufFileGet(f) != magic_header[1]))
  111. {
  112. return 0;
  113. }
  114. code = BufFileGet (f);
  115. maxbits = code & BIT_MASK;
  116. if (maxbits > BITS || maxbits < 12)
  117. return 0;
  118. hsize = hsize_table[maxbits - 12];
  119. extra = (1 << maxbits) * sizeof (char_type) +
  120. hsize * sizeof (unsigned short);
  121. file = (CompressedFile *) malloc (sizeof (CompressedFile) + extra);
  122. if (!file)
  123. return 0;
  124. file->file = f;
  125. file->maxbits = maxbits;
  126. file->block_compress = code & BLOCK_MASK;
  127. file->maxmaxcode = 1 << file->maxbits;
  128. file->tab_suffix = (char_type *) &file[1];
  129. file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
  130. /*
  131. * As above, initialize the first 256 entries in the table.
  132. */
  133. file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
  134. for ( code = 255; code >= 0; code-- ) {
  135. file->tab_prefix[code] = 0;
  136. file->tab_suffix[code] = (char_type) code;
  137. }
  138. file->free_ent = ((file->block_compress) ? FIRST : 256 );
  139. file->clear_flg = 0;
  140. file->offset = 0;
  141. file->size = 0;
  142. file->stackp = file->de_stack;
  143. file->finchar = file->oldcode = getcode (file);
  144. if (file->oldcode != -1)
  145. *file->stackp++ = file->finchar;
  146. return _DtHelpCeBufFileCreate ((char *) file,
  147. BufCompressedFill,
  148. BufCompressedSkip,
  149. BufCompressedClose);
  150. }
  151. static int
  152. BufCompressedClose (
  153. BufFilePtr f,
  154. int doClose )
  155. {
  156. CompressedFile *file;
  157. BufFilePtr raw;
  158. file = (CompressedFile *) f->hidden;
  159. raw = file->file;
  160. free (file);
  161. _DtHelpCeBufFileClose (raw, doClose);
  162. return 1;
  163. }
  164. static int
  165. BufCompressedFill (BufFilePtr f)
  166. {
  167. CompressedFile *file;
  168. char_type *stackp, *de_stack;
  169. char_type finchar;
  170. code_int code, oldcode, incode;
  171. BufChar *buf, *bufend;
  172. file = (CompressedFile *) f->hidden;
  173. buf = f->buffer;
  174. bufend = buf + BUFFILESIZE;
  175. stackp = file->stackp;
  176. de_stack = file->de_stack;
  177. finchar = file->finchar;
  178. oldcode = file->oldcode;
  179. while (buf < bufend) {
  180. while (stackp > de_stack && buf < bufend)
  181. *buf++ = *--stackp;
  182. if (buf == bufend)
  183. break;
  184. if (oldcode == -1)
  185. break;
  186. code = getcode (file);
  187. if (code == -1)
  188. break;
  189. if ( (code == CLEAR) && file->block_compress ) {
  190. for ( code = 255; code >= 0; code-- )
  191. file->tab_prefix[code] = 0;
  192. file->clear_flg = 1;
  193. file->free_ent = FIRST - 1;
  194. if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
  195. break;
  196. }
  197. incode = code;
  198. /*
  199. * Special case for KwKwK string.
  200. */
  201. if ( code >= file->free_ent ) {
  202. *stackp++ = finchar;
  203. code = oldcode;
  204. }
  205. /*
  206. * Generate output characters in reverse order
  207. */
  208. while ( code >= 256 )
  209. {
  210. *stackp++ = file->tab_suffix[code];
  211. code = file->tab_prefix[code];
  212. }
  213. finchar = file->tab_suffix[code];
  214. *stackp++ = finchar;
  215. /*
  216. * Generate the new entry.
  217. */
  218. if ( (code=file->free_ent) < file->maxmaxcode ) {
  219. file->tab_prefix[code] = (unsigned short)oldcode;
  220. file->tab_suffix[code] = finchar;
  221. file->free_ent = code+1;
  222. }
  223. /*
  224. * Remember previous code.
  225. */
  226. oldcode = incode;
  227. }
  228. file->oldcode = oldcode;
  229. file->stackp = stackp;
  230. file->finchar = finchar;
  231. if (buf == f->buffer) {
  232. f->left = 0;
  233. return BUFFILEEOF;
  234. }
  235. f->bufp = f->buffer + 1;
  236. f->left = (buf - f->buffer) - 1;
  237. return f->buffer[0];
  238. }
  239. /*****************************************************************
  240. * TAG( getcode )
  241. *
  242. * Read one code from the standard input. If BUFFILEEOF, return -1.
  243. * Inputs:
  244. * stdin
  245. * Outputs:
  246. * code or -1 is returned.
  247. */
  248. static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  249. static code_int
  250. getcode(CompressedFile *file)
  251. {
  252. code_int code;
  253. int r_off, bits;
  254. char_type *bp = file->buf;
  255. BufFilePtr raw;
  256. if ( file->clear_flg > 0 || file->offset >= file->size ||
  257. file->free_ent > file->maxcode )
  258. {
  259. /*
  260. * If the next entry will be too big for the current code
  261. * size, then we must increase the size. This implies reading
  262. * a new buffer full, too.
  263. */
  264. if ( file->free_ent > file->maxcode ) {
  265. file->n_bits++;
  266. if ( file->n_bits == file->maxbits )
  267. file->maxcode = file->maxmaxcode; /* won't get any bigger now */
  268. else
  269. file->maxcode = MAXCODE(file->n_bits);
  270. }
  271. if ( file->clear_flg > 0) {
  272. file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
  273. file->clear_flg = 0;
  274. }
  275. bits = file->n_bits;
  276. raw = file->file;
  277. while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
  278. {
  279. *bp++ = code;
  280. --bits;
  281. }
  282. bp = file->buf;
  283. if (bits == file->n_bits)
  284. return -1; /* end of file */
  285. file->size = file->n_bits - bits;
  286. file->offset = 0;
  287. /* Round size down to integral number of codes */
  288. file->size = (file->size << 3) - (file->n_bits - 1);
  289. }
  290. r_off = file->offset;
  291. bits = file->n_bits;
  292. /*
  293. * Get to the first byte.
  294. */
  295. bp += (r_off >> 3);
  296. r_off &= 7;
  297. /* Get first part (low order bits) */
  298. #ifdef NO_UCHAR
  299. code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
  300. #else
  301. code = (*bp++ >> r_off);
  302. #endif /* NO_UCHAR */
  303. bits -= (8 - r_off);
  304. r_off = 8 - r_off; /* now, offset into code word */
  305. /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  306. if ( bits >= 8 ) {
  307. #ifdef NO_UCHAR
  308. code |= (*bp++ & 0xff) << r_off;
  309. #else
  310. code |= *bp++ << r_off;
  311. #endif /* NO_UCHAR */
  312. r_off += 8;
  313. bits -= 8;
  314. }
  315. /* high order bits. */
  316. code |= (*bp & rmask[bits]) << r_off;
  317. file->offset += file->n_bits;
  318. return code;
  319. }
  320. static int
  321. BufCompressedSkip (
  322. BufFilePtr f,
  323. int bytes)
  324. {
  325. int c = 0;
  326. while (bytes-- && ((c = BufFileGet(f)) != BUFFILEEOF))
  327. ;
  328. return c;
  329. }
  330. int
  331. _DtHelpCeUncompressFile(
  332. char *infile,
  333. char *outfile )
  334. {
  335. BufFilePtr inputraw, input, output;
  336. int c;
  337. int inFd, outFd;
  338. struct stat statBuf;
  339. CECompressInfoPtr myInfo;
  340. inFd = open(infile, O_RDONLY);
  341. if (inFd < 0) return -1;
  342. if (fstat(inFd, &statBuf) < 0)
  343. {
  344. close(inFd);
  345. return -1;
  346. }
  347. outFd = open(outfile, O_CREAT | O_WRONLY, 0666);
  348. if (outFd < 0)
  349. {
  350. close(inFd);
  351. return -1;
  352. }
  353. myInfo = (CECompressInfoPtr) malloc (sizeof(CECompressInfo));
  354. if (myInfo == NULL)
  355. {
  356. close(inFd);
  357. close(outFd);
  358. return -1;
  359. }
  360. myInfo->fd = inFd;
  361. myInfo->size = statBuf.st_size;
  362. inputraw = _DtHelpCeBufFileRdRawZ (myInfo);
  363. input = _DtHelpCeBufFilePushZ (inputraw);
  364. output = _DtHelpCeBufFileOpenWr (outFd);
  365. while ((c = BufFileGet (input)) != -1)
  366. BufFilePut (c, output);
  367. c = myInfo->size;
  368. _DtHelpCeBufFileClose (input, TRUE);
  369. _DtHelpCeBufFileClose (output, TRUE);
  370. if (c != 0) /* didn't consume all the bytes in the file */
  371. return -1;
  372. return 0;
  373. }