diff options
Diffstat (limited to 'fbreader/src/formats/pdb/HuffDecompressor.cpp')
-rw-r--r-- | fbreader/src/formats/pdb/HuffDecompressor.cpp | 192 |
1 files changed, 0 insertions, 192 deletions
diff --git a/fbreader/src/formats/pdb/HuffDecompressor.cpp b/fbreader/src/formats/pdb/HuffDecompressor.cpp deleted file mode 100644 index 9b6f285..0000000 --- a/fbreader/src/formats/pdb/HuffDecompressor.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2004-2012 Geometer Plus <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include <cstring> - -#include <ZLInputStream.h> - -#include "PdbReader.h" -#include "BitReader.h" -#include "HuffDecompressor.h" - -HuffDecompressor::HuffDecompressor(ZLInputStream& stream, - const std::vector<unsigned long>::const_iterator beginIt, - const std::vector<unsigned long>::const_iterator endIt, - const unsigned long endHuffDataOffset, const unsigned long extraFlags) : myExtraFlags(extraFlags), myErrorCode(ERROR_NONE) { - - - const unsigned long huffHeaderOffset = *beginIt; - const unsigned long huffRecordsNumber = endIt - beginIt; - const unsigned long huffDataOffset = *(beginIt + 1); - - stream.seek(huffHeaderOffset, true); - stream.seek(16, false); - unsigned long cacheTableOffset, baseTableOffset; - PdbUtil::readUnsignedLongBE(stream, cacheTableOffset); - PdbUtil::readUnsignedLongBE(stream, baseTableOffset); - - - myCacheTable = new unsigned long[256]; - stream.seek(huffHeaderOffset + cacheTableOffset, true); - for (std::size_t i = 0; i < 256; ++i) { - PdbUtil::readUnsignedLongLE(stream, myCacheTable[i]); //LE - } - - myBaseTable = new unsigned long[64]; - stream.seek(huffHeaderOffset + baseTableOffset, true); - for (std::size_t i = 0; i < 64; ++i) { - PdbUtil::readUnsignedLongLE(stream, myBaseTable[i]); //LE - } - - stream.seek(huffDataOffset + 12, true); - PdbUtil::readUnsignedLongBE(stream, myEntryBits); - - std::size_t huffDataSize = endHuffDataOffset - huffDataOffset; - myData = new unsigned char[huffDataSize]; - stream.seek(huffDataOffset, true); - if (huffDataSize == stream.read((char*)myData, huffDataSize)) { - myDicts = new unsigned char* [huffRecordsNumber - 1]; - for(std::size_t i = 0; i < huffRecordsNumber - 1; ++i) { - std::size_t shift = *(beginIt + i + 1) - huffDataOffset; - myDicts[i] = myData + shift; - } - } else { - myErrorCode = ERROR_CORRUPTED_FILE; - } - - myTargetBuffer = 0; - myTargetBufferEnd = 0; - myTargetBufferPtr = 0; -} - -HuffDecompressor::~HuffDecompressor() { - delete[] myCacheTable; - delete[] myBaseTable; - delete[] myData; - delete[] myDicts; -} - -bool HuffDecompressor::error() const { - return myErrorCode == ERROR_CORRUPTED_FILE; -} - -std::size_t HuffDecompressor::decompress(ZLInputStream &stream, char *targetBuffer, std::size_t compressedSize, std::size_t maxUncompressedSize) { - if ((compressedSize == 0) || (myErrorCode == ERROR_CORRUPTED_FILE)) { - return 0; - } - if (targetBuffer != 0) { - unsigned char *sourceBuffer = new unsigned char[compressedSize]; - myTargetBuffer = targetBuffer; - myTargetBufferEnd = targetBuffer + maxUncompressedSize; - myTargetBufferPtr = targetBuffer; - if (stream.read((char*)sourceBuffer, compressedSize) == compressedSize) { - std::size_t trailSize = sizeOfTrailingEntries(sourceBuffer, compressedSize); - if (trailSize < compressedSize) { - bitsDecompress(BitReader(sourceBuffer, compressedSize - trailSize)); - } else { - myErrorCode = ERROR_CORRUPTED_FILE; - } - } - delete[] sourceBuffer; - } else { - myTargetBuffer = 0; - myTargetBufferEnd = 0; - myTargetBufferPtr = 0; - } - - return myTargetBufferPtr - myTargetBuffer; -} - -void HuffDecompressor::bitsDecompress(BitReader bits, std::size_t depth) { - if (depth > 32) { - myErrorCode = ERROR_CORRUPTED_FILE; - return; - } - - while (bits.left()) { - const unsigned long dw = (unsigned long)bits.peek(32); - const unsigned long v = myCacheTable[dw >> 24]; - unsigned long codelen = v & 0x1F; - //if ((codelen == 0) || (codelen > 32)) { - // return false; - //} - unsigned long code = dw >> (32 - codelen); - unsigned long r = (v >> 8); - if (!(v & 0x80)) { - while (code < myBaseTable[(codelen - 1) * 2]) { - codelen += 1; - code = dw >> (32 - codelen); - } - r = myBaseTable[(codelen - 1) * 2 + 1]; - } - r -= code; - //if (codelen == 0) { - // return false; - //} - if (!bits.eat(codelen)) { - return; - } - const unsigned long dicno = r >> myEntryBits; - const unsigned long off1 = 16 + (r - (dicno << myEntryBits)) * 2; - const unsigned char* dict = myDicts[dicno]; //TODO need index check - const unsigned long off2 = 16 + dict[off1] * 256 + dict[off1 + 1]; //TODO need index check - const unsigned long blen = dict[off2] * 256 + dict[off2 + 1]; //TODO need index check - const unsigned char* slice = dict + off2 + 2; - const unsigned long sliceSize = blen & 0x7fff; - if (blen & 0x8000) { - if (myTargetBufferPtr + sliceSize < myTargetBufferEnd) { - std::memcpy(myTargetBufferPtr, slice, sliceSize); - myTargetBufferPtr += sliceSize; - } else { - return; - } - } else { - bitsDecompress(BitReader(slice, sliceSize), depth + 1); - } - } -} - -std::size_t HuffDecompressor::sizeOfTrailingEntries(unsigned char* data, std::size_t size) const { - std::size_t num = 0; - std::size_t flags = myExtraFlags >> 1; - while (flags) { - if (flags & 1) { - if (num < size) { - num += readVariableWidthIntegerBE(data, size - num); - } - } - flags >>= 1; - } - return num; -} - - -std::size_t HuffDecompressor::readVariableWidthIntegerBE(unsigned char* ptr, std::size_t psize) const { - unsigned char bitsSaved = 0; - std::size_t result = 0; - while (true) { - const unsigned char oneByte = ptr[psize - 1]; - result |= (oneByte & 0x7F) << bitsSaved; - bitsSaved += 7; - psize -= 1; - if (((oneByte & 0x80) != 0) || (bitsSaved >= 28) || (psize == 0)) { - return result; - } - } -} |