Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
b4b0251c
Commit
b4b0251c
authored
Jun 04, 2018
by
antirez
Browse files
Rax library updated.
parent
f7209749
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/rax.c
View file @
b4b0251c
...
...
@@ -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
* search stopped in a compressed node, '*splitpos' returns the index
* 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
)
{
raxNode
*
h
=
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
* the pointer 'data'. If the element is already present, the associated
* data is updated, and 0 is returned, otherwise the element is inserted
* and 1 is returned. On out of memory the function returns 0 as well but
* sets errno to ENOMEM, otherwise errno will be set to 0. */
int
raxInsert
(
rax
*
rax
,
unsigned
char
*
s
,
size_t
len
,
void
*
data
,
void
**
old
)
{
* data is updated (only if 'overwrite' is set to 1), and 0 is returned,
* otherwise the element is inserted and 1 is returned. On out of memory the
* function returns 0 as well but sets errno to ENOMEM, otherwise errno will
* be set to 0.
*/
int
raxGenericInsert
(
rax
*
rax
,
unsigned
char
*
s
,
size_t
len
,
void
*
data
,
void
**
old
,
int
overwrite
)
{
size_t
i
;
int
j
=
0
;
/* Split position. If raxLowWalk() stops in a compressed
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. */
if
(
i
==
len
&&
(
!
h
->
iscompr
||
j
==
0
/* not in the middle if j is 0 */
))
{
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
);
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
;
return
0
;
}
/* Update the existing key if there is already one. */
if
(
h
->
iskey
)
{
if
(
old
)
*
old
=
raxGetData
(
h
);
raxSetData
(
h
,
data
);
if
(
overwrite
)
raxSetData
(
h
,
data
);
errno
=
0
;
return
0
;
/* Element already exists. */
}
/* Otherwise set the node as a key. Note that raxSetData()
* will set h->iskey. */
raxSetData
(
h
,
data
);
rax
->
numele
++
;
return
1
;
/* Element inserted. */
...
...
@@ -793,6 +812,19 @@ oom:
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
* if the item was not found, otherwise the value associated with the
* 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
* 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
* after processing all the key. Cotinue iterating as this was
* after processing all the key. Co
n
tinue iterating as this was
* a legitimate key we stopped at. */
it
->
flags
&=
~
RAX_ITER_JUST_SEEKED
;
if
(
gt
&&
!
raxIteratorNextStep
(
it
,
0
))
return
0
;
if
(
lt
&&
!
raxIteratorPrevStep
(
it
,
0
))
return
0
;
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
(
lt
&&
!
raxIteratorPrevStep
(
it
,
0
))
return
0
;
}
it
->
flags
|=
RAX_ITER_JUST_SEEKED
;
/* Ignore next call. */
}
}
else
{
...
...
src/rax.h
View file @
b4b0251c
...
...
@@ -145,6 +145,7 @@ extern void *raxNotFound;
/* Exported API. */
rax
*
raxNew
(
void
);
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
);
void
*
raxFind
(
rax
*
rax
,
unsigned
char
*
s
,
size_t
len
);
void
raxFree
(
rax
*
rax
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment