blob: 218264119c91a4bf7eca11d68a2a9156d24398dd [file] [log] [blame]
Gloria Wang37fe1582010-03-12 14:53:20 -08001/************************************************************************
Gloria Wang2da723a2010-03-18 15:56:16 -07002 * Copyright (C) 2002-2009, Xiph.org Foundation
3 * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
Gloria Wang37fe1582010-03-12 14:53:20 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
Gloria Wang2da723a2010-03-18 15:56:16 -07007 * modification, are permitted provided that the following conditions
8 * are met:
Gloria Wang37fe1582010-03-12 14:53:20 -08009 *
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.
Gloria Wang2da723a2010-03-18 15:56:16 -070016 * * 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.
Gloria Wang37fe1582010-03-12 14:53:20 -080020 *
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 ************************************************************************
Gloria Wang79130732010-02-08 14:41:04 -080033
34 function: packing variable sized words into an octet stream
35
Gloria Wang37fe1582010-03-12 14:53:20 -080036 ************************************************************************/
Gloria Wang79130732010-02-08 14:41:04 -080037
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)
50static 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
63extern void oggpack_readinitARM(oggpack_buffer *b,ogg_reference *r);
64
65void 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
73extern long oggpack_lookARM(oggpack_buffer *b,int bits);
74
75long 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
91extern void oggpack_advARM(oggpack_buffer *b,int bits);
92
93void 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
105extern long oggpack_readARM(oggpack_buffer *b,int bits);
106
107/* bits <= 32 */
108long 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
125int 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
134long 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
144long 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
161static 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
185void 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) {
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 */
215long oggpack_look(oggpack_buffer *b,int bits){
216 unsigned long m=mask[bits];
Bruce Beare9b3d8e42010-06-25 09:07:39 -0700217 unsigned long ret = 0;
Gloria Wang79130732010-02-08 14:41:04 -0800218 int BITS = bits;
219
220 bits+=b->headbit;
221
222 if(bits >= b->headend<<3){
223 int end=b->headend;
224 unsigned char *ptr=b->headptr;
225 ogg_reference *head=b->head;
226
227 if(end<0)return -1;
228 if (!head || !end)return -1;
229
230 if(bits){
231 _lookspan();
232 ret=*ptr++>>b->headbit;
233 if(bits>8){
234 --end;
235 _lookspan();
236 ret|=*ptr++<<(8-b->headbit);
237 if(bits>16){
238 --end;
239 _lookspan();
240 ret|=*ptr++<<(16-b->headbit);
241 if(bits>24){
242 --end;
243 _lookspan();
244 ret|=*ptr++<<(24-b->headbit);
245 if(bits>32 && b->headbit){
246 --end;
247 _lookspan();
248 ret|=*ptr<<(32-b->headbit);
249 }
250 }
251 }
252 }
253 }
254
255 }else{
256
257 /* make this a switch jump-table */
258 ret=b->headptr[0]>>b->headbit;
259 if(bits>8){
260 ret|=b->headptr[1]<<(8-b->headbit);
261 if(bits>16){
262 ret|=b->headptr[2]<<(16-b->headbit);
263 if(bits>24){
264 ret|=b->headptr[3]<<(24-b->headbit);
265 if(bits>32 && b->headbit)
266 ret|=b->headptr[4]<<(32-b->headbit);
267 }
268 }
269 }
270 }
271
272 ret&=m;
273 //fprintf(stderr,
274 // "Look: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits) return=%x\n",
275 // b->headbit, b->headptr, b->headend, b->count,
276 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
277 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
278 // BITS, ret);
279 //fflush(stderr);
280 return ret;
281}
282
283/* limited to 32 at a time */
284void oggpack_adv(oggpack_buffer *b,int bits){
285 int BITS=bits;
286 bits+=b->headbit;
287 b->headbit=bits&7;
288 b->headend-=(bits>>3);
289 b->headptr+=(bits>>3);
290 if(b->headend<1)_span(b);
291 //fprintf(stderr, "Adv: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n",
292 // b->headbit, b->headptr, b->headend,b->count,
293 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
294 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
295 // BITS);
296 //fflush(stderr);
297}
298
299int oggpack_eop(oggpack_buffer *b){
300 int ret;
301 if(b->headend<0)ret= -1;
302 else ret = 0;
303 //fprintf(stderr, "EOP %d\n", ret);
304 //fflush(stderr);
305 return ret;
306}
307
308long oggpack_bytes(oggpack_buffer *b){
309 long ret;
310 if(b->headend<0) ret = b->count+b->head->length;
311 ret = b->count + b->head->length-b->headend + (b->headbit+7)/8;
312 //fprintf(stderr, "Bytes: buffer=(%d,%x,%d,%d) %02x%02x%02x%02x%02x%02x%02x%02x (%d bytes)\n",
313 // b->headbit, b->headptr, b->headend, b->count,
314 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
315 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
316 // ret);
317 //fflush(stderr);
318 return ret;
319}
320
321long oggpack_bits(oggpack_buffer *b){
322 long ret;
323 if(b->headend<0) ret = (b->count+b->head->length)*8;
324 else ret = (b->count + b->head->length-b->headend)*8 + b->headbit;
325 //fprintf(stderr, "Bits: buffer=(%x,%x,%x) %02x%02x%02x%02x%02x%02x%02x%02x (%d bits)\n",
326 // b->headbit, b->headptr, b->headend,
327 // b->headptr[7], b->headptr[6], b->headptr[5], b->headptr[4],
328 // b->headptr[3], b->headptr[2], b->headptr[1], b->headptr[0],
329 // ret);
330 //fflush(stderr);
331 return ret;
332}
333
334/* bits <= 32 */
335long oggpack_read(oggpack_buffer *b,int bits){
336 long ret=oggpack_look(b,bits);
337 oggpack_adv(b,bits);
338 return(ret);
339}
340
341#endif
342
343/* Self test of the bitwise routines; everything else is based on
344 them, so they damned well better be solid. */
345
346#ifdef _V_BIT_TEST
347#include <string.h>
348#include <stdlib.h>
349#include <stdio.h>
350#include "framing.c"
351
352static int ilog(unsigned long v){
353 int ret=0;
354 while(v){
355 ret++;
356 v>>=1;
357 }
358 return(ret);
359}
360
361oggpack_buffer r;
362oggpack_buffer o;
363ogg_buffer_state *bs;
364ogg_reference *or;
365#define TESTWORDS 256
366
367void report(char *in){
368 fprintf(stderr,"%s",in);
369 exit(1);
370}
371
372int getbyte(ogg_reference *or,int position){
373 while(or && position>=or->length){
374 position-=or->length;
375 or=or->next;
376 if(or==NULL){
377 fprintf(stderr,"\n\tERROR: getbyte ran off end of buffer.\n");
378 exit(1);
379 }
380 }
381
382 if((position+or->begin)&1)
383 return (or->buffer->data[(position+or->begin)>>1])&0xff;
384 else
385 return (or->buffer->data[(position+or->begin)>>1]>>8)&0xff;
386}
387
388void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
389 long i,bitcount=0;
390 ogg_reference *or=ogg_buffer_alloc(bs,64);
391 for(i=0;i<compsize;i++)
392 or->buffer->data[i]= comp[i];
393 or->length=i;
394
395 oggpack_readinit(&r,or);
396 for(i=0;i<vals;i++){
397 unsigned long test;
398 int tbit=bits?bits:ilog(b[i]);
399 if((test=oggpack_look(&r,tbit))==0xffffffff)
400 report("out of data!\n");
401 if(test!=(b[i]&mask[tbit])){
402 fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
403 report("looked at incorrect value!\n");
404 }
405 if((test=oggpack_read(&r,tbit))==0xffffffff){
406 report("premature end of data when reading!\n");
407 }
408 if(test!=(b[i]&mask[tbit])){
409 fprintf(stderr,"%ld) %lx %lx\n",i,(b[i]&mask[tbit]),test);
410 report("read incorrect value!\n");
411 }
412 bitcount+=tbit;
413
414 if(bitcount!=oggpack_bits(&r))
415 report("wrong number of bits while reading!\n");
416 if((bitcount+7)/8!=oggpack_bytes(&r))
417 report("wrong number of bytes while reading!\n");
418
419 }
420 if(oggpack_bytes(&r)!=(bitcount+7)/8){
421 fprintf(stderr, "%d vs %d\n", oggpack_bytes(&r), (bitcount+7)/8);
422 report("leftover bytes after read!\n");
423 }
424 ogg_buffer_release(or);
425}
426
427void _end_verify(int count){
428 int i;
429
430 /* are the proper number of bits left over? */
431 int leftover=count*8-oggpack_bits(&o);
432 if(leftover>7)
433 report("\nERROR: too many bits reported left over.\n");
434
435 /* does reading to exactly byte alignment *not* trip EOF? */
436 if(oggpack_read(&o,leftover)==-1)
437 report("\nERROR: read to but not past exact end tripped EOF.\n");
438 if(oggpack_bits(&o)!=count*8)
439 report("\nERROR: read to but not past exact end reported bad bitcount.\n");
440
441 /* does EOF trip properly after a single additional bit? */
442 if(oggpack_read(&o,1)!=-1)
443 report("\nERROR: read past exact end did not trip EOF.\n");
444 if(oggpack_bits(&o)!=count*8)
445 report("\nERROR: read past exact end reported bad bitcount.\n");
446
447 /* does EOF stay set over additional bit reads? */
448 for(i=0;i<=32;i++){
449 if(oggpack_read(&o,i)!=-1)
450 report("\nERROR: EOF did not stay set on stream.\n");
451 if(oggpack_bits(&o)!=count*8)
452 report("\nERROR: read past exact end reported bad bitcount.\n");
453 }
454}
455
456void _end_verify2(int count){
457 int i;
458
459 /* are the proper number of bits left over? */
460 int leftover=count*8-oggpack_bits(&o);
461 if(leftover>7)
462 report("\nERROR: too many bits reported left over.\n");
463
464 /* does reading to exactly byte alignment *not* trip EOF? */
465 oggpack_adv(&o,leftover);
466#ifdef ARM_LITTLE_ENDIAN
467 if(o.bitsLeftInSegment!=0)
468#else
469 if(o.headend!=0)
470#endif
471 report("\nERROR: read to but not past exact end tripped EOF.\n");
472 if(oggpack_bits(&o)!=count*8)
473 report("\nERROR: read to but not past exact end reported bad bitcount.\n");
474
475 /* does EOF trip properly after a single additional bit? */
476 oggpack_adv(&o,1);
477#ifdef ARM_LITTLE_ENDIAN
478 if(o.bitsLeftInSegment>=0)
479#else
480 if(o.headend>=0)
481#endif
482 report("\nERROR: read past exact end did not trip EOF.\n");
483 if(oggpack_bits(&o)!=count*8)
484 report("\nERROR: read past exact end reported bad bitcount.\n");
485
486 /* does EOF stay set over additional bit reads? */
487 for(i=0;i<=32;i++){
488 oggpack_adv(&o,i);
489#ifdef ARM_LITTLE_ENDIAN
490 if(o.bitsLeftInSegment>=0)
491#else
492 if(o.headend>=0)
493#endif
494 report("\nERROR: EOF did not stay set on stream.\n");
495 if(oggpack_bits(&o)!=count*8)
496 report("\nERROR: read past exact end reported bad bitcount.\n");
497 }
498}
499
500long ogg_buffer_length(ogg_reference *or){
501 int count=0;
502 while(or){
503 count+=or->length;
504 or=or->next;
505 }
506 return count;
507}
508
509ogg_reference *ogg_buffer_extend(ogg_reference *or,long bytes){
510 if(or){
511 while(or->next){
512 or=or->next;
513 }
514 or->next=ogg_buffer_alloc(or->buffer->ptr.owner,bytes);
515 return(or->next);
516 }
517 return 0;
518}
519
520void ogg_buffer_posttruncate(ogg_reference *or,long pos){
521 /* walk to the point where we want to begin truncate */
522 while(or && pos>or->length){
523 pos-=or->length;
524 or=or->next;
525 }
526 if(or){
527 ogg_buffer_release(or->next);
528 or->next=0;
529 or->length=pos;
530 }
531}
532
533int main(void){
534 long i;
535 static unsigned long testbuffer1[]=
536 {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
537 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
538 int test1size=43;
539
540 static unsigned long testbuffer2[]=
541 {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
542 1233432,534,5,346435231,14436467,7869299,76326614,167548585,
543 85525151,0,12321,1,349528352};
544 int test2size=21;
545
546 static unsigned long testbuffer3[]=
547 {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,
548 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
549 int test3size=56;
550
551 static unsigned long large[]=
552 {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
553 1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
554 85525151,0,12321,1,2146528352};
555
556 int onesize=33;
557 static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
558 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
559 223,4};
560
561 int twosize=6;
562 static int two[6]={61,255,255,251,231,29};
563
564 int threesize=54;
565 static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
566 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
567 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
568 100,52,4,14,18,86,77,1};
569
570 int foursize=38;
571 static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
572 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
573 28,2,133,0,1};
574
575 int fivesize=45;
576 static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
577 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
578 84,75,159,2,1,0,132,192,8,0,0,18,22};
579
580 int sixsize=7;
581 static int six[7]={17,177,170,242,169,19,148};
582
583 /* Test read/write together */
584 /* Later we test against pregenerated bitstreams */
585 bs=ogg_buffer_create();
586
587 fprintf(stderr,"\nSmall preclipped packing (LSb): ");
588 cliptest(testbuffer1,test1size,0,one,onesize);
589 fprintf(stderr,"ok.");
590
591 fprintf(stderr,"\nNull bit call (LSb): ");
592 cliptest(testbuffer3,test3size,0,two,twosize);
593 fprintf(stderr,"ok.");
594
595 fprintf(stderr,"\nLarge preclipped packing (LSb): ");
596 cliptest(testbuffer2,test2size,0,three,threesize);
597 fprintf(stderr,"ok.");
598
599 fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
600
601 or=ogg_buffer_alloc(bs,128);
602 for(i=0;i<test2size;i++){
603 or->buffer->data[i*4] = large[i]&0xff;
604 or->buffer->data[i*4+1] = (large[i]>>8)&0xff;
605 or->buffer->data[i*4+2] = (large[i]>>16)&0xff;
606 or->buffer->data[i*4+3] = (large[i]>>24)&0xff;
607 }
608 or->length=test2size*4;
609 oggpack_readinit(&r,or);
610 for(i=0;i<test2size;i++){
611 unsigned long test;
612 if((test=oggpack_look(&r,32))==0xffffffffUL)report("out of data. failed!");
613 if(test!=large[i]){
614 fprintf(stderr,"%ld != %ld (%lx!=%lx):",test,large[i],
615 test,large[i]);
616 report("read incorrect value!\n");
617 }
618 oggpack_adv(&r,32);
619 }
620 ogg_buffer_release(or);
621 if(oggpack_bytes(&r)!=test2size*4){
622 fprintf(stderr, "%d vs %d\n", oggpack_bytes(&r), test2size*4);
623 report("leftover bytes after read!\n");
624 }
625 fprintf(stderr,"ok.");
626
627 fprintf(stderr,"\nSmall unclipped packing (LSb): ");
628 cliptest(testbuffer1,test1size,7,four,foursize);
629 fprintf(stderr,"ok.");
630
631 fprintf(stderr,"\nLarge unclipped packing (LSb): ");
632 cliptest(testbuffer2,test2size,17,five,fivesize);
633 fprintf(stderr,"ok.");
634
635 fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
636 cliptest(testbuffer3,test3size,1,six,sixsize);
637 fprintf(stderr,"ok.");
638
639 fprintf(stderr,"\nTesting read past end (LSb): ");
640 {
641 unsigned char dda[]={0,0,0,0};
642 ogg_buffer lob={dda,8,0,{0}};
643 ogg_reference lor={&lob,0,8,0};
644
645 oggpack_readinit(&r,&lor);
646 for(i=0;i<64;i++){
647 if(oggpack_read(&r,1)<0){
648 fprintf(stderr,"failed; got -1 prematurely.\n");
649 exit(1);
650 }
651 }
652 if(oggpack_look(&r,1)!=-1 ||
653 oggpack_read(&r,1)!=-1){
654 fprintf(stderr,"failed; read past end without -1.\n");
655 exit(1);
656 }
657 }
658 {
659 unsigned char dda[]={0,0,0,0};
660 ogg_buffer lob={dda,8,0,{0}};
661 ogg_reference lor={&lob,0,8,0};
662 unsigned long test;
663
664 oggpack_readinit(&r,&lor);
665 if((test=oggpack_read(&r,30))==0xffffffffUL ||
666 (test=oggpack_read(&r,16))==0xffffffffUL){
667 fprintf(stderr,"failed 2; got -1 prematurely.\n");
668 exit(1);
669 }
670
671 if((test=oggpack_look(&r,18))==0xffffffffUL){
672 fprintf(stderr,"failed 3; got -1 prematurely.\n");
673 exit(1);
674 }
675 if((test=oggpack_look(&r,19))!=0xffffffffUL){
676 fprintf(stderr,"failed; read past end without -1.\n");
677 exit(1);
678 }
679 if((test=oggpack_look(&r,32))!=0xffffffffUL){
680 fprintf(stderr,"failed; read past end without -1.\n");
681 exit(1);
682 }
683 }
684 fprintf(stderr,"ok.\n");
685
686 /* now the scary shit: randomized testing */
687
688 for(i=0;i<10000;i++){
689 long j,count=0,count2=0,bitcount=0;
690 unsigned long values[TESTWORDS];
691 int len[TESTWORDS];
692 unsigned char flat[4*TESTWORDS]; /* max possible needed size */
693
694 memset(flat,0,sizeof(flat));
695 fprintf(stderr,"\rRandomized testing (LSb)... (%ld) ",10000-i);
696
697 /* generate a list of words and lengths */
698 /* write the required number of bits out to packbuffer */
699 {
700 long word=0;
701 long bit=0;
702 int k;
703
704 for(j=0;j<TESTWORDS;j++){
705 values[j]=rand();
706 len[j]=(rand()%33);
707
708 for(k=0;k<len[j];k++){
709 flat[word] |= ((values[j]>>k)&0x1)<<bit;
710 bit++;
711 bitcount++;
712 if(bit>7){
713 bit=0;
714 word++;
715 }
716 }
717 }
718 }
719 count2=(bitcount+7)>>3;
720
721 /* construct random-length buffer chain from flat vector; random
722 byte starting offset within the length of the vector */
723 {
724 ogg_reference *or=NULL,*orl=NULL;
725 long pos=0;
726
727 /* build buffer chain */
728 while(count2){
729 int ilen=(rand()%32),k;
730 int ibegin=(rand()%32);
731
732
733 if(ilen>count2)ilen=count2;
734
735 if(or)
736 orl=ogg_buffer_extend(orl,64);
737 else
738 or=orl=ogg_buffer_alloc(bs,64);
739
740 orl->length=ilen;
741 orl->begin=ibegin;
742
743 for(k=0;k<ilen;k++)
744 orl->buffer->data[ibegin++]= flat[pos++];
745
746 count2-=ilen;
747 }
748
749 if(ogg_buffer_length(or)!=(bitcount+7)/8){
750 fprintf(stderr,"\nERROR: buffer length incorrect after build.\n");
751 exit(1);
752 }
753
754
755 {
756 int begin=0; //=(rand()%TESTWORDS);
757 int ilen=(rand()%(TESTWORDS-begin));
758 int bitoffset,bitcount=0;
759 unsigned long temp;
760
761 for(j=0;j<begin;j++)
762 bitcount+=len[j];
763 or=ogg_buffer_pretruncate(or,bitcount/8);
764 bitoffset=bitcount%=8;
765 for(;j<begin+ilen;j++)
766 bitcount+=len[j];
767 ogg_buffer_posttruncate(or,((bitcount+7)/8));
768
769 if((count=ogg_buffer_length(or))!=(bitcount+7)/8){
770 fprintf(stderr,"\nERROR: buffer length incorrect after truncate.\n");
771 exit(1);
772 }
773
774 oggpack_readinit(&o,or);
775
776 /* verify bit count */
777 if(oggpack_bits(&o)!=0){
778 fprintf(stderr,"\nERROR: Read bitcounter not zero!\n");
779 exit(1);
780 }
781 if(oggpack_bytes(&o)!=0){
782 fprintf(stderr,"\nERROR: Read bytecounter not zero!\n");
783 exit(1);
784 }
785
786 bitcount=bitoffset;
787 oggpack_read(&o,bitoffset);
788
789 /* read and compare to original list */
790 for(j=begin;j<begin+ilen;j++){
791 temp=oggpack_read(&o,len[j]);
792 if(temp==0xffffffffUL){
793 fprintf(stderr,"\nERROR: End of stream too soon! word: %ld,%d\n",
794 j-begin,ilen);
795 exit(1);
796 }
797 if(temp!=(values[j]&mask[len[j]])){
798 fprintf(stderr,"\nERROR: Incorrect read %lx != %lx, word %ld, len %d\n"
799,
800 values[j]&mask[len[j]],temp,j-begin,len[j]);
801 exit(1);
802 }
803 bitcount+=len[j];
804 if(oggpack_bits(&o)!=bitcount){
805 fprintf(stderr,"\nERROR: Read bitcounter %d != %ld!\n",
806 bitcount,oggpack_bits(&o));
807 exit(1);
808 }
809 if(oggpack_bytes(&o)!=(bitcount+7)/8){
810 fprintf(stderr,"\nERROR: Read bytecounter %d != %ld!\n",
811 (bitcount+7)/8,oggpack_bytes(&o));
812 exit(1);
813 }
814
815 }
816 _end_verify(count);
817
818 /* look/adv version */
819 oggpack_readinit(&o,or);
820 bitcount=bitoffset;
821 oggpack_adv(&o,bitoffset);
822
823 /* read and compare to original list */
824 for(j=begin;j<begin+ilen;j++){
825 temp=oggpack_look(&o,len[j]);
826
827 if(temp==0xffffffffUL){
828 fprintf(stderr,"\nERROR: End of stream too soon! word: %ld\n",
829 j-begin);
830 exit(1);
831 }
832 if(temp!=(values[j]&mask[len[j]])){
833 fprintf(stderr,"\nERROR: Incorrect look %lx != %lx, word %ld, len %d\n"
834,
835 values[j]&mask[len[j]],temp,j-begin,len[j]);
836 exit(1);
837 }
838 oggpack_adv(&o,len[j]);
839 bitcount+=len[j];
840 if(oggpack_bits(&o)!=bitcount){
841 fprintf(stderr,"\nERROR: Look/Adv bitcounter %d != %ld!\n",
842 bitcount,oggpack_bits(&o));
843 exit(1);
844 }
845 if(oggpack_bytes(&o)!=(bitcount+7)/8){
846 fprintf(stderr,"\nERROR: Look/Adv bytecounter %d != %ld!\n",
847 (bitcount+7)/8,oggpack_bytes(&o));
848 exit(1);
849 }
850
851 }
852 _end_verify2(count);
853
854 }
855 ogg_buffer_release(or);
856 }
857 }
858 fprintf(stderr,"\rRandomized testing (LSb)... ok. \n");
859
860 return(0);
861}
862
863#ifdef _WIN32_WCE
864int WinMain(void){
865 return main();
866}
867#endif
868
869#endif