0f9cbfe93686319fc2285767b8c4019555451f4c
[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     ssize_t  i_left;    /* i_count number of available bits */
39 } bs_t;
40
41 static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
42 {
43     s->p_start = (void *)p_data;
44     s->p       = s->p_start;
45     s->p_end   = s->p_start + i_data;
46     s->i_left  = 8;
47 }
48
49 static inline int bs_pos( const bs_t *s )
50 {
51     return( 8 * ( s->p - s->p_start ) + 8 - s->i_left );
52 }
53
54 static inline int bs_eof( const 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, ssize_t i_count )
132 {
133     s->i_left -= i_count;
134
135     if( s->i_left <= 0 )
136     {
137         const int i_bytes = ( -s->i_left + 8 ) / 8;
138
139         s->p += i_bytes;
140         s->i_left += 8 * i_bytes;
141     }
142 }
143
144 static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
145 {
146     while( i_count > 0 )
147     {
148         if( s->p >= s->p_end )
149         {
150             break;
151         }
152
153         i_count--;
154
155         if( ( i_bits >> i_count )&0x01 )
156         {
157             *s->p |= 1 << ( s->i_left - 1 );
158         }
159         else
160         {
161             *s->p &= ~( 1 << ( s->i_left - 1 ) );
162         }
163         s->i_left--;
164         if( s->i_left == 0 )
165         {
166             s->p++;
167             s->i_left = 8;
168         }
169     }
170 }
171
172 static inline void bs_align( bs_t *s )
173 {
174     if( s->i_left != 8 )
175     {
176         s->i_left = 8;
177         s->p++;
178     }
179 }
180
181 static inline void bs_align_0( bs_t *s )
182 {
183     if( s->i_left != 8 )
184     {
185         bs_write( s, s->i_left, 0 );
186     }
187 }
188
189 static inline void bs_align_1( bs_t *s )
190 {
191     while( s->i_left != 8 )
192     {
193         bs_write( s, 1, 1 );
194     }
195 }
196
197 #endif