summaryrefslogtreecommitdiffstats
path: root/fbreader/src/formats/pdb/PluckerTextStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fbreader/src/formats/pdb/PluckerTextStream.cpp')
-rw-r--r--fbreader/src/formats/pdb/PluckerTextStream.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/fbreader/src/formats/pdb/PluckerTextStream.cpp b/fbreader/src/formats/pdb/PluckerTextStream.cpp
new file mode 100644
index 0000000..01291eb
--- /dev/null
+++ b/fbreader/src/formats/pdb/PluckerTextStream.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
+ *
+ * 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 <ZLFile.h>
+#include <ZLZDecompressor.h>
+
+#include "PluckerTextStream.h"
+#include "PdbReader.h"
+#include "DocDecompressor.h"
+
+PluckerTextStream::PluckerTextStream(const ZLFile &file) : PdbStream(file) {
+ myFullBuffer = 0;
+}
+
+PluckerTextStream::~PluckerTextStream() {
+ close();
+}
+
+bool PluckerTextStream::open() {
+ if (!PdbStream::open()) {
+ return false;
+ }
+
+ PdbUtil::readUnsignedShort(*myBase, myCompressionVersion);
+
+ myBuffer = new char[65536];
+ myFullBuffer = new char[65536];
+
+ myRecordIndex = 0;
+
+ return true;
+}
+
+bool PluckerTextStream::fillBuffer() {
+ while (myBufferOffset == myBufferLength) {
+ if (myRecordIndex + 1 > header().Offsets.size() - 1) {
+ return false;
+ }
+ ++myRecordIndex;
+ const std::size_t currentOffset = recordOffset(myRecordIndex);
+ if (currentOffset < myBase->offset()) {
+ return false;
+ }
+ myBase->seek(currentOffset, true);
+ const std::size_t nextOffset = recordOffset(myRecordIndex + 1);
+ if (nextOffset < currentOffset) {
+ return false;
+ }
+ processRecord(nextOffset - currentOffset);
+ }
+ return true;
+}
+
+void PluckerTextStream::close() {
+ if (myFullBuffer != 0) {
+ delete[] myFullBuffer;
+ myFullBuffer = 0;
+ }
+ PdbStream::close();
+}
+
+void PluckerTextStream::processRecord(std::size_t recordSize) {
+ myBase->seek(2, false);
+
+ unsigned short paragraphs;
+ PdbUtil::readUnsignedShort(*myBase, paragraphs);
+
+ unsigned short size;
+ PdbUtil::readUnsignedShort(*myBase, size);
+
+ unsigned char type;
+ myBase->read((char*)&type, 1);
+ if (type > 1) { // this record is not text record
+ return;
+ }
+
+ myBase->seek(1, false);
+
+ std::vector<int> pars;
+ for (int i = 0; i < paragraphs; ++i) {
+ unsigned short pSize;
+ PdbUtil::readUnsignedShort(*myBase, pSize);
+ pars.push_back(pSize);
+ myBase->seek(2, false);
+ }
+
+ bool doProcess = false;
+ if (type == 0) {
+ doProcess = myBase->read(myFullBuffer, size) == size;
+ } else if (myCompressionVersion == 1) {
+ doProcess =
+ DocDecompressor().decompress(*myBase, myFullBuffer, recordSize - 8 - 4 * paragraphs, size) == size;
+ } else if (myCompressionVersion == 2) {
+ myBase->seek(2, false);
+ doProcess =
+ ZLZDecompressor(recordSize - 10 - 4 * paragraphs).decompress(*myBase, myFullBuffer, size) == size;
+ }
+ if (doProcess) {
+ myBufferLength = 0;
+ myBufferOffset = 0;
+
+ char *start = myFullBuffer;
+ char *end = myFullBuffer;
+
+ for (std::vector<int>::const_iterator it = pars.begin(); it != pars.end(); ++it) {
+ start = end;
+ end = start + *it;
+ if (end > myFullBuffer + size) {
+ break;
+ }
+ processTextParagraph(start, end);
+ }
+ }
+}
+
+void PluckerTextStream::processTextParagraph(char *start, char *end) {
+ char *textStart = start;
+ bool functionFlag = false;
+ for (char *ptr = start; ptr < end; ++ptr) {
+ if (*ptr == 0) {
+ functionFlag = true;
+ if (ptr != textStart) {
+ std::memcpy(myBuffer + myBufferLength, textStart, ptr - textStart);
+ myBufferLength += ptr - textStart;
+ }
+ } else if (functionFlag) {
+ int paramCounter = ((unsigned char)*ptr) % 8;
+ if (end - ptr > paramCounter + 1) {
+ ptr += paramCounter;
+ } else {
+ ptr = end - 1;
+ }
+ functionFlag = false;
+ textStart = ptr + 1;
+ }
+ }
+ if (end != textStart) {
+ std::memcpy(myBuffer + myBufferLength, textStart, end - textStart);
+ myBufferLength += end - textStart;
+ }
+}