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