* from ../src/bitio.c - r/w routines are now replaceable ("virtual")
authorkramm <kramm>
Sun, 21 Apr 2002 15:01:34 +0000 (15:01 +0000)
committerkramm <kramm>
Sun, 21 Apr 2002 15:01:34 +0000 (15:01 +0000)
* implemented zlib reader.

lib/bitio.c [new file with mode: 0644]

diff --git a/lib/bitio.c b/lib/bitio.c
new file mode 100644 (file)
index 0000000..00ac647
--- /dev/null
@@ -0,0 +1,170 @@
+#define READER_TYPE_FILE 0
+#define READER_TYPE_MEM  1
+#define READER_TYPE_ZLIB 2
+#define WRITER_TYPE_FILE 0
+#define WRITER_TYPE_MEM  1
+#define WRITER_TYPE_ZLIB 2
+
+struct reader_t
+{
+    int (*read)(struct reader_t*, void*data, int len);
+    void *internal;
+    int type;
+    unsigned char mybyte;
+    unsigned char bitpos;
+};
+struct writer_t
+{
+    int (*write)(struct writer_t*, void*data, int len);
+    void *internal;
+    int type;
+    unsigned char mybyte;
+    unsigned char bitpos;
+};
+static int reader_fileread(struct reader_t*reader, void* data, int len) 
+{
+    return read((int)reader->internal, data, len);
+}
+static void reader_resetbits(struct reader_t*r)
+{
+    r->mybyte = 0;
+    r->bitpos = 8;
+}
+static void reader_init_filereader(struct reader_t*r, int handle)
+{
+    r->read = reader_fileread;
+    r->internal = (void*)handle;
+    r->type = READER_TYPE_FILE;
+    reader_resetbits(r);
+}
+#define ZLIB_BUFFER_SIZE 16384
+struct zlibinflate_t
+{
+    z_stream zs;
+    struct reader_t*input;
+    U8 readbuffer[ZLIB_BUFFER_SIZE];
+};
+static void zlib_error(int ret, char* msg, z_stream*zs)
+{
+    fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
+         msg,
+         ret,
+         zs->msg?zs->msg:"unknown");
+    perror("errno:");
+    exit(1);
+}
+static int reader_zlibinflate(struct reader_t*reader, void* data, int len);
+static void reader_init_zlibinflate(struct reader_t*r, struct reader_t*input)
+{
+    struct zlibinflate_t*z;
+    int ret;
+    z = (struct zlibinflate_t*)malloc(sizeof(struct zlibinflate_t));
+    r->internal = z;
+    r->read = reader_zlibinflate;
+    r->type = READER_TYPE_ZLIB;
+    z->input = input;
+    memset(&z->zs,0,sizeof(z_stream));
+    z->zs.zalloc = Z_NULL;
+    z->zs.zfree  = Z_NULL;
+    z->zs.opaque = Z_NULL;
+    ret = inflateInit(&z->zs);
+    if (ret != Z_OK) zlib_error(ret, "bitio:inflate_init", &z->zs);
+    reader_resetbits(r);
+}
+static int reader_zlibinflate(struct reader_t*reader, void* data, int len) 
+{
+    struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
+    int ret;
+    if(!z)
+       return 0;
+    
+    z->zs.next_out = data;
+    z->zs.avail_out = len;
+
+    while(1) {
+       if(!z->zs.avail_in) {
+           z->zs.avail_in = z->input->read(z->input, z->readbuffer, ZLIB_BUFFER_SIZE);
+           z->zs.next_in = z->readbuffer;
+       }
+       if(z->zs.avail_in)
+           ret = inflate(&z->zs, Z_NO_FLUSH);
+       else
+           ret = inflate(&z->zs, Z_FINISH);
+    
+       if (ret != Z_OK &&
+           ret != Z_STREAM_END) zlib_error(ret, "bitio:inflate_inflate", &z->zs);
+
+       if (ret == Z_STREAM_END) {
+               int pos = z->zs.next_out - (Bytef*)data;
+               ret = inflateEnd(&z->zs);
+               if (ret != Z_OK) zlib_error(ret, "bitio:inflate_end", &z->zs);
+               free(reader->internal);
+               reader->internal = 0;
+               return pos;
+       }
+       if(!z->zs.avail_out) {
+           break;
+       }
+    }
+    return len;
+}
+static unsigned int reader_readbit(struct reader_t*r)
+{
+    if(r->bitpos==8) 
+    {
+       r->bitpos=0;
+        r->read(r, &r->mybyte, 1);
+    }
+    return (r->mybyte>>(7-r->bitpos++))&1;
+}
+static unsigned int reader_readbits(struct reader_t*r, int num)
+{
+    int t;
+    int val = 0;
+    for(t=0;t<num;t++)
+    {
+       val<<=1;
+       val|=reader_readbit(r);
+    }
+    return val;
+}
+static int writer_filewrite(struct writer_t*w, void* data, int len) 
+{
+    return write((int)w->internal, data, len);
+}
+static void writer_resetbits(struct writer_t*w)
+{
+    if(w->bitpos)
+       w->write(w, &w->mybyte, 1);
+    w->bitpos = 0;
+    w->mybyte = 0;
+}
+static void writer_init_filewriter(struct writer_t*w, int handle)
+{
+    w->write = writer_filewrite;
+    w->internal = (void*)handle;
+    w->type = WRITER_TYPE_FILE;
+    w->bitpos = 0;
+    w->mybyte = 0;
+}
+static void writer_writebit(struct writer_t*w, int bit)
+{    
+    if(w->bitpos==8) 
+    {
+        w->write(w, &w->mybyte, 1);
+       w->bitpos = 0;
+       w->mybyte = 0;
+    }
+    if(bit&1)
+       w->mybyte |= 1 << (7 - w->bitpos);
+    w->bitpos ++;
+}
+static void writer_writebits(struct writer_t*w, U32 data, int bits)
+{
+    int t;
+    for(t=0;t<bits;t++)
+    {
+       writer_writebit(w, (data >> (bits-t-1))&1);
+    }
+}
+