z0x
z0x

Reputation: 39

Gzip compress/uncompress a long char array

I need to compress a large byte array, im already using the Crypto++ library in the application, so having the compression/decompression part in the same library would be great.

this little test works as expected:

///
string test = "bleachbleachtestingbiatchbleach123123bleachbleachtestingb.....more";
string compress(string input)
{
    string result ("");
    CryptoPP::StringSource(input, true, new CryptoPP::Gzip(new CryptoPP::StringSink(result), 1));
    return result;
}

string decompress(string _input)
{
    string _result ("");
    CryptoPP::StringSource(_input, true, new CryptoPP::Gunzip(new CryptoPP::StringSink(_result), 1));
    return _result;
}

void main()
{
    string compressed = compress(test);
    string decompressed = decompress(compressed);
    cout << "orginal size :" << test.length() << endl;
    cout << "compressed size :" << compressed.length() << endl;
    cout << "decompressed size :" << decompressed.length() << endl;
    system("PAUSE");
}

I need to compress something like this:

unsigned char long_array[194506]
{
  0x00,0x00,0x02,0x00,0x00,0x04,0x00,0x00,0x00,
  0x01,0x00,0x02,0x00,0x00,0x04,0x02,0x00,0x04,
  0x04,0x00,0x02,0x00,0x01,0x04,0x02,0x00,0x04,
  0x01,0x00,0x02,0x02,0x00,0x04,0x02,0x00,0x00,
  0x03,0x00,0x02,0x00,0x00,0x04,0x01,0x00,0x04,
  ....
};

i tried to use the long_array as const char * and as byte then feed it to the compress function, it seems to be compressed but the decompressed one has a size of 4, and its clearly uncomplete. maybe its too long. How could i rewrite those compress/uncompress functions to work with that byte array? Thank you all. :)

Upvotes: 2

Views: 1449

Answers (1)

jww
jww

Reputation: 102225

i tried to use the array as const char * and as byte then feed it to the compress function, it seems to be compressed but the decompressed one has a size of 4, and its clearly uncomplete.

Use the alternate StringSource constructor that takes a pointer and a length. It will be immune to embedded NULL's.

CryptoPP::StringSource ss(long_array, sizeof(long_array), true,
    new CryptoPP::Gzip(
        new CryptoPP::StringSink(result), 1)
));

Or, you can use:

Gzip zipper(new StringSink(result), 1);
zipper.Put(long_array, sizeof(long_array));
zipper.MessageEnd();

Crypto++ added an ArraySource at 5.6. You can use it too (but its really a typedef for a StringSource):

CryptoPP::ArraySource as(long_array, sizeof(long_array), true,
    new CryptoPP::Gzip(
        new CryptoPP::StringSink(result), 1)
));

The 1 that is used as an argument to Gzip is a deflate level. 1 is one of the lowest compressions. You might consider using 9 or Gzip::MAX_DEFLATE_LEVEL (which is 9). The default log2 windows size is the max size, so there's no need to turn any knobs on it.

Gzip zipper(new StringSink(result), Gzip::MAX_DEFLATE_LEVEL);

You should also name your declarations. I've seen GCC generate bad code when using anonymous declarations.

Finally, use long_array (or similar) because array is a keyword in C++ 11.

Upvotes: 3

Related Questions