mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 16:48:27 -05:00
Rax library updated.
This commit is contained in:
parent
7c6f1be5df
commit
05a2996641
63
src/rax.c
63
src/rax.c
@ -359,7 +359,18 @@ raxNode *raxCompressNode(raxNode *n, unsigned char *s, size_t len, raxNode **chi
|
|||||||
* parent's node is returned as '*plink' if not NULL. Finally, if the
|
* parent's node is returned as '*plink' if not NULL. Finally, if the
|
||||||
* search stopped in a compressed node, '*splitpos' returns the index
|
* search stopped in a compressed node, '*splitpos' returns the index
|
||||||
* inside the compressed node where the search ended. This is useful to
|
* inside the compressed node where the search ended. This is useful to
|
||||||
* know where to split the node for insertion. */
|
* know where to split the node for insertion.
|
||||||
|
*
|
||||||
|
* Note that when we stop in the middle of a compressed node with
|
||||||
|
* a perfect match, this function will return a length equal to the
|
||||||
|
* 'len' argument (all the key matched), and will return a *splitpos which is
|
||||||
|
* always positive (that will represent the index of the character immediately
|
||||||
|
* *after* the last match in the current compressed node).
|
||||||
|
*
|
||||||
|
* When instead we stop at a compressed node and *splitpos is zero, it
|
||||||
|
* means that the current node represents the key (that is, none of the
|
||||||
|
* compressed node characters are needed to represent the key, just all
|
||||||
|
* its parents nodes). */
|
||||||
static inline size_t raxLowWalk(rax *rax, unsigned char *s, size_t len, raxNode **stopnode, raxNode ***plink, int *splitpos, raxStack *ts) {
|
static inline size_t raxLowWalk(rax *rax, unsigned char *s, size_t len, raxNode **stopnode, raxNode ***plink, int *splitpos, raxStack *ts) {
|
||||||
raxNode *h = rax->head;
|
raxNode *h = rax->head;
|
||||||
raxNode **parentlink = &rax->head;
|
raxNode **parentlink = &rax->head;
|
||||||
@ -405,10 +416,12 @@ static inline size_t raxLowWalk(rax *rax, unsigned char *s, size_t len, raxNode
|
|||||||
|
|
||||||
/* Insert the element 's' of size 'len', setting as auxiliary data
|
/* Insert the element 's' of size 'len', setting as auxiliary data
|
||||||
* the pointer 'data'. If the element is already present, the associated
|
* the pointer 'data'. If the element is already present, the associated
|
||||||
* data is updated, and 0 is returned, otherwise the element is inserted
|
* data is updated (only if 'overwrite' is set to 1), and 0 is returned,
|
||||||
* and 1 is returned. On out of memory the function returns 0 as well but
|
* otherwise the element is inserted and 1 is returned. On out of memory the
|
||||||
* sets errno to ENOMEM, otherwise errno will be set to 0. */
|
* function returns 0 as well but sets errno to ENOMEM, otherwise errno will
|
||||||
int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
|
* be set to 0.
|
||||||
|
*/
|
||||||
|
int raxGenericInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old, int overwrite) {
|
||||||
size_t i;
|
size_t i;
|
||||||
int j = 0; /* Split position. If raxLowWalk() stops in a compressed
|
int j = 0; /* Split position. If raxLowWalk() stops in a compressed
|
||||||
node, the index 'j' represents the char we stopped within the
|
node, the index 'j' represents the char we stopped within the
|
||||||
@ -426,7 +439,8 @@ int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
|
|||||||
* data pointer. */
|
* data pointer. */
|
||||||
if (i == len && (!h->iscompr || j == 0 /* not in the middle if j is 0 */)) {
|
if (i == len && (!h->iscompr || j == 0 /* not in the middle if j is 0 */)) {
|
||||||
debugf("### Insert: node representing key exists\n");
|
debugf("### Insert: node representing key exists\n");
|
||||||
if (!h->iskey || h->isnull) {
|
/* Make space for the value pointer if needed. */
|
||||||
|
if (!h->iskey || (h->isnull && overwrite)) {
|
||||||
h = raxReallocForData(h,data);
|
h = raxReallocForData(h,data);
|
||||||
if (h) memcpy(parentlink,&h,sizeof(h));
|
if (h) memcpy(parentlink,&h,sizeof(h));
|
||||||
}
|
}
|
||||||
@ -434,12 +448,17 @@ int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the existing key if there is already one. */
|
||||||
if (h->iskey) {
|
if (h->iskey) {
|
||||||
if (old) *old = raxGetData(h);
|
if (old) *old = raxGetData(h);
|
||||||
raxSetData(h,data);
|
if (overwrite) raxSetData(h,data);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
return 0; /* Element already exists. */
|
return 0; /* Element already exists. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise set the node as a key. Note that raxSetData()
|
||||||
|
* will set h->iskey. */
|
||||||
raxSetData(h,data);
|
raxSetData(h,data);
|
||||||
rax->numele++;
|
rax->numele++;
|
||||||
return 1; /* Element inserted. */
|
return 1; /* Element inserted. */
|
||||||
@ -793,6 +812,19 @@ oom:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Overwriting insert. Just a wrapper for raxGenericInsert() that will
|
||||||
|
* update the element if there is already one for the same key. */
|
||||||
|
int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
|
||||||
|
return raxGenericInsert(rax,s,len,data,old,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Non overwriting insert function: this if an element with the same key
|
||||||
|
* exists, the value is not updated and the function returns 0.
|
||||||
|
* This is a just a wrapper for raxGenericInsert(). */
|
||||||
|
int raxTryInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old) {
|
||||||
|
return raxGenericInsert(rax,s,len,data,old,0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Find a key in the rax, returns raxNotFound special void pointer value
|
/* Find a key in the rax, returns raxNotFound special void pointer value
|
||||||
* if the item was not found, otherwise the value associated with the
|
* if the item was not found, otherwise the value associated with the
|
||||||
* item is returned. */
|
* item is returned. */
|
||||||
@ -1523,11 +1555,26 @@ int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len) {
|
|||||||
/* If there was no mismatch we are into a node representing the
|
/* If there was no mismatch we are into a node representing the
|
||||||
* key, (but which is not a key or the seek operator does not
|
* key, (but which is not a key or the seek operator does not
|
||||||
* include 'eq'), or we stopped in the middle of a compressed node
|
* include 'eq'), or we stopped in the middle of a compressed node
|
||||||
* after processing all the key. Cotinue iterating as this was
|
* after processing all the key. Continue iterating as this was
|
||||||
* a legitimate key we stopped at. */
|
* a legitimate key we stopped at. */
|
||||||
it->flags &= ~RAX_ITER_JUST_SEEKED;
|
it->flags &= ~RAX_ITER_JUST_SEEKED;
|
||||||
|
if (it->node->iscompr && it->node->iskey && splitpos && lt) {
|
||||||
|
/* If we stopped in the middle of a compressed node with
|
||||||
|
* perfect match, and the condition is to seek a key "<" than
|
||||||
|
* the specified one, then if this node is a key it already
|
||||||
|
* represents our match. For instance we may have nodes:
|
||||||
|
*
|
||||||
|
* "f" -> "oobar" = 1 -> "" = 2
|
||||||
|
*
|
||||||
|
* Representing keys "f" = 1, "foobar" = 2. A seek for
|
||||||
|
* the key < "foo" will stop in the middle of the "oobar"
|
||||||
|
* node, but will be our match, representing the key "f".
|
||||||
|
*
|
||||||
|
* So in that case, we don't seek backward. */
|
||||||
|
} else {
|
||||||
if (gt && !raxIteratorNextStep(it,0)) return 0;
|
if (gt && !raxIteratorNextStep(it,0)) return 0;
|
||||||
if (lt && !raxIteratorPrevStep(it,0)) return 0;
|
if (lt && !raxIteratorPrevStep(it,0)) return 0;
|
||||||
|
}
|
||||||
it->flags |= RAX_ITER_JUST_SEEKED; /* Ignore next call. */
|
it->flags |= RAX_ITER_JUST_SEEKED; /* Ignore next call. */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,6 +145,7 @@ extern void *raxNotFound;
|
|||||||
/* Exported API. */
|
/* Exported API. */
|
||||||
rax *raxNew(void);
|
rax *raxNew(void);
|
||||||
int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old);
|
int raxInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old);
|
||||||
|
int raxTryInsert(rax *rax, unsigned char *s, size_t len, void *data, void **old);
|
||||||
int raxRemove(rax *rax, unsigned char *s, size_t len, void **old);
|
int raxRemove(rax *rax, unsigned char *s, size_t len, void **old);
|
||||||
void *raxFind(rax *rax, unsigned char *s, size_t len);
|
void *raxFind(rax *rax, unsigned char *s, size_t len);
|
||||||
void raxFree(rax *rax);
|
void raxFree(rax *rax);
|
||||||
|
Loading…
Reference in New Issue
Block a user