CDG: fix seek
[vlc.git] / include / vlc_bits.h
blob3e0478f4de3cd2dd04eaf79dbb91e34ed0de0f9c
1 /*****************************************************************************
2 * vlc_bits.h : Bit handling helpers
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin at videolan dot org>
9 * Rafaël Carré <funman at videolan dot org>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 #ifndef VLC_BITS_H
27 #define VLC_BITS_H 1
29 #include <vlc_common.h>
30 #include <vlc_block.h>
32 /**
33 * \file
34 * This file defines functions, structures for handling streams of bits in vlc
37 typedef struct bo_t
39 block_t *b;
40 size_t basesize;
41 } bo_t;
43 typedef struct bs_s
45 uint8_t *p_start;
46 uint8_t *p;
47 uint8_t *p_end;
49 ssize_t i_left; /* i_count number of available bits */
50 } bs_t;
52 static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
54 s->p_start = (uint8_t *)p_data;
55 s->p = s->p_start;
56 s->p_end = s->p_start + i_data;
57 s->i_left = 8;
60 static inline int bs_pos( const bs_t *s )
62 return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
65 static inline int bs_eof( const bs_t *s )
67 return( s->p >= s->p_end ? 1: 0 );
70 static inline uint32_t bs_read( bs_t *s, int i_count )
72 static const uint32_t i_mask[33] =
73 { 0x00,
74 0x01, 0x03, 0x07, 0x0f,
75 0x1f, 0x3f, 0x7f, 0xff,
76 0x1ff, 0x3ff, 0x7ff, 0xfff,
77 0x1fff, 0x3fff, 0x7fff, 0xffff,
78 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
79 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
80 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
81 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
82 int i_shr;
83 uint32_t i_result = 0;
85 while( i_count > 0 )
87 if( s->p >= s->p_end )
89 break;
92 if( ( i_shr = s->i_left - i_count ) >= 0 )
94 /* more in the buffer than requested */
95 i_result |= ( *s->p >> i_shr )&i_mask[i_count];
96 s->i_left -= i_count;
97 if( s->i_left == 0 )
99 s->p++;
100 s->i_left = 8;
102 return( i_result );
104 else
106 /* less in the buffer than requested */
107 i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
108 i_count -= s->i_left;
109 s->p++;
110 s->i_left = 8;
114 return( i_result );
117 static inline uint32_t bs_read1( bs_t *s )
119 if( s->p < s->p_end )
121 unsigned int i_result;
123 s->i_left--;
124 i_result = ( *s->p >> s->i_left )&0x01;
125 if( s->i_left == 0 )
127 s->p++;
128 s->i_left = 8;
130 return i_result;
133 return 0;
136 static inline uint32_t bs_show( bs_t *s, int i_count )
138 bs_t s_tmp = *s;
139 return bs_read( &s_tmp, i_count );
142 static inline void bs_skip( bs_t *s, ssize_t i_count )
144 s->i_left -= i_count;
146 if( s->i_left <= 0 )
148 const int i_bytes = ( -s->i_left + 8 ) / 8;
150 s->p += i_bytes;
151 s->i_left += 8 * i_bytes;
155 static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
157 while( i_count > 0 )
159 if( s->p >= s->p_end )
161 break;
164 i_count--;
166 if( ( i_bits >> i_count )&0x01 )
168 *s->p |= 1 << ( s->i_left - 1 );
170 else
172 *s->p &= ~( 1 << ( s->i_left - 1 ) );
174 s->i_left--;
175 if( s->i_left == 0 )
177 s->p++;
178 s->i_left = 8;
183 static inline void bs_align( bs_t *s )
185 if( s->i_left != 8 )
187 s->i_left = 8;
188 s->p++;
192 static inline void bs_align_0( bs_t *s )
194 if( s->i_left != 8 )
196 bs_write( s, s->i_left, 0 );
200 static inline void bs_align_1( bs_t *s )
202 while( s->i_left != 8 )
204 bs_write( s, 1, 1 );
208 static inline bool bo_init(bo_t *p_bo, int i_size)
210 p_bo->b = block_Alloc(i_size);
211 if (p_bo->b == NULL)
212 return false;
214 p_bo->b->i_buffer = 0;
215 p_bo->basesize = i_size;
217 return true;
220 static inline void bo_deinit(bo_t *p_bo)
222 if(p_bo->b)
223 block_Release(p_bo->b);
226 static inline void bo_free(bo_t *p_bo)
228 if(!p_bo)
229 return;
230 bo_deinit(p_bo);
231 free(p_bo);
234 static inline int bo_extend(bo_t *p_bo, size_t i_total)
236 if(!p_bo->b)
237 return false;
238 const size_t i_size = p_bo->b->i_size - (p_bo->b->p_buffer - p_bo->b->p_start);
239 if (i_total >= i_size)
241 int i_growth = p_bo->basesize;
242 while(i_total >= i_size + i_growth)
243 i_growth += p_bo->basesize;
245 int i = p_bo->b->i_buffer; /* Realloc would set payload size == buffer size */
246 p_bo->b = block_Realloc(p_bo->b, 0, i_size + i_growth);
247 if (!p_bo->b)
248 return false;
249 p_bo->b->i_buffer = i;
251 return true;
254 #define BO_SET_DECL_S(func, handler, type) static inline bool func(bo_t *p_bo, size_t i_offset, type val)\
256 if (!bo_extend(p_bo, i_offset + sizeof(type)))\
257 return false;\
258 handler(&p_bo->b->p_buffer[i_offset], val);\
259 return true;\
262 #define BO_ADD_DECL_S(func, handler, type) static inline bool func(bo_t *p_bo, type val)\
264 if(!p_bo->b || !handler(p_bo, p_bo->b->i_buffer, val))\
265 return false;\
266 p_bo->b->i_buffer += sizeof(type);\
267 return true;\
270 #define BO_FUNC_DECL(suffix, handler, type ) \
271 BO_SET_DECL_S( bo_set_ ## suffix ## be, handler ## BE, type )\
272 BO_SET_DECL_S( bo_set_ ## suffix ## le, handler ## LE, type )\
273 BO_ADD_DECL_S( bo_add_ ## suffix ## be, bo_set_ ## suffix ## be, type )\
274 BO_ADD_DECL_S( bo_add_ ## suffix ## le, bo_set_ ## suffix ## le, type )
276 static inline bool bo_set_8(bo_t *p_bo, size_t i_offset, uint8_t i)
278 if (!bo_extend(p_bo, i_offset + 1))
279 return false;
280 p_bo->b->p_buffer[i_offset] = i;
281 return true;
284 static inline bool bo_add_8(bo_t *p_bo, uint8_t i)
286 if(!p_bo->b || !bo_set_8( p_bo, p_bo->b->i_buffer, i ))
287 return false;
288 p_bo->b->i_buffer++;
289 return true;
292 /* declares all bo_[set,add]_[16,32,64] */
293 BO_FUNC_DECL( 16, SetW, uint16_t )
294 BO_FUNC_DECL( 32, SetDW, uint32_t )
295 BO_FUNC_DECL( 64, SetQW, uint64_t )
297 #undef BO_FUNC_DECL
298 #undef BO_SET_DECL_S
299 #undef BO_ADD_DECL_S
301 static inline bool bo_add_24be(bo_t *p_bo, uint32_t i)
303 if(!p_bo->b || !bo_extend(p_bo, p_bo->b->i_buffer + 3))
304 return false;
305 p_bo->b->p_buffer[p_bo->b->i_buffer++] = ((i >> 16) & 0xff);
306 p_bo->b->p_buffer[p_bo->b->i_buffer++] = ((i >> 8) & 0xff);
307 p_bo->b->p_buffer[p_bo->b->i_buffer++] = (i & 0xff);
308 return true;
311 static inline void bo_swap_32be (bo_t *p_bo, size_t i_pos, uint32_t i)
313 if (!p_bo->b || p_bo->b->i_buffer < i_pos + 4)
314 return;
315 p_bo->b->p_buffer[i_pos ] = (i >> 24)&0xff;
316 p_bo->b->p_buffer[i_pos + 1] = (i >> 16)&0xff;
317 p_bo->b->p_buffer[i_pos + 2] = (i >> 8)&0xff;
318 p_bo->b->p_buffer[i_pos + 3] = (i )&0xff;
321 static inline bool bo_add_mem(bo_t *p_bo, size_t i_size, const void *p_mem)
323 if(!p_bo->b || !bo_extend(p_bo, p_bo->b->i_buffer + i_size))
324 return false;
325 memcpy(&p_bo->b->p_buffer[p_bo->b->i_buffer], p_mem, i_size);
326 p_bo->b->i_buffer += i_size;
327 return true;
330 #define bo_add_fourcc(p_bo, fcc) bo_add_mem(p_bo, 4, fcc)
332 #endif