1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE OggTheora SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
9  * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
10  *                                                                  *
11  ********************************************************************
12 
13   function: packing variable sized words into an octet stream
14   last mod: $Id: bitpack.c 16503 2009-08-22 18:14:02Z giles $
15 
16  ********************************************************************/
17 #include <string.h>
18 #include <stdlib.h>
19 #include "bitpack.h"
20 
21 /*We're 'MSb' endian; if we write a word but read individual bits,
22    then we'll read the MSb first.*/
23 
oc_pack_readinit(oc_pack_buf * _b,unsigned char * _buf,long _bytes)24 void oc_pack_readinit(oc_pack_buf *_b,unsigned char *_buf,long _bytes){
25   memset(_b,0,sizeof(*_b));
26   _b->ptr=_buf;
27   _b->stop=_buf+_bytes;
28 }
29 
oc_pack_refill(oc_pack_buf * _b,int _bits)30 static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
31   const unsigned char *ptr;
32   const unsigned char *stop;
33   oc_pb_window         window;
34   int                  available;
35   window=_b->window;
36   available=_b->bits;
37   ptr=_b->ptr;
38   stop=_b->stop;
39   while(available<=OC_PB_WINDOW_SIZE-8&&ptr<stop){
40     available+=8;
41     window|=(oc_pb_window)*ptr++<<OC_PB_WINDOW_SIZE-available;
42   }
43   _b->ptr=ptr;
44   if(_bits>available){
45     if(ptr>=stop){
46       _b->eof=1;
47       available=OC_LOTS_OF_BITS;
48     }
49     else window|=*ptr>>(available&7);
50   }
51   _b->bits=available;
52   return window;
53 }
54 
oc_pack_look1(oc_pack_buf * _b)55 int oc_pack_look1(oc_pack_buf *_b){
56   oc_pb_window window;
57   int          available;
58   window=_b->window;
59   available=_b->bits;
60   if(available<1)_b->window=window=oc_pack_refill(_b,1);
61   return window>>OC_PB_WINDOW_SIZE-1;
62 }
63 
oc_pack_adv1(oc_pack_buf * _b)64 void oc_pack_adv1(oc_pack_buf *_b){
65   _b->window<<=1;
66   _b->bits--;
67 }
68 
69 /*Here we assume that 0<=_bits&&_bits<=32.*/
oc_pack_read(oc_pack_buf * _b,int _bits)70 long oc_pack_read(oc_pack_buf *_b,int _bits){
71   oc_pb_window window;
72   int          available;
73   long         result;
74   window=_b->window;
75   available=_b->bits;
76   if(_bits==0)return 0;
77   if(available<_bits){
78     window=oc_pack_refill(_b,_bits);
79     available=_b->bits;
80   }
81   result=window>>OC_PB_WINDOW_SIZE-_bits;
82   available-=_bits;
83   window<<=1;
84   window<<=_bits-1;
85   _b->bits=available;
86   _b->window=window;
87   return result;
88 }
89 
oc_pack_read1(oc_pack_buf * _b)90 int oc_pack_read1(oc_pack_buf *_b){
91   oc_pb_window window;
92   int          available;
93   int          result;
94   window=_b->window;
95   available=_b->bits;
96   if(available<1){
97     window=oc_pack_refill(_b,1);
98     available=_b->bits;
99   }
100   result=window>>OC_PB_WINDOW_SIZE-1;
101   available--;
102   window<<=1;
103   _b->bits=available;
104   _b->window=window;
105   return result;
106 }
107 
oc_pack_bytes_left(oc_pack_buf * _b)108 long oc_pack_bytes_left(oc_pack_buf *_b){
109   if(_b->eof)return -1;
110   return _b->stop-_b->ptr+(_b->bits>>3);
111 }
112