00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef BD_BITS_H
00024 #define BD_BITS_H
00025
00026 #include "file/file.h"
00027
00028 #include <unistd.h>
00029 #include <stdio.h>
00030
00031 #include "mythiowrapper.h"
00032
00033 #ifdef __cplusplus
00034 extern "C" {
00035 #endif
00036
00042 #define BF_BUF_SIZE (1024*32)
00043
00044 typedef struct {
00045 uint8_t *p_start;
00046 uint8_t *p;
00047 uint8_t *p_end;
00048
00049 ssize_t i_left;
00050 } BITBUFFER;
00051
00052 typedef struct {
00053 BD_FILE_H *fp;
00054 uint8_t buf[BF_BUF_SIZE];
00055 BITBUFFER bb;
00056 off_t pos;
00057 off_t end;
00058 int size;
00059 } BITSTREAM;
00060
00061 static inline void bb_init( BITBUFFER *bb, void *p_data, size_t i_data )
00062 {
00063 bb->p_start = p_data;
00064 bb->p = bb->p_start;
00065 bb->p_end = bb->p_start + i_data;
00066 bb->i_left = 8;
00067 }
00068
00069 static inline void bs_init( BITSTREAM *bs, BD_FILE_H *fp )
00070 {
00071 struct stat buf;
00072
00073 bs->fp = fp;
00074 bs->pos = 0;
00075
00076
00077
00078
00079
00080 if (file_stat(bs->fp, &buf) == 0)
00081 bs->end = buf.st_size;
00082 else
00083 bs->end = 0;
00084
00085 file_seek(bs->fp, 0, SEEK_SET);
00086 bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
00087 bb_init(&bs->bb, bs->buf, bs->size);
00088 }
00089
00090 static inline off_t bb_pos( const BITBUFFER *bb )
00091 {
00092 return 8 * ( bb->p - bb->p_start ) + 8 - bb->i_left;
00093 }
00094
00095 static inline off_t bs_pos( const BITSTREAM *bs )
00096 {
00097 return bs->pos * 8 + bb_pos(&bs->bb);
00098 }
00099
00100 static inline int bb_eof( const BITBUFFER *bb )
00101 {
00102 return bb->p >= bb->p_end ? 1: 0 ;
00103 }
00104
00105 static inline int bs_eof( const BITSTREAM *bs )
00106 {
00107 return file_eof(bs->fp) && bb_eof(&bs->bb);
00108 }
00109
00110 static inline void bb_seek( BITBUFFER *bb, off_t off, int whence)
00111 {
00112 off_t b;
00113
00114 switch (whence) {
00115 case SEEK_CUR:
00116 off = (bb->p - bb->p_start) * 8 + off;
00117 break;
00118 case SEEK_END:
00119 off = (bb->p_end - bb->p_start) * 8 - off;
00120 break;
00121 case SEEK_SET:
00122 default:
00123 break;
00124 }
00125 b = off >> 3;
00126 bb->p = &bb->p_start[b];
00127
00128 ssize_t i_tmp = bb->i_left - (off & 0x07);
00129 if (i_tmp <= 0) {
00130 bb->i_left = 8 + i_tmp;
00131 bb->p++;
00132 } else {
00133 bb->i_left = i_tmp;
00134 }
00135 }
00136
00137 static inline void bs_seek( BITSTREAM *bs, off_t off, int whence)
00138 {
00139 off_t b;
00140
00141 switch (whence) {
00142 case SEEK_CUR:
00143 off = bs->pos * 8 + (bs->bb.p - bs->bb.p_start) * 8 + off;
00144 break;
00145 case SEEK_END:
00146 off = bs->end * 8 - off;
00147 break;
00148 case SEEK_SET:
00149 default:
00150 break;
00151 }
00152 b = off >> 3;
00153 if (b >= bs->end)
00154 {
00155 if (BF_BUF_SIZE < bs->end) {
00156 bs->pos = bs->end - BF_BUF_SIZE;
00157 file_seek(bs->fp, BF_BUF_SIZE, SEEK_END);
00158 } else {
00159 bs->pos = 0;
00160 file_seek(bs->fp, 0, SEEK_SET);
00161 }
00162 bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
00163 bb_init(&bs->bb, bs->buf, bs->size);
00164 bs->bb.p = bs->bb.p_end;
00165 } else if (b < bs->pos || b >= (bs->pos + BF_BUF_SIZE)) {
00166 file_seek(bs->fp, b, SEEK_SET);
00167 bs->pos = b;
00168 bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
00169 bb_init(&bs->bb, bs->buf, bs->size);
00170 } else {
00171 b -= bs->pos;
00172 bs->bb.p = &bs->bb.p_start[b];
00173 bs->bb.i_left = 8 - (off & 0x07);
00174 }
00175 }
00176
00177 static inline void bb_seek_byte( BITBUFFER *bb, off_t off)
00178 {
00179 bb_seek(bb, off << 3, SEEK_SET);
00180 }
00181
00182 static inline void bs_seek_byte( BITSTREAM *s, off_t off)
00183 {
00184 bs_seek(s, off << 3, SEEK_SET);
00185 }
00186
00187 static inline uint32_t bb_read( BITBUFFER *bb, int i_count )
00188 {
00189 static const uint32_t i_mask[33] = {
00190 0x00,
00191 0x01, 0x03, 0x07, 0x0f,
00192 0x1f, 0x3f, 0x7f, 0xff,
00193 0x1ff, 0x3ff, 0x7ff, 0xfff,
00194 0x1fff, 0x3fff, 0x7fff, 0xffff,
00195 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
00196 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
00197 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
00198 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff
00199 };
00200 int i_shr;
00201 uint32_t i_result = 0;
00202
00203 while( i_count > 0 ) {
00204
00205 if( bb->p >= bb->p_end ) {
00206 break;
00207 }
00208
00209 i_shr = bb->i_left - i_count;
00210 if( i_shr >= 0 ) {
00211
00212 i_result |= ( *bb->p >> i_shr )&i_mask[i_count];
00213 bb->i_left -= i_count;
00214 if( bb->i_left == 0 ) {
00215 bb->p++;
00216 bb->i_left = 8;
00217 }
00218 return( i_result );
00219 } else {
00220
00221 i_result |= (*bb->p&i_mask[bb->i_left]) << -i_shr;
00222 i_count -= bb->i_left;
00223 bb->p++;
00224 bb->i_left = 8;
00225 }
00226 }
00227
00228 return( i_result );
00229 }
00230
00231 static uint32_t bs_read( BITSTREAM *bs, int i_count )
00232 {
00233 int left;
00234 int bytes = (i_count + 7) >> 3;
00235
00236 if (bs->bb.p + bytes >= bs->bb.p_end) {
00237 bs->pos = bs->pos + (bs->bb.p - bs->bb.p_start);
00238 left = bs->bb.i_left;
00239 file_seek(bs->fp, bs->pos, SEEK_SET);
00240 bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
00241 bb_init(&bs->bb, bs->buf, bs->size);
00242 bs->bb.i_left = left;
00243 }
00244 return bb_read(&bs->bb, i_count);
00245 }
00246
00247 static inline void bb_read_bytes( BITBUFFER *bb, uint8_t *buf, int i_count )
00248 {
00249 int ii;
00250
00251 for (ii = 0; ii < i_count; ii++) {
00252 buf[ii] = bb_read(bb, 8);
00253 }
00254 }
00255
00256 static inline void bs_read_bytes( BITSTREAM *s, uint8_t *buf, int i_count )
00257 {
00258 int ii;
00259
00260 for (ii = 0; ii < i_count; ii++) {
00261 buf[ii] = bs_read(s, 8);
00262 }
00263 }
00264
00265 static inline uint32_t bb_show( BITBUFFER *bb, int i_count )
00266 {
00267 BITBUFFER bb_tmp = *bb;
00268 return bb_read( &bb_tmp, i_count );
00269 }
00270
00271 static inline void bb_skip( BITBUFFER *bb, ssize_t i_count )
00272 {
00273 bb->i_left -= i_count;
00274
00275 if( bb->i_left <= 0 ) {
00276 const int i_bytes = ( -bb->i_left + 8 ) / 8;
00277
00278 bb->p += i_bytes;
00279 bb->i_left += 8 * i_bytes;
00280 }
00281 }
00282
00283 static inline void bs_skip( BITSTREAM *bs, ssize_t i_count )
00284 {
00285 int left;
00286 int bytes = i_count >> 3;
00287
00288 if (bs->bb.p + bytes >= bs->bb.p_end) {
00289 bs->pos = bs->pos + (bs->bb.p - bs->bb.p_start);
00290 left = bs->bb.i_left;
00291 file_seek(bs->fp, bs->pos, SEEK_SET);
00292 bs->size = file_read(bs->fp, bs->buf, BF_BUF_SIZE);
00293 bb_init(&bs->bb, bs->buf, bs->size);
00294 bs->bb.i_left = left;
00295 }
00296 bb_skip(&bs->bb, i_count);
00297 }
00298
00299 static inline int bb_is_align( BITBUFFER *bb, uint32_t mask )
00300 {
00301 off_t off = bb_pos(bb);
00302
00303 return !(off & mask);
00304 }
00305
00306 static inline int bs_is_align( BITSTREAM *s, uint32_t mask )
00307 {
00308 off_t off = bs_pos(s);
00309
00310 return !(off & mask);
00311 }
00312
00313 #ifdef __cplusplus
00314 };
00315 #endif
00316
00317 #endif