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