upload tizen1.0 source
[framework/uifw/xorg/lib/libxfont.git] / src / fontfile / bunzip2.c
1 /* Based on src/fontfile/gunzip.c
2    written by Mark Eichin <eichin@kitten.gen.ma.us> September 1996.
3    intended for inclusion in X11 public releases. */
4
5 /*
6  * Copyright © 2008 Sun Microsystems, Inc.  All rights reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the next
16  * paragraph) shall be included in all copies or substantial portions of the
17  * Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  */
27
28
29 #include "config.h"
30
31 #include <X11/fonts/fontmisc.h>
32 #include <X11/fonts/bufio.h>
33 #include <bzlib.h>
34
35 typedef struct _xzip_buf {
36     bz_stream z;
37     int zstat;
38     BufChar b[BUFFILESIZE];
39     BufChar b_in[BUFFILESIZE];
40     BufFilePtr f;
41 } xzip_buf;
42
43 static int BufBzip2FileClose ( BufFilePtr f, int flag );
44 static int BufBzip2FileFill ( BufFilePtr f );
45 static int BufBzip2FileSkip ( BufFilePtr f, int c );
46
47 _X_HIDDEN BufFilePtr
48 BufFilePushBZIP2 (BufFilePtr f)
49 {
50     xzip_buf *x;
51
52     x = malloc (sizeof (xzip_buf));
53     if (!x) return NULL;
54
55     bzero(&(x->z), sizeof(bz_stream));
56     x->f = f;
57
58     x->zstat = BZ2_bzDecompressInit(&(x->z),
59                                     0,  /* verbosity: 0 silent, 4 max */
60                                     0); /* 0: go faster, 1: use less memory */
61     if (x->zstat != BZ_OK) {
62         free(x);
63         return NULL;
64     }
65
66     /* now that the history buffer is allocated, we provide the data buffer */
67     x->z.next_out = (char *) x->b;
68     x->z.avail_out = BUFFILESIZE;
69     x->z.next_in = (char *) x->b_in;
70     x->z.avail_in = 0;
71
72     return BufFileCreate((char *)x,
73                          BufBzip2FileFill,
74                          NULL,
75                          BufBzip2FileSkip,
76                          BufBzip2FileClose);
77 }
78
79 static int 
80 BufBzip2FileClose(BufFilePtr f, int flag)
81 {
82     xzip_buf *x = (xzip_buf *)f->private;
83     BZ2_bzDecompressEnd (&(x->z));
84     BufFileClose (x->f, flag);
85     free (x);
86     return 1;
87 }
88
89 /* here's the real work. 
90    -- we need to put stuff in f.buffer, update f.left and f.bufp,
91    then return the first byte (or BUFFILEEOF).
92    -- to do this, we need to get stuff into avail_in, and next_in, 
93    and call BZ2_bzDecompress appropriately.
94    -- we may also need to add CRC maintenance - if BZ2_bzDecompress tells us
95    BZ_STREAM_END, we then have 4bytes CRC and 4bytes length...
96 */
97 static int 
98 BufBzip2FileFill (BufFilePtr f)
99 {
100     xzip_buf *x = (xzip_buf *)f->private;
101
102     /* we only get called when left == 0... */
103     /* but just in case, deal */
104     if (f->left >= 0) {
105         f->left--;
106         return *(f->bufp++);
107     }
108     /* did we run out last time? */
109     switch (x->zstat) {
110     case BZ_OK:
111         break;
112     case BZ_STREAM_END:
113     case BZ_DATA_ERROR:
114     case BZ_DATA_ERROR_MAGIC:
115         f->left = 0;
116         return BUFFILEEOF;
117     default:
118         return BUFFILEEOF;
119     }
120     /* now we work to consume what we can */
121     /* let libbz2 know what we can handle */
122     x->z.next_out = (char *) x->b;
123     x->z.avail_out = BUFFILESIZE;
124
125     /* and try to consume all of it */
126     while (x->z.avail_out > 0) {
127         /* if we don't have anything to work from... */
128         if (x->z.avail_in == 0) {
129             /* ... fill the z buf from underlying file */
130             int i, c;
131             for (i = 0; i < sizeof(x->b_in); i++) {
132                 c = BufFileGet(x->f);
133                 if (c == BUFFILEEOF) break;
134                 x->b_in[i] = c;
135             }
136             x->z.avail_in += i;
137             x->z.next_in = (char *) x->b_in;
138         }
139         /* so now we have some output space and some input data */
140         x->zstat = BZ2_bzDecompress(&(x->z));
141         /* the inflation output happens in the f buffer directly... */
142         if (x->zstat == BZ_STREAM_END) {
143             /* deal with EOF, crc */
144             break;
145         }
146         if (x->zstat != BZ_OK) {
147             break;
148         }
149     }
150     f->bufp = x->b;
151     f->left = BUFFILESIZE - x->z.avail_out;  
152
153     if (f->left >= 0) {
154         f->left--;
155         return *(f->bufp++);
156     } else {
157         return BUFFILEEOF;
158     }
159 }
160
161 /* there should be a BufCommonSkip... */
162 static int 
163 BufBzip2FileSkip (BufFilePtr f, int c)
164 {
165     /* BufFileRawSkip returns the count unchanged.
166        BufCompressedSkip returns 0.
167        That means it probably never gets called... */
168     int retval = c;
169     while(c--) {
170         int get = BufFileGet(f);
171         if (get == BUFFILEEOF) return get;
172     }
173     return retval;
174 }