Merge branch 'refs/heads/t/portable_io'
[paraslash.git] / bitstream.h
index 5890d08c89d4033f7fefb9a19be525860a701d77..4d81fa3b25521053c8cafcf49a4b14542b83e74a 100644 (file)
 struct getbit_context {
        /** Start of the internal buffer. */
        const uint8_t *buffer;
-       /** End of the internal buffer. */
-       const uint8_t *buffer_end;
+       /** Length of buffer in bits (always a multiple of 8). */
+       uint32_t num_bits;
        /** Bit counter. */
        int index;
 };
 
-#define VLC_TYPE int16_t
-
 /** A variable length code table. */
 struct vlc {
        /** Number of bits of the table. */
        int bits;
        /** The code and the bits table. */
-       VLC_TYPE(*table)[2];
+       int16_t (*table)[2];
        /** The size of the table. */
        int table_size;
        /** Amount of memory allocated so far. */
@@ -36,8 +34,12 @@ struct vlc {
 static inline uint32_t show_bits(struct getbit_context *gbc, int num)
 {
        int idx = gbc->index;
-       const uint8_t *p = gbc->buffer + (idx >> 3);
-       uint32_t x = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+       const char *p;
+       uint32_t x;
+
+       assert(idx + num <= gbc->num_bits);
+       p = (const char *)gbc->buffer + (idx >> 3);
+       x = read_u32_be(p);
        return (x << (idx & 7)) >> (32 - num);
 }
 
@@ -48,12 +50,13 @@ static inline int get_bits_count(struct getbit_context *gbc)
 
 static inline void skip_bits(struct getbit_context *gbc, int n)
 {
+       assert(gbc->index + n <= gbc->num_bits);
        gbc->index += n;
 }
 
 static inline unsigned int get_bits(struct getbit_context *gbc, int n)
 {
-       unsigned int ret = show_bits(gbc, n);
+       unsigned int ret = show_bits(gbc, n); /* checks n */
        skip_bits(gbc, n);
        return ret;
 }
@@ -61,8 +64,13 @@ static inline unsigned int get_bits(struct getbit_context *gbc, int n)
 /* This is rather hot, we can do better than get_bits(gbc, 1). */
 static inline unsigned int get_bit(struct getbit_context *gbc)
 {
-       int idx = gbc->index++;
-       uint8_t tmp = gbc->buffer[idx >> 3], mask = (1 << (7 - (idx & 7)));
+       int idx;
+       uint8_t tmp, mask;
+
+       assert(gbc->index < gbc->num_bits);
+       idx = gbc->index++;
+       tmp = gbc->buffer[idx >> 3];
+       mask = 1 << (7 - (idx & 7));
        return !!(tmp & mask);
 }
 
@@ -81,12 +89,11 @@ static inline void init_get_bits(struct getbit_context *gbc,
                const uint8_t *buffer, int size)
 {
        gbc->buffer = buffer;
-       gbc->buffer_end = buffer + size;
+       gbc->num_bits = size * 8;
        gbc->index = 0;
 }
 
 void init_vlc(struct vlc *vlc, int nb_bits, int nb_codes, const void *bits,
                const void *codes, int codes_size);
 void free_vlc(struct vlc *vlc);
-int get_vlc(struct getbit_context *gbc, VLC_TYPE(*table)[2], int bits,
-               int max_depth);
+int get_vlc(struct getbit_context *gbc, const struct vlc *vlc);