1 /************************************************************************
2 * Copyright (C) 2002-2009, Xiph.org Foundation
3 * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the names of the Xiph.org Foundation nor Pinknoise
17 * Productions Ltd nor the names of its contributors may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 ************************************************************************
33
34 function: packing variable sized words into an octet stream
35
36 ************************************************************************/
37
38 /* We're 'LSb' endian; if we write a word but read individual bits,
39 then we'll read the lsb first */
40
41 #include <string.h>
42 #include <stdlib.h>
43 #include "misc.h"
44 #include "ogg.h"
45
46 #include <stdio.h>
47
48
49 #if !defined(ARM_LITTLE_ENDIAN) || defined(_V_BIT_TEST)
50 static unsigned long mask[]=
51 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
52 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
53 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
54 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
55 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
56 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
57 0x3fffffff,0x7fffffff,0xffffffff };
58 #endif
59
60 #ifdef ARM_LITTLE_ENDIAN
61
62 #ifdef DEBUGGING_BITWISE
63 extern void oggpack_readinitARM(oggpack_buffer *b,ogg_reference *r);
64
oggpack_readinit(oggpack_buffer * b,ogg_reference * r)65 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
66 oggpack_readinitARM(b,r);
67 //fprintf(stderr, "Init: buffer=(%d,%x,%d,%d) %08x%08x\n",
68 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
69 // b->ptr[1], b->ptr[0]);
70 //fflush(stderr);
71 }
72
73 extern long oggpack_lookARM(oggpack_buffer *b,int bits);
74
oggpack_look(oggpack_buffer * b,int bits)75 long oggpack_look(oggpack_buffer *b,int bits){
76 long l;
77
78 //fprintf(stderr, "PreLook: buffer=(%x,%x,%x) %08x%08x (%d bits)\n",
79 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord,
80 // b->ptr[1], b->ptr[0], bits);
81 //fflush(stderr);
82 l = oggpack_lookARM(b,bits);
83 //fprintf(stderr, "Look: buffer=(%d,%x,%d,%d) %08x%08x (%d bits) (result=%x)\n",
84 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
85 // b->ptr[1], b->ptr[0], bits, l);
86 //fflush(stderr);
87
88 return l;
89 }
90
91 extern void oggpack_advARM(oggpack_buffer *b,int bits);
92
oggpack_adv(oggpack_buffer * b,int bits)93 void oggpack_adv(oggpack_buffer *b,int bits){
94 //fprintf(stderr, "Adv before: buffer=(%x,%x,%x) %08x%08x (%d bits)\n",
95 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord,
96 // b->ptr[1], b->ptr[0],bits);
97 //fflush(stderr);
98 oggpack_advARM(b,bits);
99 //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %08x%08x\n",
100 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
101 // b->ptr[1], b->ptr[0]);
102 //fflush(stderr);
103 }
104
105 extern long oggpack_readARM(oggpack_buffer *b,int bits);
106
107 /* bits <= 32 */
oggpack_read(oggpack_buffer * b,int bits)108 long oggpack_read(oggpack_buffer *b,int bits){
109 long l;
110
111 //fprintf(stderr, "PreRead: buffer=(%d,%x,%d,%d) %08x%08x (%d bits)\n",
112 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
113 // b->ptr[1], b->ptr[0], bits);
114 //fflush(stderr);
115 l = oggpack_readARM(b,bits);
116 //fprintf(stderr, "Read: buffer=(%d,%x,%d,%d) %08x%08x (%d bits) (result=%x)\n",
117 // b->bitsLeftInSegment, b->ptr, b->bitsLeftInWord, b->count,
118 // b->ptr[1], b->ptr[0], bits, l);
119 //fflush(stderr);
120
121 return l;
122 }
123 #endif
124
oggpack_eop(oggpack_buffer * b)125 int oggpack_eop(oggpack_buffer *b){
126 int ret;
127 if(b->bitsLeftInSegment<0)ret= -1;
128 else ret = 0;
129 //fprintf(stderr, "EOP %d\n", ret);
130 //fflush(stderr);
131 return ret;
132 }
133
oggpack_bytes(oggpack_buffer * b)134 long oggpack_bytes(oggpack_buffer *b){
135 long ret;
136 if(b->bitsLeftInSegment<0) ret = b->count+b->head->length;
137 else ret = b->count + b->head->length - (b->bitsLeftInSegment)/8;
138 //fprintf(stderr, "count=%d length=%d bitsLeftInSegment=%d\n",
139 // b->count, b->head->length, b->bitsLeftInSegment);
140 //fflush(stderr);
141 return ret;
142 }
143
oggpack_bits(oggpack_buffer * b)144 long oggpack_bits(oggpack_buffer *b){
145 long ret;
146 if(b->bitsLeftInSegment<0) ret=(b->count+b->head->length)*8;
147 else ret = b->count*8 + b->head->length*8 - b->bitsLeftInSegment;
148 //fprintf(stderr, "count=%d length=%d bitsLeftInSegment=%d\n",
149 // b->count, b->head->length, b->bitsLeftInSegment);
150 //fflush(stderr);
151 return ret;
152 }
153
154 #else
155
156 /* spans forward, skipping as many bytes as headend is negative; if
157 headend is zero, simply finds next byte. If we're up to the end
158 of the buffer, leaves headend at zero. If we've read past the end,
159 halt the decode process. */
160
_span(oggpack_buffer * b)161 static void _span(oggpack_buffer *b){
162 while(b->headend-(b->headbit>>3)<1){
163 b->headend-=b->headbit>>3;
164 b->headbit&=0x7;
165
166 if(b->head && b->head->next){
167 b->count+=b->head->length;
168 b->head=b->head->next;
169
170 if(b->headend+b->head->length>0)
171 b->headptr=b->head->buffer->data+b->head->begin-b->headend;
172
173 b->headend+=b->head->length;
174 }else{
175 /* we've either met the end of decode, or gone past it. halt
176 only if we're past */
177 if(b->headend*8<b->headbit)
178 /* read has fallen off the end */
179 b->headend=-1;
180 break;
181 }
182 }
183 }
184
oggpack_readinit(oggpack_buffer * b,ogg_reference * r)185 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
186 memset(b,0,sizeof(*b));
187
188 b->tail=b->head=r;
189 b->count=0;
190 if (b->head && r->length) {
191 b->headptr=b->head->buffer->data+b->head->begin;
192 b->headend=b->head->length;
193 } else {
194 b->headptr=0;
195 b->headend=0;
196 }
197 _span(b);
198
199 //fprintf(stderr,
200 // "Init: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x\n",
201 // b->headbit, b->headptr, b->headend, b->count,
202 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
203 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0]);
204 //fflush(stderr);
205 }
206
207 #define _lookspan() while(!end){\
208 head=head->next;\
209 if(!head) return -1;\
210 ptr=head->buffer->data + head->begin;\
211 end=head->length;\
212 }
213
214 /* Read in bits without advancing the bitptr; bits <= 32 */
oggpack_look(oggpack_buffer * b,int bits)215 long oggpack_look(oggpack_buffer *b,int bits){
216 unsigned long m=mask[bits];
217 unsigned long ret = 0;
218 int BITS = bits;
219
220 if (!b->headptr || b->headend < 0) return 0;
221
222 bits+=b->headbit;
223
224 if(bits >= b->headend<<3){
225 int end=b->headend;
226 unsigned char *ptr=b->headptr;
227 ogg_reference *head=b->head;
228
229 if(end<0)return 0;
230 if (!head || !end)return 0;
231
232 if(bits){
233 _lookspan();
234 ret=*ptr++>>b->headbit;
235 if(bits>8){
236 --end;
237 _lookspan();
238 ret|=*ptr++<<(8-b->headbit);
239 if(bits>16){
240 --end;
241 _lookspan();
242 ret|=*ptr++<<(16-b->headbit);
243 if(bits>24){
244 --end;
245 _lookspan();
246 ret|=*ptr++<<(24-b->headbit);
247 if(bits>32 && b->headbit){
248 --end;
249 _lookspan();
250 ret|=*ptr<<(32-b->headbit);
251 }
252 }
253 }
254 }
255 }
256
257 }else{
258
259 /* make this a switch jump-table */
260 ret=b->headptr[0]>>b->headbit;
261 if(bits>8){
262 ret|=b->headptr[1]<<(8-b->headbit);
263 if(bits>16){
264 ret|=b->headptr[2]<<(16-b->headbit);
265 if(bits>24){
266 ret|=b->headptr[3]<<(24-b->headbit);
267 if(bits>32 && b->headbit)
268 ret|=b->headptr[4]<<(32-b->headbit);
269 }
270 }
271 }
272 }
273
274 ret&=m;
275 //fprintf(stderr,
276 // "Look: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits) return=%x\n",
277 // b->headbit, b->headptr, b->headend, b->count,
278 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
279 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
280 // BITS, ret);
281 //fflush(stderr);
282 return ret;
283 }
284
285 /* limited to 32 at a time */
oggpack_adv(oggpack_buffer * b,int bits)286 void oggpack_adv(oggpack_buffer *b,int bits){
287 int BITS=bits;
288 bits+=b->headbit;
289 b->headbit=bits&7;
290 b->headend-=(bits>>3);
291 b->headptr+=(bits>>3);
292 if(b->headend<1)_span(b);
293 //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n",
294 // b->headbit, b->headptr, b->headend,b->count,
295 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
296 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
297 // BITS);
298 //fflush(stderr);
299 }
300
oggpack_eop(oggpack_buffer * b)301 int oggpack_eop(oggpack_buffer *b){
302 int ret;
303 if(b->headend<0)ret= -1;
304 else ret = 0;
305 //fprintf(stderr, "EOP %d\n", ret);
306 //fflush(stderr);
307 return ret;
308 }
309
oggpack_bytes(oggpack_buffer * b)310 long oggpack_bytes(oggpack_buffer *b){
311 long ret;
312 if(b->headend<0) ret = b->count+b->head->length;
313 ret = b->count + b->head->length-b->headend + (b->headbit+7)/8;
314 //fprintf(stderr, "Bytes: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bytes)\n",
315 // b->headbit, b->headptr, b->headend, b->count,
316 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
317 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
318 // ret);
319 //fflush(stderr);
320 return ret;
321 }
322
oggpack_bits(oggpack_buffer * b)323 long oggpack_bits(oggpack_buffer *b){
324 long ret;
325 if(b->headend<0) ret = (b->count+b->head->length)*8;
326 else ret = (b->count + b->head->length-b->headend)*8 + b->headbit;
327 //fprintf(stderr, "Bits: buffer=(%x,%x,%x) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n",
328 // b->headbit, b->headptr, b->headend,
329 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
330 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
331 // ret);
332 //fflush(stderr);
333 return ret;
334 }
335
336 /* bits <= 32 */
oggpack_read(oggpack_buffer * b,int bits)337 long oggpack_read(oggpack_buffer *b,int bits){
338 long ret=oggpack_look(b,bits);
339 oggpack_adv(b,bits);
340 return(ret);
341 }
342
343 #endif
344
345 /* Self test of the bitwise routines; everything else is based on
346 them, so they damned well better be solid. */
347
348 #ifdef _V_BIT_TEST
349 #include <string.h>
350 #include <stdlib.h>
351 #include <stdio.h>
352 #include "framing.c"
353
ilog(unsigned long v)354 static int ilog(unsigned long v){
355 int ret=0;
356 while(v){
357 ret++;
358 v>>=1;
359 }
360 return(ret);
361 }
362
363 oggpack_buffer r;
364 oggpack_buffer o;
365 ogg_buffer_state *bs;
366 ogg_reference *or;
367 #define TESTWORDS 256
368
report(char * in)369 void report(char *in){
370 fprintf(stderr,"%s",in);
371 exit(1);
372 }
373
getbyte(ogg_reference * or,int position)374 int getbyte(ogg_reference *or,int position){
375 while(or && position>=or->length){
376 position-=or->length;
377 or=or->next;
378 if(or==NULL){
379 fprintf(stderr,"\n\tERROR: getbyte ran off end of buffer.\n");
380 exit(1);
381 }
382 }
383
384 if((position+or->begin)&1)
385 return (or->buffer->data[(position+or->begin)>>1])&0xff;
386 else
387 return (or->buffer->data[(position+or->begin)>>1]>>8)&0xff;
388 }
389
cliptest(unsigned long * b,int vals,int bits,int * comp,int compsize)390 void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
391 long i,bitcount=0;
392 ogg_reference *or=ogg_buffer_alloc(bs,64);
393 for(i=0;i<compsize;i++)
394 or->buffer->data[i]= comp[i];
395 or->length=i;
396
397 oggpack_readinit(&r,or);
398 for(i=0;i<vals;i++){
399 unsigned long test;
400 int tbit=bits?bits:ilog(b[i]);
401 if((test=oggpack_look(&r,tbit))==0xffffffff)
402 report("out of data!\n");
403 if(test!=(b[i]&mask[tbit])){
404 fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
405 report("looked at incorrect value!\n");
406 }
407 if((test=oggpack_read(&r,tbit))==0xffffffff){
408 report("premature end of data when reading!\n");
409 }
410 if(test!=(b[i]&mask[tbit])){
411 fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
412 report("read incorrect value!\n");
413 }
414 bitcount+=tbit;
415
416 if(bitcount!=oggpack_bits(&r))
417 report("wrong number of bits while reading!\n");
418 if((bitcount+7)/8!=oggpack_bytes(&r))
419 report("wrong number of bytes while reading!\n");
420
421 }
422 if(oggpack_bytes(&r)!=(bitcount+7)/8){
423 fprintf(stderr, "%d vs %d\n", oggpack_bytes(&r), (bitcount+7)/8);
424 report("leftover bytes after read!\n");
425 }
426 ogg_buffer_release(or);
427 }
428
_end_verify(int count)429 void _end_verify(int count){
430 int i;
431
432 /* are the proper number of bits left over? */
433 int leftover=count*8-oggpack_bits(&o);
434 if(leftover>7)
435 report("\nERROR: too many bits reported left over.\n");
436
437 /* does reading to exactly byte alignment *not* trip EOF? */
438 if(oggpack_read(&o,leftover)==-1)
439 report("\nERROR: read to but not past exact end tripped EOF.\n");
440 if(oggpack_bits(&o)!=count*8)
441 report("\nERROR: read to but not past exact end reported bad bitcount.\n");
442
443 /* does EOF trip properly after a single additional bit? */
444 if(oggpack_read(&o,1)!=-1)
445 report("\nERROR: read past exact end did not trip EOF.\n");
446 if(oggpack_bits(&o)!=count*8)
447 report("\nERROR: read past exact end reported bad bitcount.\n");
448
449 /* does EOF stay set over additional bit reads? */
450 for(i=0;i<=32;i++){
451 if(oggpack_read(&o,i)!=-1)
452 report("\nERROR: EOF did not stay set on stream.\n");
453 if(oggpack_bits(&o)!=count*8)
454 report("\nERROR: read past exact end reported bad bitcount.\n");
455 }
456 }
457
_end_verify2(int count)458 void _end_verify2(int count){
459 int i;
460
461 /* are the proper number of bits left over? */
462 int leftover=count*8-oggpack_bits(&o);
463 if(leftover>7)
464 report("\nERROR: too many bits reported left over.\n");
465
466 /* does reading to exactly byte alignment *not* trip EOF? */
467 oggpack_adv(&o,leftover);
468 #ifdef ARM_LITTLE_ENDIAN
469 if(o.bitsLeftInSegment!=0)
470 #else
471 if(o.headend!=0)
472 #endif
473 report("\nERROR: read to but not past exact end tripped EOF.\n");
474 if(oggpack_bits(&o)!=count*8)
475 report("\nERROR: read to but not past exact end reported bad bitcount.\n");
476
477 /* does EOF trip properly after a single additional bit? */
478 oggpack_adv(&o,1);
479 #ifdef ARM_LITTLE_ENDIAN
480 if(o.bitsLeftInSegment>=0)
481 #else
482 if(o.headend>=0)
483 #endif
484 report("\nERROR: read past exact end did not trip EOF.\n");
485 if(oggpack_bits(&o)!=count*8)
486 report("\nERROR: read past exact end reported bad bitcount.\n");
487
488 /* does EOF stay set over additional bit reads? */
489 for(i=0;i<=32;i++){
490 oggpack_adv(&o,i);
491 #ifdef ARM_LITTLE_ENDIAN
492 if(o.bitsLeftInSegment>=0)
493 #else
494 if(o.headend>=0)
495 #endif
496 report("\nERROR: EOF did not stay set on stream.\n");
497 if(oggpack_bits(&o)!=count*8)
498 report("\nERROR: read past exact end reported bad bitcount.\n");
499 }
500 }
501
ogg_buffer_length(ogg_reference * or)502 long ogg_buffer_length(ogg_reference *or){
503 int count=0;
504 while(or){
505 count+=or->length;
506 or=or->next;
507 }
508 return count;
509 }
510
ogg_buffer_extend(ogg_reference * or,long bytes)511 ogg_reference *ogg_buffer_extend(ogg_reference *or,long bytes){
512 if(or){
513 while(or->next){
514 or=or->next;
515 }
516 or->next=ogg_buffer_alloc(or->buffer->ptr.owner,bytes);
517 return(or->next);
518 }
519 return 0;
520 }
521
ogg_buffer_posttruncate(ogg_reference * or,long pos)522 void ogg_buffer_posttruncate(ogg_reference *or,long pos){
523 /* walk to the point where we want to begin truncate */
524 while(or && pos>or->length){
525 pos-=or->length;
526 or=or->next;
527 }
528 if(or){
529 ogg_buffer_release(or->next);
530 or->next=0;
531 or->length=pos;
532 }
533 }
534
main(void)535 int main(void){
536 long i;
537 static unsigned long testbuffer1[]=
538 {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
539 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
540 int test1size=43;
541
542 static unsigned long testbuffer2[]=
543 {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
544 1233432,534,5,346435231,14436467,7869299,76326614,167548585,
545 85525151,0,12321,1,349528352};
546 int test2size=21;
547
548 static unsigned long testbuffer3[]=
549 {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,
550 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
551 int test3size=56;
552
553 static unsigned long large[]=
554 {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
555 1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
556 85525151,0,12321,1,2146528352};
557
558 int onesize=33;
559 static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
560 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
561 223,4};
562
563 int twosize=6;
564 static int two[6]={61,255,255,251,231,29};
565
566 int threesize=54;
567 static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
568 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
569 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
570 100,52,4,14,18,86,77,1};
571
572 int foursize=38;
573 static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
574 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
575 28,2,133,0,1};
576
577 int fivesize=45;
578 static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
579 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
580 84,75,159,2,1,0,132,192,8,0,0,18,22};
581
582 int sixsize=7;
583 static int six[7]={17,177,170,242,169,19,148};
584
585 /* Test read/write together */
586 /* Later we test against pregenerated bitstreams */
587 bs=ogg_buffer_create();
588
589 fprintf(stderr,"\nSmall preclipped packing (LSb): ");
590 cliptest(testbuffer1,test1size,0,one,onesize);
591 fprintf(stderr,"ok.");
592
593 fprintf(stderr,"\nNull bit call (LSb): ");
594 cliptest(testbuffer3,test3size,0,two,twosize);
595 fprintf(stderr,"ok.");
596
597 fprintf(stderr,"\nLarge preclipped packing (LSb): ");
598 cliptest(testbuffer2,test2size,0,three,threesize);
599 fprintf(stderr,"ok.");
600
601 fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
602
603 or=ogg_buffer_alloc(bs,128);
604 for(i=0;i<test2size;i++){
605 or->buffer->data[i*4] = large[i]&0xff;
606 or->buffer->data[i*4+1] = (large[i]>>8)&0xff;
607 or->buffer->data[i*4+2] = (large[i]>>16)&0xff;
608 or->buffer->data[i*4+3] = (large[i]>>24)&0xff;
609 }
610 or->length=test2size*4;
611 oggpack_readinit(&r,or);
612 for(i=0;i<test2size;i++){
613 unsigned long test;
614 if((test=oggpack_look(&r,32))==0xffffffffUL)report("out of data. failed!");
615 if(test!=large[i]){
616 fprintf(stderr,"%ld != %ld (%lx!=%lx):",test,large[i],
617 test,large[i]);
618 report("read incorrect value!\n");
619 }
620 oggpack_adv(&r,32);
621 }
622 ogg_buffer_release(or);
623 if(oggpack_bytes(&r)!=test2size*4){
624 fprintf(stderr, "%d vs %d\n", oggpack_bytes(&r), test2size*4);
625 report("leftover bytes after read!\n");
626 }
627 fprintf(stderr,"ok.");
628
629 fprintf(stderr,"\nSmall unclipped packing (LSb): ");
630 cliptest(testbuffer1,test1size,7,four,foursize);
631 fprintf(stderr,"ok.");
632
633 fprintf(stderr,"\nLarge unclipped packing (LSb): ");
634 cliptest(testbuffer2,test2size,17,five,fivesize);
635 fprintf(stderr,"ok.");
636
637 fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
638 cliptest(testbuffer3,test3size,1,six,sixsize);
639 fprintf(stderr,"ok.");
640
641 fprintf(stderr,"\nTesting read past end (LSb): ");
642 {
643 unsigned char dda[]={0,0,0,0};
644 ogg_buffer lob={dda,8,0,{0}};
645 ogg_reference lor={&lob,0,8,0};
646
647 oggpack_readinit(&r,&lor);
648 for(i=0;i<64;i++){
649 if(oggpack_read(&r,1)<0){
650 fprintf(stderr,"failed; got -1 prematurely.\n");
651 exit(1);
652 }
653 }
654 if(oggpack_look(&r,1)!=-1 ||
655 oggpack_read(&r,1)!=-1){
656 fprintf(stderr,"failed; read past end without -1.\n");
657 exit(1);
658 }
659 }
660 {
661 unsigned char dda[]={0,0,0,0};
662 ogg_buffer lob={dda,8,0,{0}};
663 ogg_reference lor={&lob,0,8,0};
664 unsigned long test;
665
666 oggpack_readinit(&r,&lor);
667 if((test=oggpack_read(&r,30))==0xffffffffUL ||
668 (test=oggpack_read(&r,16))==0xffffffffUL){
669 fprintf(stderr,"failed 2; got -1 prematurely.\n");
670 exit(1);
671 }
672
673 if((test=oggpack_look(&r,18))==0xffffffffUL){
674 fprintf(stderr,"failed 3; got -1 prematurely.\n");
675 exit(1);
676 }
677 if((test=oggpack_look(&r,19))!=0xffffffffUL){
678 fprintf(stderr,"failed; read past end without -1.\n");
679 exit(1);
680 }
681 if((test=oggpack_look(&r,32))!=0xffffffffUL){
682 fprintf(stderr,"failed; read past end without -1.\n");
683 exit(1);
684 }
685 }
686 fprintf(stderr,"ok.\n");
687
688 /* now the scary shit: randomized testing */
689
690 for(i=0;i<10000;i++){
691 long j,count=0,count2=0,bitcount=0;
692 unsigned long values[TESTWORDS];
693 int len[TESTWORDS];
694 unsigned char flat[4*TESTWORDS]; /* max possible needed size */
695
696 memset(flat,0,sizeof(flat));
697 fprintf(stderr,"\rRandomized testing (LSb)... (%ld) ",10000-i);
698
699 /* generate a list of words and lengths */
700 /* write the required number of bits out to packbuffer */
701 {
702 long word=0;
703 long bit=0;
704 int k;
705
706 for(j=0;j<TESTWORDS;j++){
707 values[j]=rand();
708 len[j]=(rand()%33);
709
710 for(k=0;k<len[j];k++){
711 flat[word] |= ((values[j]>>k)&0x1)<<bit;
712 bit++;
713 bitcount++;
714 if(bit>7){
715 bit=0;
716 word++;
717 }
718 }
719 }
720 }
721 count2=(bitcount+7)>>3;
722
723 /* construct random-length buffer chain from flat vector; random
724 byte starting offset within the length of the vector */
725 {
726 ogg_reference *or=NULL,*orl=NULL;
727 long pos=0;
728
729 /* build buffer chain */
730 while(count2){
731 int ilen=(rand()%32),k;
732 int ibegin=(rand()%32);
733
734
735 if(ilen>count2)ilen=count2;
736
737 if(or)
738 orl=ogg_buffer_extend(orl,64);
739 else
740 or=orl=ogg_buffer_alloc(bs,64);
741
742 orl->length=ilen;
743 orl->begin=ibegin;
744
745 for(k=0;k<ilen;k++)
746 orl->buffer->data[ibegin++]= flat[pos++];
747
748 count2-=ilen;
749 }
750
751 if(ogg_buffer_length(or)!=(bitcount+7)/8){
752 fprintf(stderr,"\nERROR: buffer length incorrect after build.\n");
753 exit(1);
754 }
755
756
757 {
758 int begin=0; //=(rand()%TESTWORDS);
759 int ilen=(rand()%(TESTWORDS-begin));
760 int bitoffset,bitcount=0;
761 unsigned long temp;
762
763 for(j=0;j<begin;j++)
764 bitcount+=len[j];
765 or=ogg_buffer_pretruncate(or,bitcount/8);
766 bitoffset=bitcount%=8;
767 for(;j<begin+ilen;j++)
768 bitcount+=len[j];
769 ogg_buffer_posttruncate(or,((bitcount+7)/8));
770
771 if((count=ogg_buffer_length(or))!=(bitcount+7)/8){
772 fprintf(stderr,"\nERROR: buffer length incorrect after truncate.\n");
773 exit(1);
774 }
775
776 oggpack_readinit(&o,or);
777
778 /* verify bit count */
779 if(oggpack_bits(&o)!=0){
780 fprintf(stderr,"\nERROR: Read bitcounter not zero!\n");
781 exit(1);
782 }
783 if(oggpack_bytes(&o)!=0){
784 fprintf(stderr,"\nERROR: Read bytecounter not zero!\n");
785 exit(1);
786 }
787
788 bitcount=bitoffset;
789 oggpack_read(&o,bitoffset);
790
791 /* read and compare to original list */
792 for(j=begin;j<begin+ilen;j++){
793 temp=oggpack_read(&o,len[j]);
794 if(temp==0xffffffffUL){
795 fprintf(stderr,"\nERROR: End of stream too soon! word: %ld,%d\n",
796 j-begin,ilen);
797 exit(1);
798 }
799 if(temp!=(values[j]&mask[len[j]])){
800 fprintf(stderr,"\nERROR: Incorrect read %lx != %lx, word %ld, len %d\n"
801 ,
802 values[j]&mask[len[j]],temp,j-begin,len[j]);
803 exit(1);
804 }
805 bitcount+=len[j];
806 if(oggpack_bits(&o)!=bitcount){
807 fprintf(stderr,"\nERROR: Read bitcounter %d != %ld!\n",
808 bitcount,oggpack_bits(&o));
809 exit(1);
810 }
811 if(oggpack_bytes(&o)!=(bitcount+7)/8){
812 fprintf(stderr,"\nERROR: Read bytecounter %d != %ld!\n",
813 (bitcount+7)/8,oggpack_bytes(&o));
814 exit(1);
815 }
816
817 }
818 _end_verify(count);
819
820 /* look/adv version */
821 oggpack_readinit(&o,or);
822 bitcount=bitoffset;
823 oggpack_adv(&o,bitoffset);
824
825 /* read and compare to original list */
826 for(j=begin;j<begin+ilen;j++){
827 temp=oggpack_look(&o,len[j]);
828
829 if(temp==0xffffffffUL){
830 fprintf(stderr,"\nERROR: End of stream too soon! word: %ld\n",
831 j-begin);
832 exit(1);
833 }
834 if(temp!=(values[j]&mask[len[j]])){
835 fprintf(stderr,"\nERROR: Incorrect look %lx != %lx, word %ld, len %d\n"
836 ,
837 values[j]&mask[len[j]],temp,j-begin,len[j]);
838 exit(1);
839 }
840 oggpack_adv(&o,len[j]);
841 bitcount+=len[j];
842 if(oggpack_bits(&o)!=bitcount){
843 fprintf(stderr,"\nERROR: Look/Adv bitcounter %d != %ld!\n",
844 bitcount,oggpack_bits(&o));
845 exit(1);
846 }
847 if(oggpack_bytes(&o)!=(bitcount+7)/8){
848 fprintf(stderr,"\nERROR: Look/Adv bytecounter %d != %ld!\n",
849 (bitcount+7)/8,oggpack_bytes(&o));
850 exit(1);
851 }
852
853 }
854 _end_verify2(count);
855
856 }
857 ogg_buffer_release(or);
858 }
859 }
860 fprintf(stderr,"\rRandomized testing (LSb)... ok. \n");
861
862 return(0);
863 }
864
865 #ifdef _WIN32_WCE
WinMain(void)866 int WinMain(void){
867 return main();
868 }
869 #endif
870
871 #endif
872