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