00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <treekeyidx.h>
00024 #include <fcntl.h>
00025 #include <stdio.h>
00026 #include <errno.h>
00027 #include <string>
00028
00029 #ifndef __GNUC__
00030 #include <io.h>
00031 #else
00032 #include <unistd.h>
00033 #endif
00034
00035 using namespace std;
00036 static const char nl = '\n';
00037 static const char *classes[] = {"TreeKeyIdx", "TreeKey", "SWKey", "SWObject", 0};
00038 SWClass TreeKeyIdx::classdef(classes);
00039
00040
00041 TreeKeyIdx::TreeKeyIdx(const TreeKeyIdx &ikey) : currentNode() {
00042 init();
00043 path = 0;
00044 idxfd = 0;
00045 datfd = 0;
00046 copyFrom(ikey);
00047 }
00048
00049 TreeKeyIdx::TreeKeyIdx(const char *idxPath, int fileMode) : currentNode() {
00050 char buf[127];
00051
00052 init();
00053 path = 0;
00054 stdstr(&path, idxPath);
00055
00056 #ifndef O_BINARY // O_BINARY is needed in Borland C++ 4.53
00057 #define O_BINARY 0 // If it hasn't been defined than we probably
00058 #endif // don't need it.
00059
00060 if (fileMode == -1) {
00061 fileMode = O_RDWR;
00062 }
00063
00064 sprintf(buf, "%s.idx", path);
00065 idxfd = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00066 sprintf(buf, "%s.dat", path);
00067 datfd = FileMgr::systemFileMgr.open(buf, fileMode|O_BINARY, true);
00068
00069 if (datfd <= 0) {
00070 sprintf(buf, "Error: %d", errno);
00071 perror(buf);
00072 error = errno;
00073 }
00074 else {
00075 root();
00076 }
00077 }
00078
00079
00080 void TreeKeyIdx::init() {
00081 myclass = &classdef;
00082 }
00083
00084
00085 TreeKeyIdx::~TreeKeyIdx () {
00086 if (path)
00087 delete [] path;
00088
00089 FileMgr::systemFileMgr.close(idxfd);
00090 FileMgr::systemFileMgr.close(datfd);
00091 }
00092
00093
00094 const char *TreeKeyIdx::getLocalName() {
00095 return currentNode.name;
00096 }
00097
00098
00099 const char *TreeKeyIdx::getUserData(int *size) {
00100 if (size)
00101 *size = (int)currentNode.dsize;
00102 return currentNode.userData;
00103 }
00104
00105
00106 void TreeKeyIdx::setUserData(const char *userData, int size) {
00107 if (currentNode.userData)
00108 delete currentNode.userData;
00109
00110 if (!size)
00111 size = strlen(userData) + 1;
00112
00113 currentNode.userData = new char [ size ];
00114 memcpy(currentNode.userData, userData, size);
00115 currentNode.dsize = size;
00116 }
00117
00118 const char *TreeKeyIdx::setLocalName(const char *newName) {
00119 stdstr(&(currentNode.name), newName);
00120 return currentNode.name;
00121 }
00122
00123
00124 void TreeKeyIdx::save() {
00125 saveTreeNode(¤tNode);
00126 }
00127
00128
00129 const char *TreeKeyIdx::getFullName() const {
00130 TreeNode parent;
00131 static string fullPath;
00132 fullPath = currentNode.name;
00133 parent.parent = currentNode.parent;
00134 while (parent.parent > -1) {
00135 getTreeNodeFromIdxOffset(parent.parent, &parent);
00136 fullPath = ((string)parent.name) + (string) "/" + fullPath;
00137 }
00138 return fullPath.c_str();
00139 }
00140
00141
00142 void TreeKeyIdx::root() {
00143 error = getTreeNodeFromIdxOffset(0, ¤tNode);
00144 }
00145
00146
00147 bool TreeKeyIdx::parent() {
00148 if (currentNode.parent > -1) {
00149 error = getTreeNodeFromIdxOffset(currentNode.parent, ¤tNode);
00150 return true;
00151 }
00152 return false;
00153 }
00154
00155
00156 bool TreeKeyIdx::firstChild() {
00157 if (currentNode.firstChild > -1) {
00158 error = getTreeNodeFromIdxOffset(currentNode.firstChild, ¤tNode);
00159 return true;
00160 }
00161 return false;
00162 }
00163
00164
00165 bool TreeKeyIdx::nextSibling() {
00166 if (currentNode.next > -1) {
00167 error = getTreeNodeFromIdxOffset(currentNode.next, ¤tNode);
00168 return true;
00169 }
00170 return false;
00171 }
00172
00173
00174 bool TreeKeyIdx::previousSibling() {
00175 TreeNode iterator;
00176 __u32 target = currentNode.offset;
00177 if (currentNode.parent > -1) {
00178 getTreeNodeFromIdxOffset(currentNode.parent, &iterator);
00179 getTreeNodeFromIdxOffset(iterator.firstChild, &iterator);
00180 if (iterator.offset != target) {
00181 while ((iterator.next != target) && (iterator.next > -1))
00182 getTreeNodeFromIdxOffset(iterator.next, &iterator);
00183 if (iterator.next > -1) {
00184 error = getTreeNodeFromIdxOffset(iterator.offset, ¤tNode);
00185 return true;
00186 }
00187 }
00188 }
00189 return false;
00190 }
00191
00192
00193 bool TreeKeyIdx::hasChildren() {
00194 return (currentNode.firstChild > -1);
00195 }
00196
00197
00198 void TreeKeyIdx::append() {
00199 TreeNode lastSib;
00200 if (currentNode.offset) {
00201 getTreeNodeFromIdxOffset(currentNode.offset, &lastSib);
00202 while (lastSib.next > -1) {
00203 getTreeNodeFromIdxOffset(lastSib.next, &lastSib);
00204 }
00205 __u32 idxOffset = lseek(idxfd->getFd(), 0, SEEK_END);
00206 lastSib.next = idxOffset;
00207 saveTreeNodeOffsets(&lastSib);
00208 __u32 parent = currentNode.parent;
00209 currentNode.clear();
00210 currentNode.offset = idxOffset;
00211 currentNode.parent = parent;
00212 }
00213 }
00214
00215
00216 void TreeKeyIdx::appendChild() {
00217 if (firstChild()) {
00218 append();
00219 }
00220 else {
00221 __u32 idxOffset = lseek(idxfd->getFd(), 0, SEEK_END);
00222 currentNode.firstChild = idxOffset;
00223 saveTreeNodeOffsets(¤tNode);
00224 __u32 parent = currentNode.offset;
00225 currentNode.clear();
00226 currentNode.offset = idxOffset;
00227 currentNode.parent = parent;
00228 }
00229 }
00230
00231
00232 void TreeKeyIdx::insertBefore() {
00233 }
00234
00235
00236 void TreeKeyIdx::remove() {
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 signed char TreeKeyIdx::create(const char *ipath) {
00248 char *path = 0;
00249 char *buf = new char [ strlen (ipath) + 20 ];
00250 FileDesc *fd, *fd2;
00251
00252 stdstr(&path, ipath);
00253
00254 if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
00255 path[strlen(path)-1] = 0;
00256
00257 sprintf(buf, "%s.dat", path);
00258 unlink(buf);
00259 fd = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00260 fd->getFd();
00261 FileMgr::systemFileMgr.close(fd);
00262
00263 sprintf(buf, "%s.idx", path);
00264 unlink(buf);
00265 fd2 = FileMgr::systemFileMgr.open(buf, O_CREAT|O_WRONLY|O_BINARY, S_IREAD|S_IWRITE);
00266 fd2->getFd();
00267 FileMgr::systemFileMgr.close(fd2);
00268
00269 TreeKeyIdx newTree(path);
00270 TreeKeyIdx::TreeNode root;
00271 stdstr(&(root.name), "");
00272 newTree.saveTreeNode(&root);
00273
00274 delete [] path;
00275
00276 return 0;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 void TreeKeyIdx::getTreeNodeFromDatOffset(long ioffset, TreeNode *node) const {
00290 char ch;
00291 __s32 tmp;
00292 __u16 tmp2;
00293
00294 if (datfd > 0) {
00295
00296 lseek(datfd->getFd(), ioffset, SEEK_SET);
00297
00298 read(datfd->getFd(), &tmp, 4);
00299 node->parent = swordtoarch32(tmp);
00300
00301 read(datfd->getFd(), &tmp, 4);
00302 node->next = swordtoarch32(tmp);
00303
00304 read(datfd->getFd(), &tmp, 4);
00305 node->firstChild = swordtoarch32(tmp);
00306
00307 string name;
00308 do {
00309 read(datfd->getFd(), &ch, 1);
00310 name += ch;
00311 } while (ch);
00312
00313 stdstr(&(node->name), name.c_str());
00314
00315 read(datfd->getFd(), &tmp2, 2);
00316 node->dsize = swordtoarch16(tmp2);
00317
00318 if (node->dsize) {
00319 if (node->userData)
00320 delete [] node->userData;
00321 node->userData = new char [node->dsize];
00322 read(datfd->getFd(), node->userData, node->dsize);
00323 }
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 char TreeKeyIdx::getTreeNodeFromIdxOffset(long ioffset, TreeNode *node) const {
00338 __u32 offset;
00339 char error = 0;
00340
00341 if (ioffset < 0) {
00342 ioffset = 0;
00343 error = KEYERR_OUTOFBOUNDS;
00344 }
00345
00346 node->offset = ioffset;
00347 if (idxfd > 0) {
00348 lseek(idxfd->getFd(), ioffset, SEEK_SET);
00349 if (read(idxfd->getFd(), &offset, 4) == 4) {
00350 offset = swordtoarch32(offset);
00351 getTreeNodeFromDatOffset(offset, node);
00352 }
00353 else {
00354 lseek(idxfd->getFd(), -4, SEEK_END);
00355 if (read(idxfd->getFd(), &offset, 4) == 4) {
00356 offset = swordtoarch32(offset);
00357 getTreeNodeFromDatOffset(offset, node);
00358 }
00359 error = KEYERR_OUTOFBOUNDS;
00360 }
00361 }
00362 return error;
00363 }
00364
00365
00366 unsigned long TreeKeyIdx::getOffset() const {
00367 return currentNode.offset;
00368 }
00369
00370 void TreeKeyIdx::setOffset(unsigned long offset) {
00371 error = getTreeNodeFromIdxOffset(offset, ¤tNode);
00372 }
00373
00374
00375 void TreeKeyIdx::saveTreeNodeOffsets(TreeNode *node) {
00376 long datOffset = 0;
00377 __s32 tmp;
00378
00379 if (idxfd > 0) {
00380 lseek(idxfd->getFd(), node->offset, SEEK_SET);
00381 if (read(idxfd->getFd(), &tmp, 4) != 4) {
00382 datOffset = lseek(datfd->getFd(), 0, SEEK_END);
00383 tmp = archtosword32(datOffset);
00384 write(idxfd->getFd(), &tmp, 4);
00385 }
00386 else {
00387 datOffset = swordtoarch32(tmp);
00388 lseek(datfd->getFd(), datOffset, SEEK_SET);
00389 }
00390
00391 tmp = archtosword32(node->parent);
00392 write(datfd->getFd(), &tmp, 4);
00393
00394 tmp = archtosword32(node->next);
00395 write(datfd->getFd(), &tmp, 4);
00396
00397 tmp = archtosword32(node->firstChild);
00398 write(datfd->getFd(), &tmp, 4);
00399 }
00400 }
00401
00402
00403 void TreeKeyIdx::copyFrom(const TreeKeyIdx &ikey) {
00404
00405 SWKey::copyFrom(ikey);
00406
00407 currentNode.offset = ikey.currentNode.offset;
00408 currentNode.parent = ikey.currentNode.parent;
00409 currentNode.next = ikey.currentNode.next;
00410 currentNode.firstChild = ikey.currentNode.firstChild;
00411 stdstr(&(currentNode.name), ikey.currentNode.name);
00412 currentNode.dsize = ikey.currentNode.dsize;
00413
00414 if (currentNode.userData)
00415 delete [] currentNode.userData;
00416 if (currentNode.dsize) {
00417 currentNode.userData = new char [ currentNode.dsize ];
00418 memcpy(currentNode.userData, ikey.currentNode.userData, currentNode.dsize);
00419 }
00420 else currentNode.userData = 0;
00421
00422 bool newFiles = true;
00423
00424 if (path && ikey.path)
00425 newFiles = strcmp(path, ikey.path);
00426
00427 if (newFiles) {
00428 stdstr(&path, ikey.path);
00429
00430 if (idxfd) {
00431 FileMgr::systemFileMgr.close(idxfd);
00432 FileMgr::systemFileMgr.close(datfd);
00433 }
00434 idxfd = FileMgr::systemFileMgr.open(ikey.idxfd->path, ikey.idxfd->mode, ikey.idxfd->perms);
00435 datfd = FileMgr::systemFileMgr.open(ikey.datfd->path, ikey.datfd->mode, ikey.datfd->perms);
00436 }
00437 }
00438
00439
00440 void TreeKeyIdx::saveTreeNode(TreeNode *node) {
00441 long datOffset = 0;
00442 __s32 tmp;
00443 if (idxfd > 0) {
00444
00445 lseek(idxfd->getFd(), node->offset, SEEK_SET);
00446 datOffset = lseek(datfd->getFd(), 0, SEEK_END);
00447 tmp = archtosword32(datOffset);
00448 write(idxfd->getFd(), &tmp, 4);
00449
00450 saveTreeNodeOffsets(node);
00451
00452 write(datfd->getFd(), node->name, strlen(node->name));
00453 char null = 0;
00454 write(datfd->getFd(), &null, 1);
00455
00456 __u16 tmp2 = archtosword16(node->dsize);
00457 write(datfd->getFd(), &tmp2, 2);
00458
00459 if (node->dsize) {
00460 write(datfd->getFd(), node->userData, node->dsize);
00461 }
00462 }
00463 }
00464
00465
00466 void TreeKeyIdx::setText(const char *ikey) {
00467 char *buf = 0;
00468 stdstr(&buf, ikey);
00469 char *leaf = strtok(buf, "/");
00470 root();
00471 while ((leaf) && (!Error())) {
00472 bool ok, inChild = false;
00473 for (ok = firstChild(); ok; ok = nextSibling()) {
00474 inChild = true;
00475 if (!stricmp(leaf, getLocalName()))
00476 break;
00477 }
00478 leaf = strtok(0, "/");
00479 if (!ok) {
00480 if (inChild) {
00481 parent();
00482 firstChild();
00483 }
00484 if (leaf)
00485 error = KEYERR_OUTOFBOUNDS;
00486 break;
00487 }
00488 }
00489 delete [] buf;
00490 }
00491
00492
00493
00494 void TreeKeyIdx::copyFrom(const SWKey &ikey) {
00495 SWKey::copyFrom(ikey);
00496 }
00497
00498 void TreeKeyIdx::setPosition(SW_POSITION p) {
00499 switch (p) {
00500 case POS_TOP:
00501 root();
00502 break;
00503 case POS_BOTTOM:
00504 error = getTreeNodeFromIdxOffset(lseek(idxfd->getFd(), -4, SEEK_END), ¤tNode);
00505 break;
00506 }
00507 Error();
00508 }
00509
00510 const char *TreeKeyIdx::getText() const {
00511 return getFullName();
00512 }
00513
00514
00515 int TreeKeyIdx::_compare (const TreeKeyIdx & ikey) {
00516 return (getOffset() - ikey.getOffset());
00517 }
00518
00519
00520 int TreeKeyIdx::compare(const SWKey &ikey) {
00521 TreeKeyIdx *treeKey = SWDYNAMIC_CAST(TreeKeyIdx, (&ikey));
00522 if (treeKey)
00523 return _compare(*treeKey);
00524 return SWKey::compare(ikey);
00525 }
00526
00527
00528 void TreeKeyIdx::decrement(int steps) {
00529 error = getTreeNodeFromIdxOffset(currentNode.offset - (4*steps), ¤tNode);
00530 }
00531
00532 void TreeKeyIdx::increment(int steps) {
00533 error = getTreeNodeFromIdxOffset(currentNode.offset + (4*steps), ¤tNode);
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 }
00553
00554
00555
00556 TreeKeyIdx::TreeNode::TreeNode() {
00557
00558 name = 0;
00559 stdstr(&name, "");
00560 userData = 0;
00561
00562 clear();
00563 }
00564
00565
00566 void TreeKeyIdx::TreeNode::clear() {
00567 offset = 0;
00568 parent = -1;
00569 next = -1;
00570 firstChild = -1;
00571 dsize = 0;
00572
00573 if (name)
00574 delete [] name;
00575 name = 0;
00576 stdstr(&name, "");
00577
00578 if (userData)
00579 delete [] userData;
00580 userData = 0;
00581 }
00582
00583
00584 TreeKeyIdx::TreeNode::~TreeNode() {
00585 if (name)
00586 delete [] name;
00587
00588 if (userData)
00589 delete [] userData;
00590 }