misc/libtremor/tremor/bitwise.c
changeset 9431 0f5961910e27
parent 9357 a501f5ec7b34
parent 9429 7a97a554ac80
child 9433 f0a8ac191839
equal deleted inserted replaced
9357:a501f5ec7b34 9431:0f5961910e27
     1 /********************************************************************
       
     2  *                                                                  *
       
     3  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
       
     4  *                                                                  *
       
     5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
       
     6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
       
     7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
       
     8  *                                                                  *
       
     9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
       
    10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
       
    11  *                                                                  *
       
    12  ********************************************************************
       
    13 
       
    14   function: packing variable sized words into an octet stream
       
    15 
       
    16  ********************************************************************/
       
    17 
       
    18 /* We're 'LSb' endian; if we write a word but read individual bits,
       
    19    then we'll read the lsb first */
       
    20 
       
    21 #include <string.h>
       
    22 #include <stdlib.h>
       
    23 #include "ogg.h"
       
    24 
       
    25 static unsigned long mask[]=
       
    26 {0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
       
    27  0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
       
    28  0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
       
    29  0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
       
    30  0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
       
    31  0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
       
    32  0x3fffffff,0x7fffffff,0xffffffff };
       
    33 
       
    34 /* mark read process as having run off the end */
       
    35 static void _adv_halt(oggpack_buffer *b){
       
    36   b->headptr=b->head->buffer->data+b->head->begin+b->head->length;
       
    37   b->headend=-1;
       
    38   b->headbit=0;
       
    39 }
       
    40 
       
    41 /* spans forward, skipping as many bytes as headend is negative; if
       
    42    headend is zero, simply finds next byte.  If we're up to the end
       
    43    of the buffer, leaves headend at zero.  If we've read past the end,
       
    44    halt the decode process. */
       
    45 static void _span(oggpack_buffer *b){
       
    46   while(b->headend<1){
       
    47     if(b->head->next){
       
    48       b->count+=b->head->length;
       
    49       b->head=b->head->next;
       
    50       b->headptr=b->head->buffer->data+b->head->begin-b->headend;
       
    51       b->headend+=b->head->length;
       
    52     }else{
       
    53       /* we've either met the end of decode, or gone past it. halt
       
    54          only if we're past */
       
    55       if(b->headend<0 || b->headbit)
       
    56         /* read has fallen off the end */
       
    57         _adv_halt(b);
       
    58 
       
    59       break;
       
    60     }
       
    61   }
       
    62 }
       
    63 
       
    64 void oggpack_readinit(oggpack_buffer *b,ogg_reference *r){
       
    65   memset(b,0,sizeof(*b));
       
    66 
       
    67   b->tail=b->head=r;
       
    68   b->count=0;
       
    69   b->headptr=b->head->buffer->data+b->head->begin;
       
    70   b->headend=b->head->length;
       
    71   _span(b);
       
    72 }
       
    73 
       
    74 #define _lookspan()   while(!end){\
       
    75                         head=head->next;\
       
    76                         if(!head) return -1;\
       
    77                         ptr=head->buffer->data + head->begin;\
       
    78                         end=head->length;\
       
    79                       }
       
    80 
       
    81 /* Read in bits without advancing the bitptr; bits <= 32 */
       
    82 long oggpack_look(oggpack_buffer *b,int bits){
       
    83   unsigned long m=mask[bits];
       
    84   unsigned long ret=-1;
       
    85 
       
    86   bits+=b->headbit;
       
    87 
       
    88   if(bits >= b->headend<<3){
       
    89     int            end=b->headend;
       
    90     unsigned char *ptr=b->headptr;
       
    91     ogg_reference *head=b->head;
       
    92 
       
    93     if(end<0)return -1;
       
    94 
       
    95     if(bits){
       
    96       _lookspan();
       
    97       ret=*ptr++>>b->headbit;
       
    98       if(bits>8){
       
    99         --end;
       
   100         _lookspan();
       
   101         ret|=*ptr++<<(8-b->headbit);
       
   102         if(bits>16){
       
   103           --end;
       
   104           _lookspan();
       
   105           ret|=*ptr++<<(16-b->headbit);
       
   106           if(bits>24){
       
   107             --end;
       
   108             _lookspan();
       
   109             ret|=*ptr++<<(24-b->headbit);
       
   110             if(bits>32 && b->headbit){
       
   111               --end;
       
   112               _lookspan();
       
   113               ret|=*ptr<<(32-b->headbit);
       
   114             }
       
   115           }
       
   116         }
       
   117       }
       
   118     }
       
   119 
       
   120   }else{
       
   121 
       
   122     /* make this a switch jump-table */
       
   123     ret=b->headptr[0]>>b->headbit;
       
   124     if(bits>8){
       
   125       ret|=b->headptr[1]<<(8-b->headbit);  
       
   126       if(bits>16){
       
   127         ret|=b->headptr[2]<<(16-b->headbit);  
       
   128         if(bits>24){
       
   129           ret|=b->headptr[3]<<(24-b->headbit);  
       
   130           if(bits>32 && b->headbit)
       
   131             ret|=b->headptr[4]<<(32-b->headbit);
       
   132         }
       
   133       }
       
   134     }
       
   135   }
       
   136 
       
   137   ret&=m;
       
   138   return ret;
       
   139 }
       
   140 
       
   141 /* limited to 32 at a time */
       
   142 void oggpack_adv(oggpack_buffer *b,int bits){
       
   143   bits+=b->headbit;
       
   144   b->headbit=bits&7;
       
   145   b->headptr+=bits/8;
       
   146   if((b->headend-=bits/8)<1)_span(b);
       
   147 }
       
   148 
       
   149 /* spans forward and finds next byte.  Never halts */
       
   150 static void _span_one(oggpack_buffer *b){
       
   151   while(b->headend<1){
       
   152     if(b->head->next){
       
   153       b->count+=b->head->length;
       
   154       b->head=b->head->next;
       
   155       b->headptr=b->head->buffer->data+b->head->begin;
       
   156       b->headend=b->head->length;
       
   157     }else
       
   158       break;
       
   159   }
       
   160 }
       
   161 
       
   162 static int _halt_one(oggpack_buffer *b){
       
   163   if(b->headend<1){
       
   164     _adv_halt(b);
       
   165     return -1;
       
   166   }
       
   167   return 0;
       
   168 }
       
   169 
       
   170 int oggpack_eop(oggpack_buffer *b){
       
   171   if(b->headend<0)return -1;
       
   172   return 0;
       
   173 }
       
   174 
       
   175 /* bits <= 32 */
       
   176 long oggpack_read(oggpack_buffer *b,int bits){
       
   177   unsigned long m=mask[bits];
       
   178   ogg_uint32_t ret=-1;
       
   179 
       
   180   bits+=b->headbit;
       
   181 
       
   182   if(bits >= b->headend<<3){
       
   183 
       
   184     if(b->headend<0)return -1;
       
   185 
       
   186     if(bits){
       
   187       if (_halt_one(b)) return -1;
       
   188       ret=*b->headptr>>b->headbit;
       
   189 
       
   190       if(bits>=8){
       
   191         ++b->headptr;
       
   192         --b->headend;
       
   193         _span_one(b);
       
   194         if(bits>8){
       
   195           if (_halt_one(b)) return -1;
       
   196           ret|=*b->headptr<<(8-b->headbit);
       
   197 
       
   198           if(bits>=16){
       
   199             ++b->headptr;
       
   200             --b->headend;
       
   201             _span_one(b);
       
   202             if(bits>16){
       
   203               if (_halt_one(b)) return -1;
       
   204               ret|=*b->headptr<<(16-b->headbit);
       
   205 
       
   206               if(bits>=24){
       
   207                 ++b->headptr;
       
   208                 --b->headend;
       
   209                 _span_one(b);
       
   210                 if(bits>24){
       
   211                   if (_halt_one(b)) return -1;
       
   212                   ret|=*b->headptr<<(24-b->headbit);
       
   213 
       
   214                   if(bits>=32){
       
   215                     ++b->headptr;
       
   216                     --b->headend;
       
   217                     _span_one(b);
       
   218                     if(bits>32){
       
   219                       if (_halt_one(b)) return -1;
       
   220                       if(b->headbit)ret|=*b->headptr<<(32-b->headbit);
       
   221 
       
   222                     }
       
   223                   }
       
   224                 }
       
   225               }
       
   226             }
       
   227           }
       
   228         }
       
   229       }
       
   230     }
       
   231   }else{
       
   232 
       
   233     ret=b->headptr[0]>>b->headbit;
       
   234     if(bits>8){
       
   235       ret|=b->headptr[1]<<(8-b->headbit);
       
   236       if(bits>16){
       
   237         ret|=b->headptr[2]<<(16-b->headbit);
       
   238         if(bits>24){
       
   239           ret|=b->headptr[3]<<(24-b->headbit);
       
   240           if(bits>32 && b->headbit){
       
   241             ret|=b->headptr[4]<<(32-b->headbit);
       
   242           }
       
   243         }
       
   244       }
       
   245     }
       
   246 
       
   247     b->headptr+=bits/8;
       
   248     b->headend-=bits/8;
       
   249   }
       
   250 
       
   251   ret&=m;
       
   252   b->headbit=bits&7;
       
   253   return ret;
       
   254 }
       
   255 
       
   256 long oggpack_bytes(oggpack_buffer *b){
       
   257   return(b->count+b->headptr-b->head->buffer->data-b->head->begin+
       
   258          (b->headbit+7)/8);
       
   259 }
       
   260 
       
   261 long oggpack_bits(oggpack_buffer *b){
       
   262   return((b->count+b->headptr-b->head->buffer->data-b->head->begin)*8+
       
   263          b->headbit);
       
   264 }
       
   265