Add a bunch of \file doxygen comments
[vlc.git] / include / vlc_bits.h
1 /*****************************************************************************
2  * bits.h : Bit handling helpers
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifndef VLC_BITS_H
25 #define VLC_BITS_H 1
26
27 /**
28  * \file
29  * This file defines functions, structures for handling streams of bits in vlc
30  */
31
32 typedef struct bs_s
33 {
34     uint8_t *p_start;
35     uint8_t *p;
36     uint8_t *p_end;
37
38     int     i_left;    /* i_count number of available bits */
39 } bs_t;
40
41 static inline void bs_init( bs_t *s, void *p_data, int i_data )
42 {
43     s->p_start = p_data;
44     s->p       = p_data;
45     s->p_end   = s->p + i_data;
46     s->i_left  = 8;
47 }
48
49 static inline int bs_pos( bs_t *s )
50 {
51     return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
52 }
53
54 static inline int bs_eof( bs_t *s )
55 {
56     return( s->p >= s->p_end ? 1: 0 );
57 }
58
59 static inline uint32_t bs_read( bs_t *s, int i_count )
60 {
61      static const uint32_t i_mask[33] =
62      {  0x00,
63         0x01,      0x03,      0x07,      0x0f,
64         0x1f,      0x3f,      0x7f,      0xff,
65         0x1ff,     0x3ff,     0x7ff,     0xfff,
66         0x1fff,    0x3fff,    0x7fff,    0xffff,
67         0x1ffff,   0x3ffff,   0x7ffff,   0xfffff,
68         0x1fffff,  0x3fffff,  0x7fffff,  0xffffff,
69         0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
70         0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
71     int      i_shr;
72     uint32_t i_result = 0;
73
74     while( i_count > 0 )
75     {
76         if( s->p >= s->p_end )
77         {
78             break;
79         }
80
81         if( ( i_shr = s->i_left - i_count ) >= 0 )
82         {
83             /* more in the buffer than requested */
84             i_result |= ( *s->p >> i_shr )&i_mask[i_count];
85             s->i_left -= i_count;
86             if( s->i_left == 0 )
87             {
88                 s->p++;
89                 s->i_left = 8;
90             }
91             return( i_result );
92         }
93         else
94         {
95             /* less in the buffer than requested */
96            i_result |= (*s->p&i_mask[s->i_left]) << -i_shr;
97            i_count  -= s->i_left;
98            s->p++;
99            s->i_left = 8;
100         }
101     }
102
103     return( i_result );
104 }
105
106 static inline uint32_t bs_read1( bs_t *s )
107 {
108     if( s->p < s->p_end )
109     {
110         unsigned int i_result;
111
112         s->i_left--;
113         i_result = ( *s->p >> s->i_left )&0x01;
114         if( s->i_left == 0 )
115         {
116             s->p++;
117             s->i_left = 8;
118         }
119         return i_result;
120     }
121
122     return 0;
123 }
124
125 static inline uint32_t bs_show( bs_t *s, int i_count )
126 {
127     bs_t     s_tmp = *s;
128     return bs_read( &s_tmp, i_count );
129 }
130
131 static inline void bs_skip( bs_t *s, int i_count )
132 {
133     s->i_left -= i_count;
134
135     while( s->i_left <= 0 )
136     {
137         s->p++;
138         s->i_left += 8;
139     }
140 }
141
142 static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
143 {
144     while( i_count > 0 )
145     {
146         if( s->p >= s->p_end )
147         {
148             break;
149         }
150
151         i_count--;
152
153         if( ( i_bits >> i_count )&0x01 )
154         {
155             *s->p |= 1 << ( s->i_left - 1 );
156         }
157         else
158         {
159             *s->p &= ~( 1 << ( s->i_left - 1 ) );
160         }
161         s->i_left--;
162         if( s->i_left == 0 )
163         {
164             s->p++;
165             s->i_left = 8;
166         }
167     }
168 }
169
170 static inline void bs_align( bs_t *s )
171 {
172     if( s->i_left != 8 )
173     {
174         s->i_left = 8;
175         s->p++;
176     }
177 }
178
179 static inline void bs_align_0( bs_t *s )
180 {
181     if( s->i_left != 8 )
182     {
183         bs_write( s, s->i_left, 0 );
184     }
185 }
186
187 static inline void bs_align_1( bs_t *s )
188 {
189     while( s->i_left != 8 )
190     {
191         bs_write( s, 1, 1 );
192     }
193 }
194
195 #endif