gui
[lbook_fbreader.git] / fbreader / src / formats / pdb / DocDecompressor.cpp
bloba6414b14e94927186366b3e4d5d53bec4c156c3a
1 /*
2 * Copyright (C) 2004-2008 Geometer Plus <contact@geometerplus.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
20 #include <string.h>
22 #include <ZLInputStream.h>
24 #include "DocDecompressor.h"
26 static unsigned char TOKEN_CODE[256] = {
27 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
36 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
37 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
38 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
39 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
40 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
41 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
42 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
45 size_t DocDecompressor::decompress(ZLInputStream &stream, char *targetBuffer, size_t compressedSize, size_t maxUncompressedSize) {
46 const unsigned char *sourceBuffer = new unsigned char[compressedSize];
47 const unsigned char *sourceBufferEnd = sourceBuffer + compressedSize;
48 const unsigned char *sourcePtr = sourceBuffer;
50 unsigned char *targetBufferEnd = (unsigned char*)targetBuffer + maxUncompressedSize;
51 unsigned char *targetPtr = (unsigned char*)targetBuffer;
53 if (stream.read((char*)sourceBuffer, compressedSize) == compressedSize) {
54 unsigned char token;
55 unsigned short copyLength, N, shift;
56 unsigned char *shifted;
58 while ((sourcePtr < sourceBufferEnd) && (targetPtr < targetBufferEnd)) {
59 token = *(sourcePtr++);
60 switch (TOKEN_CODE[token]) {
61 case 0:
62 *(targetPtr++) = token;
63 break;
64 case 1:
65 if ((sourcePtr + token > sourceBufferEnd) || (targetPtr + token > targetBufferEnd)) {
66 goto endOfLoop;
68 memcpy(targetPtr, sourcePtr, token);
69 sourcePtr += token;
70 targetPtr += token;
71 break;
72 case 2:
73 if (targetPtr + 2 > targetBufferEnd) {
74 goto endOfLoop;
76 *(targetPtr++) = ' ';
77 *(targetPtr++) = token ^ 0x80;
78 break;
79 case 3:
80 if (sourcePtr + 1 > sourceBufferEnd) {
81 goto endOfLoop;
83 N = 256 * token + *(sourcePtr++);
84 copyLength = (N & 7) + 3;
85 if (targetPtr + copyLength > targetBufferEnd) {
86 goto endOfLoop;
88 shift = (N & 0x3fff) / 8;
89 shifted = targetPtr - shift;
90 if ((char*)shifted >= targetBuffer) {
91 for (short i = 0; i < copyLength; i++) {
92 *(targetPtr++) = *(shifted++);
95 break;
99 endOfLoop:
101 delete[] sourceBuffer;
102 return targetPtr - (unsigned char*)targetBuffer;