From: teodor Date: Fri, 11 Jul 2008 10:15:12 +0000 (+0000) Subject: Add FindOrSavePosition interface for suffix tree X-Git-Url: http://sigaev.ru/git/gitweb.cgi?a=commitdiff_plain;h=bbc6315ba6b766b9fb39a2d3c0818cf663ed42a4;hp=515bf0a51a077b6f807b3be138c5d11e8e69a7e7;p=tedtools.git Add FindOrSavePosition interface for suffix tree --- 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; diff --git a/sfxstr.h b/sfxstr.h index 22f8410..c49ac24 100644 --- a/sfxstr.h +++ b/sfxstr.h @@ -185,6 +185,15 @@ void SFSAdd(SFSTree *info, SFSDataIO *in); */ void* SFSFindData(SFSTree *info, char *word, int len /* optional */ ); +typedef struct SFSTreePosition { + SFSNode **nodeptr; + SFSNode *node; + int level; +} SFSTreePosition; + +void* SFSFindDataOrSave(SFSTree *info, SFSDataIO *in, SFSTreePosition *position); +void SFSAddSaved(SFSTree *info, SFSDataIO *in, SFSTreePosition *position); + /* * éÎÉÃÉÁÌÉÚÁÃÉÑ ÉÔÅÒÁÔÏÒÁ × ÎÁÞÁÌÏ ÄÅÒÅ×Á */