#include <errno.h>
#include <string.h>
+#include <stdint.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/uio.h>
#define SFSTREE_VERSION 0x0100
-typedef unsigned long Opaque; /* XXX sizeof(Opaque) == sizeof(void *) */
+typedef uintptr_t Opaque; /* XXX sizeof(Opaque) == sizeof(void *) */
#define CHECK_MEMORY(tree) ( ( (tree)->plainmemory ) ? \
tlog(TL_CRIT|TL_EXIT, "Tree in plain memory - read only access") : (void)0 )
void*
SFSFindData(SFSTree *info, char *word, int len) {
+ SFSDataIO in;
+
+ in.key = word;
+ in.keylen = len;
+
+ return SFSFindDataFromSavedOrSave(info, &in, NULL);
+}
+
+void*
+SFSFindDataOrSave(SFSTree *info, SFSDataIO *in, SFSTreePosition *position) {
+ if ( position )
+ memset(position, 0, sizeof(position));
+
+ return SFSFindDataFromSavedOrSave(info, in, position);
+}
+
+void*
+SFSFindDataFromSavedOrSave(SFSTree *info, SFSDataIO *in, SFSTreePosition *position) {
SFSNode *node = info->node;
+ SFSNode **pnode = &(info->node);
SFSNodeData *StopLow, *StopHigh, *StopMiddle;
- u_int8_t *ptr =(u_int8_t*)word;
+ u_int8_t *ptr =(u_int8_t*)in->key;
+
+ if ( position && position->nodeptr && position->node && in->keylen > position->level ) {
+ node = position->node;
+ pnode = position->nodeptr;
+ ptr += position->level;
+ }
+
+ while( node && !ISEND(ptr, in->key, in->keylen) ) {
+ if ( position ) {
+ position->nodeptr = pnode;
+ position->node = node;
+ position->level = ((char*)ptr) - in->key;
+ }
- while( node && !ISEND(ptr, word, len) ) {
if ( node->isskip ) {
- /*
- if ( len>0 && len - (((char*)ptr) - word) > node->nchar )
+ if ( in->keylen>0 && in->keylen - (((char*)ptr) - in->key) > node->nchar )
return NULL;
- else */ if ( STRNCMP(ptr, ((char*)node)+node->dataptr, node->nchar) ) {
+ else if ( STRNCMP(ptr, ((char*)node)+node->dataptr, node->nchar) ) {
ptr+=node->nchar;
- if ( ISEND(ptr, word, len) && node->isword) {
+ if ( ISEND(ptr, in->key, in->keylen) && node->isword) {
return (void*) ( ((char*)(node->data)) + ((node->haschild) ? sizeof(SFSNode*) : 0) );
} else if ( node->haschild ) {
node = getSkipChildPointer(info, node);
+ pnode = (SFSNode**)( (char*)(node->data) );
} else {
return NULL;
}
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
if ( StopMiddle->val == *ptr ) {
ptr++;
- if ( ISEND(ptr, word, len) && StopMiddle->isword ) {
+ if ( ISEND(ptr, in->key, in->keylen) && StopMiddle->isword ) {
return (void*)( ((char*)node) + node->dataptr + info->datasize * StopMiddle->data );
} else if ( StopMiddle->haschild ) {
node = getChildPointer(info, StopMiddle);
+ pnode = (SFSNode**)(((char*)StopMiddle) + StopMiddle->child);
} else {
return NULL;
}
return NULL;
}
+void
+SFSAddSaved(SFSTree *info, SFSDataIO *in, SFSTreePosition *position) {
+ CHECK_MEMORY(info);
+
+ if ( !(position->nodeptr && position->node) ) {
+ SFSAdd(info, in);
+ return;
+ }
+
+ position->node = *(position->nodeptr) = addRecord(info, position->node, in, position->level);
+}
+
static void
freeFSFNode(SFSTree *info, SFSNode *node, void (*freefunc)(void*)) {
u_int32_t i;
else
node = splitSkipNode(info, node, in, level);
} else {
- StopLow = node->data;
+ StopLow = node->data;
StopHigh = StopLow + node->nchar;
while (StopLow < StopHigh) {
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
- if ( StopMiddle->val == *ptr ) {
+ if ( StopMiddle->val == *ptr ) {
if ( *(ptr+1)=='\0' ) {
if ( StopMiddle->isword ) {
/* already exists */
tlog(TL_CRIT|TL_EXIT, "sizeof(Opaque) mismatch");
if ( dh->headersize != SFSTDHSZ )
tlog(TL_CRIT|TL_EXIT, "Tree's header size mismatch (should be %d but %d bytes)", SFSTDHSZ, dh->headersize);
- if ( size && size != dh->totalen + SFSTDHSZ + dh->extrasize )
+ if ( size && size != dh->totalen + SFSTDHSZ + MAXALIGN(dh->extrasize) )
tlog(TL_CRIT|TL_EXIT, "Memory size mismatch (should be %d but %d bytes)", dh->totalen + SFSTDHSZ + dh->extrasize , size);
info->totalen = dh->totalen;