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