+#define check_partial(loc, start, end, mask) \
+ (((long)(start) - (long)mask - 1) <= (long)loc && loc < end)
+
+static inline struct btrie_node*
+__get_immediate_node(struct btrie* tree, struct btrie_node *root,
+ unsigned long start, unsigned long end, unsigned long loc)
+{
+ unsigned int index;
+ unsigned long mask;
+ struct btrie_node *node;
+
+ mask = (1UL << tree->order) - 1;
+ index = loc & mask;
+ for (unsigned long i = 0; i <= mask; ++i, index = (index + 1) & mask)
+ {
+ loc = (loc & ~mask) + index;
+ node = __btrie_get_child(root, index);
+
+ if (loc < start || loc >= end) {
+ continue;
+ }
+
+ if (!node) {
+ return __btrie_create(tree, root, index);
+ }
+
+ if (!node->data) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+static struct btrie_node*
+__btrie_find_free(struct btrie* tree, struct btrie_node *root,
+ unsigned long start, unsigned long end, unsigned long loc)
+{
+ unsigned long mask, next_loc;
+ struct btrie_node *node, *found;
+
+ if (!root) return NULL;
+
+ mask = (1UL << tree->order) - 1;
+
+ __btrie_visit_child(root->parent, root->index);
+
+ if (!__full_node(tree, root)) {
+ found = __get_immediate_node(tree, root, start, end, loc);
+ if (found) goto done;
+ }
+
+ for (unsigned int i = 0; i <= mask; i++)
+ {
+ next_loc = ((loc & ~mask) + i) << tree->order;
+
+ if (!next_loc || !check_partial(next_loc, start, end, mask)) {
+ continue;
+ }
+
+ if (__btrie_child_visited(root, i)) {
+ continue;
+ }
+
+ node = __btrie_get_child(root, i);
+ node = node ?: __btrie_create(tree, root, i);
+
+ found = __btrie_find_free(tree, node, start, end, next_loc);
+
+ if (found) {
+ goto done;
+ }
+ }
+
+ loc >>= tree->order;
+ found = __btrie_find_free(tree, root->parent, start, end, loc + 1);
+
+done:
+ __btrie_unvisit_child(root->parent, root->index);
+ return found;
+}
+
+static unsigned long
+__btrie_alloc_slot(struct btrie* tree, struct btrie_node **slot,
+ unsigned long start, unsigned long end)
+{
+ unsigned int od;
+ unsigned long result, mask;
+ struct btrie_node *found, *node;
+
+ od = 0;
+ mask = (1 << od) - 1;
+ found = tree->btrie_root;
+ result = 0;
+
+ if (!start && !__btrie_get_child(found, 0)) {
+ *slot = __btrie_create(tree, found, 0);
+ return 0;
+ }
+
+ found = __btrie_traversal(tree, start, BTRIE_FIND_PARENT);
+ found = __btrie_find_free(tree, found, start, end, start);
+
+ node = found;
+ while (node)
+ {
+ result |= node->index << od;
+ od += tree->order;
+ node = node->parent;
+ }
+
+ *slot = found;
+ return found ? result : -1UL;
+}
+