Recognizes if input is ogg or not.
[xiph.git] / Tremor / bitwise.c
blob5274a0cb369f6bd6fa4c02c5be1afdcd4a065f3e
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
11 * *
12 ********************************************************************
14 function: packing variable sized words into an octet stream
16 ********************************************************************/
18 /* We're 'LSb' endian; if we write a word but read individual bits,
19 then we'll read the lsb first */
21 #include <string.h>
22 #include <stdlib.h>
23 #include "ogg.h"
25 static unsigned long mask[]=
26 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
27 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
28 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
29 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
30 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
31 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
32 0x3fffffff,0x7fffffff,0xffffffff };
34 /* mark read process as having run off the end */
35 static void _adv_halt(oggpack_buffer *b){
36 b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
37 b->headend=-1;
38 b->headbit=0;
41 /* spans forward, skipping as many bytes as headend is negative; if
42 headend is zero, simply finds next byte. If we're up to the end
43 of the buffer, leaves headend at zero. If we've read past the end,
44 halt the decode process. */
45 static void _span(oggpack_buffer *b){
46 while(b->headend<1){
47 if(b->head->next){
48 b->count+=b->head->length;
49 b->head=b->head->next;
50 b->headptr=b->head->buffer->data+b->head->begin-b->headend;
51 b->headend+=b->head->length;
52 }else{
53 /* we've either met the end of decode, or gone past it. halt
54 only if we're past */
55 if(b->headend<0 || b->headbit)
56 /* read has fallen off the end */
57 _adv_halt(b);
59 break;
64 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
65 memset(b,0,sizeof(*b));
67 b->tail=b->head=r;
68 b->count=0;
69 b->headptr=b->head->buffer->data+b->head->begin;
70 b->headend=b->head->length;
71 _span(b);
74 #define _lookspan() while(!end){\
75 head=head->next;\
76 if(!head) return -1;\
77 ptr=head->buffer->data + head->begin;\
78 end=head->length;\
81 /* Read in bits without advancing the bitptr; bits <= 32 */
82 long oggpack_look(oggpack_buffer *b,int bits){
83 unsigned long m=mask[bits];
84 unsigned long ret=-1;
86 bits+=b->headbit;
88 if(bits >= b->headend<<3){
89 int end=b->headend;
90 unsigned char *ptr=b->headptr;
91 ogg_reference *head=b->head;
93 if(end<0)return -1;
95 if(bits){
96 _lookspan();
97 ret=*ptr++>>b->headbit;
98 if(bits>8){
99 --end;
100 _lookspan();
101 ret|=*ptr++<<(8-b->headbit);
102 if(bits>16){
103 --end;
104 _lookspan();
105 ret|=*ptr++<<(16-b->headbit);
106 if(bits>24){
107 --end;
108 _lookspan();
109 ret|=*ptr++<<(24-b->headbit);
110 if(bits>32 && b->headbit){
111 --end;
112 _lookspan();
113 ret|=*ptr<<(32-b->headbit);
120 }else{
122 /* make this a switch jump-table */
123 ret=b->headptr[0]>>b->headbit;
124 if(bits>8){
125 ret|=b->headptr[1]<<(8-b->headbit);
126 if(bits>16){
127 ret|=b->headptr[2]<<(16-b->headbit);
128 if(bits>24){
129 ret|=b->headptr[3]<<(24-b->headbit);
130 if(bits>32 && b->headbit)
131 ret|=b->headptr[4]<<(32-b->headbit);
137 ret&=m;
138 return ret;
141 /* limited to 32 at a time */
142 void oggpack_adv(oggpack_buffer *b,int bits){
143 bits+=b->headbit;
144 b->headbit=bits&7;
145 b->headptr+=bits/8;
146 if((b->headend-=bits/8)<1)_span(b);
149 /* spans forward and finds next byte. Never halts */
150 static void _span_one(oggpack_buffer *b){
151 while(b->headend<1){
152 if(b->head->next){
153 b->count+=b->head->length;
154 b->head=b->head->next;
155 b->headptr=b->head->buffer->data+b->head->begin;
156 b->headend=b->head->length;
157 }else
158 break;
162 static int _halt_one(oggpack_buffer *b){
163 if(b->headend<1){
164 _adv_halt(b);
165 return -1;
167 return 0;
170 int oggpack_eop(oggpack_buffer *b){
171 if(b->headend<0)return -1;
172 return 0;
175 /* bits <= 32 */
176 long oggpack_read(oggpack_buffer *b,int bits){
177 unsigned long m=mask[bits];
178 ogg_uint32_t ret=-1;
180 bits+=b->headbit;
182 if(bits >= b->headend<<3){
184 if(b->headend<0)return -1;
186 if(bits){
187 if (_halt_one(b)) return -1;
188 ret=*b->headptr>>b->headbit;
190 if(bits>=8){
191 ++b->headptr;
192 --b->headend;
193 _span_one(b);
194 if(bits>8){
195 if (_halt_one(b)) return -1;
196 ret|=*b->headptr<<(8-b->headbit);
198 if(bits>=16){
199 ++b->headptr;
200 --b->headend;
201 _span_one(b);
202 if(bits>16){
203 if (_halt_one(b)) return -1;
204 ret|=*b->headptr<<(16-b->headbit);
206 if(bits>=24){
207 ++b->headptr;
208 --b->headend;
209 _span_one(b);
210 if(bits>24){
211 if (_halt_one(b)) return -1;
212 ret|=*b->headptr<<(24-b->headbit);
214 if(bits>=32){
215 ++b->headptr;
216 --b->headend;
217 _span_one(b);
218 if(bits>32){
219 if (_halt_one(b)) return -1;
220 if(b->headbit)ret|=*b->headptr<<(32-b->headbit);
231 }else{
233 ret=b->headptr[0]>>b->headbit;
234 if(bits>8){
235 ret|=b->headptr[1]<<(8-b->headbit);
236 if(bits>16){
237 ret|=b->headptr[2]<<(16-b->headbit);
238 if(bits>24){
239 ret|=b->headptr[3]<<(24-b->headbit);
240 if(bits>32 && b->headbit){
241 ret|=b->headptr[4]<<(32-b->headbit);
247 b->headptr+=bits/8;
248 b->headend-=bits/8;
251 ret&=m;
252 b->headbit=bits&7;
253 return ret;
256 long oggpack_bytes(oggpack_buffer *b){
257 return(b->count+b->headptr-b->head->buffer->data-b->head->begin+
258 (b->headbit+7)/8);
261 long oggpack_bits(oggpack_buffer *b){
262 return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+
263 b->headbit);