The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
zverse4.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * zverse4.cpp - code for class 'zVerse4'- 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 for compressed modules
7  *
8  * $Id: zverse4.cpp 3754 2020-07-10 17:45:48Z scribe $
9  *
10  * Copyright 1996-2014 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 #include <ctype.h>
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 
32 #include <utilstr.h>
33 #include <versekey.h>
34 #include <zverse4.h>
35 #include <sysdata.h>
36 #include <swbuf.h>
37 #include <filemgr.h>
38 #include <swcomprs.h>
39 
40 
42 
43 /******************************************************************************
44  * zVerse4 Statics
45  */
46 
47 int zVerse4::instance = 0;
48 
49 const char zVerse4::uniqueIndexID[] = {'X', 'r', 'v', 'c', 'b'};
50 
51 /******************************************************************************
52  * zVerse4 Constructor - Initializes data for instance of zVerse4
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  * fileMode - open mode for the files (FileMgr::RDONLY, etc.)
58  * blockType - verse, chapter, book, etc.
59  */
60 
61 zVerse4::zVerse4(const char *ipath, int fileMode, int blockType, SWCompress *icomp)
62 {
63  // this line, instead of just defaulting, to keep FileMgr out of header
64  if (fileMode == -1) fileMode = FileMgr::RDONLY;
65 
66  SWBuf buf;
67 
68  path = 0;
69  cacheBufIdx = -1;
70  cacheTestament = 0;
71  cacheBuf = 0;
72  dirtyCache = false;
73  stdstr(&path, ipath);
74 
75  if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
76  path[strlen(path)-1] = 0;
77 
78  compressor = (icomp) ? icomp : new SWCompress();
79 
80  if (fileMode == -1) { // try read/write if possible
81  fileMode = FileMgr::RDWR;
82  }
83 
84  buf.setFormatted("%s/ot.%czs", path, uniqueIndexID[blockType]);
85  idxfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
86 
87  buf.setFormatted("%s/nt.%czs", path, uniqueIndexID[blockType]);
88  idxfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
89 
90  buf.setFormatted("%s/ot.%czz", path, uniqueIndexID[blockType]);
91  textfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
92 
93  buf.setFormatted("%s/nt.%czz", path, uniqueIndexID[blockType]);
94  textfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
95 
96  buf.setFormatted("%s/ot.%czv", path, uniqueIndexID[blockType]);
97  compfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
98 
99  buf.setFormatted("%s/nt.%czv", path, uniqueIndexID[blockType]);
100  compfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true);
101 
102  instance++;
103 }
104 
105 
106 /******************************************************************************
107  * zVerse4 Destructor - Cleans up instance of zVerse4
108  */
109 
111 {
112  int loop1;
113 
114  if (cacheBuf) {
115  flushCache();
116  free(cacheBuf);
117  }
118 
119  if (path)
120  delete [] path;
121 
122  if (compressor)
123  delete compressor;
124 
125  --instance;
126 
127  for (loop1 = 0; loop1 < 2; loop1++) {
131  }
132 }
133 
134 
135 /******************************************************************************
136  * zVerse4::findoffset - Finds the offset of the key verse from the indexes
137  *
138  *
139  *
140  * ENT: testmt - testament to find (0 - Bible/module introduction)
141  * book - book to find (0 - testament introduction)
142  * chapter - chapter to find (0 - book introduction)
143  * verse - verse to find (0 - chapter introduction)
144  * start - address to store the starting offset
145  * size - address to store the size of the entry
146  */
147 
148 void zVerse4::findOffset(char testmt, long idxoff, long *start, unsigned long *size, unsigned long *buffnum) const
149 {
150  SW_u32 ulBuffNum = 0; // buffer number
151  SW_u32 ulVerseStart = 0; // verse offset within buffer
152  SW_u32 usVerseSize = 0; // verse size
153  // set start to offset in
154  // set size to
155  // set
156  *start = *size = *buffnum = 0;
157  //fprintf(stderr, "Finding offset %ld\n", idxoff);
158  idxoff *= 12; // TODO: Is this the correct size? (throughout)
159  if (!testmt) {
160  testmt = ((idxfp[0]) ? 1:2);
161  }
162 
163  // assert we have and valid file descriptor
164  if (compfp[testmt-1]->getFd() < 1)
165  return;
166 
167  long newOffset = compfp[testmt-1]->seek(idxoff, SEEK_SET);
168  if (newOffset == idxoff) {
169  if (compfp[testmt-1]->read(&ulBuffNum, 4) != 4) {
170  fprintf(stderr, "Error reading ulBuffNum\n");
171  return;
172  }
173  }
174  else return;
175 
176  if (compfp[testmt-1]->read(&ulVerseStart, 4) < 4)
177  {
178  fprintf(stderr, "Error reading ulVerseStart\n");
179  return;
180  }
181  if (compfp[testmt-1]->read(&usVerseSize, 4) < 4)
182  {
183  fprintf(stderr, "Error reading usVerseSize\n");
184  return;
185  }
186 
187  *buffnum = swordtoarch32(ulBuffNum);
188  *start = swordtoarch32(ulVerseStart);
189  *size = swordtoarch32(usVerseSize);
190 
191 }
192 
193 
194 /******************************************************************************
195  * zVerse4::zreadtext - gets text at a given offset
196  *
197  * ENT: testmt - testament file to search in (0 - Old; 1 - New)
198  * start - starting offset where the text is located in the file
199  * size - size of text entry + 1 (null)
200  * buf - buffer to store text
201  *
202  */
203 
204 void zVerse4::zReadText(char testmt, long start, unsigned long size, unsigned long ulBuffNum, SWBuf &inBuf) const {
205  SW_u32 ulCompOffset = 0; // compressed buffer start
206  SW_u32 ulCompSize = 0; // buffer size compressed
207  SW_u32 ulUnCompSize = 0; // buffer size uncompressed
208 
209  if (!testmt) {
210  testmt = ((idxfp[0]) ? 1:2);
211  }
212 
213  // assert we have and valid file descriptor
214  if (compfp[testmt-1]->getFd() < 1)
215  return;
216 
217  if (size &&
218  !(((long) ulBuffNum == cacheBufIdx) && (testmt == cacheTestament) && (cacheBuf))) {
219  //fprintf(stderr, "Got buffer number{%ld} versestart{%ld} versesize{%d}\n", ulBuffNum, ulVerseStart, usVerseSize);
220 
221  if (idxfp[testmt-1]->seek(ulBuffNum*12, SEEK_SET)!=(long) ulBuffNum*12)
222  {
223  fprintf(stderr, "Error seeking compressed file index\n");
224  return;
225  }
226  if (idxfp[testmt-1]->read(&ulCompOffset, 4)<4)
227  {
228  fprintf(stderr, "Error reading ulCompOffset\n");
229  return;
230  }
231  if (idxfp[testmt-1]->read(&ulCompSize, 4)<4)
232  {
233  fprintf(stderr, "Error reading ulCompSize\n");
234  return;
235  }
236  if (idxfp[testmt-1]->read(&ulUnCompSize, 4)<4)
237  {
238  fprintf(stderr, "Error reading ulUnCompSize\n");
239  return;
240  }
241 
242  ulCompOffset = swordtoarch32(ulCompOffset);
243  ulCompSize = swordtoarch32(ulCompSize);
244  ulUnCompSize = swordtoarch32(ulUnCompSize);
245 
246  if (textfp[testmt-1]->seek(ulCompOffset, SEEK_SET)!=(long)ulCompOffset)
247  {
248  fprintf(stderr, "Error: could not seek to right place in compressed text\n");
249  return;
250  }
251  SWBuf pcCompText;
252  pcCompText.setSize(ulCompSize+5);
253 
254  if (textfp[testmt-1]->read(pcCompText.getRawData(), ulCompSize)<(long)ulCompSize) {
255  fprintf(stderr, "Error reading compressed text\n");
256  return;
257  }
258  pcCompText.setSize(ulCompSize);
259  rawZFilter(pcCompText, 0); // 0 = decipher
260 
261  unsigned long bufSize = ulCompSize;
262  compressor->setCompressedBuf(&bufSize, pcCompText.getRawData());
263 
264  if (cacheBuf) {
265  flushCache();
266  free(cacheBuf);
267  }
268 
269  unsigned long len = 0;
270  compressor->setUncompressedBuf(0, &len);
271  cacheBuf = (char *)calloc(len + 1, 1);
272  memcpy(cacheBuf, compressor->getUncompressedBuf(), len);
273  cacheBufSize = (int)strlen(cacheBuf); // TODO: can we just use len?
274  cacheTestament = testmt;
275  cacheBufIdx = ulBuffNum;
276  }
277 
278  inBuf = "";
279  if ((size > 0) && cacheBuf && ((unsigned)start < cacheBufSize)) {
280  inBuf.setFillByte(0);
281  inBuf.setSize(size+1);
282  strncpy(inBuf.getRawData(), &(cacheBuf[start]), size);
283  inBuf.setSize(strlen(inBuf.c_str()));
284  }
285 }
286 
287 
288 /******************************************************************************
289  * zVerse4::settext - Sets text for current offset
290  *
291  * ENT: testmt - testament to find (0 - Bible/module introduction)
292  * idxoff - offset into .vss
293  * buf - buffer to store
294  * len - length of buffer (0 - null terminated)
295  */
296 
297 void zVerse4::doSetText(char testmt, long idxoff, const char *buf, long len) {
298 
299  len = (len < 0) ? strlen(buf) : len;
300  if (!testmt)
301  testmt = ((idxfp[0]) ? 1:2);
302  if ((!dirtyCache) || (cacheBufIdx < 0)) {
303  cacheBufIdx = idxfp[testmt-1]->seek(0, SEEK_END) / 12;
304  cacheTestament = testmt;
305  if (cacheBuf)
306  free(cacheBuf);
307  cacheBuf = (char *)calloc(len + 1, 1);
308  }
309  else cacheBuf = (char *)((cacheBuf)?realloc(cacheBuf, strlen(cacheBuf)+(len + 1)):calloc((len + 1), 1));
310 
311  dirtyCache = true;
312 
313  SW_u32 start;
314  SW_u32 size;
315  SW_u32 outBufIdx = (SW_u32)cacheBufIdx;
316 
317  idxoff *= 12;
318  size = (SW_u32)len;
319 
320  start = (SW_u32)strlen(cacheBuf);
321 
322  if (!size)
323  start = outBufIdx = 0;
324 
325  outBufIdx = archtosword32(outBufIdx);
326  start = archtosword32(start);
327  size = archtosword32(size);
328 
329  compfp[testmt-1]->seek(idxoff, SEEK_SET);
330  compfp[testmt-1]->write(&outBufIdx, 4);
331  compfp[testmt-1]->write(&start, 4);
332  compfp[testmt-1]->write(&size, 4);
333  strcat(cacheBuf, buf);
334 }
335 
336 
337 void zVerse4::flushCache() const {
338  if (dirtyCache) {
339  SW_u32 idxoff;
340  SW_u32 start, outstart;
341  SW_u32 size, outsize;
342  SW_u32 zsize, outzsize;
343 
344  idxoff = (SW_u32)cacheBufIdx * 12;
345  if (cacheBuf) {
346  size = outsize = zsize = outzsize = (SW_u32)strlen(cacheBuf);
347  if (size) {
349  unsigned long tmpSize;
350  compressor->getCompressedBuf(&tmpSize);
351  outzsize = zsize = (SW_u32)tmpSize;
352 
353  SWBuf buf;
354  buf.setSize(zsize + 5);
355  memcpy(buf.getRawData(), compressor->getCompressedBuf(&tmpSize), tmpSize);
356  outzsize = zsize = (SW_u32)tmpSize;
357  buf.setSize(zsize);
358  rawZFilter(buf, 1); // 1 = encipher
359 
360  start = outstart = (SW_u32)textfp[cacheTestament - 1]->seek(0, SEEK_END);
361 
362  outstart = archtosword32(start);
363  outsize = archtosword32(size);
364  outzsize = archtosword32(zsize);
365 
366  textfp[cacheTestament-1]->write(buf, zsize);
367 
368  idxfp[cacheTestament-1]->seek(idxoff, SEEK_SET);
369  idxfp[cacheTestament-1]->write(&outstart, 4);
370  idxfp[cacheTestament-1]->write(&outzsize, 4);
371  idxfp[cacheTestament-1]->write(&outsize, 4);
372  }
373  free(cacheBuf);
374  cacheBuf = 0;
375  }
376  dirtyCache = false;
377  }
378 }
379 
380 /******************************************************************************
381  * RawVerse::linkentry - links one entry to another
382  *
383  * ENT: testmt - testament to find (0 - Bible/module introduction)
384  * destidxoff - dest offset into .vss
385  * srcidxoff - source offset into .vss
386  */
387 
388 void zVerse4::doLinkEntry(char testmt, long destidxoff, long srcidxoff) {
389  SW_s32 bufidx;
390  SW_s32 start;
391  SW_u32 size;
392 
393  destidxoff *= 12;
394  srcidxoff *= 12;
395 
396  if (!testmt)
397  testmt = ((idxfp[1]) ? 1:2);
398 
399  // get source
400  compfp[testmt-1]->seek(srcidxoff, SEEK_SET);
401  compfp[testmt-1]->read(&bufidx, 4);
402  compfp[testmt-1]->read(&start, 4);
403  compfp[testmt-1]->read(&size, 4);
404 
405  // write dest
406  compfp[testmt-1]->seek(destidxoff, SEEK_SET);
407  compfp[testmt-1]->write(&bufidx, 4);
408  compfp[testmt-1]->write(&start, 4);
409  compfp[testmt-1]->write(&size, 4);
410 }
411 
412 
413 /******************************************************************************
414  * RawVerse::CreateModule - Creates new module files
415  *
416  * ENT: path - directory to store module files
417  * RET: error status
418  */
419 
420 char zVerse4::createModule(const char *ipath, int blockBound, const char *v11n)
421 {
422  char *path = 0;
423  char *buf = new char [ strlen (ipath) + 20 ];
424  char retVal = 0;
425  FileDesc *fd, *fd2;
426  SW_s32 offset = 0;
427  SW_s32 size = 0;
428  VerseKey vk;
429 
430  stdstr(&path, ipath);
431 
432  if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
433  path[strlen(path)-1] = 0;
434 
435  sprintf(buf, "%s/ot.%czs", path, uniqueIndexID[blockBound]);
436  FileMgr::removeFile(buf);
438  if (fd->getFd() < 1) goto erroropen1;
440 
441  sprintf(buf, "%s/nt.%czs", path, uniqueIndexID[blockBound]);
442  FileMgr::removeFile(buf);
444  if (fd->getFd() < 1) goto erroropen1;
446 
447  sprintf(buf, "%s/ot.%czz", path, uniqueIndexID[blockBound]);
448  FileMgr::removeFile(buf);
450  if (fd->getFd() < 1) goto erroropen1;
452 
453  sprintf(buf, "%s/nt.%czz", path, uniqueIndexID[blockBound]);
454  FileMgr::removeFile(buf);
456  if (fd->getFd() < 1) goto erroropen1;
458 
459  sprintf(buf, "%s/ot.%czv", path, uniqueIndexID[blockBound]);
460  FileMgr::removeFile(buf);
462  if (fd->getFd() < 1) goto erroropen1;
463 
464  sprintf(buf, "%s/nt.%czv", path, uniqueIndexID[blockBound]);
465  FileMgr::removeFile(buf);
467  if (fd2->getFd() < 1) goto erroropen2;
468 
469  vk.setVersificationSystem(v11n);
470  vk.setIntros(true);
471 
472  offset = archtosword32(offset);
473  size = archtosword32(size);
474 
475  for (vk = TOP; !vk.popError(); vk++) {
476  if (vk.getTestament() < 2) {
477  if (fd->write(&offset, 4) != 4) goto writefailure; //compBufIdxOffset
478  if (fd->write(&offset, 4) != 4) goto writefailure;
479  if (fd->write(&size, 4) != 4) goto writefailure;
480  }
481  else {
482  if (fd2->write(&offset, 4) != 4) goto writefailure; //compBufIdxOffset
483  if (fd2->write(&offset, 4) != 4) goto writefailure;
484  if (fd2->write(&size, 4) != 4) goto writefailure;
485  }
486  }
487  fd2->write(&offset, 4); //compBufIdxOffset
488  fd2->write(&offset, 4);
489  fd2->write(&size, 4);
490 
491  goto cleanup;
492 
493 erroropen1:
494  retVal = -1;
495  goto cleanup1;
496 
497 erroropen2:
498  retVal = -1;
499  goto cleanup;
500 
501 writefailure:
502  retVal = -2;
503 
504 cleanup:
506 cleanup1:
508 
509  delete [] path;
510  delete [] buf;
511 
512  return retVal;
513 }
514 
515 
void setFillByte(char ch)
Definition: swbuf.h:146
virtual void rawZFilter(SWBuf &buf, char direction=0) const
Definition: zverse4.h:73
void findOffset(char testmt, long idxoff, long *start, unsigned long *size, unsigned long *buffnum) const
Definition: zverse4.cpp:148
#define TOP
Definition: swkey.h:68
#define SWORD_NAMESPACE_START
Definition: defs.h:39
long seek(long offset, int whence)
Definition: filemgr.cpp:143
bool dirtyCache
Definition: zverse4.h:56
FileDesc * open(const char *path, int mode, bool tryDowngrade)
Definition: filemgr.cpp:175
Definition: swbuf.h:47
char cacheTestament
Definition: zverse4.h:54
virtual ~zVerse4()
Definition: zverse4.cpp:110
FileDesc * textfp[2]
Definition: zverse4.h:46
static unsigned int RDONLY
Definition: filemgr.h:75
#define archtosword32(x)
Definition: sysdata.h:97
char * path
Definition: zverse4.h:48
virtual void setCompressedBuf(unsigned long *len, char *buf=0)
Definition: swcomprs.cpp:101
#define SEEK_END
Definition: zconf.h:246
static unsigned int RDWR
Definition: filemgr.h:76
signed int SW_s32
Definition: sysdata.h:40
virtual char * getCompressedBuf(unsigned long *len=0)
Definition: swcomprs.cpp:111
void doSetText(char testmt, long idxoff, const char *buf, long len=0)
Definition: zverse4.cpp:297
SWBuf v11n
Definition: osis2mod.cpp:107
int getFd()
Definition: filemgr.h:231
static char createModule(const char *path, int blockBound, const char *v11n="KJV")
Definition: zverse4.cpp:420
FileDesc * compfp[2]
Definition: zverse4.h:47
void doLinkEntry(char testmt, long destidxoff, long srcidxoff)
Definition: zverse4.cpp:388
long write(const void *buf, long count)
Definition: filemgr.cpp:153
virtual char * getUncompressedBuf(unsigned long *len=0)
Definition: swcomprs.cpp:90
zVerse4(const char *ipath, int fileMode=-1, int blockType=CHAPTERBLOCKS, SWCompress *icomp=0)
Definition: zverse4.cpp:61
FileDesc * idxfp[2]
Definition: zverse4.h:45
SWORD_NAMESPACE_START char * stdstr(char **ipstr, const char *istr, unsigned int memPadFactor=1)
Definition: utilstr.h:44
virtual void setUncompressedBuf(const char *buf=0, unsigned long *len=0)
Definition: swcomprs.cpp:75
void close(FileDesc *file)
Definition: filemgr.cpp:196
virtual void setIntros(bool val)
Definition: versekey.cpp:1663
char * cacheBuf
Definition: zverse4.h:52
char * getRawData()
Definition: swbuf.h:379
void zReadText(char testmt, long start, unsigned long size, unsigned long buffnum, SWBuf &buf) const
Definition: zverse4.cpp:204
free(preg->fastmap)
const char * c_str() const
Definition: swbuf.h:158
virtual void setVersificationSystem(const char *name)
Definition: versekey.cpp:298
static int removeFile(const char *fName)
Definition: filemgr.cpp:517
char * realloc()
long cacheBufIdx
Definition: zverse4.h:55
#define swordtoarch32(x)
Definition: sysdata.h:94
virtual char popError()
Definition: swkey.cpp:147
#define SEEK_SET
Definition: zconf.h:244
int size
Definition: regex.c:5043
static unsigned int CREAT
Definition: filemgr.h:72
unsigned int cacheBufSize
Definition: zverse4.h:53
void flushCache() const
Definition: zverse4.cpp:337
unsigned int SW_u32
Definition: sysdata.h:41
static unsigned int IWRITE
Definition: filemgr.h:79
static unsigned int WRONLY
Definition: filemgr.h:77
long read(void *buf, long count)
Definition: filemgr.cpp:148
static unsigned int IREAD
Definition: filemgr.h:78
static const char uniqueIndexID[]
Definition: zverse4.h:64
#define SWORD_NAMESPACE_END
Definition: defs.h:40
SWBuf & setFormatted(const char *format,...)
Definition: swbuf.cpp:50
SWCompress * compressor
Definition: zverse4.h:40
void setSize(unsigned long len)
Definition: swbuf.h:255
virtual char getTestament() const
Definition: versekey.cpp:1498
static int instance
Definition: zverse4.h:43
static FileMgr * getSystemFileMgr()
Definition: filemgr.cpp:101