X-Git-Url: http://sigaev.ru/git/gitweb.cgi?a=blobdiff_plain;f=sfxstr.c;h=d65bf7c118b1e00e04fd6e6b44b8b856e9ff3b88;hb=5bd16a99921291ce46fac6db14972ca7bca5c155;hp=1a1bb8e15b349ff32a4cbabd91b5f2f518067e41;hpb=7580701d62cce570f061d96018f3e90c2365d2be;p=tedtools.git diff --git a/sfxstr.c b/sfxstr.c index 1a1bb8e..d65bf7c 100644 --- a/sfxstr.c +++ b/sfxstr.c @@ -144,20 +144,53 @@ SFSInit_c(SFSTree *info, char **in) { 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(SFSTreePosition)); + + 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) { - return (void*) ( ((char*)(node->data)) + ((node->haschild) ? sizeof(SFSNode*) : 0) ); + if ( ISEND(ptr, in->key, in->keylen) ) { + if (node->isword) + return (void*) ( ((char*)(node->data)) + ((node->haschild) ? sizeof(SFSNode*) : 0) ); + return NULL; } else if ( node->haschild ) { + pnode = (SFSNode**)( (char*)(node->data) ); node = getSkipChildPointer(info, node); } else { return NULL; @@ -171,9 +204,12 @@ SFSFindData(SFSTree *info, char *word, int len) { StopMiddle = StopLow + ((StopHigh - StopLow) >> 1); if ( StopMiddle->val == *ptr ) { ptr++; - if ( ISEND(ptr, word, len) && StopMiddle->isword ) { - return (void*)( ((char*)node) + node->dataptr + info->datasize * StopMiddle->data ); + if ( ISEND(ptr, in->key, in->keylen) ) { + if ( StopMiddle->isword ) + return (void*)( ((char*)node) + node->dataptr + info->datasize * StopMiddle->data ); + return NULL; } else if ( StopMiddle->haschild ) { + pnode = (SFSNode**)(((char*)StopMiddle) + StopMiddle->child); node = getChildPointer(info, StopMiddle); } else { return NULL; @@ -192,6 +228,18 @@ SFSFindData(SFSTree *info, char *word, int len) { return NULL; } +void +SFSAddSaved(SFSTree *info, SFSDataIO *in, SFSTreePosition *position) { + CHECK_MEMORY(info); + + if ( !(position && 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; @@ -590,11 +638,11 @@ addRecord(SFSTree *info, SFSNode* node, SFSDataIO *in, int level) { 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 */ @@ -755,8 +803,13 @@ SFSIterate(SFSTree *info, SFSDataIO *out) { return 1; } - if ( s == NULL || s->node == NULL) + if ( s == NULL ) return 0; + if ( s->node == NULL ) { + info->stack = s->next; + tfree(s); + return SFSIterate(info, out); + } while ( s->level + s->node->nchar + 1 >= info->tlen ) { info->tlen *= 2; @@ -1073,8 +1126,9 @@ SFSWriteDump(SFSTree *info, char *filename, void *extradata, u_int32_t extrasize wp.info = info; wp.offset = 0; - - writeNode(&wp, fd, info->node, extrasize); + + if ( info->node ) + writeNode(&wp, fd, info->node, extrasize); } flock(fd, LOCK_UN); @@ -1200,7 +1254,7 @@ SFSInitFromDump(SFSTree *info, void *pointer, u_int64_t size, void **extradata, 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;