1 /*
2  * Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19 
20 #include <cstring>
21 #include <cctype>
22 
23 #include "PPLBookReader.h"
24 #include <ZLInputStream.h>
25 
26 static const size_t BUFFER_SIZE = 2048;
27 
PPLBookReader(BookModel & model,const std::string & encoding)28 PPLBookReader::PPLBookReader(BookModel &model, const std::string &encoding) : EncodedTextReader(encoding), myModelReader(model) {
29 	myBuffer = new char[BUFFER_SIZE + 1];
30 }
31 
~PPLBookReader()32 PPLBookReader::~PPLBookReader() {
33 	delete[] myBuffer;
34 }
35 
currentParagraphIsEmpty() const36 bool PPLBookReader::currentParagraphIsEmpty() const {
37 	const char *ptr = myCurrentParagraph.data();
38 	const char *end = ptr + myCurrentParagraph.length();
39 	for (; ptr < end; ++ptr) {
40 		if (!isspace((unsigned char)*ptr)) {
41 			return false;
42 		}
43 	}
44 	return true;
45 }
46 
addParagraph()47 void PPLBookReader::addParagraph() {
48 	static const std::string END_OF_TEXT = "<* >";
49 	if (!myCurrentParagraph.empty()) {
50 		if (currentParagraphIsEmpty()) {
51 			++myEmptyLineCounter;
52 			if (myEmptyLineCounter >= 2) {
53 				myModelReader.beginParagraph(ZLTextParagraph::EMPTY_LINE_PARAGRAPH);
54 				myModelReader.endParagraph();
55 			}
56 		} else if (myEmptyLineCounter < 2) {
57 			myModelReader.beginParagraph();
58 			myModelReader.addControl(TITLE, true);
59 			myModelReader.addData(myCurrentParagraph);
60 			myModelReader.endParagraph();
61 		} else if (myCurrentParagraph[0] == 9) {
62 			myModelReader.beginParagraph();
63 			myModelReader.addData(myCurrentParagraph);
64 			myModelReader.endParagraph();
65 		} else if ((myCurrentParagraph.length() >= 2) &&
66 				(myCurrentParagraph[0] == '*') &&
67 				(myCurrentParagraph[1] == ' ')) {
68 			myCurrentParagraph.erase(0, 2);
69 			myModelReader.insertEndOfSectionParagraph();
70 			myModelReader.beginContentsParagraph();
71 			myModelReader.addContentsData(myCurrentParagraph);
72 			myModelReader.endContentsParagraph();
73 			myModelReader.beginParagraph();
74 			myModelReader.addControl(SECTION_TITLE, true);
75 			myModelReader.addData(myCurrentParagraph);
76 			myModelReader.endParagraph();
77 		} else if (myCurrentParagraph.substr(0, 4) != END_OF_TEXT) {
78 			myModelReader.beginParagraph();
79 			myModelReader.addControl(SUBTITLE, true);
80 			myModelReader.addData(myCurrentParagraph);
81 			myModelReader.endParagraph();
82 		}
83 		myCurrentParagraph.erase();
84 	}
85 }
86 
readDocument(ZLInputStream & stream)87 bool PPLBookReader::readDocument(ZLInputStream &stream) {
88 	if (!stream.open()) {
89 		return false;
90 	}
91 
92 	myModelReader.setMainTextModel();
93 	myModelReader.pushKind(REGULAR);
94 	myCurrentParagraph.erase();
95 	myEmptyLineCounter = 0;
96 
97 	// "PPL\r\n"
98 	stream.seek(5, false);
99 
100 	size_t size;
101 	do {
102 		size = stream.read(myBuffer, BUFFER_SIZE);
103 		myBuffer[size] = '\0';
104 
105 		const char *start = myBuffer;
106 		const char *end = myBuffer + size;
107 		const char *eol;
108 		do {
109 			eol = strchr(start, '\n');
110 			if (eol != 0) {
111 				if (start < eol) {
112 					myConverter->convert(myCurrentParagraph, start, eol);
113 				}
114 				addParagraph();
115 				start = eol + 1;
116 			} else {
117 				if (start < end) {
118 					myConverter->convert(myCurrentParagraph, start, end);
119 				}
120 			}
121 		} while (eol != 0);
122 	} while (size == BUFFER_SIZE);
123 
124 	addParagraph();
125 
126 	stream.close();
127 
128 	return true;
129 }
130