Created
December 18, 2016 15:25
-
-
Save VictorZhang2014/e718c03729e3ff03eb222a956a9b1770 to your computer and use it in GitHub Desktop.
Compressing From string to string by zlib. Imported zlib.tbd directly if you're on the MAC.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bool CompressByGZIP(std::string & uncompressedStr, std::string & compressedStr) | |
{ | |
if (uncompressedStr.length() <= 0) { | |
return false; | |
} | |
compressedStr.resize(uncompressedStr.size() * 1.5 + 12); | |
/* Before we can begin compressing (aka "deflating") data using the zlib | |
functions, we must initialize zlib. Normally this is done by calling the | |
deflateInit() function; in this case, however, we'll use deflateInit2() so | |
that the compressed data will have gzip headers. This will make it easy to | |
decompress the data later using a tool like gunzip, WinZip, etc. | |
deflateInit2() accepts many parameters, the first of which is a C struct of | |
type "z_stream" defined in zlib.h. The properties of this struct are used to | |
control how the compression algorithms work. z_stream is also used to | |
maintain pointers to the "input" and "output" byte buffers (next_in/out) as | |
well as information about how many bytes have been processed, how many are | |
left to process, etc. */ | |
z_stream zlibStreamStruct; | |
zlibStreamStruct.zalloc = Z_NULL; // Set zalloc, zfree, and opaque to Z_NULL so | |
zlibStreamStruct.zfree = Z_NULL; // that when we call deflateInit2 they will be | |
zlibStreamStruct.opaque = Z_NULL; // updated to use default allocation functions. | |
zlibStreamStruct.total_out = 0; // Total number of output bytes produced so far | |
zlibStreamStruct.next_in = (Bytef *)uncompressedStr.data(); // Pointer to input bytes | |
zlibStreamStruct.avail_in = (uInt)uncompressedStr.size(); // Number of input bytes left to process | |
/* Initialize the zlib deflation (i.e. compression) internals with deflateInit2(). | |
The parameters are as follows: | |
z_streamp strm - Pointer to a zstream struct | |
int level - Compression level. Must be Z_DEFAULT_COMPRESSION, or between | |
0 and 9: 1 gives best speed, 9 gives best compression, 0 gives | |
no compression. | |
int method - Compression method. Only method supported is "Z_DEFLATED". | |
int windowBits - Base two logarithm of the maximum window size (the size of | |
the history buffer). It should be in the range 8..15. Add | |
16 to windowBits to write a simple gzip header and trailer | |
around the compressed data instead of a zlib wrapper. The | |
gzip header will have no file name, no extra data, no comment, | |
no modification time (set to zero), no header crc, and the | |
operating system will be set to 255 (unknown). | |
int memLevel - Amount of memory allocated for internal compression state. | |
1 uses minimum memory but is slow and reduces compression | |
ratio; 9 uses maximum memory for optimal speed. Default value | |
is 8. | |
int strategy - Used to tune the compression algorithm. Use the value | |
Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data | |
produced by a filter (or predictor), or Z_HUFFMAN_ONLY to | |
force Huffman encoding only (no string match) */ | |
int initError = deflateInit2(&zlibStreamStruct, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY); | |
if (initError != Z_OK) | |
{ | |
std::string errorMsg; | |
switch (initError) | |
{ | |
case Z_STREAM_ERROR: | |
errorMsg = "Invalid parameter passed in to function."; | |
break; | |
case Z_MEM_ERROR: | |
errorMsg = "Insufficient memory."; | |
break; | |
case Z_VERSION_ERROR: | |
errorMsg = "The version of zlib.h and the version of the library linked do not match."; | |
break; | |
default: | |
errorMsg = "Unknown error code."; | |
break; | |
} | |
std::cout << "%s" << errorMsg << ": deflateInit2() Error: " << zlibStreamStruct.msg << " Message: \"%s\""; | |
return false; | |
} | |
int deflateStatus; | |
do | |
{ | |
// Store location where next byte should be put in next_out | |
zlibStreamStruct.next_out = (Bytef *)compressedStr.data() + zlibStreamStruct.total_out; | |
// Calculate the amount of remaining free space in the output buffer | |
// by subtracting the number of bytes that have been written so far | |
// from the buffer's total capacity | |
zlibStreamStruct.avail_out = (uInt)(compressedStr.size() - zlibStreamStruct.total_out); | |
/* deflate() compresses as much data as possible, and stops/returns when | |
the input buffer becomes empty or the output buffer becomes full. If | |
deflate() returns Z_OK, it means that there are more bytes left to | |
compress in the input buffer but the output buffer is full; the output | |
buffer should be expanded and deflate should be called again (i.e., the | |
loop should continue to rune). If deflate() returns Z_STREAM_END, the | |
end of the input stream was reached (i.e.g, all of the data has been | |
compressed) and the loop should stop. */ | |
deflateStatus = deflate(&zlibStreamStruct, Z_FINISH); | |
} while ( deflateStatus == Z_OK ); | |
// Check for zlib error and convert code to usable error message if appropriate | |
if (deflateStatus != Z_STREAM_END) | |
{ | |
std::string errorMsg; | |
switch (deflateStatus) | |
{ | |
case Z_ERRNO: | |
errorMsg = "Error occured while reading file."; | |
break; | |
case Z_STREAM_ERROR: | |
errorMsg = "The stream state was inconsistent (e.g., next_in or next_out was NULL)."; | |
break; | |
case Z_DATA_ERROR: | |
errorMsg = "The deflate data was invalid or incomplete."; | |
break; | |
case Z_MEM_ERROR: | |
errorMsg = "Memory could not be allocated for processing."; | |
break; | |
case Z_BUF_ERROR: | |
errorMsg = "Ran out of output buffer for writing compressed bytes."; | |
break; | |
case Z_VERSION_ERROR: | |
errorMsg = "The version of zlib.h and the version of the library linked do not match."; | |
break; | |
default: | |
errorMsg = "Unknown error code."; | |
break; | |
} | |
printf("%s: zlib error while attempting compression message: \"%s\"", errorMsg.c_str(), zlibStreamStruct.msg); | |
compressedStr.resize(zlibStreamStruct.total_out); | |
// Free data structures that were dynamically created for the stream. | |
deflateEnd(&zlibStreamStruct); | |
return true; | |
} | |
return false; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment