Doxygen Source Code Documentation
Main Page Alphabetical List Data Structures File List Data Fields Globals Search
bitio.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #include <assert.h>
00095 #include "all.h"
00096 #include "byteorder.h"
00097 #include "bitio.h"
00098 #include "mtypes.h"
00099
00100
00101
00102
00103
00104
00105 static void Dump _ANSI_ARGS_((BitBucket *bbPtr));
00106
00107
00108
00109
00110
00111
00112 static uint32 lower_mask[33] = {
00113 0,
00114 0x1, 0x3, 0x7, 0xf,
00115 0x1f, 0x3f, 0x7f, 0xff,
00116 0x1ff, 0x3ff, 0x7ff, 0xfff,
00117 0x1fff, 0x3fff, 0x7fff, 0xffff,
00118 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
00119 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
00120 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
00121 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
00122 };
00123
00124
00125 extern time_t IOtime;
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 BitBucket *
00146 Bitio_New(filePtr)
00147 FILE *filePtr;
00148 {
00149 BitBucket *bbPtr;
00150
00151 bbPtr = (BitBucket *) malloc(sizeof(BitBucket));
00152 ERRCHK(bbPtr, "malloc");
00153
00154 bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
00155 ERRCHK(bbPtr->firstPtr, "malloc");
00156
00157 bbPtr->totalbits = 0;
00158 bbPtr->cumulativeBits = 0;
00159 bbPtr->bitsWritten = 0;
00160 bbPtr->filePtr = filePtr;
00161
00162 bbPtr->firstPtr->nextPtr = NULL;
00163 bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;
00164 bbPtr->firstPtr->bitsleftcur = 32;
00165 bbPtr->firstPtr->currword = 0;
00166 memset((char *)bbPtr->firstPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
00167
00168 return bbPtr;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 void
00184 Bitio_Free(bbPtr)
00185 BitBucket *bbPtr;
00186 {
00187 struct bitBucket *tmpPtr, *nextPtr;
00188
00189 for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {
00190 nextPtr = tmpPtr->nextPtr;
00191 free(tmpPtr);
00192 }
00193 free(bbPtr);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 void
00212 Bitio_Write(bbPtr, bits, nbits)
00213 BitBucket *bbPtr;
00214 uint32 bits;
00215 int nbits;
00216 {
00217 register struct bitBucket *lastPtr, *newPtr;
00218 register int delta;
00219
00220 assert(nbits <= 32 && nbits >= 0);
00221
00222
00223
00224
00225
00226
00227 bits = bits & lower_mask[nbits];
00228
00229 bbPtr->totalbits += nbits;
00230 bbPtr->cumulativeBits += nbits;
00231 lastPtr = bbPtr->lastPtr;
00232
00233 delta = nbits - lastPtr->bitsleft;
00234 if (delta >= 0) {
00235
00236
00237
00238
00239 newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
00240 ERRCHK(newPtr, "malloc");
00241 newPtr->nextPtr = NULL;
00242 newPtr->bitsleft = MAXBITS_PER_BUCKET;
00243 newPtr->bitsleftcur = 32;
00244 newPtr->currword = 0;
00245 memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
00246 bbPtr->lastPtr = newPtr;
00247
00248 assert(lastPtr->currword == WORDS_PER_BUCKET - 1);
00249 lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);
00250 lastPtr->bitsleft = 0;
00251 lastPtr->bitsleftcur = 0;
00252
00253
00254 if (!delta) {
00255 if ( bbPtr->totalbits > MAX_BITS ) {
00256 Dump(bbPtr);
00257 }
00258 }
00259
00260 assert(delta <= 32);
00261 newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);
00262 newPtr->bitsleft -= delta;
00263 newPtr->bitsleftcur -= delta;
00264 } else {
00265
00266
00267
00268 delta = nbits - lastPtr->bitsleftcur;
00269 lastPtr->bitsleftcur -= nbits;
00270 lastPtr->bitsleft -= nbits;
00271
00272 if (delta >= 0)
00273 {
00274
00275
00276
00277 lastPtr->bits[lastPtr->currword] |= (bits >> delta);
00278 lastPtr->currword++;
00279 lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);
00280 lastPtr->bitsleftcur = 32 - delta;
00281 } else {
00282
00283
00284
00285 lastPtr->bits[lastPtr->currword] |= (bits << (-delta));
00286 }
00287 }
00288
00289 if ( bbPtr->totalbits > MAX_BITS )
00290 Dump(bbPtr);
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 void
00309 Bitio_Flush(bbPtr)
00310 BitBucket *bbPtr;
00311 {
00312 struct bitBucket *ptr, *tempPtr;
00313 uint32 buffer[WORDS_PER_BUCKET];
00314 uint32 lastWord;
00315 int i, nitems;
00316 int bitsWritten = 0;
00317 int bitsLeft;
00318 int numWords;
00319 uint8 charBuf[4];
00320 boolean flushHere = FALSE;
00321 time_t tempTimeStart, tempTimeEnd;
00322
00323 time(&tempTimeStart);
00324
00325 bitsLeft = bbPtr->totalbits;
00326
00327 for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
00328 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
00329 continue;
00330 }
00331
00332 if ( bitsLeft >= 32 ) {
00333 if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
00334 numWords = ptr->currword;
00335 flushHere = TRUE;
00336 } else {
00337 numWords = ptr->currword+1;
00338 }
00339
00340 for (i = 0; i < numWords; i++) {
00341 buffer[i] = htonl(ptr->bits[i]);
00342 }
00343
00344 nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);
00345 if (nitems != numWords) {
00346 fprintf(stderr, "Whoa! Trouble writing %d bytes (got %d items)! Game over, dude!\n",
00347 (int)(numWords), nitems);
00348 exit(1);
00349 }
00350
00351 bitsWritten += (numWords * 32);
00352 bitsLeft -= (numWords * 32);
00353 } else {
00354 flushHere = TRUE;
00355 }
00356
00357 if ( (bitsLeft < 32) && flushHere ) {
00358 lastWord = ptr->bits[ptr->currword];
00359
00360
00361
00362
00363 while ( bitsLeft > 0 ) {
00364 charBuf[0] = (lastWord >> 24);
00365 charBuf[0] &= lower_mask[8];
00366 fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);
00367 lastWord = (lastWord << 8);
00368 bitsLeft -= 8;
00369 bitsWritten += 8;
00370 }
00371 }
00372 }
00373 fflush(bbPtr->filePtr);
00374 while ( bbPtr->firstPtr != ptr ) {
00375 tempPtr = bbPtr->firstPtr;
00376 bbPtr->firstPtr = tempPtr->nextPtr;
00377 free(tempPtr);
00378 }
00379
00380 free(bbPtr);
00381
00382 time(&tempTimeEnd);
00383 IOtime += (tempTimeEnd-tempTimeStart);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 void
00401 Bitio_WriteToSocket(bbPtr, socket)
00402 BitBucket *bbPtr;
00403 int socket;
00404 {
00405 struct bitBucket *ptr, *tempPtr;
00406 uint32 buffer[WORDS_PER_BUCKET];
00407 uint32 lastWord;
00408 int i, nitems;
00409 int bitsWritten = 0;
00410 int bitsLeft;
00411 int numWords;
00412 uint8 charBuf[4];
00413 boolean flushHere = FALSE;
00414
00415 bitsLeft = bbPtr->totalbits;
00416
00417 for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
00418 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
00419 continue;
00420 }
00421
00422 if ( bitsLeft >= 32 ) {
00423 if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
00424 numWords = ptr->currword;
00425 flushHere = TRUE;
00426 } else {
00427 numWords = ptr->currword+1;
00428 }
00429
00430 for (i = 0; i < numWords; i++) {
00431 buffer[i] = htonl(ptr->bits[i]);
00432 }
00433
00434 nitems = write(socket, buffer, numWords * sizeof(uint32));
00435 if (nitems != numWords*sizeof(uint32)) {
00436 fprintf(stderr, "Whoa! Trouble writing %d bytes (got %d bytes)! Game over, dude!\n",
00437 (int)(numWords*sizeof(uint32)), nitems);
00438 exit(1);
00439 }
00440
00441 bitsWritten += (numWords * 32);
00442 bitsLeft -= (numWords * 32);
00443 } else {
00444 flushHere = TRUE;
00445 }
00446
00447 if ( (bitsLeft < 32) && flushHere ) {
00448 lastWord = ptr->bits[ptr->currword];
00449
00450
00451
00452
00453 while ( bitsLeft > 0 ) {
00454 charBuf[0] = (lastWord >> 24);
00455 charBuf[0] &= lower_mask[8];
00456 if ( write(socket, charBuf, 1) != 1 ) {
00457 fprintf(stderr, "ERROR: write of lastPtr bits\n");
00458 exit(1);
00459 }
00460 lastWord = (lastWord << 8);
00461 bitsLeft -= 8;
00462 bitsWritten += 8;
00463 }
00464 }
00465 }
00466
00467 while ( bbPtr->firstPtr != ptr ) {
00468 tempPtr = bbPtr->firstPtr;
00469 bbPtr->firstPtr = tempPtr->nextPtr;
00470 free(tempPtr);
00471 }
00472
00473 free(bbPtr);
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 void
00487 Bitio_BytePad(bbPtr)
00488 BitBucket *bbPtr;
00489 {
00490 struct bitBucket *lastPtrPtr = bbPtr->lastPtr;
00491
00492 if (lastPtrPtr->bitsleftcur % 8) {
00493 Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);
00494 }
00495 }
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 static void
00516 Dump(bbPtr)
00517 BitBucket *bbPtr;
00518 {
00519 struct bitBucket *ptr, *tempPtr;
00520 uint32 buffer[WORDS_PER_BUCKET];
00521 int i, nitems;
00522 int bitsWritten = 0;
00523 time_t tempTimeStart, tempTimeEnd;
00524
00525 time(&tempTimeStart);
00526
00527 for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);
00528 ptr = ptr->nextPtr) {
00529 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
00530 continue;
00531 }
00532
00533 for (i = 0; i <= ptr->currword; i++) {
00534 buffer[i] = htonl(ptr->bits[i]);
00535 }
00536
00537 nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr);
00538 if (nitems != (ptr->currword+1)) {
00539 fprintf(stderr, "Whoa! Trouble writing %d bytes (got %d items)! Game over, dude!\n",
00540 (int)((ptr->currword+1)), nitems);
00541 assert(0);
00542 exit(1);
00543 }
00544
00545 bitsWritten += ((ptr->currword + 1) * 32);
00546 }
00547
00548 while ( bbPtr->firstPtr != ptr ) {
00549 tempPtr = bbPtr->firstPtr;
00550 bbPtr->firstPtr = tempPtr->nextPtr;
00551 free(tempPtr);
00552 }
00553
00554 bbPtr->totalbits -= bitsWritten;
00555 bbPtr->bitsWritten += bitsWritten;
00556
00557 time(&tempTimeEnd);
00558 IOtime += (tempTimeEnd-tempTimeStart);
00559 }
00560
00561