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 ((!dirtyCache) || (cacheBufIdx < 0)) {
00280                 cacheBufIdx = lseek(idxfp[testmt-1]->getFd(), 0, SEEK_END) / 12;
00281                 cacheTestament = testmt;
00282                 if (cacheBuf)
00283                         free(cacheBuf);
00284                 cacheBuf = (char *)calloc(len ? len : strlen(buf)+1, 1);
00285         }
00286         else cacheBuf = (char *)((cacheBuf)?realloc(cacheBuf, strlen(cacheBuf)+(len ? len : strlen(buf)+1)):calloc((len ? len : strlen(buf)+1), 1));
00287 
00288         dirtyCache = true;
00289 
00290         unsigned long start, outstart;
00291         unsigned long outBufIdx = cacheBufIdx;
00292         unsigned short size;
00293         unsigned short outsize;
00294 
00295         idxoff *= 10;
00296         size = outsize = len ? len : strlen(buf);
00297 
00298         start = strlen(cacheBuf);
00299 
00300         if (!size)
00301                 start = outBufIdx = 0;
00302 
00303         outBufIdx = archtosword32(outBufIdx);
00304         outstart  = archtosword32(start);
00305         outsize   = archtosword16(size);
00306 
00307         lseek(compfp[testmt-1]->getFd(), idxoff, SEEK_SET);
00308         write(compfp[testmt-1]->getFd(), &outBufIdx, 4);
00309         write(compfp[testmt-1]->getFd(), &outstart, 4);
00310         write(compfp[testmt-1]->getFd(), &outsize, 2);
00311         strcat(cacheBuf, buf);
00312 }
00313 
00314 
00315 void zVerse::flushCache() {
00316         if (dirtyCache) {
00317                 unsigned long idxoff;
00318                 unsigned long start, outstart;
00319                 unsigned long size, outsize;
00320                 unsigned long zsize, outzsize;
00321 
00322                 idxoff = cacheBufIdx * 12;
00323                 size = outsize = zsize = outzsize = strlen(cacheBuf);
00324                 if (size) {
00325 //                      if (compressor) {
00326 //                              delete compressor;
00327 //                              compressor = new LZSSCompress();
00328 //                      }
00329                         compressor->Buf(cacheBuf);
00330                         compressor->zBuf(&zsize);
00331                         outzsize = zsize;
00332 
00333                         start = outstart = lseek(textfp[cacheTestament-1]->getFd(), 0, SEEK_END);
00334 
00335                         outstart  = archtosword32(start);
00336                         outsize   = archtosword32(size);
00337                         outzsize  = archtosword32(zsize);
00338 
00339                         write(textfp[cacheTestament-1]->getFd(), compressor->zBuf(&zsize), zsize);
00340 
00341                         lseek(idxfp[cacheTestament-1]->getFd(), idxoff, SEEK_SET);
00342                         write(idxfp[cacheTestament-1]->getFd(), &outstart, 4);
00343                         write(idxfp[cacheTestament-1]->getFd(), &outzsize, 4);
00344                         write(idxfp[cacheTestament-1]->getFd(), &outsize, 4);
00345                 }
00346                 dirtyCache = false;
00347         }
00348 }
00349 
00350 /******************************************************************************
00351  * RawVerse::linkentry  - links one entry to another
00352  *
00353  * ENT: testmt  - testament to find (0 - Bible/module introduction)
00354  *      destidxoff      - dest offset into .vss
00355  *      srcidxoff               - source offset into .vss
00356  */
00357 
00358 void zVerse::linkentry(char testmt, long destidxoff, long srcidxoff) {
00359         long bufidx;
00360         long start;
00361         unsigned short size;
00362 
00363         destidxoff *= 10;
00364         srcidxoff  *= 10;
00365 
00366         if (!testmt)
00367                 testmt = ((idxfp[1]) ? 1:2);
00368 
00369         // get source
00370         lseek(compfp[testmt-1]->getFd(), srcidxoff, SEEK_SET);
00371         read(compfp[testmt-1]->getFd(), &bufidx, 4);
00372         read(compfp[testmt-1]->getFd(), &start, 4);
00373         read(compfp[testmt-1]->getFd(), &size, 2);
00374 
00375         // write dest
00376         lseek(compfp[testmt-1]->getFd(), destidxoff, SEEK_SET);
00377         write(compfp[testmt-1]->getFd(), &bufidx, 4);
00378         write(compfp[testmt-1]->getFd(), &start, 4);
00379         write(compfp[testmt-1]->getFd(), &size, 2);
00380 }
00381 
00382 
00383 /******************************************************************************
00384  * RawVerse::CreateModule       - Creates new module files
00385  *
00386  * ENT: path    - directory to store module files
00387  * RET: error status
00388  */
00389 
00390 char zVerse::createModule(const char *ipath, int blockBound)
00391 {
00392         char *path = 0;
00393         char *buf = new char [ strlen (ipath) + 20 ];
00394         FileDesc *fd, *fd2;
00395 
00396         stdstr(&path, ipath);
00397 
00398         if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
00399                 path[strlen(path)-1] = 0;
00400 
00401         sprintf(buf, "%s/ot.%czs", path, uniqueIndexID[blockBound]);
00402         unlink(buf);
00403         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00404         fd->getFd();
00405         FileMgr::systemFileMgr.close(fd);
00406 
00407         sprintf(buf, "%s/nt.%czs", path, uniqueIndexID[blockBound]);
00408         unlink(buf);
00409         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00410         fd->getFd();
00411         FileMgr::systemFileMgr.close(fd);
00412 
00413         sprintf(buf, "%s/ot.%czz", path, uniqueIndexID[blockBound]);
00414         unlink(buf);
00415         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00416         fd->getFd();
00417         FileMgr::systemFileMgr.close(fd);
00418 
00419         sprintf(buf, "%s/nt.%czz", path, uniqueIndexID[blockBound]);
00420         unlink(buf);
00421         fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00422         fd2->getFd();
00423         FileMgr::systemFileMgr.close(fd);
00424 
00425         sprintf(buf, "%s/ot.%czv", path, uniqueIndexID[blockBound]);
00426         unlink(buf);
00427         fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00428         fd->getFd();
00429 
00430         sprintf(buf, "%s/nt.%czv", path, uniqueIndexID[blockBound]);
00431         unlink(buf);
00432         fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00433         fd2->getFd();
00434 
00435         VerseKey vk;
00436         vk.Headings(1);
00437         long offset = 0;
00438         short size = 0;
00439         for (vk = TOP; !vk.Error(); vk++) {
00440                 write((vk.Testament() == 1) ? fd->getFd() : fd2->getFd(), &offset, 4);  //compBufIdxOffset
00441                 write((vk.Testament() == 1) ? fd->getFd() : fd2->getFd(), &offset, 4);
00442                 write((vk.Testament() == 1) ? fd->getFd() : fd2->getFd(), &size, 2);
00443         }
00444 
00445         FileMgr::systemFileMgr.close(fd);
00446         FileMgr::systemFileMgr.close(fd2);
00447 
00448         delete [] path;
00449 /*
00450         RawVerse rv(path);
00451         VerseKey mykey("Rev 22:21");
00452 */
00453         
00454         return 0;
00455 }
00456 
00457 
00458 /******************************************************************************
00459  * zVerse::preptext     - Prepares the text before returning it to external
00460  *                              objects
00461  *
00462  * ENT: buf     - buffer where text is stored and where to store the prep'd
00463  *                      text.
00464  */
00465 
00466 void zVerse::preptext(char *buf)
00467 {
00468         char *to, *from, space = 0, cr = 0, realdata = 0, nlcnt = 0;
00469 
00470         for (to = from = buf; *from; from++) {
00471                 switch (*from) {
00472                 case 10:
00473                         if (!realdata)
00474                                 continue;
00475                         space = (cr) ? 0 : 1;
00476                         cr = 0;
00477                         nlcnt++;
00478                         if (nlcnt > 1) {
00479 //                              *to++ = nl;
00480                                 *to++ = nl;
00481 //                              nlcnt = 0;
00482                         }
00483                         continue;
00484                 case 13:
00485                         if (!realdata)
00486                                 continue;
00487                         *to++ = nl;
00488                         space = 0;
00489                         cr = 1;
00490                         continue;
00491                 }
00492                 realdata = 1;
00493                 nlcnt = 0;
00494                 if (space) {
00495                         space = 0;
00496                         if (*from != ' ') {
00497                                 *to++ = ' ';
00498                                 from--;
00499                                 continue;
00500                         }
00501                 }
00502                 *to++ = *from;
00503         }
00504         *to = 0;
00505 
00506      if (to > buf) {
00507           for (to--; to > buf; to--) {                  // remove trailing excess
00508                if ((*to == 10) || (*to == ' '))
00509                     *to = 0;
00510                else break;
00511           }
00512      }
00513 }

Generated on Wed Apr 3 22:34:16 2002 for The Sword Project by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002