00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <fcntl.h>
00009 #include <errno.h>
00010
00011 #ifndef __GNUC__
00012 #include <io.h>
00013 #else
00014 #include <unistd.h>
00015 #endif
00016
00017 #include <string.h>
00018 #include <stdlib.h>
00019 #include <utilfuns.h>
00020 #include <zstr.h>
00021 #include <swcomprs.h>
00022
00023 #include <sysdata.h>
00024 #include <entriesblk.h>
00025
00026
00027
00028
00029
00030 int zStr::instance = 0;
00031 const int zStr::IDXENTRYSIZE = 8;
00032 const int zStr::ZDXENTRYSIZE = 8;
00033
00034
00035
00036
00037
00038
00039
00040
00041 zStr::zStr(const char *ipath, int fileMode, long blockCount, SWCompress *icomp) {
00042 char buf[127];
00043
00044 nl = '\n';
00045 lastoff = -1;
00046 path = 0;
00047 stdstr(&path, ipath);
00048
00049 compressor = (icomp) ? icomp : new SWCompress();
00050 this->blockCount = blockCount;
00051 #ifndef O_BINARY // O_BINARY is needed in Borland C++ 4.53
00052 #define O_BINARY 0 // If it hasn't been defined than we probably
00053 #endif // don't need it.
00054
00055 if (fileMode == -1) {
00056 fileMode = O_RDWR;
00057 }
00058
00059 sprintf(buf, "%s.idx", path);
00060 idxfd = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00061
00062 sprintf(buf, "%s.dat", path);
00063 datfd = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00064
00065 sprintf(buf, "%s.zdx", path);
00066 zdxfd = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00067
00068 sprintf(buf, "%s.zdt", path);
00069 zdtfd = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00070
00071 if (datfd <= 0) {
00072 sprintf(buf, "Error: %d", errno);
00073 perror(buf);
00074 }
00075
00076 cacheBlock = 0;
00077 cacheBlockIndex = -1;
00078 cacheDirty = false;
00079
00080 instance++;
00081 }
00082
00083
00084
00085
00086
00087
00088 zStr::~zStr() {
00089
00090 flushCache();
00091
00092 if (path)
00093 delete [] path;
00094
00095 --instance;
00096
00097 FileMgr::systemFileMgr.close(idxfd);
00098 FileMgr::systemFileMgr.close(datfd);
00099 FileMgr::systemFileMgr.close(zdxfd);
00100 FileMgr::systemFileMgr.close(zdtfd);
00101
00102
00103 if (compressor)
00104 delete compressor;
00105
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 void zStr::getKeyFromDatOffset(long ioffset, char **buf) {
00119 int size;
00120 char ch;
00121 if (datfd > 0) {
00122 lseek(datfd->getFd(), ioffset, SEEK_SET);
00123 for (size = 0; read(datfd->getFd(), &ch, 1) == 1; size++) {
00124 if ((ch == '\\') || (ch == 10) || (ch == 13))
00125 break;
00126 }
00127 *buf = (*buf) ? (char *)realloc(*buf, size + 1) : (char *)malloc(size + 1);
00128 if (size) {
00129 lseek(datfd->getFd(), ioffset, SEEK_SET);
00130 read(datfd->getFd(), *buf, size);
00131 }
00132 (*buf)[size] = 0;
00133 for (size--; size > 0; size--)
00134 (*buf)[size] = SW_toupper((*buf)[size]);
00135 }
00136 else {
00137 *buf = (*buf) ? (char *)realloc(*buf, 1) : (char *)malloc(1);
00138 **buf = 0;
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 void zStr::getKeyFromIdxOffset(long ioffset, char **buf) {
00153 __u32 offset;
00154
00155 if (idxfd > 0) {
00156 lseek(idxfd->getFd(), ioffset, SEEK_SET);
00157 read(idxfd->getFd(), &offset, sizeof(__u32));
00158 offset = swordtoarch32(offset);
00159 getKeyFromDatOffset(offset, buf);
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) {
00177 char *trybuf = 0, *key = 0, quitflag = 0;
00178 signed char retval = 0;
00179 __s32 headoff, tailoff, tryoff = 0, maxoff = 0;
00180 __u32 start, size;
00181
00182 if (idxfd->getFd() >= 0) {
00183 tailoff = maxoff = lseek(idxfd->getFd(), 0, SEEK_END) - IDXENTRYSIZE;
00184 if (*ikey) {
00185 headoff = 0;
00186 stdstr(&key, ikey);
00187 toupperstr(key);
00188
00189 while (headoff < tailoff) {
00190 tryoff = (lastoff == -1) ? headoff + (((((tailoff / IDXENTRYSIZE) - (headoff / IDXENTRYSIZE))) / 2) * IDXENTRYSIZE) : lastoff;
00191 lastoff = -1;
00192
00193 getKeyFromIdxOffset(tryoff, &trybuf);
00194
00195 if (!*trybuf && tryoff) {
00196 tryoff += (tryoff > (maxoff / 2))?-IDXENTRYSIZE:IDXENTRYSIZE;
00197 retval = -1;
00198 break;
00199 }
00200
00201 int diff = strcmp(key, trybuf);
00202 if (!diff)
00203 break;
00204
00205 if (diff < 0)
00206 tailoff = (tryoff == headoff) ? headoff : tryoff;
00207 else headoff = tryoff;
00208 if (tailoff == headoff + IDXENTRYSIZE) {
00209 if (quitflag++)
00210 headoff = tailoff;
00211 }
00212 }
00213 if (headoff >= tailoff)
00214 tryoff = headoff;
00215 if (trybuf)
00216 free(trybuf);
00217 delete [] key;
00218 }
00219 else { tryoff = 0; }
00220
00221 lseek(idxfd->getFd(), tryoff, SEEK_SET);
00222
00223 start = size = 0;
00224 retval = (read(idxfd->getFd(), &start, sizeof(__u32))==sizeof(__u32)) ? retval : -1;
00225 retval = (read(idxfd->getFd(), &size, sizeof(__u32))==sizeof(__u32)) ? retval : -1;
00226 start = swordtoarch32(start);
00227 size = swordtoarch32(size);
00228
00229 if (idxoff)
00230 *idxoff = tryoff;
00231
00232 while (away) {
00233 __u32 laststart = start;
00234 __u32 lastsize = size;
00235 __s32 lasttry = tryoff;
00236 tryoff += (away > 0) ? IDXENTRYSIZE : -IDXENTRYSIZE;
00237
00238 bool bad = false;
00239 if (((long)(tryoff + (away*IDXENTRYSIZE)) < -IDXENTRYSIZE) || (tryoff + (away*IDXENTRYSIZE) > (maxoff+IDXENTRYSIZE)))
00240 bad = true;
00241 else if (lseek(idxfd->getFd(), tryoff, SEEK_SET) < 0)
00242 bad = true;
00243 if (bad) {
00244 retval = -1;
00245 start = laststart;
00246 size = lastsize;
00247 tryoff = lasttry;
00248 if (idxoff)
00249 *idxoff = tryoff;
00250 break;
00251 }
00252 read(idxfd->getFd(), &start, sizeof(__u32));
00253 read(idxfd->getFd(), &size, sizeof(__u32));
00254 start = swordtoarch32(start);
00255 size = swordtoarch32(size);
00256
00257 if (idxoff)
00258 *idxoff = tryoff;
00259
00260
00261 if (((laststart != start) || (lastsize != size)) && (start >= 0) && (size))
00262 away += (away < 0) ? 1 : -1;
00263 }
00264
00265 lastoff = tryoff;
00266 }
00267 else {
00268 if (idxoff)
00269 *idxoff = 0;
00270 retval = -1;
00271 }
00272 return retval;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 void zStr::prepText(char *buf) {
00285 char *to, *from, space = 0, cr = 0, realdata = 0, nlcnt = 0;
00286
00287 for (to = from = buf; *from; from++) {
00288 switch (*from) {
00289 case 10:
00290 if (!realdata)
00291 continue;
00292 space = (cr) ? 0 : 1;
00293 cr = 0;
00294 nlcnt++;
00295 if (nlcnt > 1) {
00296
00297 *to++ = nl;
00298
00299 }
00300 continue;
00301 case 13:
00302 if (!realdata)
00303 continue;
00304 *to++ = nl;
00305 space = 0;
00306 cr = 1;
00307 continue;
00308 }
00309 realdata = 1;
00310 nlcnt = 0;
00311 if (space) {
00312 space = 0;
00313 if (*from != ' ') {
00314 *to++ = ' ';
00315 from--;
00316 continue;
00317 }
00318 }
00319 *to++ = *from;
00320 }
00321 *to = 0;
00322
00323 while (to > (buf+1)) {
00324 to--;
00325 if ((*to == 10) || (*to == ' '))
00326 *to = 0;
00327 else break;
00328 }
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 void zStr::getText(long offset, char **idxbuf, char **buf) {
00345 char *ch;
00346 char *idxbuflocal = 0;
00347 getKeyFromIdxOffset(offset, &idxbuflocal);
00348 __u32 start;
00349 __u32 size;
00350
00351 do {
00352 lseek(idxfd->getFd(), offset, SEEK_SET);
00353 read(idxfd->getFd(), &start, sizeof(__u32));
00354 read(idxfd->getFd(), &size, sizeof(__u32));
00355 start = swordtoarch32(start);
00356 size = swordtoarch32(size);
00357
00358 *buf = (*buf) ? (char *)realloc(*buf, size + 1) : (char *)malloc(size + 1);
00359 *idxbuf = (*idxbuf) ? (char *)realloc(*idxbuf, size + 1) : (char *)malloc(size + 1);
00360 memset(*buf, 0, size + 1);
00361 memset(*idxbuf, 0, size + 1);
00362 lseek(datfd->getFd(), start, SEEK_SET);
00363 read(datfd->getFd(), *buf, (int)(size));
00364
00365 for (ch = *buf; *ch; ch++) {
00366 if (*ch == 10) {
00367 ch++;
00368 break;
00369 }
00370 }
00371 memmove(*buf, ch, size - (unsigned long)(ch-*buf));
00372
00373
00374 if (!strncmp(*buf, "@LINK", 5)) {
00375 for (ch = *buf; *ch; ch++) {
00376 if (*ch == 10) {
00377 *ch = 0;
00378 break;
00379 }
00380 }
00381 findKeyIndex(*buf + IDXENTRYSIZE, &offset);
00382 }
00383 else break;
00384 }
00385 while (true);
00386
00387 if (idxbuflocal) {
00388 __u32 localsize = strlen(idxbuflocal);
00389 localsize = (localsize < (size - 1)) ? localsize : (size - 1);
00390 strncpy(*idxbuf, idxbuflocal, localsize);
00391 (*idxbuf)[localsize] = 0;
00392 free(idxbuflocal);
00393 }
00394 __u32 block = 0;
00395 __u32 entry = 0;
00396 memmove(&block, *buf, sizeof(__u32));
00397 memmove(&entry, *buf + sizeof(__u32), sizeof(__u32));
00398 block = swordtoarch32(block);
00399 entry = swordtoarch32(entry);
00400 getCompressedText(block, entry, buf);
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 void zStr::getCompressedText(long block, long entry, char **buf) {
00410
00411 __u32 size = 0;
00412
00413 if (cacheBlockIndex != block) {
00414 __u32 start = 0;
00415
00416 lseek(zdxfd->getFd(), block * ZDXENTRYSIZE, SEEK_SET);
00417 read(zdxfd->getFd(), &start, sizeof(__u32));
00418 read(zdxfd->getFd(), &size, sizeof(__u32));
00419 start = swordtoarch32(start);
00420 size = swordtoarch32(size);
00421
00422 *buf = (*buf) ? (char *)realloc(*buf, size + 1) : (char *)malloc(size + 1);
00423
00424 lseek(zdtfd->getFd(), start, SEEK_SET);
00425 read(zdtfd->getFd(), *buf, size);
00426
00427 flushCache();
00428
00429 unsigned long len = size;
00430 compressor->zBuf(&len, *buf);
00431 char * rawBuf = compressor->Buf(0, &len);
00432 cacheBlock = new EntriesBlock(rawBuf, len);
00433 cacheBlockIndex = block;
00434 }
00435 size = cacheBlock->getEntrySize(entry);
00436 *buf = (*buf) ? (char *)realloc(*buf, size + 1) : (char *)malloc(size + 1);
00437 strcpy(*buf, cacheBlock->getEntry(entry));
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 void zStr::setText(const char *ikey, const char *buf, long len) {
00450
00451 __u32 start, outstart;
00452 __u32 size, outsize;
00453 __s32 endoff;
00454 long idxoff = 0;
00455 __s32 shiftSize;
00456 static const char nl[] = {13, 10};
00457 char *tmpbuf = 0;
00458 char *key = 0;
00459 char *dbKey = 0;
00460 char *idxBytes = 0;
00461 char *outbuf = 0;
00462 char *ch = 0;
00463
00464 stdstr(&key, ikey);
00465 toupperstr(key);
00466
00467 char notFound = findKeyIndex(ikey, &idxoff, 0);
00468 if (!notFound) {
00469 getKeyFromIdxOffset(idxoff, &dbKey);
00470 int diff = strcmp(key, dbKey);
00471 if (diff < 0) {
00472 }
00473 else if (diff > 0) {
00474 idxoff += IDXENTRYSIZE;
00475 }
00476 else if ((!diff) && (len || strlen(buf) )) {
00477 do {
00478 lseek(idxfd->getFd(), idxoff, SEEK_SET);
00479 read(idxfd->getFd(), &start, sizeof(__u32));
00480 read(idxfd->getFd(), &size, sizeof(__u32));
00481 start = swordtoarch32(start);
00482 size = swordtoarch32(size);
00483
00484 tmpbuf = new char [ size + 2 ];
00485 memset(tmpbuf, 0, size + 2);
00486 lseek(datfd->getFd(), start, SEEK_SET);
00487 read(datfd->getFd(), tmpbuf, size);
00488
00489 for (ch = tmpbuf; *ch; ch++) {
00490 if (*ch == 10) {
00491 ch++;
00492 break;
00493 }
00494 }
00495 memmove(tmpbuf, ch, size - (unsigned long)(ch-tmpbuf));
00496
00497
00498 if (!strncmp(tmpbuf, "@LINK", 5) && (len ? len : strlen(buf))) {
00499 for (ch = tmpbuf; *ch; ch++) {
00500 if (*ch == 10) {
00501 *ch = 0;
00502 break;
00503 }
00504 }
00505 findKeyIndex(tmpbuf + IDXENTRYSIZE, &idxoff);
00506 delete [] tmpbuf;
00507 }
00508 else break;
00509 }
00510 while (true);
00511 }
00512 }
00513
00514 endoff = lseek(idxfd->getFd(), 0, SEEK_END);
00515
00516 shiftSize = endoff - idxoff;
00517
00518 if (shiftSize > 0) {
00519 idxBytes = new char [ shiftSize ];
00520 lseek(idxfd->getFd(), idxoff, SEEK_SET);
00521 read(idxfd->getFd(), idxBytes, shiftSize);
00522 }
00523
00524 outbuf = new char [ (len ? len : strlen(buf)) + strlen(key) + 5 ];
00525 sprintf(outbuf, "%s%c%c", key, 13, 10);
00526 size = strlen(outbuf);
00527 if (len ? len : strlen(buf)) {
00528 if (!cacheBlock) {
00529 flushCache();
00530 cacheBlock = new EntriesBlock();
00531 cacheBlockIndex = (lseek(zdxfd->getFd(), 0, SEEK_END) / ZDXENTRYSIZE);
00532 }
00533 else if (cacheBlock->getCount() >= blockCount) {
00534 flushCache();
00535 cacheBlock = new EntriesBlock();
00536 cacheBlockIndex = (lseek(zdxfd->getFd(), 0, SEEK_END) / ZDXENTRYSIZE);
00537 }
00538 __u32 entry = cacheBlock->addEntry(buf);
00539 cacheDirty = true;
00540 outstart = archtosword32(cacheBlockIndex);
00541 outsize = archtosword32(entry);
00542 memcpy (outbuf + size, &outstart, sizeof(__u32));
00543 memcpy (outbuf + size + sizeof(__u32), &outsize, sizeof(__u32));
00544 size += (sizeof(__u32) * 2);
00545 }
00546 else {
00547 memcpy(outbuf + size, buf, len ? len : strlen(buf));
00548 size += (len ? len : strlen(buf));
00549 }
00550
00551 start = lseek(datfd->getFd(), 0, SEEK_END);
00552
00553 outstart = archtosword32(start);
00554 outsize = archtosword32(size);
00555
00556 lseek(idxfd->getFd(), idxoff, SEEK_SET);
00557 if (len ? len : strlen(buf)) {
00558 lseek(datfd->getFd(), start, SEEK_SET);
00559 write(datfd->getFd(), outbuf, size);
00560
00561
00562 write(datfd->getFd(), &nl, 2);
00563
00564 write(idxfd->getFd(), &outstart, sizeof(__u32));
00565 write(idxfd->getFd(), &outsize, sizeof(__u32));
00566 if (idxBytes) {
00567 write(idxfd->getFd(), idxBytes, shiftSize);
00568 }
00569 }
00570 else {
00571 if (idxBytes) {
00572 write(idxfd->getFd(), idxBytes+IDXENTRYSIZE, shiftSize-IDXENTRYSIZE);
00573 lseek(idxfd->getFd(), -1, SEEK_CUR);
00574 FileMgr::systemFileMgr.trunc(idxfd);
00575 }
00576 }
00577
00578 if (idxBytes)
00579 delete [] idxBytes;
00580 delete [] key;
00581 delete [] outbuf;
00582 free(dbKey);
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 void zStr::linkEntry(const char *destkey, const char *srckey) {
00595 char *text = new char [ strlen(destkey) + 7 ];
00596 sprintf(text, "@LINK %s", destkey);
00597 setText(srckey, text);
00598 delete [] text;
00599 }
00600
00601
00602 void zStr::flushCache() {
00603 if (cacheBlock) {
00604 if (cacheDirty) {
00605 __u32 start = 0;
00606 unsigned long size = 0;
00607 __u32 outstart = 0, outsize = 0;
00608
00609 const char *rawBuf = cacheBlock->getRawData(&size);
00610 compressor->Buf(rawBuf, &size);
00611 compressor->zBuf(&size);
00612
00613 long zdxSize = lseek(zdxfd->getFd(), 0, SEEK_END);
00614 long zdtSize = lseek(zdtfd->getFd(), 0, SEEK_END);
00615
00616 if ((cacheBlockIndex * ZDXENTRYSIZE) > (zdxSize - ZDXENTRYSIZE)) {
00617 start = zdtSize;
00618 }
00619 else {
00620 lseek(zdxfd->getFd(), cacheBlockIndex * ZDXENTRYSIZE, SEEK_SET);
00621 read(zdxfd->getFd(), &start, sizeof(__u32));
00622 read(zdxfd->getFd(), &outsize, sizeof(__u32));
00623 start = swordtoarch32(start);
00624 outsize = swordtoarch32(outsize);
00625 if (start + outsize >= zdtSize) {
00626
00627 }
00628 else if (size < outsize) {
00629 size = outsize;
00630 }
00631 else {
00632 start = zdtSize;
00633 }
00634 }
00635
00636
00637
00638 outstart = archtosword32(start);
00639 outsize = archtosword32((__u32)size);
00640
00641 lseek(zdxfd->getFd(), cacheBlockIndex * ZDXENTRYSIZE, SEEK_SET);
00642 lseek(zdtfd->getFd(), start, SEEK_SET);
00643 rawBuf = compressor->zBuf(&size);
00644 write(zdtfd->getFd(), rawBuf, size);
00645
00646
00647 write(zdtfd->getFd(), &nl, 2);
00648
00649 write(zdxfd->getFd(), &outstart, sizeof(__u32));
00650 write(zdxfd->getFd(), &outsize, sizeof(__u32));
00651
00652 delete cacheBlock;
00653 }
00654 }
00655 cacheBlockIndex = -1;
00656 cacheBlock = 0;
00657 cacheDirty = false;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 signed char zStr::createModule(const char *ipath) {
00669 char *path = 0;
00670 char *buf = new char [ strlen (ipath) + 20 ];
00671 FileDesc *fd, *fd2;
00672
00673 stdstr(&path, ipath);
00674
00675 if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
00676 path[strlen(path)-1] = 0;
00677
00678 sprintf(buf, "%s.dat", path);
00679 unlink(buf);
00680 fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00681 fd->getFd();
00682 FileMgr::systemFileMgr.close(fd);
00683
00684 sprintf(buf, "%s.idx", path);
00685 unlink(buf);
00686 fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00687 fd2->getFd();
00688 FileMgr::systemFileMgr.close(fd2);
00689
00690 sprintf(buf, "%s.zdt", path);
00691 unlink(buf);
00692 fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00693 fd2->getFd();
00694 FileMgr::systemFileMgr.close(fd2);
00695
00696 sprintf(buf, "%s.zdx", path);
00697 unlink(buf);
00698 fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00699 fd2->getFd();
00700 FileMgr::systemFileMgr.close(fd2);
00701
00702 delete [] path;
00703
00704 return 0;
00705 }