ys2-intro/loader/tools/exomizer-3.1/src/radix.c
2025-11-13 19:07:39 +03:00

159 lines
4.2 KiB
C

/*
* Copyright (c) 2002, 2003 Magnus Lind.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software, alter it and re-
* distribute it freely for any non-commercial, non-profit purpose subject to
* the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any distribution.
*
* 4. The names of this software and/or it's copyright holders may not be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "log.h"
#include "radix.h"
#include "chunkpool.h"
#define RADIX_TREE_NODE_RADIX 8U
#define RADIX_TREE_NODE_MASK ((1U << RADIX_TREE_NODE_RADIX) - 1U)
struct radix_node {
struct radix_node *rn;
};
void radix_tree_init(struct radix_root *rr) /* IN */
{
rr->depth = 0;
rr->root = NULL;
chunkpool_init(&rr->mem, (1 << RADIX_TREE_NODE_RADIX) * sizeof(void *));
}
static
void radix_tree_free_helper(int depth, struct radix_node *rnp,
free_callback * f, /* IN */
void *priv) /* IN */
{
int i;
do
{
if (depth == 0)
{
/* do something to the data pointer? */
if (f != NULL)
{
f(rnp, priv);
}
break;
}
if (rnp == NULL)
{
/* tree not grown here */
break;
}
for (i = RADIX_TREE_NODE_MASK; i >= 0; --i)
{
radix_tree_free_helper(depth - 1, rnp[i].rn, f, priv);
rnp[i].rn = NULL;
}
}
while (0);
}
void radix_tree_free(struct radix_root *rr, /* IN */
free_callback * f, /* IN */
void *priv) /* IN */
{
radix_tree_free_helper(rr->depth, rr->root, f, priv);
rr->depth = 0;
rr->root = NULL;
chunkpool_free(&rr->mem);
}
void radix_node_set(struct radix_root *rrp, /* IN */
unsigned int index, /* IN */
void *data) /* IN */
{
struct radix_node *rnp;
struct radix_node **rnpp;
unsigned int mask;
int depth;
mask = ~0U << (RADIX_TREE_NODE_RADIX * rrp->depth);
while (index & mask)
{
/*LOG(LOG_DUMP, ("calloc called\n")); */
/* not deep enough, let's deepen the tree */
rnp = chunkpool_calloc(&rrp->mem);
rnp[0].rn = rrp->root;
rrp->root = rnp;
rrp->depth += 1;
mask = ~0U << (RADIX_TREE_NODE_RADIX * rrp->depth);
}
/* go down */
rnpp = &rrp->root;
for (depth = rrp->depth - 1; depth >= 0; --depth)
{
unsigned int node_index;
if (*rnpp == NULL)
{
/*LOG(LOG_DUMP, ("calloc called\n")); */
/* tree is not grown in this interval */
*rnpp = chunkpool_calloc(&rrp->mem);
}
node_index = ((index >> (RADIX_TREE_NODE_RADIX * depth)) &
RADIX_TREE_NODE_MASK);
rnpp = &((*rnpp)[node_index].rn);
}
*rnpp = data;
}
void *radix_node_get(struct radix_root *rr, /* IN */
unsigned int index) /* IN */
{
struct radix_node *rnp;
unsigned short int depth;
/* go down */
rnp = rr->root;
for (depth = rr->depth - 1; depth < 0xffff; --depth)
{
unsigned short int node_index;
if (rnp == NULL)
{
/* tree is not grown in this interval */
break;
}
node_index = ((index >> (RADIX_TREE_NODE_RADIX * depth)) &
RADIX_TREE_NODE_MASK);
rnp = rnp[node_index].rn;
}
return rnp;
}