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         break;
181     }
182   }
183 }
184 
oggpack_readinit(oggpack_buffer * b,ogg_reference * r)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 */
oggpack_look(oggpack_buffer * b,int bits)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 */
oggpack_adv(oggpack_buffer * b,int bits)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 
oggpack_eop(oggpack_buffer * b)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 
oggpack_bytes(oggpack_buffer * b)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 
oggpack_bits(oggpack_buffer * b)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 */
oggpack_read(oggpack_buffer * b,int bits)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 
ilog(unsigned long v)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 
report(char * in)369 void report(char *in){
370   fprintf(stderr,"%s",in);
371   exit(1);
372 }
373 
getbyte(ogg_reference * or,int position)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 
cliptest(unsigned long * b,int vals,int bits,int * comp,int compsize)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 
_end_verify(int count)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 
_end_verify2(int count)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 
ogg_buffer_length(ogg_reference * or)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 
ogg_buffer_extend(ogg_reference * or,long bytes)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 
ogg_buffer_posttruncate(ogg_reference * or,long pos)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 
main(void)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
WinMain(void)866 int WinMain(void){
867     return main();
868 }
869 #endif
870 
871 #endif
872