Blame arch.c

9953f6
9953f6
#include "arch.h"
9953f6
9953f6
#include <assert.h></assert.h>
9953f6
#include <stdlib.h></stdlib.h>
9953f6
#include <string.h></string.h>
576e4a
//#include <stdio.h></stdio.h>
9953f6
9953f6
9953f6
enum {
9953f6
    NO_CODE   = 0xffff,
9953f6
    DICT_SIZE = 0xffff };
9953f6
9953f6
9953f6
int arch_init(Arch *a) {
9953f6
    memset(a, 0, sizeof(*a));
576e4a
    a->entries = (Entry*)calloc(sizeof(Entry), DICT_SIZE);
9953f6
    if (!a->entries) return RES_FAIL;
9953f6
    for(int i = 0; i < 256; ++i) {
9953f6
        Entry *e = a->entries + i;
9953f6
        memset(e->children, 0xff, sizeof(e->children));
9953f6
        e->value = i;
9953f6
        a->root.children[i] = i;
9953f6
    }
9953f6
    a->nextcode = 0x100;
9953f6
    a->codebits = 9;
9953f6
    return RES_DONE;
9953f6
}
9953f6
9953f6
9953f6
void arch_deinit(Arch *a) {
9953f6
    free(a->entries);
9953f6
    memset(a, 0, sizeof(*a));
9953f6
}
9953f6
9953f6
576e4a
static void arch_entry_use(Arch *a, Entry *e) {
576e4a
    if (!e->parent) return;
576e4a
    if (e->next) {
576e4a
        if (e->prev) e->prev->next = e->next;
576e4a
                     else a->first = e->next;
576e4a
        e->next->prev = e->prev;
576e4a
        e->prev = a->last;
576e4a
        e->next = NULL;
576e4a
        a->last = a->last->next = e;
576e4a
    }
576e4a
    arch_entry_use(a, e->parent);
9953f6
}
9953f6
9953f6
9953f6
static Entry* arch_entry_add(Arch *a, Entry *parent, Byte value) {
9953f6
    Entry *e;
9953f6
    Code nextcode = a->nextcode;
9953f6
    if (nextcode < DICT_SIZE) {
9953f6
        ++a->nextcode;
9953f6
        if (!(nextcode & a->nextcode)) ++a->codebits;
9953f6
        assert(a->codebits <= 16);
576e4a
        assert(nextcode < DICT_SIZE);
576e4a
        e = a->entries + nextcode;
9953f6
        memset(e->children, 0xff, sizeof(e->children));
576e4a
        e->prev = a->last; e->next = NULL;
576e4a
        if (a->last) a->last->next = e;
576e4a
                     else a->first = e;
576e4a
        a->last = e;
9953f6
    } else {
576e4a
        arch_entry_use(a, parent);
576e4a
9953f6
        e = a->first;
9953f6
        assert(e);
576e4a
        assert(e != parent);
9953f6
        assert(e->parent);
9953f6
        assert(e->parent->children[e->value] == e - a->entries);
9953f6
        e->parent->children[e->value] = NO_CODE;
576e4a
576e4a
        //assert(!e->prev);
576e4a
        //assert(e->next);
576e4a
        //a->first = e->next; e->prev = a->last;
576e4a
        //e->next = e->next->prev = NULL;
576e4a
        //a->last = a->last->next = e;
9953f6
    }
9953f6
9953f6
    assert(parent);
9953f6
    assert(parent->children[value] == NO_CODE);
576e4a
    e->value = value;
9953f6
    e->parent = parent;
9953f6
    parent->children[value] = e - a->entries;
576e4a
    //printf("add code: %d\n", (int)(e - a->entries));
576e4a
    //for(int i = 0; i < 256; ++i) assert(e->children[i] == NO_CODE);
9953f6
576e4a
    arch_entry_use(a, e);
9953f6
    return e;
9953f6
}
9953f6
9953f6
9953f6
int arch_deflate(Arch *a, int final) {
9953f6
    if (a->rb.bits) return RES_FAIL;
9953f6
    while(1) {
576e4a
        if (a->wb.end - a->wb.cur < 5) return RES_RETRY;
9953f6
        Entry *e = &a->root;
9953f6
        Byte *bp = a->rb.cur;
576e4a
        Bits codebits = a->codebits;
9953f6
        while(1) {
9953f6
            Byte b;
9953f6
            if (!buf_read_byte(&a->rb, &b)) {
576e4a
                if (final) { arch_entry_use(a, e); break; }
9953f6
                a->rb.cur = bp;
9953f6
                break;
9953f6
            }
9953f6
            if (e->children[b] == NO_CODE) { e = arch_entry_add(a, e, b); break; }
576e4a
            e = a->entries + e->children[b];
9953f6
        }
9953f6
        if (bp == a->rb.cur) break;
9953f6
9953f6
        assert(e);
9953f6
        assert(e != &a->root);
576e4a
576e4a
        Code code; Byte b = e->value;
576e4a
        if (e->parent) { code = e->parent - a->entries; }
576e4a
                  else { code = a->nextcode; assert(final); }
576e4a
        //printf("pos: %d/%d, code %d/%d, byte %d (%c)\n", (int)(a->rb.cur - a->rb.begin), (int)(a->rb.end - a->rb.begin), (int)code, (int)a->nextcode, (int)b, (char)b);
576e4a
        if ( !buf_write_bits(&a->wb, (((Word)code) << 8) | b, codebits + 8) ) return RES_FAIL;
9953f6
    }
9953f6
9953f6
    if (final && a->rb.cur >= a->rb.end) { buf_write_pad(&a->wb); return RES_DONE; }
9953f6
    return RES_RETRY;
9953f6
}
9953f6
9953f6
9953f6
static int arch_entry_write(Arch *a, Entry *e, TinySize count) {
9953f6
    if (!e->parent) {
9953f6
        if (a->wb.end - a->wb.cur < count) return 0;
9953f6
    } else {
9953f6
        if (!arch_entry_write(a, e->parent, count+1)) return 0;
9953f6
    }
576e4a
    //fputc(e->value, stdout);
9953f6
    buf_write_byte(&a->wb, e->value);
9953f6
    return 1;
9953f6
}
9953f6
9953f6
9953f6
int arch_inflate(Arch *a, int final) {
9953f6
    if (a->wb.bits) return RES_FAIL;
9953f6
    while(1) {
9953f6
        Byte *bp = a->rb.cur;
9953f6
        Bits bb = a->rb.bits;
9953f6
576e4a
        Word w;
576e4a
        if (!buf_read_bits(&a->rb, &w, a->codebits + 8)) break;
576e4a
        Code code = w >> 8;
576e4a
        Byte b = w;
9953f6
576e4a
        //printf("pos: %d/%d + %d, code %d/%d, byte %d (%c)\n", (int)(a->rb.cur - a->rb.begin), (int)(a->rb.end - a->rb.begin), (int)a->rb.bits, (int)code, (int)a->nextcode, (int)b, (char)b);
576e4a
        if (code < a->nextcode) {
576e4a
            Entry *e = &a->entries[code];
576e4a
            if (!arch_entry_write(a, e, 1)) {
576e4a
                a->rb.cur = bp;
576e4a
                a->rb.bits = bb;
576e4a
                return RES_RETRY;
576e4a
            }
576e4a
            //fputc(b, stdout); fputc('\n', stdout);
576e4a
            if (e->children[b] == NO_CODE) e = arch_entry_add(a, e, b); else arch_entry_use(a, e);
576e4a
        } else
576e4a
        if (code != a->nextcode) {
576e4a
            return RES_FAIL;
576e4a
        } else {
576e4a
            //printf("pos: %d/%d + %d, code %d/%d, byte %d (%c)\n", (int)(a->rb.cur - a->rb.begin), (int)(a->rb.end - a->rb.begin), (int)a->rb.bits, (int)code, (int)a->nextcode, (int)b, (char)b);
9953f6
        }
9953f6
576e4a
        if (!buf_write_byte(&a->wb, b)) return RES_FAIL;
9953f6
    }
9953f6
9953f6
    if (final) { buf_read_pad(&a->rb); return RES_DONE; }
9953f6
    return RES_RETRY;
9953f6
}
9953f6