summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/prefix_string.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/prefix_string.c')
-rw-r--r--subversion/libsvn_subr/prefix_string.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/subversion/libsvn_subr/prefix_string.c b/subversion/libsvn_subr/prefix_string.c
index fcf11bd2bf73a..8e64ace1c3381 100644
--- a/subversion/libsvn_subr/prefix_string.c
+++ b/subversion/libsvn_subr/prefix_string.c
@@ -49,7 +49,12 @@ struct svn_prefix_string__t
/* mandatory prefix */
node_t *prefix;
- /* 0 ..7 chars to add the the prefix. NUL-terminated. */
+ /* 0 ..7 chars to add the prefix.
+ *
+ * NUL-terminated, if this is indeed a tree leaf. We use the same struct
+ * within node_t for inner tree nodes, too. There, DATA[7] is not NUL,
+ * meaning DATA may or may not be NUL terminated. The actual length is
+ * provided by the node_t.length field (minus parent node length). */
char data[8];
};
@@ -94,6 +99,12 @@ struct svn_prefix_tree__t
static svn_boolean_t
is_leaf(node_t *node)
{
+ /* If this NOT a leaf node and this node has ...
+ * ... 8 chars, data[7] will not be NUL because we only support
+ * NUL-*terminated* strings.
+ * ... less than 8 chars, this will be set to 0xff
+ * (any other non-NUL would do as well but this is not valid UTF8
+ * making it easy to recognize during debugging etc.) */
return node->key.data[7] == 0;
}
@@ -154,7 +165,7 @@ svn_prefix_tree__create(apr_pool_t *pool)
tree->pool = pool;
tree->root = apr_pcalloc(pool, sizeof(*tree->root));
- tree->root->key.data[7] = '\xff';
+ tree->root->key.data[7] = '\xff'; /* This is not a leaf. See is_leaf(). */
return tree;
}
@@ -188,6 +199,7 @@ svn_prefix_string__create(svn_prefix_tree__t *tree,
|| node->sub_nodes[idx]->key.data[0] != s[node->length])
break;
+ /* Yes, it matches - at least the first character does. */
sub_node = node->sub_nodes[idx];
/* fully matching sub-node? */
@@ -198,6 +210,11 @@ svn_prefix_string__create(svn_prefix_tree__t *tree,
}
else
{
+ /* The string formed by the path from the root down to
+ * SUB_NODE differs from S.
+ *
+ * Is it a prefix? In that case, the chars added by SUB_NODE
+ * must fully match the respective chars in S. */
apr_size_t sub_node_len = sub_node->length - node->length;
if (strncmp(sub_node->key.data, s + node->length,
sub_node_len) == 0)
@@ -207,14 +224,24 @@ svn_prefix_string__create(svn_prefix_tree__t *tree,
}
}
- /* partial match -> split */
+ /* partial match -> split
+ *
+ * At this point, S may either be a prefix to the string represented
+ * by SUB_NODE, or they may diverge at some offset with
+ * SUB_NODE->KEY.DATA .
+ *
+ * MATCH starts with 1 here b/c we already know that at least one
+ * char matches. Also, the loop will terminate because the strings
+ * differ before SUB_NODE->KEY.DATA - either at the NUL terminator
+ * of S or some char before that.
+ */
while (sub_node->key.data[match] == s[node->length + match])
++match;
new_node = apr_pcalloc(tree->pool, sizeof(*new_node));
new_node->key = sub_node->key;
new_node->length = node->length + match;
- new_node->key.data[7] = '\xff';
+ new_node->key.data[7] = '\xff'; /* This is not a leaf. See is_leaf(). */
new_node->sub_node_count = 1;
new_node->sub_nodes = apr_palloc(tree->pool, sizeof(node_t *));
new_node->sub_nodes[0] = sub_node;
@@ -228,7 +255,7 @@ svn_prefix_string__create(svn_prefix_tree__t *tree,
}
/* add sub-node(s) and final string */
- while (node->length + 7 < len)
+ while (len - node->length > 7)
{
new_node = apr_pcalloc(tree->pool, sizeof(*new_node));
new_node->key.prefix = node;