* from ../src/bitio.c - r/w routines are now replaceable ("virtual")
[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 *internal;
20     int type;
21     unsigned char mybyte;
22     unsigned char bitpos;
23 };
24 static int reader_fileread(struct reader_t*reader, void* data, int len) 
25 {
26     return read((int)reader->internal, data, len);
27 }
28 static void reader_resetbits(struct reader_t*r)
29 {
30     r->mybyte = 0;
31     r->bitpos = 8;
32 }
33 static void reader_init_filereader(struct reader_t*r, int handle)
34 {
35     r->read = reader_fileread;
36     r->internal = (void*)handle;
37     r->type = READER_TYPE_FILE;
38     reader_resetbits(r);
39 }
40 #define ZLIB_BUFFER_SIZE 16384
41 struct zlibinflate_t
42 {
43     z_stream zs;
44     struct reader_t*input;
45     U8 readbuffer[ZLIB_BUFFER_SIZE];
46 };
47 static void zlib_error(int ret, char* msg, z_stream*zs)
48 {
49     fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
50           msg,
51           ret,
52           zs->msg?zs->msg:"unknown");
53     perror("errno:");
54     exit(1);
55 }
56 static int reader_zlibinflate(struct reader_t*reader, void* data, int len);
57 static void reader_init_zlibinflate(struct reader_t*r, struct reader_t*input)
58 {
59     struct zlibinflate_t*z;
60     int ret;
61     z = (struct zlibinflate_t*)malloc(sizeof(struct zlibinflate_t));
62     r->internal = z;
63     r->read = reader_zlibinflate;
64     r->type = READER_TYPE_ZLIB;
65     z->input = input;
66     memset(&z->zs,0,sizeof(z_stream));
67     z->zs.zalloc = Z_NULL;
68     z->zs.zfree  = Z_NULL;
69     z->zs.opaque = Z_NULL;
70     ret = inflateInit(&z->zs);
71     if (ret != Z_OK) zlib_error(ret, "bitio:inflate_init", &z->zs);
72     reader_resetbits(r);
73 }
74 static int reader_zlibinflate(struct reader_t*reader, void* data, int len) 
75 {
76     struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
77     int ret;
78     if(!z)
79         return 0;
80     
81     z->zs.next_out = data;
82     z->zs.avail_out = len;
83
84     while(1) {
85         if(!z->zs.avail_in) {
86             z->zs.avail_in = z->input->read(z->input, z->readbuffer, ZLIB_BUFFER_SIZE);
87             z->zs.next_in = z->readbuffer;
88         }
89         if(z->zs.avail_in)
90             ret = inflate(&z->zs, Z_NO_FLUSH);
91         else
92             ret = inflate(&z->zs, Z_FINISH);
93     
94         if (ret != Z_OK &&
95             ret != Z_STREAM_END) zlib_error(ret, "bitio:inflate_inflate", &z->zs);
96
97         if (ret == Z_STREAM_END) {
98                 int pos = z->zs.next_out - (Bytef*)data;
99                 ret = inflateEnd(&z->zs);
100                 if (ret != Z_OK) zlib_error(ret, "bitio:inflate_end", &z->zs);
101                 free(reader->internal);
102                 reader->internal = 0;
103                 return pos;
104         }
105         if(!z->zs.avail_out) {
106             break;
107         }
108     }
109     return len;
110 }
111 static unsigned int reader_readbit(struct reader_t*r)
112 {
113     if(r->bitpos==8) 
114     {
115         r->bitpos=0;
116         r->read(r, &r->mybyte, 1);
117     }
118     return (r->mybyte>>(7-r->bitpos++))&1;
119 }
120 static unsigned int reader_readbits(struct reader_t*r, int num)
121 {
122     int t;
123     int val = 0;
124     for(t=0;t<num;t++)
125     {
126         val<<=1;
127         val|=reader_readbit(r);
128     }
129     return val;
130 }
131 static int writer_filewrite(struct writer_t*w, void* data, int len) 
132 {
133     return write((int)w->internal, data, len);
134 }
135 static void writer_resetbits(struct writer_t*w)
136 {
137     if(w->bitpos)
138         w->write(w, &w->mybyte, 1);
139     w->bitpos = 0;
140     w->mybyte = 0;
141 }
142 static void writer_init_filewriter(struct writer_t*w, int handle)
143 {
144     w->write = writer_filewrite;
145     w->internal = (void*)handle;
146     w->type = WRITER_TYPE_FILE;
147     w->bitpos = 0;
148     w->mybyte = 0;
149 }
150 static void writer_writebit(struct writer_t*w, int bit)
151 {    
152     if(w->bitpos==8) 
153     {
154         w->write(w, &w->mybyte, 1);
155         w->bitpos = 0;
156         w->mybyte = 0;
157     }
158     if(bit&1)
159         w->mybyte |= 1 << (7 - w->bitpos);
160     w->bitpos ++;
161 }
162 static void writer_writebits(struct writer_t*w, U32 data, int bits)
163 {
164     int t;
165     for(t=0;t<bits;t++)
166     {
167         writer_writebit(w, (data >> (bits-t-1))&1);
168     }
169 }
170