X-Git-Url: http://www.sigaev.ru/git/gitweb.cgi?a=blobdiff_plain;f=sfxstr.c;h=337831c5d0c2569acca4cdadacc919bb15c1426b;hb=bbc6315ba6b766b9fb39a2d3c0818cf663ed42a4;hp=0803345f958503dbdd3957b46965cc4cf1ead824;hpb=515bf0a51a077b6f807b3be138c5d11e8e69a7e7;p=tedtools.git diff --git a/sfxstr.c b/sfxstr.c index 0803345..337831c 100644 --- a/sfxstr.c +++ b/sfxstr.c @@ -144,21 +144,44 @@ SFSInit_c(SFSTree *info, char **in) { void* SFSFindData(SFSTree *info, char *word, int len) { + SFSDataIO in; + + in.key = word; + in.keylen = len; + + return SFSFindDataOrSave(info, &in, NULL); +} + +void* +SFSFindDataOrSave(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 = NULL; + position->node = NULL; + position->level = 0; + } + + 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) ) { 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; } @@ -171,10 +194,11 @@ SFSFindData(SFSTree *info, char *word, int len) { 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; } @@ -192,6 +216,18 @@ SFSFindData(SFSTree *info, char *word, int len) { return NULL; } +void +SFSAddSaved(SFSTree *info, SFSDataIO *in, SFSTreePosition *position) { + CHECK_MEMORY(info); + + if ( !(position->nodeptr && position->node) ) { + SFSAdd(info, in); + return; + } + + *(position->nodeptr) = addRecord(info, position->node, in, position->level); +} + static void freeFSFNode(SFSTree *info, SFSNode *node, void (*freefunc)(void*)) { u_int32_t i;