Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

zverse.cpp

00001 /******************************************************************************
00002  *  zverse.h   - code for class 'zVerse'- a module that reads raw text
00003  *                              files:  ot and nt using indexs ??.bks ??.cps ??.vss
00004  *                              and provides lookup and parsing functions based on
00005  *                              class VerseKey for compressed modules
00006  */
00007 
00008 
00009 #include <ctype.h>
00010 #include <stdio.h>
00011 #include <fcntl.h>
00012 #include <errno.h>
00013 #include <stdlib.h>
00014 
00015 #ifndef __GNUC__
00016 #include <io.h>
00017 #else
00018 #include <unistd.h>
00019 #endif
00020 
00021 #include <string.h>
00022 #include <utilfuns.h>
00023 #include <versekey.h>
00024 #include <zverse.h>
00025 #include <sysdata.h>
00026 
00027 
00028 #ifndef O_BINARY
00029 #define O_BINARY 0
00030 #endif
00031 
00032 
00033 /******************************************************************************
00034  * zVerse Statics
00035  */
00036 
00037 int zVerse::instance = 0;
00038 
00039 const char zVerse::uniqueIndexID[] = {'X', 'r', 'v', 'c', 'b'};
00040 
00041 /******************************************************************************
00042  * zVerse Constructor - Initializes data for instance of zVerse
00043  *
00044  * ENT: ipath - path of the directory where data and index files are located.
00045  *              be sure to include the trailing separator (e.g. '/' or '\')
00046  *              (e.g. 'modules/texts/rawtext/webster/')
00047  *              fileMode - open mode for the files (O_RDONLY, etc.)
00048  *              blockType - verse, chapter, book, etc.
00049  */
00050 
00051 zVerse::zVerse(const char *ipath, int fileMode, int blockType, SWCompress *icomp)
00052 {
00053         char buf[127];
00054 
00055         nl = '\n';
00056         path = 0;
00057         cacheBufIdx = -1;
00058         cacheTestament = 0;
00059         cacheBuf = 0;
00060         dirtyCache = false;
00061         stdstr(&path, ipath);
00062 
00063         if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
00064                 path[strlen(path)-1] = 0;
00065 
00066         compressor = (icomp) ? icomp : new SWCompress();
00067 
00068         if (fileMode == -1) { // try read/write if possible
00069                 fileMode = O_RDWR;
00070         }
00071                 
00072         sprintf(buf, "%s/ot.%czs", path, uniqueIndexID[blockType]);
00073         idxfp[0] = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00074 
00075         sprintf(buf, "%s/nt.%czs", path, uniqueIndexID[blockType]);
00076         idxfp[1] = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00077 
00078         sprintf(buf, "%s/ot.%czz", path, uniqueIndexID[blockType]);
00079         textfp[0] = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00080 
00081         sprintf(buf, "%s/nt.%czz", path, uniqueIndexID[blockType]);
00082         textfp[1] = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00083 
00084         sprintf(buf, "%s/ot.%czv", path, uniqueIndexID[blockType]);
00085         compfp[0] = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00086 
00087         sprintf(buf, "%s/nt.%czv", path, uniqueIndexID[blockType]);
00088         compfp[1] = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00089         
00090         instance++;
00091 }
00092 
00093 
00094 /******************************************************************************
00095  * zVerse Destructor - Cleans up instance of zVerse
00096  */
00097 
00098 zVerse::~zVerse()
00099 {
00100         int loop1;
00101 
00102         if (cacheBuf) {
00103                 flushCache();
00104                 free(cacheBuf);
00105         }
00106 
00107         if (path)
00108                 delete [] path;
00109 
00110         if (compressor)
00111                 delete compressor;
00112 
00113         --instance;
00114 
00115         for (loop1 = 0; loop1 < 2; loop1++) {
00116                 FileMgr::systemFileMgr.close(idxfp[loop1]);
00117                 FileMgr::systemFileMgr.close(textfp[loop1]);
00118                 FileMgr::systemFileMgr.close(compfp[loop1]);
00119         }
00120 }
00121 
00122 
00123 /******************************************************************************
00124  * zVerse::findoffset   - Finds the offset of the key verse from the indexes
00125  *
00126  *
00127  *
00128  * ENT: testmt  - testament to find (0 - Bible/module introduction)
00129  *      book    - book      to find (0 - testament    introduction)
00130  *      chapter - chapter   to find (0 - book         introduction)
00131  *      verse   - verse     to find (0 - chapter      introduction)
00132  *      start   - address to store the starting offset
00133  *      size    - address to store the size of the entry
00134  */
00135 
00136 void zVerse::findoffset(char testmt, long idxoff, long *start, unsigned short *size)
00137 {
00138         // set start to offset in
00139         // set size to
00140         // set
00141         unsigned long ulBuffNum=0;                // buffer number
00142         unsigned long ulVerseStart=0;          // verse offset within buffer
00143         unsigned short usVerseSize=0;          // verse size
00144         unsigned long ulCompOffset=0;          // compressed buffer start
00145         unsigned long ulCompSize=0;                  // buffer size compressed
00146         unsigned long ulUnCompSize=0;             // buffer size uncompressed
00147         char *pcCompText=NULL;                                   // compressed text
00148 
00149         *start = *size = 0;
00150         //printf ("Finding offset %ld\n", idxoff);
00151         idxoff *= 10;
00152         if (!testmt) {
00153                 testmt = ((idxfp[0]) ? 1:2);
00154         }
00155         
00156         // assert we have and valid file descriptor
00157         if (compfp[testmt-1]->getFd() < 1)
00158                 return;
00159                 
00160         long newOffset = lseek(compfp[testmt-1]->getFd(), idxoff, SEEK_SET);
00161         if (newOffset == idxoff) {
00162                 if (read(compfp[testmt-1]->getFd(), &ulBuffNum, 4) != 4) {
00163                         printf ("Error reading ulBuffNum\n");
00164                         return;
00165                 }
00166         }
00167         else return;
00168 
00169         ulBuffNum = swordtoarch32(ulBuffNum);
00170 
00171         if (read(compfp[testmt-1]->getFd(), &ulVerseStart, 4) < 2)
00172         {
00173                 printf ("Error reading ulVerseStart\n");
00174                 return;
00175         }
00176         if (read(compfp[testmt-1]->getFd(), &usVerseSize, 2) < 2)
00177         {
00178                 printf ("Error reading usVerseSize\n");
00179                 return;
00180         }
00181 
00182         *start = swordtoarch32(ulVerseStart);
00183         *size = swordtoarch16(usVerseSize);
00184 
00185         if (*size) {
00186                 if (((long) ulBuffNum == cacheBufIdx) && (testmt == cacheTestament) && (cacheBuf)) {
00187                         // have the text buffered
00188                         return;
00189                 }
00190 
00191                 //printf ("Got buffer number{%ld} versestart{%ld} versesize{%d}\n", ulBuffNum, ulVerseStart, usVerseSize);
00192 
00193 
00194                 if (lseek(idxfp[testmt-1]->getFd(), ulBuffNum*12, SEEK_SET)!=(long) ulBuffNum*12)
00195                 {
00196                         printf ("Error seeking compressed file index\n");
00197                         return;
00198                 }
00199                 if (read(idxfp[testmt-1]->getFd(), &ulCompOffset, 4)<4)
00200                 {
00201                         printf ("Error reading ulCompOffset\n");
00202                         return;
00203                 }
00204                 if (read(idxfp[testmt-1]->getFd(), &ulCompSize, 4)<4)
00205                 {
00206                         printf ("Error reading ulCompSize\n");
00207                         return;
00208                 }
00209                 if (read(idxfp[testmt-1]->getFd(), &ulUnCompSize, 4)<4)
00210                 {
00211                         printf ("Error reading ulUnCompSize\n");
00212                         return;
00213                 }
00214 
00215                 ulCompOffset  = swordtoarch32(ulCompOffset);
00216                 ulCompSize  = swordtoarch32(ulCompSize);
00217                 ulUnCompSize  = swordtoarch32(ulUnCompSize);
00218 
00219                 if (lseek(textfp[testmt-1]->getFd(), ulCompOffset, SEEK_SET)!=(long)ulCompOffset)
00220                 {
00221                         printf ("Error: could not seek to right place in compressed text\n");
00222                         return;
00223                 }
00224                 pcCompText = new char[ulCompSize];
00225 
00226                 if (read(textfp[testmt-1]->getFd(), pcCompText, ulCompSize)<(long)ulCompSize)
00227                 {
00228                         printf ("Error reading compressed text\n");
00229                         return;
00230                 }
00231                 compressor->zBuf(&ulCompSize, pcCompText);
00232 
00233                 if (cacheBuf) {
00234                         flushCache();
00235                         free(cacheBuf);
00236                 }
00237                 
00238                 unsigned long len = 0;
00239                 compressor->Buf(0, &len);
00240                 cacheBuf = (char *)calloc(len + 1, 1);
00241                 memcpy(cacheBuf, compressor->Buf(), len);
00242 
00243                 cacheTestament = testmt;
00244                 cacheBufIdx = ulBuffNum;
00245         }
00246 }
00247 
00248 
00249 /******************************************************************************
00250  * zVerse::swgettext    - gets text at a given offset
00251  *
00252  * ENT: testmt  - testament file to search in (0 - Old; 1 - New)
00253  *      start   - starting offset where the text is located in the file
00254  *      size    - size of text entry + 1 (null)
00255  *      buf     - buffer to store text
00256  *
00257  */
00258 
00259 void zVerse::swgettext(char testmt, long start, unsigned short size, char *inbuf)
00260 {
00261         memset(inbuf, 0, size);
00262         if (size > 2) {
00263                 strncpy(inbuf, &(cacheBuf[start]), size-2);
00264         }
00265 }
00266 
00267 
00268 /******************************************************************************
00269  * zVerse::settext      - Sets text for current offset
00270  *
00271  * ENT: testmt  - testament to find (0 - Bible/module introduction)
00272  *      idxoff  - offset into .vss
00273  *      buf     - buffer to store
00274  *      len     - length of buffer (0 - null terminated)
00275  */
00276 
00277 void zVerse::settext(char testmt, long idxoff, const char *buf, long len)
00278 {
00279         if (!testmt) 
00280                 testmt = ((idxfp[0]) ? 1:2);
00281         if ((!dirtyCache) || (cacheBufIdx < 0)) {
00282                 cacheBufIdx = lseek(idxfp[testmt-1]->getFd(), 0, SEEK_END) / 12;
00283                 cacheTestament = testmt;
00284                 if (cacheBuf)
00285                         free(cacheBuf);
00286                 cacheBuf = (char *)calloc(len ? len : strlen(buf)+1, 1);
00287         }
00288         else cacheBuf = (char *)((cacheBuf)?realloc(cacheBuf, strlen(cacheBuf)+(len ? len : strlen(buf)+1)):calloc((len ? len : strlen(buf)+1), 1));
00289 
00290         dirtyCache = true;
00291 
00292         unsigned long start, outstart;
00293         unsigned long outBufIdx = cacheBufIdx;
00294         unsigned short size;
00295         unsigned short outsize;
00296 
00297         idxoff *= 10;
00298         size = outsize = len ? len : strlen(buf);
00299 
00300         start = strlen(cacheBuf);
00301 
00302         if (!size)
00303                 start = outBufIdx = 0;
00304 
00305         outBufIdx = archtosword32(outBufIdx);
00306         outstart  = archtosword32(start);
00307         outsize   = archtosword16(size);
00308 
00309         lseek(compfp[testmt-1]->getFd(), idxoff, SEEK_SET);
00310         write(compfp[testmt-1]->getFd(), &outBufIdx, 4);
00311         write(compfp[testmt-1]->getFd(), &outstart, 4);
00312         write(compfp[testmt-1]->getFd(), &outsize, 2);
00313         strcat(cacheBuf, buf);
00314 }
00315 
00316 
00317 void zVerse::flushCache() {
00318         if (dirtyCache) {
00319                 unsigned long idxoff;
00320                 unsigned long start, outstart;
00321                 unsigned long size, outsize;
00322                 unsigned long zsize, outzsize;
00323 
00324                 idxoff = cacheBufIdx * 12;
00325                 size = outsize = zsize = outzsize = strlen(cacheBuf);
00326                 if (size) {
00327 //                      if (compressor) {
00328 //                              delete compressor;
00329 //                              compressor = new LZSSCompress();
00330 //                      }
00331                         compressor->Buf(cacheBuf);
00332                         compressor->zBuf(&zsize);
00333                         outzsize = zsize;
00334 
00335                         start = outstart = lseek(textfp[cacheTestament-1]->getFd(), 0, SEEK_END);
00336 
00337                         outstart  = archtosword32(start);
00338                         outsize   = archtosword32(size);
00339                         outzsize  = archtosword32(zsize);
00340 
00341                         write(textfp[cacheTestament-1]->getFd(), compressor->zBuf(&zsize), zsize);
00342 
00343                         lseek(idxfp[cacheTestament-1]->getFd(), idxoff, SEEK_SET);
00344                         write(idxfp[cacheTestament-1]->getFd(), &outstart, 4);
00345                         write(idxfp[cacheTestament-1]->getFd(), &outzsize, 4);
00346                         write(idxfp[cacheTestament-1]->getFd(), &outsize, 4);
00347                 }
00348                 dirtyCache = false;
00349         }
00350 }
00351 
00352 /******************************************************************************
00353  * RawVerse::linkentry  - links one entry to another
00354  *
00355  * ENT: testmt  - testament to find (0 - Bible/module introduction)
00356  *      destidxoff      - dest offset into .vss
00357  *      srcidxoff               - source offset into .vss
00358  */
00359 
00360 void zVerse::linkentry(char testmt, long destidxoff, long srcidxoff) {
00361         long bufidx;
00362         long start;
00363         unsigned short size;
00364 
00365         destidxoff *= 10;
00366         srcidxoff  *= 10;
00367 
00368         if (!testmt)
00369                 testmt = ((idxfp[1]) ? 1:2);
00370 
00371         // get source
00372         lseek(compfp[testmt-1]->getFd(), srcidxoff, SEEK_SET);
00373         read(compfp[testmt-1]->getFd(), &bufidx, 4);
00374         read(compfp[testmt-1]->getFd(), &start, 4);
00375         read(compfp[testmt-1]->getFd(), &size, 2);
00376 
00377         // write dest
00378         lseek(compfp[testmt-1]->getFd(), destidxoff, SEEK_SET);
00379         write(compfp[testmt-1]->getFd(), &bufidx, 4);
00380         write(compfp[testmt-1]->getFd(), &start, 4);
00381         write(compfp[testmt-1]->getFd(), &size, 2);
00382 }
00383 
00384 
00385 /******************************************************************************
00386  * RawVerse::CreateModule       - Creates new module files
00387  *
00388  * ENT: path    - directory to store module files
00389  * RET: error status
00390  */
00391 
00392 char zVerse::createModule(const char *ipath, int blockBound)
00393 {
00394         char *path = 0;
00395         char *buf = new char [ strlen (ipath) + 20 ];
00396         FileDesc *fd, *fd2;
00397 
00398         stdstr(&path, ipath);
00399 
00400         if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
00401                 path[strlen(path)-1] = 0;
00402 
00403         sprintf(buf, "%s/ot.%czs", path, uniqueIndexID[blockBound]);
00404         unlink(buf);
00405         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00406         fd->getFd();
00407         FileMgr::systemFileMgr.close(fd);
00408 
00409         sprintf(buf, "%s/nt.%czs", path, uniqueIndexID[blockBound]);
00410         unlink(buf);
00411         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00412         fd->getFd();
00413         FileMgr::systemFileMgr.close(fd);
00414 
00415         sprintf(buf, "%s/ot.%czz", path, uniqueIndexID[blockBound]);
00416         unlink(buf);
00417         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00418         fd->getFd();
00419         FileMgr::systemFileMgr.close(fd);
00420 
00421         sprintf(buf, "%s/nt.%czz", path, uniqueIndexID[blockBound]);
00422         unlink(buf);
00423         fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00424         fd2->getFd();
00425         FileMgr::systemFileMgr.close(fd);
00426 
00427         sprintf(buf, "%s/ot.%czv", path, uniqueIndexID[blockBound]);
00428         unlink(buf);
00429         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00430         fd->getFd();
00431 
00432         sprintf(buf, "%s/nt.%czv", path, uniqueIndexID[blockBound]);
00433         unlink(buf);
00434         fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00435         fd2->getFd();
00436 
00437         VerseKey vk;
00438         vk.Headings(1);
00439         long offset = 0;
00440         short size = 0;
00441         for (vk = TOP; !vk.Error(); vk++) {
00442                 write((vk.Testament() == 1) ? fd->getFd() : fd2->getFd(), &offset, 4);  //compBufIdxOffset
00443                 write((vk.Testament() == 1) ? fd->getFd() : fd2->getFd(), &offset, 4);
00444                 write((vk.Testament() == 1) ? fd->getFd() : fd2->getFd(), &size, 2);
00445         }
00446 
00447         FileMgr::systemFileMgr.close(fd);
00448         FileMgr::systemFileMgr.close(fd2);
00449 
00450         delete [] path;
00451 /*
00452         RawVerse rv(path);
00453         VerseKey mykey("Rev 22:21");
00454 */
00455         
00456         return 0;
00457 }
00458 
00459 
00460 /******************************************************************************
00461  * zVerse::preptext     - Prepares the text before returning it to external
00462  *                              objects
00463  *
00464  * ENT: buf     - buffer where text is stored and where to store the prep'd
00465  *                      text.
00466  */
00467 
00468 void zVerse::preptext(char *buf)
00469 {
00470         char *to, *from, space = 0, cr = 0, realdata = 0, nlcnt = 0;
00471 
00472         for (to = from = buf; *from; from++) {
00473                 switch (*from) {
00474                 case 10:
00475                         if (!realdata)
00476                                 continue;
00477                         space = (cr) ? 0 : 1;
00478                         cr = 0;
00479                         nlcnt++;
00480                         if (nlcnt > 1) {
00481 //                              *to++ = nl;
00482                                 *to++ = nl;
00483 //                              nlcnt = 0;
00484                         }
00485                         continue;
00486                 case 13:
00487                         if (!realdata)
00488                                 continue;
00489                         *to++ = nl;
00490                         space = 0;
00491                         cr = 1;
00492                         continue;
00493                 }
00494                 realdata = 1;
00495                 nlcnt = 0;
00496                 if (space) {
00497                         space = 0;
00498                         if (*from != ' ') {
00499                                 *to++ = ' ';
00500                                 from--;
00501                                 continue;
00502                         }
00503                 }
00504                 *to++ = *from;
00505         }
00506         *to = 0;
00507 
00508      if (to > buf) {
00509           for (to--; to > buf; to--) {                  // remove trailing excess
00510                if ((*to == 10) || (*to == ' '))
00511                     *to = 0;
00512                else break;
00513           }
00514      }
00515 }

Generated on Thu Jun 20 22:13:01 2002 for The Sword Project by doxygen1.2.15