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