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 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 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 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 */ 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 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 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 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 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 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 */ 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) 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 */ 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 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 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 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 */ 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 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 369 void report(char *in){ 370 fprintf(stderr,"%s",in); 371 exit(1); 372 } 373 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 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 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 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 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 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 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 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 866 int WinMain(void){ 867 return main(); 868 } 869 #endif 870 871 #endif 872