Panda3D
panda
src
pnmimage
pnmbitio.cxx
1
/*
2
* bitio.c - bitstream I/O
3
*
4
* Works for (sizeof(unsigned long)-1)*8 bits.
5
*
6
* Copyright (C) 1992 by David W. Sanderson.
7
*
8
* Permission to use, copy, modify, and distribute this software and its
9
* documentation for any purpose and without fee is hereby granted,
10
* provided that the above copyright notice appear in all copies and
11
* that both that copyright notice and this permission notice appear
12
* in supporting documentation. This software is provided "as is"
13
* without express or implied warranty.
14
*/
15
16
#include "pnmbitio.h"
17
#include <assert.h>
18
19
using
std::istream;
20
using
std::ostream;
21
22
struct
bitstream
23
{
24
istream *inf;
25
ostream *outf;
26
unsigned
long
27
bitbuf;
/* bit buffer */
28
int
29
nbitbuf;
/* number of bits in 'bitbuf' */
30
char
31
mode;
32
};
33
34
#define Mask(n) ((1<<(n))-1)
35
36
#define BitPut(b,ul,n) ((b)->bitbuf = (((b)->bitbuf<<(n)) \
37
|((ul)&Mask(n))), \
38
(b)->nbitbuf += (n))
39
40
#define BitGet(b,n) (((b)->bitbuf>>((b)->nbitbuf-=(n))) & Mask(n))
41
42
/*
43
* pm_bitinit() - allocate and return a struct bitstream * for the
44
* given FILE*.
45
*
46
* mode must be one of "r" or "w", according to whether you will be
47
* reading from or writing to the struct bitstream *.
48
*
49
* Returns 0 on error.
50
*/
51
52
EXPCL_PANDA_PNMIMAGE
struct
bitstream *
53
pm_bitinit(istream *f,
const
char
*mode)
54
{
55
struct
bitstream *ans =
nullptr
;
56
57
if
(!f || !mode || !*mode)
58
return
ans;
59
if
(strcmp(mode,
"r"
))
60
return
ans;
61
62
ans = (
struct
bitstream *)calloc(1,
sizeof
(
struct
bitstream));
63
if
(ans)
64
{
65
ans->inf = f;
66
ans->mode = *mode;
67
}
68
69
return
ans;
70
}
71
72
EXPCL_PANDA_PNMIMAGE
struct
bitstream *
73
pm_bitinit(ostream *f,
const
char
*mode)
74
{
75
struct
bitstream *ans =
nullptr
;
76
77
if
(!f || !mode || !*mode)
78
return
ans;
79
if
(strcmp(mode,
"w"
))
80
return
ans;
81
82
ans = (
struct
bitstream *)calloc(1,
sizeof
(
struct
bitstream));
83
if
(ans)
84
{
85
ans->outf = f;
86
ans->mode = *mode;
87
}
88
89
return
ans;
90
}
91
92
/*
93
* pm_bitfini() - deallocate the given struct bitstream *.
94
*
95
* You must call this after you are done with the struct bitstream *.
96
*
97
* It may flush some bits left in the buffer.
98
*
99
* Returns the number of bytes written, -1 on error.
100
*/
101
102
EXPCL_PANDA_PNMIMAGE
int
103
pm_bitfini(
struct
bitstream *b)
104
{
105
int
nbyte = 0;
106
107
if
(!b)
108
return
-1;
109
110
/* flush the output */
111
if
(b->mode ==
'w'
)
112
{
113
/* flush the bits */
114
if
(b->nbitbuf < 0 || b->nbitbuf >= 8)
115
{
116
/* pm_bitwrite() didn't work */
117
return
-1;
118
}
119
120
/*
121
* If we get to here, nbitbuf is 0..7
122
*/
123
if
(b->nbitbuf)
124
{
125
char
c;
126
127
BitPut(b, 0, (
long
)8-(b->nbitbuf));
128
c = (char) BitGet(b, (
long
)8);
129
if
(!b->outf->put(c))
130
{
131
return
-1;
132
}
133
nbyte++;
134
}
135
}
136
137
free(b);
138
return
nbyte;
139
}
140
141
/*
142
* pm_bitread() - read the next nbits into *val from the given file.
143
*
144
* The last pm_bitread() must be followed by a call to pm_bitfini().
145
*
146
* Returns the number of bytes read, -1 on error.
147
*/
148
149
EXPCL_PANDA_PNMIMAGE
int
150
pm_bitread(
struct
bitstream *b,
unsigned
long
nbits,
unsigned
long
*val)
151
{
152
int
nbyte = 0;
153
int
c;
154
155
if
(!b)
156
return
-1;
157
158
#ifdef _DEBUG
159
assert(((
signed
long
)nbits) > 0);
160
#endif
161
162
while
(b->nbitbuf < (
signed
long
)nbits)
163
{
164
if
((c = b->inf->get()) == EOF)
165
{
166
return
-1;
167
}
168
nbyte++;
169
170
BitPut(b, c, (
long
) 8);
171
}
172
173
*val = BitGet(b, nbits);
174
return
nbyte;
175
}
176
177
/*
178
* pm_bitwrite() - write the low nbits of val to the given file.
179
*
180
* The last pm_bitwrite() must be followed by a call to pm_bitfini().
181
*
182
* Returns the number of bytes written, -1 on error.
183
*/
184
185
EXPCL_PANDA_PNMIMAGE
int
186
pm_bitwrite(
struct
bitstream *b,
unsigned
long
nbits,
unsigned
long
val)
187
{
188
int
nbyte = 0;
189
char
c;
190
191
if
(!b)
192
return
-1;
193
194
BitPut(b, val, nbits);
195
196
while
(b->nbitbuf >= 8)
197
{
198
c = (char) BitGet(b, (
long
)8);
199
200
if
(!b->outf->put(c))
201
{
202
return
-1;
203
}
204
nbyte++;
205
}
206
207
return
nbyte;
208
}
Generated on Wed Jan 23 2019 21:40:15 for Panda3D by
1.8.15