Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

mrcf.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 mrcf.c 00008 00009 Abstract: 00010 00011 This module implements the Mrcf compression engine. 00012 00013 Author: 00014 00015 Gary Kimura [GaryKi] 21-Jan-1994 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "ntrtlp.h" 00022 00023 #include <stdio.h> 00024 00025 00026 // 00027 // To decompress/compress a block of data the user needs to 00028 // provide a work space as an extra parameter to all the exported 00029 // procedures. That way the routines will not need to use excessive 00030 // stack space and will still be multithread safe 00031 // 00032 00033 // 00034 // Variables for reading and writing bits 00035 // 00036 00037 typedef struct _MRCF_BIT_IO { 00038 00039 USHORT abitsBB; // 16-bit buffer being read 00040 LONG cbitsBB; // Number of bits left in abitsBB 00041 00042 PUCHAR pbBB; // Pointer to byte stream being read 00043 ULONG cbBB; // Number of bytes left in pbBB 00044 ULONG cbBBInitial; // Initial size of pbBB 00045 00046 } MRCF_BIT_IO; 00047 typedef MRCF_BIT_IO *PMRCF_BIT_IO; 00048 00049 // 00050 // Maximum back-pointer value, also used to indicate end of compressed stream! 00051 // 00052 00053 #define wBACKPOINTERMAX (4415) 00054 00055 // 00056 // MDSIGNATURE - Signature at start of each compressed block 00057 // 00058 // This 4-byte signature is used as a check to ensure that we 00059 // are decompressing data we compressed, and also to indicate 00060 // which compression method was used. 00061 // 00062 // NOTE: A compressed block consists of one or more "chunks", separated 00063 // by the bitsEND_OF_STREAM pattern. 00064 // 00065 // Byte Word 00066 // ----------- --------- 00067 // 0 1 2 3 0 1 Meaning 00068 // -- -- -- -- ---- ---- ---------------- 00069 // 44 53 00 01 5344 0100 MaxCompression 00070 // 44 53 00 02 5344 0200 StandardCompression 00071 // 00072 // NOTE: The *WORD* values are listed to be clear about the 00073 // byte ordering! 00074 // 00075 00076 typedef struct _MDSIGNATURE { 00077 00078 // 00079 // Must be MD_STAMP 00080 // 00081 00082 USHORT sigStamp; 00083 00084 // 00085 // mdsSTANDARD or mdsMAX 00086 // 00087 00088 USHORT sigType; 00089 00090 } MDSIGNATURE; 00091 typedef MDSIGNATURE *PMDSIGNATURE; 00092 00093 #define MD_STAMP 0x5344 // Signature stamp at start of compressed blk 00094 #define MASK_VALID_mds 0x0300 // All other bits must be zero 00095 00096 00097 // 00098 // Local procedure declarations and macros 00099 // 00100 00101 #define minimum(a,b) (a < b ? a : b) 00102 00103 // 00104 // Local procedure prototypes 00105 // 00106 00107 VOID 00108 MrcfSetBitBuffer ( 00109 PUCHAR pb, 00110 ULONG cb, 00111 PMRCF_BIT_IO BitIo 00112 ); 00113 00114 VOID 00115 MrcfFillBitBuffer ( 00116 PMRCF_BIT_IO BitIo 00117 ); 00118 00119 USHORT 00120 MrcfReadBit ( 00121 PMRCF_BIT_IO BitIo 00122 ); 00123 00124 USHORT 00125 MrcfReadNBits ( 00126 LONG cbits, 00127 PMRCF_BIT_IO BitIo 00128 ); 00129 00130 00131 NTSTATUS 00132 RtlDecompressBufferMrcf ( 00133 OUT PUCHAR UncompressedBuffer, 00134 IN ULONG UncompressedBufferSize, 00135 IN PUCHAR CompressedBuffer, 00136 IN ULONG CompressedBufferSize, 00137 OUT PULONG FinalUncompressedSize 00138 ) 00139 00140 /*++ 00141 00142 Routine Description: 00143 00144 This routine decompresses a buffer of StandardCompressed or MaxCompressed 00145 data. 00146 00147 Arguments: 00148 00149 UncompressedBuffer - buffer to receive uncompressed data 00150 00151 UncompressedBufferSize - length of UncompressedBuffer 00152 00153 NOTE: UncompressedBufferSize must be the EXACT length of the uncompressed 00154 data, as Decompress uses this information to detect 00155 when decompression is complete. If this value is 00156 incorrect, Decompress may crash! 00157 00158 CompressedBuffer - buffer containing compressed data 00159 00160 CompressedBufferSize - length of CompressedBuffer 00161 00162 WorkSpace - pointer to a private work area for use by this operation 00163 00164 Return Value: 00165 00166 ULONG - Returns the size of the decompressed data in bytes. Returns 0 if 00167 there was an error in the decompress. 00168 00169 --*/ 00170 00171 { 00172 MRCF_BIT_IO WorkSpace; 00173 00174 ULONG cbMatch; // Length of match string 00175 ULONG i; // Index in UncompressedBuffer to receive decoded data 00176 ULONG iMatch; // Index in UncompressedBuffer of matched string 00177 ULONG k; // Number of bits in length string 00178 ULONG off; // Offset from i in UncompressedBuffer of match string 00179 USHORT x; // Current bit being examined 00180 ULONG y; 00181 00182 // 00183 // verify that compressed data starts with proper signature 00184 // 00185 00186 if (CompressedBufferSize < sizeof(MDSIGNATURE) || // Must have signature 00187 ((PMDSIGNATURE)CompressedBuffer)->sigStamp != MD_STAMP || // Stamp must be OK 00188 ((PMDSIGNATURE)CompressedBuffer)->sigType & (~MASK_VALID_mds)) { // Type must be OK 00189 00190 *FinalUncompressedSize = 0; 00191 return STATUS_BAD_COMPRESSION_BUFFER; 00192 } 00193 00194 // 00195 // Skip over the valid signature 00196 // 00197 00198 CompressedBufferSize -= sizeof(MDSIGNATURE); 00199 CompressedBuffer += sizeof(MDSIGNATURE); 00200 00201 // 00202 // Set up for decompress, start filling UncompressedBuffer at front 00203 // 00204 00205 i = 0; 00206 00207 // 00208 // Set statics to save parm passing 00209 // 00210 00211 MrcfSetBitBuffer(CompressedBuffer,CompressedBufferSize,&WorkSpace); 00212 00213 while (TRUE) { 00214 00215 y = MrcfReadNBits(2,&WorkSpace); 00216 00217 // 00218 // Check if next 7 bits are a byte 00219 // 1 if 128..255 (0x80..0xff), 2 if 0..127 (0x00..0x7f) 00220 // 00221 00222 if (y == 1 || y == 2) { 00223 00224 ASSERTMSG("Don't exceed expected length ", i<UncompressedBufferSize); 00225 00226 UncompressedBuffer[i] = (UCHAR)((y == 1 ? 0x80 : 0) | MrcfReadNBits(7,&WorkSpace)); 00227 00228 i++; 00229 00230 } else { 00231 00232 // 00233 // Have match sequence 00234 // 00235 00236 // 00237 // Get the offset 00238 // 00239 00240 if (y == 0) { 00241 00242 // 00243 // next 6 bits are offset 00244 // 00245 00246 off = MrcfReadNBits(6,&WorkSpace); 00247 00248 ASSERTMSG("offset 0 is invalid ", off != 0); 00249 00250 } else { 00251 00252 x = MrcfReadBit(&WorkSpace); 00253 00254 if (x == 0) { 00255 00256 // 00257 // next 8 bits are offset-64 (0x40) 00258 // 00259 00260 off = MrcfReadNBits(8, &WorkSpace) + 64; 00261 00262 } else { 00263 00264 // 00265 // next 12 bits are offset-320 (0x140) 00266 // 00267 00268 off = MrcfReadNBits(12, &WorkSpace) + 320; 00269 00270 if (off == wBACKPOINTERMAX) { 00271 00272 // 00273 // EOS marker 00274 // 00275 00276 if (i >= UncompressedBufferSize) { 00277 00278 // 00279 // Done with entire buffer 00280 // 00281 00282 *FinalUncompressedSize = i; 00283 return STATUS_SUCCESS; 00284 00285 } else { 00286 00287 // 00288 // More to do 00289 // Done with a 512-byte chunk 00290 // 00291 00292 continue; 00293 } 00294 } 00295 } 00296 } 00297 00298 ASSERTMSG("Don't exceed expected length ", i<UncompressedBufferSize); 00299 ASSERTMSG("Cannot match before start of uncoded buffer! ", off <= i); 00300 00301 // 00302 // Get the length - logarithmically encoded 00303 // 00304 00305 for (k=0; (x=MrcfReadBit(&WorkSpace)) == 0; k++) { NOTHING; } 00306 00307 ASSERT(k <= 8); 00308 00309 if (k == 0) { 00310 00311 // 00312 // All matches at least 2 chars long 00313 // 00314 00315 cbMatch = 2; 00316 00317 } else { 00318 00319 cbMatch = (1 << k) + 1 + MrcfReadNBits(k, &WorkSpace); 00320 } 00321 00322 ASSERTMSG("Don't exceed buffer size ", (i - off + cbMatch - 1) <= UncompressedBufferSize); 00323 00324 // 00325 // Copy the matched string 00326 // 00327 00328 iMatch = i - off; 00329 00330 while ( (cbMatch > 0) && (i<UncompressedBufferSize) ) { 00331 00332 UncompressedBuffer[i++] = UncompressedBuffer[iMatch++]; 00333 cbMatch--; 00334 } 00335 00336 ASSERTMSG("Should have copied it all ", cbMatch == 0); 00337 } 00338 } 00339 } 00340 00341 00342 // 00343 // Internal Support Routine 00344 // 00345 00346 VOID 00347 MrcfSetBitBuffer ( 00348 PUCHAR pb, 00349 ULONG cb, 00350 PMRCF_BIT_IO BitIo 00351 ) 00352 00353 /*++ 00354 00355 Routine Description: 00356 00357 Set statics with coded buffer pointer and length 00358 00359 Arguments: 00360 00361 pb - pointer to compressed data buffer 00362 00363 cb - length of compressed data buffer 00364 00365 BitIo - Supplies a pointer to the bit buffer statics 00366 00367 Return Value: 00368 00369 None. 00370 00371 --*/ 00372 00373 { 00374 BitIo->pbBB = pb; 00375 BitIo->cbBB = cb; 00376 BitIo->cbBBInitial = cb; 00377 BitIo->cbitsBB = 0; 00378 BitIo->abitsBB = 0; 00379 } 00380 00381 00382 // 00383 // Internal Support Routine 00384 // 00385 00386 USHORT 00387 MrcfReadBit ( 00388 PMRCF_BIT_IO BitIo 00389 ) 00390 00391 /*++ 00392 00393 Routine Description: 00394 00395 Get next bit from bit buffer 00396 00397 Arguments: 00398 00399 BitIo - Supplies a pointer to the bit buffer statics 00400 00401 Return Value: 00402 00403 USHORT - Returns next bit (0 or 1) 00404 00405 --*/ 00406 00407 { 00408 USHORT bit; 00409 00410 // 00411 // Check if no bits available 00412 // 00413 00414 if ((BitIo->cbitsBB) == 0) { 00415 00416 MrcfFillBitBuffer(BitIo); 00417 } 00418 00419 // 00420 // Decrement the bit count 00421 // get the bit, remove it, and return the bit 00422 // 00423 00424 (BitIo->cbitsBB)--; 00425 bit = (BitIo->abitsBB) & 1; 00426 (BitIo->abitsBB) >>= 1; 00427 00428 return bit; 00429 } 00430 00431 00432 // 00433 // Internal Support Routine 00434 // 00435 00436 USHORT 00437 MrcfReadNBits ( 00438 LONG cbits, 00439 PMRCF_BIT_IO BitIo 00440 ) 00441 00442 /*++ 00443 00444 Routine Description: 00445 00446 Get next N bits from bit buffer 00447 00448 Arguments: 00449 00450 cbits - count of bits to get 00451 00452 BitIo - Supplies a pointer to the bit buffer statics 00453 00454 Return Value: 00455 00456 USHORT - Returns next cbits bits. 00457 00458 --*/ 00459 00460 { 00461 ULONG abits; // Bits to return 00462 LONG cbitsPart; // Partial count of bits 00463 ULONG cshift; // Shift count 00464 ULONG mask; // Mask 00465 00466 // 00467 // Largest number of bits we should read at one time is 12 bits for 00468 // a 12-bit offset. The largest length field component that we 00469 // read is 8 bits. If this routine were used for some other purpose, 00470 // it can support up to 15 (NOT 16) bit reads, due to how the masking 00471 // code works. 00472 // 00473 00474 ASSERT(cbits <= 12); 00475 00476 // 00477 // No shift and no bits yet 00478 // 00479 00480 cshift = 0; 00481 abits = 0; 00482 00483 while (cbits > 0) { 00484 00485 // 00486 // If not bits available get some bits 00487 // 00488 00489 if ((BitIo->cbitsBB) == 0) { 00490 00491 MrcfFillBitBuffer(BitIo); 00492 } 00493 00494 // 00495 // Number of bits we can read 00496 // 00497 00498 cbitsPart = minimum((BitIo->cbitsBB), cbits); 00499 00500 // 00501 // Mask for bits we want, extract and store them 00502 // 00503 00504 mask = (1 << cbitsPart) - 1; 00505 abits |= ((BitIo->abitsBB) & mask) << cshift; 00506 00507 // 00508 // Remember the next chunk of bits 00509 // 00510 00511 cshift = cbitsPart; 00512 00513 // 00514 // Update bit buffer, move remaining bits down and 00515 // update count of bits left 00516 // 00517 00518 (BitIo->abitsBB) >>= cbitsPart; 00519 (BitIo->cbitsBB) -= cbitsPart; 00520 00521 // 00522 // Update count of bits left to read 00523 // 00524 00525 cbits -= cbitsPart; 00526 } 00527 00528 // 00529 // Return requested bits 00530 // 00531 00532 return (USHORT)abits; 00533 } 00534 00535 00536 // 00537 // Internal Support Routine 00538 // 00539 00540 VOID 00541 MrcfFillBitBuffer ( 00542 PMRCF_BIT_IO BitIo 00543 ) 00544 00545 /*++ 00546 00547 Routine Description: 00548 00549 Fill abitsBB from static bit buffer 00550 00551 Arguments: 00552 00553 BitIo - Supplies a pointer to the bit buffer statics 00554 00555 Return Value: 00556 00557 None. 00558 00559 --*/ 00560 00561 { 00562 ASSERT((BitIo->cbitsBB) == 0); 00563 00564 switch (BitIo->cbBB) { 00565 00566 case 0: 00567 00568 ASSERTMSG("no bits left in coded buffer!", FALSE); 00569 00570 break; 00571 00572 case 1: 00573 00574 // 00575 // Get last byte and adjust count 00576 // 00577 00578 BitIo->cbitsBB = 8; 00579 BitIo->abitsBB = *(BitIo->pbBB)++; 00580 BitIo->cbBB--; 00581 00582 break; 00583 00584 default: 00585 00586 // 00587 // Get word and adjust count 00588 // 00589 00590 BitIo->cbitsBB = 16; 00591 BitIo->abitsBB = *((USHORT *)(BitIo->pbBB))++; 00592 BitIo->cbBB -= 2; 00593 00594 break; 00595 } 00596 } 00597 00598 

Generated on Sat May 15 19:40:53 2004 for test by doxygen 1.3.7