1 /******************************************************************************
2  *
3  *  rawverse.cpp -	code for class 'RawVerse'- a module that reads raw text
4  *			files:  ot and nt using indexs ??.bks ??.cps ??.vss
5  *			and provides lookup and parsing functions based on
6  *			class VerseKey
7  *
8  * $Id: rawverse.cpp 3439 2016-10-23 08:32:02Z scribe $
9  *
10  * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org)
11  *	CrossWire Bible Society
12  *	P. O. Box 2528
13  *	Tempe, AZ  85280-2528
14  *
15  * This program is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation version 2.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * General Public License for more details.
23  *
24  */
25 
26 
27 
28 #include <ctype.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 
33 #include <utilstr.h>
34 #include <rawverse.h>
35 #include <versekey.h>
36 #include <sysdata.h>
37 #include <filemgr.h>
38 #include <swbuf.h>
39 
40 
41 SWORD_NAMESPACE_START
42 
43 /******************************************************************************
44  * RawVerse Statics
45  */
46 
47 int RawVerse::instance = 0;
48 const char RawVerse::nl = '\n';
49 
50 
51 /******************************************************************************
52  * RawVerse Constructor - Initializes data for instance of RawVerse
53  *
54  * ENT:	ipath - path of the directory where data and index files are located.
55  *		be sure to include the trailing separator (e.g. '/' or '\')
56  *		(e.g. 'modules/texts/rawtext/webster/')
57  */
58 
RawVerse(const char * ipath,int fileMode)59 RawVerse::RawVerse(const char *ipath, int fileMode)
60 {
61 	SWBuf buf;
62 
63 	path = 0;
64 	stdstr(&path, ipath);
65 
66 	if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
67 		path[strlen(path)-1] = 0;
68 
69 	if (fileMode == -1) { // try read/write if possible
70 		fileMode = FileMgr::RDWR;
71 	}
72 
73 	buf.setFormatted("%s/ot.vss", path);
74 	idxfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
75 
76 	buf.setFormatted("%s/nt.vss", path);
77 	idxfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
78 
79 	buf.setFormatted("%s/ot", path);
80 	textfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
81 
82 	buf.setFormatted("%s/nt", path);
83 	textfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
84 
85 	instance++;
86 }
87 
88 
89 /******************************************************************************
90  * RawVerse Destructor - Cleans up instance of RawVerse
91  */
92 
~RawVerse()93 RawVerse::~RawVerse()
94 {
95 	int loop1;
96 
97 	if (path)
98 		delete [] path;
99 
100 	--instance;
101 
102 	for (loop1 = 0; loop1 < 2; loop1++) {
103 		FileMgr::getSystemFileMgr()->close(idxfp[loop1]);
104 		FileMgr::getSystemFileMgr()->close(textfp[loop1]);
105 	}
106 }
107 
108 
109 /******************************************************************************
110  * RawVerse::findoffset	- Finds the offset of the key verse from the indexes
111  *
112  * ENT: testmt	- testament to find (0 - Bible/module introduction)
113  *	idxoff	- offset into .vss
114  *	start	- address to store the starting offset
115  *	size	- address to store the size of the entry
116  */
117 
findOffset(char testmt,long idxoff,long * start,unsigned short * size) const118 void RawVerse::findOffset(char testmt, long idxoff, long *start, unsigned short *size) const {
119 	idxoff *= 6;
120 	if (!testmt)
121 		testmt = ((idxfp[1]) ? 1:2);
122 
123 	if (idxfp[testmt-1]->getFd() >= 0) {
124 		idxfp[testmt-1]->seek(idxoff, SEEK_SET);
125 		__s32 tmpStart;
126 		__u16 tmpSize;
127 		idxfp[testmt-1]->read(&tmpStart, 4);
128 		long len = idxfp[testmt-1]->read(&tmpSize, 2); 		// read size
129 
130 		*start = swordtoarch32(tmpStart);
131 		*size  = swordtoarch16(tmpSize);
132 
133 		if (len < 2) {
134 			*size = (unsigned short)((*start) ? (textfp[testmt-1]->seek(0, SEEK_END) - (long)*start) : 0);	// if for some reason we get an error reading size, make size to end of file
135 		}
136 	}
137 	else {
138 		*start = 0;
139 		*size = 0;
140 	}
141 }
142 
143 
144 /******************************************************************************
145  * RawVerse::readtext	- gets text at a given offset
146  *
147  * ENT:	testmt	- testament file to search in (0 - Old; 1 - New)
148  *	start	- starting offset where the text is located in the file
149  *	size	- size of text entry + 2 (null)(null)
150  *	buf	- buffer to store text
151  *
152  */
153 
readText(char testmt,long start,unsigned short size,SWBuf & buf) const154 void RawVerse::readText(char testmt, long start, unsigned short size, SWBuf &buf) const {
155 	buf = "";
156 	buf.setFillByte(0);
157 	buf.setSize(size + 1);
158 	if (!testmt)
159 		testmt = ((idxfp[1]) ? 1:2);
160 	if (size) {
161 		if (textfp[testmt-1]->getFd() >= 0) {
162 			textfp[testmt-1]->seek(start, SEEK_SET);
163 			textfp[testmt-1]->read(buf.getRawData(), (int)size);
164 		}
165 	}
166 }
167 
168 
169 /******************************************************************************
170  * RawVerse::settext	- Sets text for current offset
171  *
172  * ENT: testmt	- testament to find (0 - Bible/module introduction)
173  *	idxoff	- offset into .vss
174  *	buf	- buffer to store
175  *      len     - length of buffer (0 - null terminated)
176  */
177 
doSetText(char testmt,long idxoff,const char * buf,long len)178 void RawVerse::doSetText(char testmt, long idxoff, const char *buf, long len)
179 {
180 	__s32 start;
181 	__u16 size;
182 
183 	idxoff *= 6;
184 	if (!testmt)
185 		testmt = ((idxfp[1]) ? 1:2);
186 
187 	size = (len < 0) ? strlen(buf) : len;
188 
189 	start = (__s32)textfp[testmt-1]->seek(0, SEEK_END);
190 	idxfp[testmt-1]->seek(idxoff, SEEK_SET);
191 
192 	if (size) {
193 		textfp[testmt-1]->seek(start, SEEK_SET);
194 		textfp[testmt-1]->write(buf, (int)size);
195 
196 		// add a new line to make data file easier to read in an editor
197 		textfp[testmt-1]->write(&nl, 1);
198 	}
199 	else {
200 		start = 0;
201 	}
202 
203 	start = archtosword32(start);
204 	size  = archtosword16(size);
205 
206 	idxfp[testmt-1]->write(&start, 4);
207 	idxfp[testmt-1]->write(&size, 2);
208 }
209 
210 
211 /******************************************************************************
212  * RawVerse::linkentry	- links one entry to another
213  *
214  * ENT: testmt	- testament to find (0 - Bible/module introduction)
215  *	destidxoff	- dest offset into .vss
216  *	srcidxoff		- source offset into .vss
217  */
218 
doLinkEntry(char testmt,long destidxoff,long srcidxoff)219 void RawVerse::doLinkEntry(char testmt, long destidxoff, long srcidxoff) {
220 	__s32 start;
221 	__u16 size;
222 
223 	destidxoff *= 6;
224 	srcidxoff  *= 6;
225 
226 	if (!testmt)
227 		testmt = ((idxfp[1]) ? 1:2);
228 
229 	// get source
230 	idxfp[testmt-1]->seek(srcidxoff, SEEK_SET);
231 	idxfp[testmt-1]->read(&start, 4);
232 	idxfp[testmt-1]->read(&size, 2);
233 
234 	// write dest
235 	idxfp[testmt-1]->seek(destidxoff, SEEK_SET);
236 	idxfp[testmt-1]->write(&start, 4);
237 	idxfp[testmt-1]->write(&size, 2);
238 }
239 
240 
241 /******************************************************************************
242  * RawVerse::createModule	- Creates new module files
243  *
244  * ENT: path	- directory to store module files
245  * RET: error status
246  */
247 
createModule(const char * ipath,const char * v11n)248 char RawVerse::createModule(const char *ipath, const char *v11n)
249 {
250 	char *path = 0;
251 	char *buf = new char [ strlen (ipath) + 20 ];
252 	FileDesc *fd, *fd2;
253 
254 	stdstr(&path, ipath);
255 
256 	if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
257 		path[strlen(path)-1] = 0;
258 
259 	sprintf(buf, "%s/ot", path);
260 	FileMgr::removeFile(buf);
261 	fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE);
262 	fd->getFd();
263 	FileMgr::getSystemFileMgr()->close(fd);
264 
265 	sprintf(buf, "%s/nt", path);
266 	FileMgr::removeFile(buf);
267 	fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE);
268 	fd->getFd();
269 	FileMgr::getSystemFileMgr()->close(fd);
270 
271 	sprintf(buf, "%s/ot.vss", path);
272 	FileMgr::removeFile(buf);
273 	fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE);
274 	fd->getFd();
275 
276 	sprintf(buf, "%s/nt.vss", path);
277 	FileMgr::removeFile(buf);
278 	fd2 = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE);
279 	fd2->getFd();
280 
281 	VerseKey vk;
282 	vk.setVersificationSystem(v11n);
283 	vk.setIntros(1);
284 
285 	__s32 offset = 0;
286 	__u16 size = 0;
287 	offset = archtosword32(offset);
288 	size = archtosword16(size);
289 
290 	for (vk = TOP; !vk.popError(); vk++) {
291 		if (vk.getTestament() < 2) {
292 			fd->write(&offset, 4);
293 			fd->write(&size, 2);
294 		}
295 		else	{
296 			fd2->write(&offset, 4);
297 			fd2->write(&size, 2);
298 		}
299 	}
300 	fd2->write(&offset, 4);
301 	fd2->write(&size, 2);
302 
303 	FileMgr::getSystemFileMgr()->close(fd);
304 	FileMgr::getSystemFileMgr()->close(fd2);
305 
306 	delete [] path;
307 	delete [] buf;
308 
309 	return 0;
310 }
311 
312 SWORD_NAMESPACE_END
313