forked from enlightenment/efl
453 lines
15 KiB
C
453 lines
15 KiB
C
/* EINA - EFL data type library
|
|
* Copyright (C) 2008 Cedric Bail
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library;
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
#include "eina_suite.h"
|
|
#include "Eina.h"
|
|
|
|
static inline Eina_Bool
|
|
_eina_rbtree_is_red(Eina_Rbtree *tree)
|
|
{
|
|
return !!tree && tree->color == EINA_RBTREE_RED;
|
|
}
|
|
|
|
static int
|
|
_eina_rbtree_black_height(Eina_Rbtree *tree, Eina_Rbtree_Cmp_Node_Cb cmp)
|
|
{
|
|
Eina_Rbtree *left;
|
|
Eina_Rbtree *right;
|
|
Eina_Rbtree_Direction dir;
|
|
int left_height;
|
|
int right_height;
|
|
|
|
if (!tree)
|
|
return 1;
|
|
|
|
left = tree->son[EINA_RBTREE_LEFT];
|
|
right = tree->son[EINA_RBTREE_RIGHT];
|
|
|
|
/* Consecutive red links. */
|
|
fail_if(_eina_rbtree_is_red(tree) &&
|
|
(_eina_rbtree_is_red(left) || _eina_rbtree_is_red(right)));
|
|
|
|
left_height = _eina_rbtree_black_height(left, cmp);
|
|
right_height = _eina_rbtree_black_height(right, cmp);
|
|
|
|
/* Check binary search tree. */
|
|
if (left)
|
|
{
|
|
dir = cmp(tree, left, NULL);
|
|
fail_if(dir != EINA_RBTREE_LEFT);
|
|
}
|
|
|
|
if (right)
|
|
{
|
|
dir = cmp(tree, right, NULL);
|
|
fail_if(dir != EINA_RBTREE_RIGHT);
|
|
}
|
|
|
|
/* Check black height */
|
|
if (left_height != right_height)
|
|
fprintf(stderr, "%i != %i\n", left_height, right_height);
|
|
|
|
fail_if(left_height != right_height);
|
|
|
|
return _eina_rbtree_is_red(tree) ? left_height : left_height + 1;
|
|
}
|
|
|
|
typedef struct _Eina_Rbtree_Int Eina_Rbtree_Int;
|
|
struct _Eina_Rbtree_Int
|
|
{
|
|
Eina_Rbtree node;
|
|
int value;
|
|
};
|
|
|
|
static Eina_Rbtree_Direction
|
|
eina_rbtree_int_cmp(const Eina_Rbtree_Int *left,
|
|
const Eina_Rbtree_Int *right,
|
|
__UNUSED__ void *data)
|
|
{
|
|
fail_if(!left);
|
|
fail_if(!right);
|
|
|
|
if (left->value < right->value)
|
|
return EINA_RBTREE_LEFT;
|
|
|
|
return EINA_RBTREE_RIGHT;
|
|
}
|
|
|
|
static int
|
|
eina_rbtree_int_key(const Eina_Rbtree_Int *node,
|
|
const int *key,
|
|
__UNUSED__ int length,
|
|
__UNUSED__ void *data)
|
|
{
|
|
fail_if(!node);
|
|
return node->value - *key;
|
|
}
|
|
|
|
static Eina_Rbtree_Int *
|
|
_eina_rbtree_int_new(int value)
|
|
{
|
|
Eina_Rbtree_Int *it;
|
|
|
|
it = malloc(sizeof (Eina_Rbtree_Int));
|
|
fail_if(!it);
|
|
|
|
it->value = value;
|
|
|
|
return it;
|
|
}
|
|
|
|
START_TEST(eina_rbtree_insertion)
|
|
{
|
|
Eina_Rbtree_Int *root = NULL;
|
|
Eina_Rbtree_Int *item;
|
|
int i;
|
|
|
|
srand(time(NULL));
|
|
|
|
for (i = 0; i < 500; ++i)
|
|
{
|
|
item = _eina_rbtree_int_new(rand());
|
|
root = (Eina_Rbtree_Int *)eina_rbtree_inline_insert(
|
|
&root->node,
|
|
&item->node,
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp),
|
|
NULL);
|
|
}
|
|
|
|
_eina_rbtree_black_height(&root->node,
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(eina_rbtree_lookup)
|
|
{
|
|
Eina_Rbtree_Int *root = NULL;
|
|
Eina_Rbtree_Int *item;
|
|
int list[] = { 50, 100, 10, 43, 23 };
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < sizeof (list) / sizeof (int); ++i)
|
|
{
|
|
item = _eina_rbtree_int_new(list[i]);
|
|
root = (Eina_Rbtree_Int *)eina_rbtree_inline_insert(
|
|
&root->node,
|
|
&item->node,
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp),
|
|
NULL);
|
|
}
|
|
|
|
item = (Eina_Rbtree_Int *)eina_rbtree_inline_lookup(&root->node,
|
|
&list[0],
|
|
sizeof(int),
|
|
EINA_RBTREE_CMP_KEY_CB(
|
|
eina_rbtree_int_key),
|
|
NULL);
|
|
fail_if(!item);
|
|
|
|
i = 42;
|
|
item =
|
|
(Eina_Rbtree_Int *)eina_rbtree_inline_lookup(&root->node,
|
|
&i,
|
|
sizeof(int),
|
|
EINA_RBTREE_CMP_KEY_CB(
|
|
eina_rbtree_int_key),
|
|
NULL);
|
|
fail_if(item);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(eina_rbtree_remove)
|
|
{
|
|
Eina_Rbtree_Int *root = NULL;
|
|
Eina_Rbtree_Int *item;
|
|
Eina_Array *ea;
|
|
Eina_Array_Iterator it;
|
|
unsigned int i;
|
|
|
|
eina_init();
|
|
|
|
ea = eina_array_new(11);
|
|
fail_if(!ea);
|
|
|
|
srand(time(NULL));
|
|
|
|
for (i = 0; i < 500; ++i)
|
|
{
|
|
item = _eina_rbtree_int_new(rand());
|
|
eina_array_push(ea, item);
|
|
root = (Eina_Rbtree_Int *)eina_rbtree_inline_insert(
|
|
&root->node,
|
|
&item->node,
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp),
|
|
NULL);
|
|
}
|
|
|
|
_eina_rbtree_black_height(&root->node,
|
|
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
|
|
EINA_ARRAY_ITER_NEXT(ea, i, item, it)
|
|
{
|
|
root = (Eina_Rbtree_Int *)eina_rbtree_inline_remove(
|
|
&root->node,
|
|
&item->node,
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp),
|
|
NULL);
|
|
_eina_rbtree_black_height(&root->node,
|
|
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
}
|
|
|
|
fail_if(root != NULL);
|
|
|
|
eina_shutdown();
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(eina_rbtree_simple_remove)
|
|
{
|
|
Eina_Rbtree *root = NULL;
|
|
Eina_Rbtree *lookup;
|
|
int i;
|
|
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
10),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
42),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
69),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1337),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
_eina_rbtree_black_height(root,
|
|
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
|
|
fail_if(!root);
|
|
|
|
i = 69;
|
|
lookup = eina_rbtree_inline_lookup(root,
|
|
&i,
|
|
sizeof (int),
|
|
EINA_RBTREE_CMP_KEY_CB(
|
|
eina_rbtree_int_key),
|
|
NULL);
|
|
_eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
fail_if(!lookup);
|
|
|
|
root =
|
|
eina_rbtree_inline_remove(root, lookup, EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
|
|
_eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(eina_rbtree_simple_remove2)
|
|
{
|
|
Eina_Rbtree *root = NULL;
|
|
Eina_Rbtree *lookup;
|
|
int i;
|
|
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
10),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
42),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
69),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1337),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
77),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
75),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
81),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
_eina_rbtree_black_height(root,
|
|
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
|
|
fail_if(!root);
|
|
|
|
i = 69;
|
|
lookup = eina_rbtree_inline_lookup(root,
|
|
&i,
|
|
sizeof (int),
|
|
EINA_RBTREE_CMP_KEY_CB(
|
|
eina_rbtree_int_key),
|
|
NULL);
|
|
_eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
fail_if(!lookup);
|
|
|
|
root =
|
|
eina_rbtree_inline_remove(root, lookup, EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
|
|
_eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(eina_rbtree_simple_remove3)
|
|
{
|
|
Eina_Rbtree *root = NULL;
|
|
Eina_Rbtree *lookup;
|
|
int i;
|
|
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1113497590),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
499187507),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1693860487),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
26211080),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
797272577),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1252184882),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1448158229),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1821884856),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
346086006),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
936357333),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1462073936),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1717320055),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
root =
|
|
eina_rbtree_inline_insert(root, (Eina_Rbtree *)_eina_rbtree_int_new(
|
|
1845524606),
|
|
EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
_eina_rbtree_black_height(root,
|
|
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
|
|
fail_if(!root);
|
|
|
|
i = 1113497590;
|
|
lookup = eina_rbtree_inline_lookup(root,
|
|
&i,
|
|
sizeof (int),
|
|
EINA_RBTREE_CMP_KEY_CB(
|
|
eina_rbtree_int_key),
|
|
NULL);
|
|
_eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
fail_if(!lookup);
|
|
|
|
root =
|
|
eina_rbtree_inline_remove(root, lookup, EINA_RBTREE_CMP_NODE_CB(
|
|
eina_rbtree_int_cmp), NULL);
|
|
|
|
_eina_rbtree_black_height(root, EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
|
|
}
|
|
END_TEST
|
|
|
|
void
|
|
eina_test_rbtree(TCase *tc)
|
|
{
|
|
tcase_add_test(tc, eina_rbtree_insertion);
|
|
tcase_add_test(tc, eina_rbtree_lookup);
|
|
tcase_add_test(tc, eina_rbtree_remove);
|
|
tcase_add_test(tc, eina_rbtree_simple_remove);
|
|
tcase_add_test(tc, eina_rbtree_simple_remove2);
|
|
tcase_add_test(tc, eina_rbtree_simple_remove3);
|
|
}
|
|
|