1 /*===========================================================================*
2 * bitio.c *
3 * *
4 * Procedures concerned with the bit-wise I/O *
5 * *
6 * EXPORTED PROCEDURES: *
7 * Bitio_New *
8 * Bitio_Free *
9 * Bitio_Write *
10 * Bitio_Flush *
11 * Bitio_WriteToSocket *
12 * Bitio_BytePad *
13 * *
14 *===========================================================================*/
15
16 /*
17 * Copyright (c) 1995 The Regents of the University of California.
18 * All rights reserved.
19 *
20 * Permission to use, copy, modify, and distribute this software and its
21 * documentation for any purpose, without fee, and without written agreement is
22 * hereby granted, provided that the above copyright notice and the following
23 * two paragraphs appear in all copies of this software.
24 *
25 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
26 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
27 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
28 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
33 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
34 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
35 */
36
37 /*
38 * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/bitio.c,v 1.13 1995/06/21 18:36:06 smoot Exp $
39 * $Log: bitio.c,v $
40 * Revision 1.13 1995/06/21 18:36:06 smoot
41 * added a flush when done with file
42 *
43 * Revision 1.12 1995/01/19 23:07:15 eyhung
44 * Changed copyrights
45 *
46 * Revision 1.11 1994/11/12 02:11:43 keving
47 * nothing
48 *
49 * Revision 1.10 1993/12/22 19:19:01 keving
50 * nothing
51 *
52 * Revision 1.10 1993/12/22 19:19:01 keving
53 * nothing
54 *
55 * Revision 1.9 1993/07/22 22:23:43 keving
56 * nothing
57 *
58 * Revision 1.8 1993/06/30 20:06:09 keving
59 * nothing
60 *
61 * Revision 1.7 1993/06/03 21:08:08 keving
62 * nothing
63 *
64 * Revision 1.6 1993/02/17 23:21:41 dwallach
65 * checkin prior to keving's joining the project
66 *
67 * Revision 1.5 1993/01/18 10:20:02 dwallach
68 * *** empty log message ***
69 *
70 * Revision 1.4 1993/01/18 10:17:29 dwallach
71 * RCS headers installed, code indented uniformly
72 *
73 * Revision 1.4 1993/01/18 10:17:29 dwallach
74 * RCS headers installed, code indented uniformly
75 *
76 */
77
78 /*==============*
79 * HEADER FILES *
80 *==============*/
81
82 #include <assert.h>
83 #include <time.h>
84 #include <stdio.h>
85 #include <string.h>
86 #include "all.h"
87 #include "byteorder.h"
88 #include "bitio.h"
89 #include "mtypes.h"
90
91 /*===============================*
92 * INTERNAL PROCEDURE prototypes *
93 *===============================*/
94
95 static void Dump _ANSI_ARGS_((BitBucket *bbPtr));
96
97
98 /*==================*
99 * STATIC VARIABLES *
100 *==================*/
101
102 static uint32 lower_mask[33] = {
103 0,
104 0x1, 0x3, 0x7, 0xf,
105 0x1f, 0x3f, 0x7f, 0xff,
106 0x1ff, 0x3ff, 0x7ff, 0xfff,
107 0x1fff, 0x3fff, 0x7fff, 0xffff,
108 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
109 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
110 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
111 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
112 };
113
114
115 extern time_t IOtime;
116
117
118 /*=====================*
119 * EXPORTED PROCEDURES *
120 *=====================*/
121
122
123 /*===========================================================================*
124 *
125 * Bitio_New
126 *
127 * Create a new bit bucket; filePtr is a pointer to the open file the
128 * bits should ultimately be written to.
129 *
130 * RETURNS: pointer to the resulting bit bucket
131 *
132 * SIDE EFFECTS: none
133 *
134 *===========================================================================*/
135 BitBucket *
Bitio_New(FILE * filePtr)136 Bitio_New(FILE *filePtr)
137 {
138 BitBucket *bbPtr;
139
140 bbPtr = (BitBucket *) malloc(sizeof(BitBucket));
141 ERRCHK(bbPtr, "malloc");
142
143 bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
144 ERRCHK(bbPtr->firstPtr, "malloc");
145
146 bbPtr->totalbits = 0;
147 bbPtr->cumulativeBits = 0;
148 bbPtr->bitsWritten = 0;
149 bbPtr->filePtr = filePtr;
150
151 bbPtr->firstPtr->nextPtr = NULL;
152 bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;
153 bbPtr->firstPtr->bitsleftcur = 32;
154 bbPtr->firstPtr->currword = 0;
155 memset((char *)bbPtr->firstPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
156
157 return bbPtr;
158 }
159
160
161 /*===========================================================================*
162 *
163 * Bitio_Free
164 *
165 * Frees the memory associated with the given bit bucket
166 *
167 * RETURNS: nothing
168 *
169 * SIDE EFFECTS: none
170 *
171 *===========================================================================*/
172 void
Bitio_Free(BitBucket * bbPtr)173 Bitio_Free(BitBucket *bbPtr)
174 {
175 struct bitBucket *tmpPtr, *nextPtr;
176
177 for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {
178 nextPtr = tmpPtr->nextPtr;
179 free(tmpPtr);
180 }
181 free(bbPtr);
182 }
183
184
185 /*===========================================================================*
186 *
187 * Bitio_Write
188 *
189 * Writes 'nbits' bits from 'bits' into the given bit bucket
190 * 'nbits' must be between 0 and 32
191 *
192 * RETURNS: nothing
193 *
194 * SIDE EFFECTS: if the number of bits in the bit bucket surpasses
195 * MAX_BITS, then that many bits are flushed to the
196 * appropriate output file
197 *
198 *===========================================================================*/
199 void
Bitio_Write(BitBucket * bbPtr,uint32 bits,int nbits)200 Bitio_Write(BitBucket *bbPtr,
201 uint32 bits,
202 int nbits)
203 {
204 register struct bitBucket *lastPtr, *newPtr;
205 register int delta;
206
207 assert(nbits <= 32 && nbits >= 0);
208
209 /*
210 * Clear top bits if not part of data, necessary due to down and
211 * dirty calls of Bitio_Write with unecessary top bits set.
212 */
213
214 bits = bits & lower_mask[nbits];
215
216 bbPtr->totalbits += nbits;
217 bbPtr->cumulativeBits += nbits;
218 lastPtr = bbPtr->lastPtr;
219
220 delta = nbits - lastPtr->bitsleft;
221 if (delta >= 0) {
222 /*
223 * there's not enough room in the current bucket, so we're
224 * going to have to allocate another bucket
225 */
226 newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
227 ERRCHK(newPtr, "malloc");
228 newPtr->nextPtr = NULL;
229 newPtr->bitsleft = MAXBITS_PER_BUCKET;
230 newPtr->bitsleftcur = 32;
231 newPtr->currword = 0;
232 memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
233 bbPtr->lastPtr = newPtr;
234
235 assert(lastPtr->currword == WORDS_PER_BUCKET - 1);
236 lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);
237 lastPtr->bitsleft = 0;
238 lastPtr->bitsleftcur = 0;
239 /* lastPtr->currword++; */
240
241 if (!delta) {
242 if ( bbPtr->totalbits > MAX_BITS ) {
243 Dump(bbPtr);
244 }
245 }
246
247 assert(delta <= 32);
248 newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);
249 newPtr->bitsleft -= delta;
250 newPtr->bitsleftcur -= delta;
251 } else {
252 /*
253 * the current bucket will be sufficient
254 */
255 delta = nbits - lastPtr->bitsleftcur;
256 lastPtr->bitsleftcur -= nbits;
257 lastPtr->bitsleft -= nbits;
258
259 if (delta >= 0)
260 {
261 /*
262 * these bits will span more than one word
263 */
264 lastPtr->bits[lastPtr->currword] |= (bits >> delta);
265 lastPtr->currword++;
266 lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);
267 lastPtr->bitsleftcur = 32 - delta;
268 } else {
269 /*
270 * these bits will fit, whole
271 */
272 lastPtr->bits[lastPtr->currword] |= (bits << (-delta));
273 }
274 }
275
276 if ( bbPtr->totalbits > MAX_BITS ) /* flush bits */
277 Dump(bbPtr);
278 }
279
280
281 /*===========================================================================*
282 *
283 * Bitio_Flush
284 *
285 * Flushes all of the remaining bits in the given bit bucket to the
286 * appropriate output file. It will generate up to the nearest 8-bit
287 * unit of bits, which means that up to 7 extra 0 bits will be appended
288 * to the end of the file.
289 *
290 * RETURNS: nothing
291 *
292 * SIDE EFFECTS: frees the bit bucket
293 *
294 *===========================================================================*/
295 void
Bitio_Flush(BitBucket * bbPtr)296 Bitio_Flush(BitBucket *bbPtr)
297 {
298 struct bitBucket *ptr, *tempPtr;
299 uint32 buffer[WORDS_PER_BUCKET];
300 uint32 lastWord;
301 int i, nitems;
302 int bitsWritten = 0;
303 int bitsLeft;
304 int numWords;
305 uint8 charBuf[4];
306 boolean flushHere = FALSE;
307 time_t tempTimeStart, tempTimeEnd;
308
309 time(&tempTimeStart);
310
311 bitsLeft = bbPtr->totalbits;
312
313 for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
314 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
315 continue; /* empty */
316 }
317
318 if ( bitsLeft >= 32 ) {
319 if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
320 numWords = ptr->currword;
321 flushHere = TRUE;
322 } else {
323 numWords = ptr->currword+1;
324 }
325
326 for (i = 0; i < numWords; i++) {
327 buffer[i] = htonl(ptr->bits[i]);
328 }
329
330 nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);
331 if (nitems != numWords) {
332 throw "Whoa! Trouble writing bytes";
333 }
334
335 bitsWritten += (numWords * 32);
336 bitsLeft -= (numWords * 32);
337 } else {
338 flushHere = TRUE;
339 }
340
341 if ( (bitsLeft < 32) && flushHere ) {
342 lastWord = ptr->bits[ptr->currword];
343
344 /* output the lastPtr word in big-endian order (network) */
345
346 /* now write out lastPtr bits */
347 while ( bitsLeft > 0 ) {
348 charBuf[0] = (lastWord >> 24);
349 charBuf[0] &= lower_mask[8];
350 fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);
351 lastWord = (lastWord << 8);
352 bitsLeft -= 8;
353 bitsWritten += 8;
354 }
355 }
356 }
357 fflush(bbPtr->filePtr);
358 while ( bbPtr->firstPtr != ptr ) {
359 tempPtr = bbPtr->firstPtr;
360 bbPtr->firstPtr = tempPtr->nextPtr;
361 free(tempPtr);
362 }
363
364 free(bbPtr);
365
366 time(&tempTimeEnd);
367 IOtime += (tempTimeEnd-tempTimeStart);
368 }
369
370
371 /*===========================================================================*
372 *
373 * Bitio_WriteToSocket
374 *
375 * Writes all of the remaining bits in the given bit bucket to the
376 * given socket. May pad the end of the socket stream with extra 0
377 * bits as does Bitio_Flush.
378 *
379 * RETURNS: nothing
380 *
381 * SIDE EFFECTS: frees the bit bucket
382 *
383 *===========================================================================*/
384 void
Bitio_WriteToSocket(BitBucket * bbPtr,int socket)385 Bitio_WriteToSocket(BitBucket *bbPtr,
386 int socket)
387 {
388 throw "WriteToSocket not implemented";
389 }
390
391
392 /*===========================================================================*
393 *
394 * Bitio_BytePad
395 *
396 * Pads the end of the bit bucket to the nearest byte with 0 bits
397 *
398 * RETURNS: nothing
399 *
400 *===========================================================================*/
401 void
Bitio_BytePad(BitBucket * bbPtr)402 Bitio_BytePad(BitBucket *bbPtr)
403 {
404 struct bitBucket *lastPtrPtr = bbPtr->lastPtr;
405
406 if (lastPtrPtr->bitsleftcur % 8) {
407 Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);
408 }
409 }
410
411
412 /*=====================*
413 * INTERNAL PROCEDURES *
414 *=====================*/
415
416
417 /*===========================================================================*
418 *
419 * Dump
420 *
421 * Writes out the first MAX_BITS bits of the bit bucket to the
422 * appropriate output file
423 *
424 * RETURNS: nothing
425 *
426 * SIDE EFFECTS: none
427 *
428 *===========================================================================*/
429 static void
Dump(BitBucket * bbPtr)430 Dump(BitBucket *bbPtr)
431 {
432 struct bitBucket *ptr, *tempPtr;
433 uint32 buffer[WORDS_PER_BUCKET];
434 int i, nitems;
435 int bitsWritten = 0;
436 time_t tempTimeStart, tempTimeEnd;
437
438 time(&tempTimeStart);
439
440 for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);
441 ptr = ptr->nextPtr) {
442 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
443 continue; /* empty */
444 }
445
446 for (i = 0; i <= ptr->currword; i++) {
447 buffer[i] = htonl(ptr->bits[i]);
448 }
449
450 nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr);
451 if (nitems != (ptr->currword+1)) {
452 throw "Whoa! Trouble writing bytes";
453 }
454
455 bitsWritten += ((ptr->currword + 1) * 32);
456 }
457
458 while ( bbPtr->firstPtr != ptr ) {
459 tempPtr = bbPtr->firstPtr;
460 bbPtr->firstPtr = tempPtr->nextPtr;
461 free(tempPtr);
462 }
463
464 bbPtr->totalbits -= bitsWritten;
465 bbPtr->bitsWritten += bitsWritten;
466
467 time(&tempTimeEnd);
468 IOtime += (tempTimeEnd-tempTimeStart);
469 }
470
471
472