examples/sfexamples/oggvorbiscodec/src/tremor/bitwise.c

00001 /********************************************************************
00002  *                                                                  *
00003  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
00004  *                                                                  *
00005  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
00006  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
00007  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
00008  *                                                                  *
00009  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
00010  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
00011  *                                                                  *
00012  ********************************************************************
00013 
00014   function: packing variable sized words into an octet stream
00015 
00016  ********************************************************************/
00017 
00018 /* We're 'LSb' endian; if we write a word but read individual bits,
00019    then we'll read the lsb first */
00020 
00021 #include <string.h>
00022 #include <stdlib.h>
00023 #include "ogg.h"
00024 
00025 const static unsigned long mask[]=
00026 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
00027  0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
00028  0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
00029  0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
00030  0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
00031  0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
00032  0x3fffffff,0x7fffffff,0xffffffff };
00033 
00034 /* mark read process as having run off the end */
00035 static void _adv_halt(oggpack_buffer *b){
00036   b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
00037   b->headend=-1;
00038   b->headbit=0;
00039 }
00040 
00041 /* spans forward, skipping as many bytes as headend is negative; if
00042    headend is zero, simply finds next byte.  If we're up to the end
00043    of the buffer, leaves headend at zero.  If we've read past the end,
00044    halt the decode process. */
00045 static void _span(oggpack_buffer *b){
00046   while(b->headend<1){
00047     if(b->head->next){
00048       b->count+=b->head->length;
00049       b->head=b->head->next;
00050       b->headptr=b->head->buffer->data+b->head->begin-b->headend; 
00051       b->headend+=b->head->length;      
00052     }else{
00053       /* we've either met the end of decode, or gone past it. halt
00054          only if we're past */
00055       if(b->headend<0 || b->headbit)
00056         /* read has fallen off the end */
00057         _adv_halt(b);
00058 
00059       break;
00060     }
00061   }
00062 }
00063 
00064 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
00065   memset(b,0,sizeof(*b));
00066 
00067   b->tail=b->head=r;
00068   b->count=0;
00069   b->headptr=b->head->buffer->data+b->head->begin;
00070   b->headend=b->head->length;
00071   _span(b);
00072 }
00073 
00074 #define _lookspan()   while(!end){\
00075                         head=head->next;\
00076                         if(!head) return -1;\
00077                         ptr=head->buffer->data + head->begin;\
00078                         end=head->length;\
00079                       }
00080 
00081 /* Read in bits without advancing the bitptr; bits <= 32 */
00082 long oggpack_look(oggpack_buffer *b,int bits){
00083   unsigned long m=mask[bits];
00084   unsigned long ret=0;
00085 
00086   bits+=b->headbit;
00087 
00088   if(bits >= b->headend<<3){
00089     int            end=b->headend;
00090     unsigned char *ptr=b->headptr;
00091     ogg_reference *head=b->head;
00092 
00093     if(end<0)return -1;
00094     
00095     if(bits){
00096       _lookspan();
00097       ret=*ptr++>>b->headbit;
00098       if(bits>8){
00099         --end;
00100         _lookspan();
00101         ret|=*ptr++<<(8-b->headbit);  
00102         if(bits>16){
00103           --end;
00104           _lookspan();
00105           ret|=*ptr++<<(16-b->headbit);  
00106           if(bits>24){
00107             --end;
00108             _lookspan();
00109             ret|=*ptr++<<(24-b->headbit);  
00110             if(bits>32 && b->headbit){
00111               --end;
00112               _lookspan();
00113               ret|=*ptr<<(32-b->headbit);
00114             }
00115           }
00116         }
00117       }
00118     }
00119 
00120   }else{
00121 
00122     /* make this a switch jump-table */
00123     ret=b->headptr[0]>>b->headbit;
00124     if(bits>8){
00125       ret|=b->headptr[1]<<(8-b->headbit);  
00126       if(bits>16){
00127         ret|=b->headptr[2]<<(16-b->headbit);  
00128         if(bits>24){
00129           ret|=b->headptr[3]<<(24-b->headbit);  
00130           if(bits>32 && b->headbit)
00131             ret|=b->headptr[4]<<(32-b->headbit);
00132         }
00133       }
00134     }
00135   }
00136 
00137   ret&=m;
00138   return ret;
00139 }
00140 
00141 /* limited to 32 at a time */
00142 void oggpack_adv(oggpack_buffer *b,int bits){
00143   bits+=b->headbit;
00144   b->headbit=bits&7;
00145   b->headptr+=bits/8;
00146   if((b->headend-=bits/8)<1)_span(b);
00147 }
00148 
00149 /* spans forward and finds next byte.  Never halts */
00150 static void _span_one(oggpack_buffer *b){
00151   while(b->headend<1){
00152     if(b->head->next){
00153       b->count+=b->head->length;
00154       b->head=b->head->next;
00155       b->headptr=b->head->buffer->data+b->head->begin; 
00156       b->headend=b->head->length;      
00157     }else
00158       break;
00159   }
00160 }
00161 
00162 static int _halt_one(oggpack_buffer *b){
00163   if(b->headend<1){
00164     _adv_halt(b);
00165     return -1;
00166   }
00167   return 0;
00168 }
00169 
00170 int oggpack_eop(oggpack_buffer *b){
00171   if(b->headend<0)return -1;
00172   return 0;
00173 }
00174 
00175 /* bits <= 32 */
00176 long oggpack_read(oggpack_buffer *b,int bits){
00177   unsigned long m=mask[bits];
00178   ogg_uint32_t ret=0;
00179 
00180   bits+=b->headbit;
00181 
00182   if(bits >= b->headend<<3){
00183 
00184     if(b->headend<0)return -1;
00185     
00186     if(bits){
00187       if (_halt_one(b)) return -1;
00188       ret=*b->headptr>>b->headbit;
00189       
00190       if(bits>=8){
00191         ++b->headptr;
00192         --b->headend;
00193         _span_one(b);
00194         if(bits>8){
00195           if (_halt_one(b)) return -1;
00196           ret|=*b->headptr<<(8-b->headbit);   
00197           
00198           if(bits>=16){
00199             ++b->headptr;
00200             --b->headend;
00201             _span_one(b);
00202             if(bits>16){
00203               if (_halt_one(b)) return -1;
00204               ret|=*b->headptr<<(16-b->headbit);  
00205               
00206               if(bits>=24){
00207                 ++b->headptr;
00208                 --b->headend;
00209                 _span_one(b);
00210                 if(bits>24){
00211                   if (_halt_one(b)) return -1;
00212                   ret|=*b->headptr<<(24-b->headbit);
00213                   
00214                   if(bits>=32){
00215                     ++b->headptr;
00216                     --b->headend;
00217                     _span_one(b);
00218                     if(bits>32){
00219                       if (_halt_one(b)) return -1;
00220                       if(b->headbit)ret|=*b->headptr<<(32-b->headbit);
00221                       
00222                     }
00223                   }
00224                 }
00225               }
00226             }
00227           }
00228         }
00229       }
00230     }
00231   }else{
00232   
00233     ret=b->headptr[0]>>b->headbit;
00234     if(bits>8){
00235       ret|=b->headptr[1]<<(8-b->headbit);  
00236       if(bits>16){
00237         ret|=b->headptr[2]<<(16-b->headbit);  
00238         if(bits>24){
00239           ret|=b->headptr[3]<<(24-b->headbit);  
00240           if(bits>32 && b->headbit){
00241             ret|=b->headptr[4]<<(32-b->headbit);
00242           }
00243         }
00244       }
00245     }
00246     
00247     b->headptr+=bits/8;
00248     b->headend-=bits/8;
00249   }
00250 
00251   ret&=m;
00252   b->headbit=bits&7;   
00253   return ret;
00254 }
00255 
00256 long oggpack_bytes(oggpack_buffer *b){
00257   return(b->count+b->headptr-b->head->buffer->data-b->head->begin+
00258          (b->headbit+7)/8);
00259 }
00260 
00261 long oggpack_bits(oggpack_buffer *b){
00262   return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+
00263          b->headbit);
00264 }
00265 

Generated by  doxygen 1.6.2