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) { 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 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 */ 284 void 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 299 int 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 308 long 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 321 long 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 */ 335 long 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 352 static int ilog(unsigned long v){ 353 int ret=0; 354 while(v){ 355 ret++; 356 v>>=1; 357 } 358 return(ret); 359 } 360 361 oggpack_buffer r; 362 oggpack_buffer o; 363 ogg_buffer_state *bs; 364 ogg_reference *or; 365 #define TESTWORDS 256 366 367 void report(char *in){ 368 fprintf(stderr,"%s",in); 369 exit(1); 370 } 371 372 int 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 388 void 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 427 void _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 456 void _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 500 long 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 509 ogg_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 520 void 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 533 int 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 864 int WinMain(void){ 865 return main(); 866 } 867 #endif 868 869 #endif 870