• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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