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$
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
24void 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
30static 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 unsigned shift;
36 stop=_b->stop;
37 ptr=_b->ptr;
38 window=_b->window;
39 available=_b->bits;
40 shift=OC_PB_WINDOW_SIZE-available;
41 while(7<shift&&ptr<stop){
42 shift-=8;
43 window|=(oc_pb_window)*ptr++<<shift;
44 }
45 _b->ptr=ptr;
46 available=OC_PB_WINDOW_SIZE-shift;
47 if(_bits>available){
48 if(ptr>=stop){
49 _b->eof=1;
50 available=OC_LOTS_OF_BITS;
51 }
52 else window|=*ptr>>(available&7);
53 }
54 _b->bits=available;
55 return window;
56}
57
58int oc_pack_look1(oc_pack_buf *_b){
59 oc_pb_window window;
60 int available;
61 window=_b->window;
62 available=_b->bits;
63 if(available<1)_b->window=window=oc_pack_refill(_b,1);
64 return window>>OC_PB_WINDOW_SIZE-1;
65}
66
67void oc_pack_adv1(oc_pack_buf *_b){
68 _b->window<<=1;
69 _b->bits--;
70}
71
72/*Here we assume that 0<=_bits&&_bits<=32.*/
73long oc_pack_read_c(oc_pack_buf *_b,int _bits){
74 oc_pb_window window;
75 int available;
76 long result;
77 window=_b->window;
78 available=_b->bits;
79 if(_bits==0)return 0;
80 if(available<_bits){
81 window=oc_pack_refill(_b,_bits);
82 available=_b->bits;
83 }
84 result=window>>OC_PB_WINDOW_SIZE-_bits;
85 available-=_bits;
86 window<<=1;
87 window<<=_bits-1;
88 _b->window=window;
89 _b->bits=available;
90 return result;
91}
92
93int oc_pack_read1_c(oc_pack_buf *_b){
94 oc_pb_window window;
95 int available;
96 int result;
97 window=_b->window;
98 available=_b->bits;
99 if(available<1){
100 window=oc_pack_refill(_b,1);
101 available=_b->bits;
102 }
103 result=window>>OC_PB_WINDOW_SIZE-1;
104 available--;
105 window<<=1;
106 _b->window=window;
107 _b->bits=available;
108 return result;
109}
110
111long oc_pack_bytes_left(oc_pack_buf *_b){
112 if(_b->eof)return -1;
113 return _b->stop-_b->ptr+(_b->bits>>3);
114}
115