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 | |
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 | |
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 | 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 | |
58 | int 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 | |
67 | void 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.*/ |
73 | long 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 | |
93 | int 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 | |
111 | long 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 | |