spu: rss: fix first character of display being omitted
[vlc.git] / include / vlc_bits.h
blob8d3ae8f0986bb88092add331a31109cb18f08a2e
1 /*****************************************************************************
2 * vlc_bits.h : Bit handling helpers
3 *****************************************************************************
4 * Copyright (C) 2001, 2002, 2003, 2006, 2015 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 * Gildas Bazin <gbazin at videolan dot org>
8 * Rafaël Carré <funman at videolan dot org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
24 #ifndef VLC_BITS_H
25 #define VLC_BITS_H 1
27 #include <vlc_common.h>
29 /**
30 * \file
31 * This file defines functions, structures for handling streams of bits in vlc
34 typedef struct bs_s bs_t;
36 typedef struct
38 /* forward read modifier (p_start, p_end, p_fwpriv, count, pos) */
39 size_t (*pf_byte_forward)(bs_t *, size_t);
40 size_t (*pf_byte_pos)(const bs_t *);
41 } bs_byte_callbacks_t;
43 typedef struct bs_s
45 uint8_t *p_start;
46 uint8_t *p; /* points to currently read/written byte */
47 uint8_t *p_end;
49 uint8_t i_left; /* i_count number of available bits */
50 bool b_read_only;
51 bool b_error;
53 bs_byte_callbacks_t cb;
54 void *p_priv;
55 } bs_t;
57 static size_t bs_impl_bytes_forward( bs_t *s, size_t i_count )
59 if( s->p == NULL )
61 s->p = s->p_start;
62 return 1;
65 if( s->p >= s->p_end )
66 return 0;
68 if( (size_t) (s->p_end - s->p) < i_count )
69 i_count = s->p_end - s->p;
70 s->p += i_count;
71 return i_count;
74 static size_t bs_impl_bytes_pos( const bs_t *s )
76 if( s->p )
77 return s->p < s->p_end ? s->p - s->p_start + 1 : s->p - s->p_start;
78 else
79 return 0;
82 static inline void bs_init_custom( bs_t *s, const void *p_data, size_t i_data,
83 const bs_byte_callbacks_t *cb, void *priv )
85 s->p_start = (uint8_t *)p_data;
86 s->p = NULL;
87 s->p_end = s->p_start + i_data;
88 s->i_left = 0;
89 s->b_read_only = true;
90 s->b_error = false;
91 s->p_priv = priv;
92 s->cb = *cb;
95 static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
97 bs_byte_callbacks_t cb = {
98 bs_impl_bytes_forward,
99 bs_impl_bytes_pos,
101 bs_init_custom( s, p_data, i_data, &cb, NULL );
104 static inline void bs_write_init( bs_t *s, void *p_data, size_t i_data )
106 bs_init( s, (const void *) p_data, i_data );
107 s->b_read_only = false;
110 static inline int bs_refill( bs_t *s )
112 if( s->i_left == 0 )
114 if( s->cb.pf_byte_forward( s, 1 ) != 1 )
115 return -1;
117 if( s->p < s->p_end )
118 s->i_left = 8;
120 return s->i_left > 0 ? 0 : 1;
123 static inline bool bs_error( const bs_t *s )
125 return s->b_error;
128 static inline bool bs_eof( bs_t *s )
130 return bs_refill( s ) != 0;
133 static inline size_t bs_pos( const bs_t *s )
135 return 8 * s->cb.pf_byte_pos( s ) - s->i_left;
138 static inline void bs_skip( bs_t *s, size_t i_count )
140 if( i_count == 0 )
141 return;
143 if( bs_refill( s ) )
145 s->b_error = true;
146 return;
149 if( i_count > s->i_left )
151 i_count -= s->i_left;
152 s->i_left = 0;
153 size_t bytes = i_count / 8;
154 if( bytes && s->cb.pf_byte_forward( s, bytes ) != bytes )
156 s->b_error = true;
157 return;
159 i_count = i_count % 8;
160 if( i_count > 0 )
162 if( !bs_refill( s ) )
163 s->i_left = 8 - i_count;
164 else
165 s->b_error = true;
168 else s->i_left -= i_count;
171 static inline uint32_t bs_read( bs_t *s, uint8_t i_count )
173 uint8_t i_shr, i_drop = 0;
174 uint32_t i_result = 0;
176 if( i_count > 32 )
178 i_drop = i_count - 32;
179 i_count = 32;
182 while( i_count > 0 )
184 if( bs_refill( s ) )
186 s->b_error = true;
187 break;
190 if( s->i_left > i_count )
192 uint_fast32_t mask = (UINT64_C(1) << i_count) - 1;
194 i_shr = s->i_left - i_count;
195 /* more in the buffer than requested */
196 i_result |= ( *s->p >> i_shr ) & mask;
197 s->i_left -= i_count;
198 break;
200 else
202 uint_fast32_t mask = (UINT64_C(1) << s->i_left) - 1;
204 i_shr = i_count - s->i_left;
205 /* less in the buffer than requested */
206 if( i_shr >= 32 )
207 i_result = 0;
208 else
209 i_result |= (*s->p & mask) << i_shr;
210 i_count -= s->i_left;
211 s->i_left = 0;
215 if( i_drop )
216 bs_skip( s, i_drop );
218 return( i_result );
221 static inline uint32_t bs_read1( bs_t *s )
223 if( bs_refill( s ) )
225 s->b_error = true;
226 return 0;
228 s->i_left--;
229 return ( *s->p >> s->i_left )&0x01;
232 static inline void bs_write( bs_t *s, uint8_t i_count, uint32_t i_bits )
234 if( s->b_read_only )
235 return;
237 while( i_count > 0 )
239 if( bs_refill( s ) )
241 s->b_error = true;
242 break;
245 i_count--;
247 if( ( i_bits >> i_count )&0x01 )
249 *s->p |= 1 << ( s->i_left - 1 );
251 else
253 *s->p &= ~( 1 << ( s->i_left - 1 ) );
255 s->i_left--;
259 static inline bool bs_aligned( bs_t *s )
261 return s->i_left % 8 == 0;
264 static inline void bs_align( bs_t *s )
266 if( s->i_left % 8 )
267 s->i_left = 0;
270 static inline void bs_write_align( bs_t *s, uint8_t v )
272 if( !s->b_read_only && (s->i_left % 8) )
273 bs_write( s, s->i_left, v ? 0xFF : 0 );
276 #define bs_align_0( s ) bs_write_align( s, 0 )
277 #define bs_align_1( s ) bs_write_align( s, 1 )
279 /* Read unsigned Exp-Golomb code */
280 static inline uint_fast32_t bs_read_ue( bs_t * bs )
282 unsigned i = 0;
284 while( !bs->b_error &&
285 bs_read1( bs ) == 0 &&
286 bs->p < bs->p_end && i < 31 )
287 i++;
289 return (1U << i) - 1 + bs_read( bs, i );
292 /* Read signed Exp-Golomb code */
293 static inline int_fast32_t bs_read_se( bs_t *s )
295 uint_fast32_t val = bs_read_ue( s );
297 return (val & 0x01) ? (int_fast32_t)((val + 1) / 2)
298 : -(int_fast32_t)(val / 2);
301 #undef bs_forward
303 #endif