std::vector<unsigned char> Compressor::compress(void* data, unsigned length) { mFrequency = getFrequency(data, length); int bits = getBestRatio(length); char* ptr = (char*)data; int i; if (bits == -1) return std::vector<unsigned char>(); BitStream bs; unsigned totalSize = 27 + ((1 << bits) - 1) * 8; if (mIsLittleEndian) bs.insert((int)length, 24); else bs.insert(reverseEndianess((int)length), 24); bs.insert(bits, 3); for (i = 0; i < (1 << bits) - 1; i++) { if ((int)mFrequency.size() > i) bs.insert(mFrequency[i].character); else bs.insert(0); } std::vector<char> uncompressed; for (i = 0; i < (int)length; i++) { int vecPos = findChar(mFrequency, *ptr, (1 << bits) - 1); if (vecPos == -1) { bs.insert(0U, bits); uncompressed.push_back(*ptr); } else { bs.insert(vecPos + 1, bits); } totalSize += bits; ptr++; } for (i = 0; i < (int)uncompressed.size(); i++) { bs.insert(uncompressed[i]); totalSize += 8; } return bs.getData(); }
std::vector<unsigned char> Compressor::decompress(void* data, unsigned length) { BitStream bs; bs.insert(data, length); bs.read_bytes(&length, 3); if (!mIsLittleEndian) length = (unsigned)reverseEndianess((int)length); unsigned char bits; bs.read_bits(bits, 3); if (bits < 1 || bits > 7) { char bStr[4]; throw (std::string("Bit-size of enconding isn't valid: ") + std::string(itoa(bits, bStr, 10))); } unsigned char byte; int bitsRead = 27; int i; std::vector<char> charTable; std::vector<char> compressedChars; for (i = 1; i <= (1 << bits) - 1; i++) { bs.read_bits(byte, 8); charTable.push_back(byte); bitsRead += 8; if (!bs.canRead()) throw std::string ("Bad file for decompression [1]"); } for (unsigned j = 1; j <= length; j++) { bs.read_bits(byte, bits); bitsRead += bits; compressedChars.push_back(byte); if (!bs.canRead()) throw std::string ("Bad file for decompression [2]"); } std::vector<unsigned char> result(length, 0); for (i = 0; i < (int)compressedChars.size(); i++) { if (compressedChars[i] == 0 || (unsigned char)compressedChars[i] > charTable.size()) { if (!bs.canRead()) throw std::string ("Bad file for decompression [3]"); bs.read_bits(result[i], 8); bitsRead += 8; } else { result[i] = charTable[compressedChars[i] - 1]; } } return result; }