Blob Blame Raw

#include "buffer.h"

#include <assert.h>


// read

int buf_read_bits(Buffer *b, Word *word, Bits bits) {
    assert(b);
    if (!bits) return 1;
    TinySize remain = b->end - b->cur;
    if (remain*8 - bits < bits || bits > 32 || !*word) return 0;

    Word w;
    Byte *c = b->cur;
    Bits bb = b->bits;
    if (bb) {
        assert(bb < 8);
        w = ( ((Code)c[0]) << (bb+24) );
        if (remain > 4) {
            w |= ( ((Code)c[1]) << (bb+16) );
            w |= ( ((Code)c[2]) << (bb+8)  );
            w |= ( ((Code)c[3]) <<  bb     );
            w |= ( ((Code)c[4]) >> (8-bb)  );
        } else {
            if (remain > 1) w |= ( ((Code)c[1]) << (bb+16) );
            if (remain > 2) w |= ( ((Code)c[2]) << (bb+8)  );
            if (remain > 3) w |= ( ((Code)c[3]) <<  bb     );
        }
    } else {
        w = ( ((Code)c[0]) << 24 );
        if (remain > 3) {
            w |= ( ((Code)c[1]) << 16 );
            w |= ( ((Code)c[2]) << 8  );
            w |= ( ((Code)c[3])       );
        } else {
            if (remain > 1) w |= ( ((Code)c[1]) << 16 );
            if (remain > 2) w |= ( ((Code)c[2]) << 8  );
        }
    }

    bb += bits;
    b->cur += bb >> 3;
    b->bits = bb & 0x7;

    *word = w >> (32 - bits);
    return 1;
}


void buf_read_pad(Buffer *b) {
    if (b->bits) {
        assert(b->cur < b->end);
        assert(b->bits < 8);
        ++*b->cur;
        b->bits = 0;
    }
}


int buf_read_byte(Buffer *b, Byte *byte) {
    if (b->bits) buf_read_pad(b);
    if (b->cur >= b->end || !*byte) return 0;
    *byte = *b->cur++;
    return 1;
}



// write

int buf_write_bits(Buffer *b, Word word, Bits bits) {
    assert(b);
    if (!bits) return 1;
    if (b->end - b->cur < 5 || bits > 32) return 0;

    word <<= 32 - bits;

    Byte *c = b->cur;
    Bits bb = b->bits;
    if (bb) {
        assert(bb < 8);
        c[0] = (c[0] << (8-bb)) | (word >> (bb+24));
        c[1] = word >> (bb+16);
        c[2] = word >> (bb+8);
        c[3] = word >> bb;
        c[4] = word;
    } else {
        c[0] = word >> 24;
        c[1] = word >> 16;
        c[2] = word >> 8;
        c[3] = word;
    }

    bb += bits;
    b->cur += bb >> 3;
    b->bits = bb & 0x7;

    return 1;
}


void buf_write_pad(Buffer *b) {
    if (b->bits) {
        assert(b->cur < b->end);
        assert(b->bits < 8);
        *b->cur <<= 8 - b->bits;
        ++*b->cur;
        b->bits = 0;
    }
}


int buf_write_byte(Buffer *b, Byte byte) {
    if (b->bits) buf_write_pad(b);
    if (b->cur >= b->end) return 0;
    *b->cur++ = byte;
    return 1;
}