bf3fe05dfb
This needs some more testing before it's on by default. If the card is otherwise functioning, these messages may be confusing to the user. If the card is not functioning, the driver can be reloaded with debug to check for this condition. Signed-off-by: Shaun Ruffell <sruffell@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9205 a0bf4364-ded3-4de4-8d8a-66a801d63aff
1218 lines
36 KiB
C
1218 lines
36 KiB
C
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\
|
|
|
|
File: octapi_bt0.c
|
|
|
|
Copyright (c) 2001-2007 Octasic Inc.
|
|
|
|
Description:
|
|
|
|
Library used to manage a binary tree of variable max size. Library is
|
|
made to use one block of contiguous memory to manage the tree.
|
|
|
|
This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is
|
|
free software; you can redistribute it and/or modify it under the terms of
|
|
the GNU General Public License as published by the Free Software Foundation;
|
|
either version 2 of the License, or (at your option) any later version.
|
|
|
|
The OCT6100 GPL API is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with the OCT6100 GPL API; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
$Octasic_Release: OCT612xAPI-01.00-PR49 $
|
|
|
|
$Octasic_Revision: 18 $
|
|
|
|
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
|
|
#include "apilib/octapi_bt0.h"
|
|
#include "octapi_bt0_private.h"
|
|
|
|
|
|
|
|
#if !SKIP_OctApiBt0GetSize
|
|
UINT32 OctApiBt0GetSize(UINT32 number_of_items,UINT32 key_size, UINT32 data_size, UINT32 * b_size)
|
|
{
|
|
if ((key_size % 4) != 0) return(OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32);
|
|
if ((data_size % 4) != 0) return(OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32);
|
|
|
|
*b_size = 0;
|
|
*b_size += sizeof(OCTAPI_BT0);
|
|
*b_size += sizeof(OCTAPI_BT0_NODE) * number_of_items;
|
|
*b_size += key_size * number_of_items;
|
|
*b_size += data_size * number_of_items;
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0Init
|
|
UINT32 OctApiBt0Init(void ** b,UINT32 number_of_items,UINT32 key_size, UINT32 data_size)
|
|
{
|
|
UINT32 i;
|
|
OCTAPI_BT0 * bb;
|
|
|
|
/* Check input parameters.*/
|
|
if ((key_size % 4) != 0) return(OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32);
|
|
if ((data_size % 4) != 0) return(OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32);
|
|
|
|
/* If b is not already allocated.*/
|
|
if (*b == NULL) return(OCTAPI_BT0_MALLOC_FAILED);
|
|
|
|
bb = (OCTAPI_BT0 *)(*b);
|
|
|
|
/* Initialize the tree to an empty one!*/
|
|
bb->root_link.node_number = 0xFFFFFFFF;
|
|
bb->root_link.depth = 0;
|
|
|
|
/* Initialize tree parameters.*/
|
|
bb->number_of_items = number_of_items;
|
|
bb->key_size = key_size / 4;
|
|
bb->data_size = data_size / 4;
|
|
|
|
/* Initialize the next free node pointer.*/
|
|
if (number_of_items != 0)
|
|
bb->next_free_node = 0;
|
|
else
|
|
bb->next_free_node = 0xFFFFFFFF;
|
|
|
|
/* Setup the arrays.*/
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Initialize the Nodes to unused!*/
|
|
for(i=0;i<number_of_items;i++)
|
|
{
|
|
bb->node[i].next_free_node = i + 1;
|
|
}
|
|
|
|
/* Last empty node points to invalid node.*/
|
|
bb->node[number_of_items-1].next_free_node = 0xFFFFFFFF;
|
|
|
|
bb->invalid_value = 0xFFFFFFFF;
|
|
bb->no_smaller_key = OCTAPI_BT0_NO_SMALLER_KEY;
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !SKIP_OctApiBt0CorrectPointers
|
|
void OctApiBt0CorrectPointers(OCTAPI_BT0 * bb)
|
|
{
|
|
bb->node = (OCTAPI_BT0_NODE *)(((BYTE *)bb) + sizeof(OCTAPI_BT0));
|
|
bb->key = (UINT32 *)(((BYTE *)bb->node) + (sizeof(OCTAPI_BT0_NODE) * bb->number_of_items));
|
|
bb->data = (UINT32 *)(((BYTE *)bb->key) + (sizeof(UINT32) * bb->number_of_items * bb->key_size));
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !SKIP_OctApiBt0AddNode
|
|
UINT32 OctApiBt0AddNode(void * b,void * key,void ** data)
|
|
{
|
|
OCTAPI_BT0 * bb;
|
|
OCTAPI_BT0_NODE * new_node;
|
|
UINT32 * lkey;
|
|
UINT32 * nkey;
|
|
UINT32 i;
|
|
UINT32 new_node_number;
|
|
UINT32 result;
|
|
|
|
/* Load all!*/
|
|
bb = (OCTAPI_BT0 *)(b);
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Check that there is at least one block left.*/
|
|
if (bb->next_free_node == 0xFFFFFFFF) return(OCTAPI_BT0_NO_NODES_AVAILABLE);
|
|
|
|
/* Seize the node!*/
|
|
new_node_number = bb->next_free_node;
|
|
new_node = &(bb->node[new_node_number]);
|
|
bb->next_free_node = new_node->next_free_node;
|
|
|
|
/* Register in the key and the data.*/
|
|
lkey = ((UINT32 *)key);
|
|
|
|
/* Find the first UINT32 of the key.*/
|
|
nkey = &(bb->key[bb->key_size * new_node_number]);
|
|
|
|
/* Copy the key.*/
|
|
for(i=0;i<bb->key_size;i++)
|
|
nkey[i] = lkey[i];
|
|
|
|
/* Attempt to place the node. Only a "multiple hit" will cause an error.*/
|
|
result = OctApiBt0AddNode2(bb,&(bb->root_link), lkey, new_node_number);
|
|
if (result != GENERIC_OK)
|
|
{
|
|
/* This attempt failed. Refree the node!*/
|
|
bb->next_free_node = new_node_number;
|
|
|
|
/* Return the error code.*/
|
|
return(result);
|
|
}
|
|
|
|
/* Return the address of the data to the user.*/
|
|
if ( bb->data_size > 0 )
|
|
*data = (void *)(&(bb->data[bb->data_size * new_node_number]));
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0AddNode2
|
|
UINT32 OctApiBt0AddNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 new_node_number)
|
|
{
|
|
UINT32 result;
|
|
|
|
if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/
|
|
{
|
|
bb->node[new_node_number].l[0].node_number = 0xFFFFFFFF;
|
|
bb->node[new_node_number].l[0].depth = 0;
|
|
bb->node[new_node_number].l[1].node_number = 0xFFFFFFFF;
|
|
bb->node[new_node_number].l[1].depth = 0;
|
|
|
|
/* OCTAPI_BT0_LINK to parent!*/
|
|
link->node_number = new_node_number;
|
|
link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else /* Current node is used, check for a match and a direction.*/
|
|
{
|
|
OCTAPI_BT0_NODE * this_node;
|
|
UINT32 compare;
|
|
|
|
/* Get a pointer to this node.*/
|
|
this_node = &(bb->node[link->node_number]);
|
|
|
|
/* Compare this node to the lkey.*/
|
|
compare = OctApiBt0KeyCompare(bb,link,lkey);
|
|
|
|
if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/
|
|
{
|
|
result = OctApiBt0AddNode2(bb,&(this_node->l[0]), lkey, new_node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/
|
|
{
|
|
result = OctApiBt0AddNode2(bb,&(this_node->l[1]), lkey, new_node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else
|
|
{
|
|
return(OCTAPI_BT0_KEY_ALREADY_IN_TREE);
|
|
}
|
|
|
|
/* Check if this node is unbalanced by 2. If so, rebalance it:*/
|
|
if (this_node->l[0].depth > (this_node->l[1].depth + 1) ||
|
|
this_node->l[1].depth > (this_node->l[0].depth + 1))
|
|
{
|
|
OctApiBt0Rebalance(bb,link);
|
|
}
|
|
|
|
/* Always update the OCTAPI_BT0_LINK depth before exiting.*/
|
|
OctApiBt0UpdateLinkDepth(bb,link);
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !SKIP_OctApiBt0AddNode3
|
|
UINT32 OctApiBt0AddNode3(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number)
|
|
{
|
|
UINT32 result;
|
|
|
|
if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/
|
|
{
|
|
if ( *p_new_node_number == 0xFFFFFFFF )
|
|
return(OCTAPI_BT0_NO_NODES_AVAILABLE);
|
|
|
|
bb->node[*p_new_node_number].l[0].node_number = 0xFFFFFFFF;
|
|
bb->node[*p_new_node_number].l[0].depth = 0;
|
|
bb->node[*p_new_node_number].l[1].node_number = 0xFFFFFFFF;
|
|
bb->node[*p_new_node_number].l[1].depth = 0;
|
|
|
|
/* OCTAPI_BT0_LINK to parent!*/
|
|
link->node_number = *p_new_node_number;
|
|
link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else /* Current node is used, check for a match and a direction.*/
|
|
{
|
|
OCTAPI_BT0_NODE * this_node;
|
|
UINT32 compare;
|
|
|
|
/* Get a pointer to this node.*/
|
|
this_node = &(bb->node[link->node_number]);
|
|
|
|
/* Compare this node to the lkey.*/
|
|
compare = OctApiBt0KeyCompare(bb,link,lkey);
|
|
|
|
if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/
|
|
{
|
|
result = OctApiBt0AddNode3(bb,&(this_node->l[0]), lkey, p_new_node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/
|
|
{
|
|
result = OctApiBt0AddNode3(bb,&(this_node->l[1]), lkey, p_new_node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else
|
|
{
|
|
*p_new_node_number = link->node_number;
|
|
return(OCTAPI_BT0_KEY_ALREADY_IN_TREE);
|
|
}
|
|
|
|
/* Check if this node is unbalanced by 2. If so, rebalance it:*/
|
|
if (this_node->l[0].depth > (this_node->l[1].depth + 1) ||
|
|
this_node->l[1].depth > (this_node->l[0].depth + 1))
|
|
{
|
|
OctApiBt0Rebalance(bb,link);
|
|
}
|
|
|
|
/* Always update the OCTAPI_BT0_LINK depth before exiting.*/
|
|
OctApiBt0UpdateLinkDepth(bb,link);
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* state
|
|
0 -> first call to the function.
|
|
1 -> recursive call.*/
|
|
#if !SKIP_OctApiBt0AddNode4
|
|
UINT32 OctApiBt0AddNode4(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number, UINT32 *p_prev_node_number, UINT32 state )
|
|
{
|
|
UINT32 result;
|
|
UINT32 *nkey;
|
|
UINT32 *okey;
|
|
|
|
if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/
|
|
{
|
|
bb->node[*p_new_node_number].l[0].node_number = 0xFFFFFFFF;
|
|
bb->node[*p_new_node_number].l[0].depth = 0;
|
|
bb->node[*p_new_node_number].l[1].node_number = 0xFFFFFFFF;
|
|
bb->node[*p_new_node_number].l[1].depth = 0;
|
|
|
|
/* OCTAPI_BT0_LINK to parent!*/
|
|
link->node_number = *p_new_node_number;
|
|
link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/
|
|
|
|
if ( state == 0 )
|
|
*p_prev_node_number = 0xFFFFFFFF;
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else /* Current node is used, check for a match and a direction.*/
|
|
{
|
|
OCTAPI_BT0_NODE * this_node;
|
|
UINT32 compare;
|
|
|
|
/* Get a pointer to this node.*/
|
|
this_node = &(bb->node[link->node_number]);
|
|
|
|
/* Compare this node to the lkey.*/
|
|
compare = OctApiBt0KeyCompare(bb,link,lkey);
|
|
|
|
if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/
|
|
{
|
|
if ( state == 0 )
|
|
*p_prev_node_number = OCTAPI_BT0_NO_SMALLER_KEY;
|
|
|
|
if ( *p_prev_node_number != OCTAPI_BT0_NO_SMALLER_KEY )
|
|
{
|
|
/* Check if the key is the smallest one encountered yet.*/
|
|
okey = &(bb->key[bb->key_size * (*p_prev_node_number)]);
|
|
nkey = &(bb->key[bb->key_size * link->node_number]);
|
|
/* If the node is key smaller then the old small one, change the value.*/
|
|
if ( *nkey > *okey )
|
|
{
|
|
if ( *nkey < *lkey )
|
|
*p_prev_node_number = link->node_number;
|
|
}
|
|
}
|
|
|
|
result = OctApiBt0AddNode4(bb,&(this_node->l[0]), lkey, p_new_node_number, p_prev_node_number, 1);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/
|
|
{
|
|
if ( state == 0 )
|
|
*p_prev_node_number = link->node_number;
|
|
else
|
|
{
|
|
if ( *p_prev_node_number == OCTAPI_BT0_NO_SMALLER_KEY )
|
|
*p_prev_node_number = link->node_number;
|
|
else
|
|
{
|
|
/* Check if the key is the smallest one encountered yet.*/
|
|
okey = &(bb->key[bb->key_size * (*p_prev_node_number)]);
|
|
nkey = &(bb->key[bb->key_size * link->node_number]);
|
|
/* If the node is key smaller then the old small one, change the value.*/
|
|
if ( *nkey > *okey )
|
|
{
|
|
if ( *nkey < *lkey )
|
|
*p_prev_node_number = link->node_number;
|
|
}
|
|
}
|
|
}
|
|
|
|
result = OctApiBt0AddNode4(bb,&(this_node->l[1]), lkey, p_new_node_number, p_prev_node_number, 1);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else
|
|
{
|
|
*p_new_node_number = link->node_number;
|
|
return(OCTAPI_BT0_KEY_ALREADY_IN_TREE);
|
|
}
|
|
|
|
/* Check if this node is unbalanced by 2. If so, rebalance it:*/
|
|
if (this_node->l[0].depth > (this_node->l[1].depth + 1) ||
|
|
this_node->l[1].depth > (this_node->l[0].depth + 1))
|
|
{
|
|
OctApiBt0Rebalance(bb,link);
|
|
}
|
|
|
|
/* Always update the OCTAPI_BT0_LINK depth before exiting.*/
|
|
OctApiBt0UpdateLinkDepth(bb,link);
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0KeyCompare
|
|
UINT32 OctApiBt0KeyCompare(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey)
|
|
{
|
|
UINT32 * nkey;
|
|
UINT32 i;
|
|
|
|
/* Find the first UINT32 of the key.*/
|
|
nkey = &(bb->key[bb->key_size * link->node_number]);
|
|
|
|
for(i=0;i<bb->key_size;i++)
|
|
{
|
|
if (lkey[i] < nkey[i])
|
|
return(OCTAPI_BT0_LKEY_SMALLER);
|
|
else if (lkey[i] > nkey[i])
|
|
return(OCTAPI_BT0_LKEY_LARGER);
|
|
}
|
|
|
|
return(OCTAPI_BT0_LKEY_EQUAL);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !SKIP_OctApiBt0UpdateLinkDepth
|
|
void OctApiBt0UpdateLinkDepth(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link)
|
|
{
|
|
OCTAPI_BT0_NODE * this_node;
|
|
|
|
/* Get a pointer to this node.*/
|
|
this_node = &(bb->node[link->node_number]);
|
|
|
|
if (this_node->l[0].depth > this_node->l[1].depth)
|
|
link->depth = this_node->l[0].depth + 1;
|
|
else
|
|
link->depth = this_node->l[1].depth + 1;
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0Rebalance
|
|
void OctApiBt0Rebalance(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * root_link)
|
|
{
|
|
if (bb->node[root_link->node_number].l[0].depth > (bb->node[root_link->node_number].l[1].depth + 1)) /* Heavy to the left.*/
|
|
{
|
|
/* Check if the right child of the heavy child node is causing a problem.*/
|
|
/* If so, do a left rotate in order to make the left most child the longer one.*/
|
|
{
|
|
OCTAPI_BT0_LINK * heavy_link;
|
|
heavy_link = &(bb->node[root_link->node_number].l[0]);
|
|
|
|
if (bb->node[heavy_link->node_number].l[1].depth > bb->node[heavy_link->node_number].l[0].depth)
|
|
{
|
|
OctApiBt0ExternalHeavy(bb,heavy_link);
|
|
}
|
|
}
|
|
|
|
/* Ready to do super rotation!*/
|
|
{
|
|
OCTAPI_BT0_LINK init_root_link;
|
|
OCTAPI_BT0_LINK init_heavy_link;
|
|
OCTAPI_BT0_LINK init_leaf_tree[3];
|
|
|
|
/* Save pertinent initial OCTAPI_BT0_LINK information.*/
|
|
init_root_link = *root_link;
|
|
init_heavy_link = bb->node[root_link->node_number].l[0];
|
|
init_leaf_tree[2] = bb->node[root_link->node_number].l[1];
|
|
init_leaf_tree[0] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[0];
|
|
init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[1];
|
|
|
|
/* Restructure the tree.*/
|
|
*root_link = init_heavy_link;
|
|
bb->node[init_heavy_link.node_number].l[1] = init_root_link;
|
|
bb->node[init_root_link.node_number].l[0] = init_leaf_tree[1];
|
|
|
|
/* Reconstruct the depth of the branches.*/
|
|
OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[1]));
|
|
OctApiBt0UpdateLinkDepth(bb,root_link);
|
|
}
|
|
}
|
|
else if (bb->node[root_link->node_number].l[1].depth > (bb->node[root_link->node_number].l[0].depth + 1)) /* Heavy to the right.*/
|
|
{
|
|
/* Check if the right child of the heavy child node is causing a problem.*/
|
|
/* If so, do a left rotate in order to make the left most child the longer one.*/
|
|
{
|
|
OCTAPI_BT0_LINK * heavy_link;
|
|
heavy_link = &(bb->node[root_link->node_number].l[1]);
|
|
|
|
if (bb->node[heavy_link->node_number].l[0].depth > bb->node[heavy_link->node_number].l[1].depth)
|
|
{
|
|
OctApiBt0ExternalHeavy(bb,heavy_link);
|
|
}
|
|
}
|
|
|
|
/* Ready to do super rotation!*/
|
|
{
|
|
OCTAPI_BT0_LINK init_root_link;
|
|
OCTAPI_BT0_LINK init_heavy_link;
|
|
OCTAPI_BT0_LINK init_leaf_tree[3];
|
|
|
|
/* Save pertinent initial OCTAPI_BT0_LINK information.*/
|
|
init_root_link = *root_link;
|
|
init_heavy_link = bb->node[root_link->node_number].l[1];
|
|
init_leaf_tree[2] = bb->node[root_link->node_number].l[0];
|
|
init_leaf_tree[0] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[1];
|
|
init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[0];
|
|
|
|
/* Restructure the tree.*/
|
|
*root_link = init_heavy_link;
|
|
bb->node[init_heavy_link.node_number].l[0] = init_root_link;
|
|
bb->node[init_root_link.node_number].l[1] = init_leaf_tree[1];
|
|
|
|
/* Reconstruct the depth of the branches.*/
|
|
OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[0]));
|
|
OctApiBt0UpdateLinkDepth(bb,root_link);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* This function does a rotation towards the outside of the tree*/
|
|
/* in order to keep the heavy branches towards the outside.*/
|
|
#if !SKIP_OctApiBt0ExternalHeavy
|
|
void OctApiBt0ExternalHeavy(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * root_link)
|
|
{
|
|
if (bb->node[root_link->node_number].l[1].depth > bb->node[root_link->node_number].l[0].depth) /* Exterior of tree is towards the left.*/
|
|
{
|
|
OCTAPI_BT0_LINK init_root_link;
|
|
OCTAPI_BT0_LINK init_heavy_link;
|
|
OCTAPI_BT0_LINK init_leaf_tree[3];
|
|
|
|
/* Save pertinent initial OCTAPI_BT0_LINK information.*/
|
|
init_root_link = *root_link;
|
|
init_leaf_tree[0] = bb->node[root_link->node_number].l[0];
|
|
init_heavy_link = bb->node[root_link->node_number].l[1];
|
|
init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[0];
|
|
init_leaf_tree[2] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[1];
|
|
|
|
/* Restructure the tree.*/
|
|
*root_link = init_heavy_link;
|
|
bb->node[init_heavy_link.node_number].l[0] = init_root_link;
|
|
bb->node[init_root_link.node_number].l[1] = init_leaf_tree[1];
|
|
|
|
/* Reconstruct the depth of the branches.*/
|
|
OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[0]));
|
|
OctApiBt0UpdateLinkDepth(bb,root_link);
|
|
}
|
|
else if (bb->node[root_link->node_number].l[0].depth > bb->node[root_link->node_number].l[1].depth) /* Exterior of tree is towards the right.*/
|
|
{
|
|
OCTAPI_BT0_LINK init_root_link;
|
|
OCTAPI_BT0_LINK init_heavy_link;
|
|
OCTAPI_BT0_LINK init_leaf_tree[3];
|
|
|
|
/* Save pertinent initial OCTAPI_BT0_LINK information.*/
|
|
init_root_link = *root_link;
|
|
init_leaf_tree[0] = bb->node[root_link->node_number].l[1];
|
|
init_heavy_link = bb->node[root_link->node_number].l[0];
|
|
init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[1];
|
|
init_leaf_tree[2] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[0];
|
|
|
|
/* Restructure the tree.*/
|
|
*root_link = init_heavy_link;
|
|
bb->node[init_heavy_link.node_number].l[1] = init_root_link;
|
|
bb->node[init_root_link.node_number].l[0] = init_leaf_tree[1];
|
|
|
|
/* Reconstruct the depth of the branches.*/
|
|
OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[1]));
|
|
OctApiBt0UpdateLinkDepth(bb,root_link);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/* State:*/
|
|
/* 0 = seeking node to be removed.*/
|
|
/* 1 = node found, left branch taken.*/
|
|
/* 2 = node found, right branch taken.*/
|
|
#if !SKIP_OctApiBt0RemoveNode2
|
|
UINT32 OctApiBt0RemoveNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey, OCTAPI_BT0_LINK * link_to_removed_node, UINT32 state, OCTAPI_BT0_LINK * volatile_grandparent_link)
|
|
{
|
|
UINT32 result;
|
|
OCTAPI_BT0_NODE * this_node;
|
|
|
|
/* Get a pointer to this node.*/
|
|
this_node = &(bb->node[link->node_number]);
|
|
|
|
if (state == 0)
|
|
{
|
|
if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/
|
|
{
|
|
return(OCTAPI_BT0_KEY_NOT_IN_TREE);
|
|
}
|
|
else /* Current node is used, check for a match and a direction.*/
|
|
{
|
|
UINT32 compare;
|
|
|
|
/* Compare this node to the lkey.*/
|
|
compare = OctApiBt0KeyCompare(bb,link,lkey);
|
|
|
|
if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/
|
|
{
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, 0, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/
|
|
{
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, 0, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else
|
|
{
|
|
link_to_removed_node = link;
|
|
|
|
/* Keep on going down to find a replacement node.*/
|
|
if (bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF)
|
|
{
|
|
/* Doe! No tree left! WHAT TO DO? */
|
|
/* Just delete the current node. That's it.*/
|
|
|
|
/* Release the current node (restore free node link-list)*/
|
|
bb->node[link->node_number].next_free_node = bb->next_free_node;
|
|
bb->next_free_node = link->node_number;
|
|
|
|
link->node_number = 0xFFFFFFFF;
|
|
link->depth = 0;
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else if (bb->node[link->node_number].l[0].node_number != 0xFFFFFFFF) /* Left node is present. Go left, then permanently right.*/
|
|
{
|
|
OCTAPI_BT0_NODE * removed_node_pnt;
|
|
removed_node_pnt = &(bb->node[link->node_number]);
|
|
|
|
result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[0]), lkey, link_to_removed_node, 1, link);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/
|
|
/* but is about to be discarded! Save it quickly!*/
|
|
/* bb->node[link->node_number].l[0] = removed_node_pnt->l[0];*/
|
|
}
|
|
else /* Right node is present. Go right, then permanently left.*/
|
|
{
|
|
OCTAPI_BT0_NODE * removed_node_pnt;
|
|
removed_node_pnt = &(bb->node[link->node_number]);
|
|
|
|
result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[1]), lkey, link_to_removed_node, 2, link);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/
|
|
/* but is about to be discarded! Save it quickly!*/
|
|
/* bb->node[link->node_number].l[1] = removed_node_pnt->l[1];*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Left side, Right-most node found! OR*/
|
|
/* Right side, Left-most node found!*/
|
|
if ((state == 1 && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) ||
|
|
(state == 2 && bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF))
|
|
{
|
|
OCTAPI_BT0_LINK init_chosen_link;
|
|
|
|
/* Release the current node (restore free node link-list)*/
|
|
bb->node[link_to_removed_node->node_number].next_free_node = bb->next_free_node;
|
|
bb->next_free_node = link_to_removed_node->node_number;
|
|
|
|
/* Save the link to the chosen node, because it is about to be deleted.*/
|
|
init_chosen_link = *link;
|
|
|
|
/* Remove this node, and allow the tree to go on:*/
|
|
{
|
|
OCTAPI_BT0_LINK init_child_link[2];
|
|
|
|
init_child_link[0] = bb->node[link->node_number].l[0];
|
|
init_child_link[1] = bb->node[link->node_number].l[1];
|
|
|
|
if (state == 1)
|
|
*link = init_child_link[0];
|
|
else
|
|
*link = init_child_link[1];
|
|
}
|
|
|
|
/* Replace the removed node by this node.*/
|
|
{
|
|
OCTAPI_BT0_LINK init_removed_child_link[2];
|
|
|
|
init_removed_child_link[0] = bb->node[link_to_removed_node->node_number].l[0];
|
|
init_removed_child_link[1] = bb->node[link_to_removed_node->node_number].l[1];
|
|
|
|
*link_to_removed_node = init_chosen_link;
|
|
bb->node[init_chosen_link.node_number].l[0] = init_removed_child_link[0];
|
|
bb->node[init_chosen_link.node_number].l[1] = init_removed_child_link[1];
|
|
}
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else
|
|
{
|
|
/* Keep on going, we have not found the center most node yet!*/
|
|
if (state == 1)
|
|
{
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, state, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Refresh the link if our link is volatile.*/
|
|
if (volatile_grandparent_link != NULL)
|
|
{
|
|
link = &(bb->node[volatile_grandparent_link->node_number].l[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, state, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Refresh the link if our link is volatile.*/
|
|
if (volatile_grandparent_link != NULL)
|
|
{
|
|
link = &(bb->node[volatile_grandparent_link->node_number].l[1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* We may have messed up the tree. So patch it!*/
|
|
/* Check if this node is unbalanced by 2. If so, rebalance it:*/
|
|
if (this_node->l[0].depth > (this_node->l[1].depth + 1) ||
|
|
this_node->l[1].depth > (this_node->l[0].depth + 1))
|
|
{
|
|
OctApiBt0Rebalance(bb,link);
|
|
}
|
|
|
|
/* Always update the OCTAPI_BT0_LINK depth before exiting.*/
|
|
OctApiBt0UpdateLinkDepth(bb,link);
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
|
|
/* State:*/
|
|
/* 0 = seeking node to be removed.*/
|
|
/* 1 = node found, left branch taken.*/
|
|
/* 2 = node found, right branch taken.*/
|
|
#if !SKIP_OctApiBt0RemoveNode3
|
|
UINT32 OctApiBt0RemoveNode3(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey, OCTAPI_BT0_LINK * link_to_removed_node, UINT32 state, OCTAPI_BT0_LINK * volatile_grandparent_link, UINT32 *p_prev_node_number )
|
|
{
|
|
UINT32 result;
|
|
UINT32 *nkey;
|
|
UINT32 *okey;
|
|
OCTAPI_BT0_NODE * this_node;
|
|
|
|
/* Get a pointer to this node.*/
|
|
this_node = &(bb->node[link->node_number]);
|
|
|
|
if (state == 0)
|
|
{
|
|
if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/
|
|
{
|
|
return(OCTAPI_BT0_KEY_NOT_IN_TREE);
|
|
}
|
|
else /* Current node is used, check for a match and a direction.*/
|
|
{
|
|
UINT32 compare;
|
|
|
|
/* Compare this node to the lkey.*/
|
|
compare = OctApiBt0KeyCompare(bb,link,lkey);
|
|
|
|
if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/
|
|
{
|
|
/* Check if the key is the biggest one encountered yet.*/
|
|
okey = &(bb->key[bb->key_size * (*p_prev_node_number)]);
|
|
nkey = &(bb->key[bb->key_size * link->node_number]);
|
|
/* If the node is key bigger then the old one, change the value.*/
|
|
if ( *nkey > *okey )
|
|
{
|
|
if ( *nkey < *lkey )
|
|
*p_prev_node_number = link->node_number;
|
|
}
|
|
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, 0, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/
|
|
{
|
|
/* Check if the key is the biggest one encountered yet.*/
|
|
okey = &(bb->key[bb->key_size * (*p_prev_node_number)]);
|
|
nkey = &(bb->key[bb->key_size * link->node_number]);
|
|
/* If the node is key bigger then the old one, change the value.*/
|
|
if ( *nkey > *okey )
|
|
{
|
|
if ( *nkey < *lkey )
|
|
*p_prev_node_number = link->node_number;
|
|
}
|
|
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, 0, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else
|
|
{
|
|
link_to_removed_node = link;
|
|
|
|
/* Keep on going down to find a replacement node.*/
|
|
if (bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF)
|
|
{
|
|
/* Doe! No tree left! WHAT TO DO? */
|
|
/* Just delete the current node. That's it.*/
|
|
|
|
/* Release the current node (restore free node link-list)*/
|
|
bb->node[link->node_number].next_free_node = bb->next_free_node;
|
|
bb->next_free_node = link->node_number;
|
|
|
|
link->node_number = 0xFFFFFFFF;
|
|
link->depth = 0;
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else if (bb->node[link->node_number].l[0].node_number != 0xFFFFFFFF) /* Left node is present. Go left, then permanently right.*/
|
|
{
|
|
OCTAPI_BT0_NODE * removed_node_pnt;
|
|
removed_node_pnt = &(bb->node[link->node_number]);
|
|
|
|
result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[0]), lkey, link_to_removed_node, 1, link);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/
|
|
/* but is about to be discarded! Save it quickly!*/
|
|
/* bb->node[link->node_number].l[0] = removed_node_pnt->l[0];*/
|
|
}
|
|
else /* Right node is present. Go right, then permanently left.*/
|
|
{
|
|
OCTAPI_BT0_NODE * removed_node_pnt;
|
|
removed_node_pnt = &(bb->node[link->node_number]);
|
|
|
|
result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[1]), lkey, link_to_removed_node, 2, link);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/
|
|
/* but is about to be discarded! Save it quickly!*/
|
|
/* bb->node[link->node_number].l[1] = removed_node_pnt->l[1];*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Check if the key is the biggest one encountered yet.*/
|
|
okey = &(bb->key[bb->key_size * (*p_prev_node_number)]);
|
|
nkey = &(bb->key[bb->key_size * link->node_number]);
|
|
/* If the node is key bigger then the old one, change the value.*/
|
|
if ( *nkey > *okey )
|
|
{
|
|
if ( *nkey < *lkey )
|
|
*p_prev_node_number = link->node_number;
|
|
}
|
|
|
|
/* Left side, Right-most node found! OR*/
|
|
/* Right side, Left-most node found!*/
|
|
if ((state == 1 && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) ||
|
|
(state == 2 && bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF))
|
|
{
|
|
OCTAPI_BT0_LINK init_chosen_link;
|
|
|
|
/* Release the current node (restore free node link-list)*/
|
|
bb->node[link_to_removed_node->node_number].next_free_node = bb->next_free_node;
|
|
bb->next_free_node = link_to_removed_node->node_number;
|
|
|
|
/* Save the link to the chosen node, because it is about to be deleted.*/
|
|
init_chosen_link = *link;
|
|
|
|
/* Remove this node, and allow the tree to go on:*/
|
|
{
|
|
OCTAPI_BT0_LINK init_child_link[2];
|
|
|
|
init_child_link[0] = bb->node[link->node_number].l[0];
|
|
init_child_link[1] = bb->node[link->node_number].l[1];
|
|
|
|
if (state == 1)
|
|
*link = init_child_link[0];
|
|
else
|
|
*link = init_child_link[1];
|
|
}
|
|
|
|
/* Replace the removed node by this node.*/
|
|
{
|
|
OCTAPI_BT0_LINK init_removed_child_link[2];
|
|
|
|
init_removed_child_link[0] = bb->node[link_to_removed_node->node_number].l[0];
|
|
init_removed_child_link[1] = bb->node[link_to_removed_node->node_number].l[1];
|
|
|
|
*link_to_removed_node = init_chosen_link;
|
|
bb->node[init_chosen_link.node_number].l[0] = init_removed_child_link[0];
|
|
bb->node[init_chosen_link.node_number].l[1] = init_removed_child_link[1];
|
|
}
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
else
|
|
{
|
|
/* Keep on going, we have not found the center most node yet!*/
|
|
if (state == 1)
|
|
{
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, state, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Refresh the link if our link is volatile.*/
|
|
if (volatile_grandparent_link != NULL)
|
|
{
|
|
link = &(bb->node[volatile_grandparent_link->node_number].l[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, state, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Refresh the link if our link is volatile.*/
|
|
if (volatile_grandparent_link != NULL)
|
|
{
|
|
link = &(bb->node[volatile_grandparent_link->node_number].l[1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* We may have messed up the tree. So patch it!*/
|
|
/* Check if this node is unbalanced by 2. If so, rebalance it:*/
|
|
if (this_node->l[0].depth > (this_node->l[1].depth + 1) ||
|
|
this_node->l[1].depth > (this_node->l[0].depth + 1))
|
|
{
|
|
OctApiBt0Rebalance(bb,link);
|
|
}
|
|
|
|
/* Always update the OCTAPI_BT0_LINK depth before exiting.*/
|
|
OctApiBt0UpdateLinkDepth(bb,link);
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0RemoveNode
|
|
UINT32 OctApiBt0RemoveNode(void * b,void * key)
|
|
{
|
|
OCTAPI_BT0 * bb;
|
|
UINT32 result;
|
|
UINT32 * lkey;
|
|
|
|
/* Load all!*/
|
|
bb = (OCTAPI_BT0 *)(b);
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Register in the key and the data.*/
|
|
lkey = ((UINT32 *)key);
|
|
|
|
/* Attempt to remove the node. Only a "no hit" will cause an error.*/
|
|
result = OctApiBt0RemoveNode2(bb,&(bb->root_link), lkey, NULL, 0, NULL);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0QueryNode2
|
|
UINT32 OctApiBt0QueryNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 * node_number)
|
|
{
|
|
UINT32 result;
|
|
|
|
if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/
|
|
{
|
|
return(OCTAPI_BT0_KEY_NOT_IN_TREE);
|
|
}
|
|
else /* Current node is used, check for a match and a direction.*/
|
|
{
|
|
UINT32 compare;
|
|
|
|
/* Compare this node to the lkey.*/
|
|
compare = OctApiBt0KeyCompare(bb,link,lkey);
|
|
|
|
if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/
|
|
{
|
|
result = OctApiBt0QueryNode2(bb,&(bb->node[link->node_number].l[0]), lkey, node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/
|
|
{
|
|
result = OctApiBt0QueryNode2(bb,&(bb->node[link->node_number].l[1]), lkey, node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
}
|
|
else
|
|
{
|
|
/* A match!*/
|
|
*node_number = link->node_number;
|
|
}
|
|
}
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !SKIP_OctApiBt0QueryNode
|
|
UINT32 OctApiBt0QueryNode(void * b,void * key,void ** data)
|
|
{
|
|
OCTAPI_BT0 * bb;
|
|
UINT32 node_number;
|
|
UINT32 result;
|
|
UINT32 * lkey;
|
|
|
|
/* Load all!*/
|
|
bb = (OCTAPI_BT0 *)(b);
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Register in the key and the data.*/
|
|
lkey = ((UINT32 *)key);
|
|
|
|
/* Get the node number.*/
|
|
result = OctApiBt0QueryNode2(bb,&(bb->root_link),lkey,&node_number);
|
|
if (result != GENERIC_OK) return(result);
|
|
|
|
/* Return the address of the data to the user.*/
|
|
if ( bb->data_size > 0 )
|
|
*data = (void *)(&(bb->data[bb->data_size * node_number]));
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0GetFirstNode
|
|
UINT32 OctApiBt0GetFirstNode(void * b,void ** key, void ** data)
|
|
{
|
|
OCTAPI_BT0 * bb;
|
|
OCTAPI_BT0_NODE * node;
|
|
UINT32 node_number;
|
|
UINT32 * lkey;
|
|
|
|
/* Load all!*/
|
|
bb = (OCTAPI_BT0 *)(b);
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Register in the key and the data.*/
|
|
lkey = ((UINT32 *)key);
|
|
|
|
/* Check if there are any keys present in the tree. */
|
|
if (bb->root_link.node_number == 0xFFFFFFFF) return OCTAPI_BT0_NO_NODES_AVAILABLE;
|
|
|
|
node_number = bb->root_link.node_number;
|
|
node = &bb->node[node_number];
|
|
|
|
/* Make our way down to the left-most node. */
|
|
while (node->l[0].node_number != 0xFFFFFFFF)
|
|
{
|
|
node_number = node->l[0].node_number;
|
|
node = &bb->node[node_number];
|
|
}
|
|
|
|
/* Return the address of the data to the user.*/
|
|
if ( bb->key_size > 0 )
|
|
*key = (void *)(&(bb->key[bb->key_size * node_number]));
|
|
|
|
if ( bb->data_size > 0 )
|
|
*data = (void *)(&(bb->data[bb->data_size * node_number]));
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
#if !SKIP_OctApiBt0FindOrAddNode
|
|
UINT32 OctApiBt0FindOrAddNode(void * b,void * key,void ** data, UINT32 *fnct_result)
|
|
{
|
|
OCTAPI_BT0 * bb;
|
|
OCTAPI_BT0_NODE * new_node;
|
|
UINT32 * lkey;
|
|
UINT32 * nkey;
|
|
UINT32 i;
|
|
UINT32 new_node_number;
|
|
UINT32 temp_node_number = 0;
|
|
UINT32 result;
|
|
UINT32 tree_already_full = FALSE;
|
|
|
|
/* Load all!*/
|
|
bb = (OCTAPI_BT0 *)(b);
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Seize the node!*/
|
|
new_node_number = bb->next_free_node;
|
|
/* Register in the key and the data.*/
|
|
lkey = ((UINT32 *)key);
|
|
|
|
/* Check that there is at least one block left.*/
|
|
if (bb->next_free_node != 0xFFFFFFFF)
|
|
{
|
|
|
|
temp_node_number = new_node_number;
|
|
new_node = &(bb->node[new_node_number]);
|
|
bb->next_free_node = new_node->next_free_node;
|
|
|
|
/* Find the first UINT32 of the key.*/
|
|
nkey = &(bb->key[bb->key_size * new_node_number]);
|
|
|
|
/* Copy the key.*/
|
|
for(i=0;i<bb->key_size;i++)
|
|
nkey[i] = lkey[i];
|
|
}
|
|
else
|
|
tree_already_full = TRUE; /* Signal that the tree was already full when the function was called.*/
|
|
|
|
/* Attempt to place the node. Only a "multiple hit" will cause an error.*/
|
|
result = OctApiBt0AddNode3(bb,&(bb->root_link), lkey, &new_node_number);
|
|
switch( result )
|
|
{
|
|
case GENERIC_OK:
|
|
*fnct_result = OCTAPI0_BT0_NODE_ADDDED;
|
|
break;
|
|
case OCTAPI_BT0_KEY_ALREADY_IN_TREE:
|
|
*fnct_result = OCTAPI0_BT0_NODE_FOUND;
|
|
/* This attempt did not add a new node. Refree the node!*/
|
|
if ( tree_already_full == FALSE )
|
|
bb->next_free_node = temp_node_number;
|
|
result = GENERIC_OK;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (result != GENERIC_OK)
|
|
{
|
|
/* This attempt failed. Refree the node!*/
|
|
if ( tree_already_full == FALSE )
|
|
bb->next_free_node = new_node_number;
|
|
|
|
/* Return the error code.*/
|
|
return(result);
|
|
}
|
|
|
|
/* Return the address of the data to the user.*/
|
|
if ( bb->data_size > 0 )
|
|
*data = (void *)(&(bb->data[bb->data_size * new_node_number]));
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !SKIP_OctApiBt0AddNodeReportPrevNodeData
|
|
UINT32 OctApiBt0AddNodeReportPrevNodeData(void * b,void * key,void ** data, void ** prev_data, PUINT32 fnct_result )
|
|
{
|
|
OCTAPI_BT0 * bb;
|
|
OCTAPI_BT0_NODE * new_node;
|
|
UINT32 * lkey;
|
|
UINT32 * nkey;
|
|
UINT32 i;
|
|
UINT32 new_node_number;
|
|
UINT32 temp_node_number;
|
|
UINT32 prev_node_number;
|
|
UINT32 result;
|
|
|
|
/* Load all!*/
|
|
bb = (OCTAPI_BT0 *)(b);
|
|
OctApiBt0CorrectPointers(bb);
|
|
|
|
/* Check that there is at least one block left.*/
|
|
if (bb->next_free_node == 0xFFFFFFFF) return(OCTAPI_BT0_NO_NODES_AVAILABLE);
|
|
|
|
/* Seize the node!*/
|
|
new_node_number = bb->next_free_node;
|
|
temp_node_number = new_node_number;
|
|
new_node = &(bb->node[new_node_number]);
|
|
bb->next_free_node = new_node->next_free_node;
|
|
|
|
/* Set the previous node value */
|
|
prev_node_number = 0xFFFFFFFF;
|
|
|
|
/* Register in the key and the data.*/
|
|
lkey = ((UINT32 *)key);
|
|
|
|
/* Find the first UINT32 of the key.*/
|
|
nkey = &(bb->key[bb->key_size * new_node_number]);
|
|
|
|
/* Copy the key.*/
|
|
for(i=0;i<bb->key_size;i++)
|
|
nkey[i] = lkey[i];
|
|
|
|
/* Attempt to place the node. Only a "multiple hit" will cause an error.*/
|
|
result = OctApiBt0AddNode4(bb,&(bb->root_link), lkey, &new_node_number, &prev_node_number, 0);
|
|
switch( result )
|
|
{
|
|
case GENERIC_OK:
|
|
*fnct_result = OCTAPI0_BT0_NODE_ADDDED;
|
|
break;
|
|
case OCTAPI_BT0_KEY_ALREADY_IN_TREE:
|
|
*fnct_result = OCTAPI0_BT0_NODE_FOUND;
|
|
/* This attempt did not add a new node. Refree the node!*/
|
|
bb->next_free_node = temp_node_number;
|
|
result = GENERIC_OK;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (result != GENERIC_OK)
|
|
{
|
|
/* This attempt failed. Refree the node!*/
|
|
bb->next_free_node = new_node_number;
|
|
|
|
/* Return the error code.*/
|
|
return(result);
|
|
}
|
|
|
|
/* Return the address of the data to the user.*/
|
|
if ( bb->data_size > 0 )
|
|
*data = (void *)(&(bb->data[bb->data_size * new_node_number]));
|
|
|
|
if ( bb->data_size > 0 )
|
|
{
|
|
if ( (prev_node_number != 0xFFFFFFFF) &&
|
|
(prev_node_number != OCTAPI_BT0_NO_SMALLER_KEY) &&
|
|
(*fnct_result == OCTAPI0_BT0_NODE_ADDDED))
|
|
*prev_data = ( void* )(&(bb->data[bb->data_size * prev_node_number]));
|
|
else if ( prev_node_number == 0xFFFFFFFF )
|
|
*prev_data = ( void* )(&bb->invalid_value);
|
|
else if ( prev_node_number == OCTAPI_BT0_NO_SMALLER_KEY )
|
|
*prev_data = ( void* )(&bb->no_smaller_key);
|
|
}
|
|
|
|
return(GENERIC_OK);
|
|
}
|
|
#endif
|
|
|