brought up to date.
[swftools.git] / lib / bitio.c
1 #define READER_TYPE_FILE 0
2 #define READER_TYPE_MEM  1
3 #define READER_TYPE_ZLIB 2
4 #define WRITER_TYPE_FILE 0
5 #define WRITER_TYPE_MEM  1
6 #define WRITER_TYPE_ZLIB 2
7
8 struct reader_t
9 {
10     int (*read)(struct reader_t*, void*data, int len);
11     void *internal;
12     int type;
13     unsigned char mybyte;
14     unsigned char bitpos;
15 };
16 struct writer_t
17 {
18     int (*write)(struct writer_t*, void*data, int len);
19     void (*finish)(struct writer_t*);
20     void *internal;
21     int type;
22     unsigned char mybyte;
23     unsigned char bitpos;
24 };
25 static int reader_fileread(struct reader_t*reader, void* data, int len) 
26 {
27     return read((int)reader->internal, data, len);
28 }
29 static void reader_resetbits(struct reader_t*r)
30 {
31     r->mybyte = 0;
32     r->bitpos = 8;
33 }
34 static void reader_init_filereader(struct reader_t*r, int handle)
35 {
36     r->read = reader_fileread;
37     r->internal = (void*)handle;
38     r->type = READER_TYPE_FILE;
39     r->mybyte = 0;
40     r->bitpos = 8;
41 }
42 #define ZLIB_BUFFER_SIZE 16384
43 struct zlibinflate_t
44 {
45     z_stream zs;
46     struct reader_t*input;
47     U8 readbuffer[ZLIB_BUFFER_SIZE];
48 };
49 static void zlib_error(int ret, char* msg, z_stream*zs)
50 {
51     fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
52           msg,
53           ret,
54           zs->msg?zs->msg:"unknown");
55     perror("errno:");
56     exit(1);
57 }
58 static int reader_zlibinflate(struct reader_t*reader, void* data, int len);
59 static void reader_init_zlibinflate(struct reader_t*r, struct reader_t*input)
60 {
61     struct zlibinflate_t*z;
62     int ret;
63     memset(r, 0, sizeof(struct reader_t));
64     z = (struct zlibinflate_t*)malloc(sizeof(struct zlibinflate_t));
65     memset(z, 0, sizeof(struct zlibinflate_t));
66     r->internal = z;
67     r->read = reader_zlibinflate;
68     r->type = READER_TYPE_ZLIB;
69     z->input = input;
70     memset(&z->zs,0,sizeof(z_stream));
71     z->zs.zalloc = Z_NULL;
72     z->zs.zfree  = Z_NULL;
73     z->zs.opaque = Z_NULL;
74     ret = inflateInit(&z->zs);
75     if (ret != Z_OK) zlib_error(ret, "bitio:inflate_init", &z->zs);
76     reader_resetbits(r);
77 }
78 static int reader_zlibinflate(struct reader_t*reader, void* data, int len) 
79 {
80     struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
81     int ret;
82     if(!z)
83         return 0;
84     
85     z->zs.next_out = data;
86     z->zs.avail_out = len;
87
88     while(1) {
89         if(!z->zs.avail_in) {
90             z->zs.avail_in = z->input->read(z->input, z->readbuffer, ZLIB_BUFFER_SIZE);
91             z->zs.next_in = z->readbuffer;
92         }
93         if(z->zs.avail_in)
94             ret = inflate(&z->zs, Z_NO_FLUSH);
95         else
96             ret = inflate(&z->zs, Z_FINISH);
97     
98         if (ret != Z_OK &&
99             ret != Z_STREAM_END) zlib_error(ret, "bitio:inflate_inflate", &z->zs);
100
101         if (ret == Z_STREAM_END) {
102                 int pos = z->zs.next_out - (Bytef*)data;
103                 ret = inflateEnd(&z->zs);
104                 if (ret != Z_OK) zlib_error(ret, "bitio:inflate_end", &z->zs);
105                 free(reader->internal);
106                 reader->internal = 0;
107                 return pos;
108         }
109         if(!z->zs.avail_out) {
110             break;
111         }
112     }
113     return len;
114 }
115 static unsigned int reader_readbit(struct reader_t*r)
116 {
117     if(r->bitpos==8) 
118     {
119         r->bitpos=0;
120         r->read(r, &r->mybyte, 1);
121     }
122     return (r->mybyte>>(7-r->bitpos++))&1;
123 }
124 static unsigned int reader_readbits(struct reader_t*r, int num)
125 {
126     int t;
127     int val = 0;
128     for(t=0;t<num;t++)
129     {
130         val<<=1;
131         val|=reader_readbit(r);
132     }
133     return val;
134 }
135 static int writer_filewrite_write(struct writer_t*w, void* data, int len) 
136 {
137     return write((int)w->internal, data, len);
138 }
139 static void writer_filewrite_finish(struct writer_t*w)
140 {
141 }
142 static void writer_resetbits(struct writer_t*w)
143 {
144     if(w->bitpos)
145         w->write(w, &w->mybyte, 1);
146     w->bitpos = 0;
147     w->mybyte = 0;
148 }
149 static void writer_init_filewriter(struct writer_t*w, int handle)
150 {
151     memset(w, 0, sizeof(struct writer_t));
152     w->write = writer_filewrite_write;
153     w->finish = writer_filewrite_finish;
154     w->internal = (void*)handle;
155     w->type = WRITER_TYPE_FILE;
156     w->bitpos = 0;
157     w->mybyte = 0;
158 }
159 struct zlibdeflate_t
160 {
161     z_stream zs;
162     struct writer_t*output;
163     U8 writebuffer[ZLIB_BUFFER_SIZE];
164 };
165 static int writer_zlibdeflate_write(struct writer_t*writer, void* data, int len);
166 static void writer_zlibdeflate_finish(struct writer_t*writer);
167 static void writer_init_zlibdeflate(struct writer_t*w, struct writer_t*output)
168 {
169     struct zlibdeflate_t*z;
170     int ret;
171     memset(w, 0, sizeof(struct writer_t));
172     z = (struct zlibdeflate_t*)malloc(sizeof(struct zlibdeflate_t));
173     memset(z, 0, sizeof(struct zlibdeflate_t));
174     w->internal = z;
175     w->write = writer_zlibdeflate_write;
176     w->finish = writer_zlibdeflate_finish;
177     w->type = WRITER_TYPE_ZLIB;
178     z->output = output;
179     memset(&z->zs,0,sizeof(z_stream));
180     z->zs.zalloc = Z_NULL;
181     z->zs.zfree  = Z_NULL;
182     z->zs.opaque = Z_NULL;
183     ret = deflateInit(&z->zs, 9);
184     if (ret != Z_OK) zlib_error(ret, "bitio:deflate_init", &z->zs);
185     w->bitpos = 0;
186     w->mybyte = 0;
187     z->zs.next_out = z->writebuffer;
188     z->zs.avail_out = ZLIB_BUFFER_SIZE;
189 }
190 static int writer_zlibdeflate_write(struct writer_t*writer, void* data, int len) 
191 {
192     struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
193     int ret;
194     if(!z)
195         return 0;
196     
197     z->zs.next_in = data;
198     z->zs.avail_in = len;
199
200     while(1) {
201         ret = deflate(&z->zs, Z_NO_FLUSH);
202         
203         if (ret != Z_OK) zlib_error(ret, "bitio:deflate_deflate", &z->zs);
204
205         if(z->zs.next_out != z->writebuffer) {
206             z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
207             z->zs.next_out = z->writebuffer;
208             z->zs.avail_out = ZLIB_BUFFER_SIZE;
209         }
210
211         if(!z->zs.avail_in) {
212             break;
213         }
214     }
215     return len;
216 }
217 static void writer_zlibdeflate_finish(struct writer_t*writer)
218 {
219     struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
220     struct writer_t*output;
221     int ret;
222     if(!z)
223         return;
224     output= z->output;
225     while(1) {
226         ret = deflate(&z->zs, Z_FINISH);
227         if (ret != Z_OK &&
228             ret != Z_STREAM_END) zlib_error(ret, "bitio:deflate_deflate", &z->zs);
229
230         if(z->zs.next_out != z->writebuffer) {
231             z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
232             z->zs.next_out = z->writebuffer;
233             z->zs.avail_out = ZLIB_BUFFER_SIZE;
234         }
235
236         if (ret == Z_STREAM_END) {
237             break;
238
239         }
240     }
241     ret = deflateEnd(&z->zs);
242     if (ret != Z_OK) zlib_error(ret, "bitio:deflate_end", &z->zs);
243     free(writer->internal);
244     writer->internal = 0;
245     output->finish(output);
246 }
247
248 static void writer_writebit(struct writer_t*w, int bit)
249 {    
250     if(w->bitpos==8) 
251     {
252         w->write(w, &w->mybyte, 1);
253         w->bitpos = 0;
254         w->mybyte = 0;
255     }
256     if(bit&1)
257         w->mybyte |= 1 << (7 - w->bitpos);
258     w->bitpos ++;
259 }
260 static void writer_writebits(struct writer_t*w, U32 data, int bits)
261 {
262     int t;
263     for(t=0;t<bits;t++)
264     {
265         writer_writebit(w, (data >> (bits-t-1))&1);
266     }
267 }
268