forked from enlightenment/efl
eina: fix eina inlist sorted insert (with and without state)
SVN revision: 63398
This commit is contained in:
parent
d5a1614b2f
commit
60d03bc2d2
|
@ -674,13 +674,14 @@ EAPI Eina_Inlist_Sorted_State *eina_inlist_sorted_state_new(void);
|
|||
*
|
||||
* @param state The state to update
|
||||
* @param list The list to match
|
||||
* @return The number of item in the actually in the list
|
||||
* @since 1.1.0
|
||||
*
|
||||
* See eina_inlist_sorted_state_insert() for more information. This function is
|
||||
* usefull if you didn't use eina_inlist_sorted_state_insert() at some point, but
|
||||
* still think you have a sorted list. It will only correctly work on a sorted list.
|
||||
*/
|
||||
EAPI void eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list);
|
||||
EAPI int eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list);
|
||||
|
||||
/**
|
||||
* @brief Free an Eina_Inlist_Sorted_State.
|
||||
|
|
|
@ -190,6 +190,21 @@ eina_inlist_sort_rebuild_prev(Eina_Inlist *list)
|
|||
return prev;
|
||||
}
|
||||
|
||||
static void
|
||||
_eina_inlist_sorted_state_compact(Eina_Inlist_Sorted_State *state)
|
||||
{
|
||||
unsigned short i, j;
|
||||
|
||||
/* compress the jump table */
|
||||
state->jump_div *= 2;
|
||||
state->jump_limit /= 2;
|
||||
|
||||
for (i = 2, j = 1;
|
||||
i < EINA_INLIST_JUMP_SIZE;
|
||||
i += 2, j++)
|
||||
state->jump_table[j] = state->jump_table[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @endcond
|
||||
*/
|
||||
|
@ -434,7 +449,7 @@ eina_inlist_count(const Eina_Inlist *list)
|
|||
return i;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
EAPI int
|
||||
eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list)
|
||||
{
|
||||
Eina_Inlist *ct = NULL;
|
||||
|
@ -451,16 +466,7 @@ eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list
|
|||
{
|
||||
if (state->jump_limit == EINA_INLIST_JUMP_SIZE)
|
||||
{
|
||||
unsigned short i, j;
|
||||
|
||||
/* compress the jump table */
|
||||
state->jump_div *= 2;
|
||||
state->jump_limit /= 2;
|
||||
|
||||
for (i = 2, j = 1;
|
||||
i < EINA_INLIST_JUMP_SIZE;
|
||||
i += 2, j++)
|
||||
state->jump_table[j] = state->jump_table[i];
|
||||
_eina_inlist_sorted_state_compact(state);
|
||||
}
|
||||
|
||||
state->jump_table[state->jump_limit] = ct;
|
||||
|
@ -468,6 +474,9 @@ eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list
|
|||
jump_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
state->inserted = count;
|
||||
return count;
|
||||
}
|
||||
|
||||
EAPI Eina_Inlist_Sorted_State *
|
||||
|
@ -496,6 +505,7 @@ _eina_inlist_sorted_state_insert(Eina_Inlist_Sorted_State *state,
|
|||
{
|
||||
Eina_Inlist *last;
|
||||
int jump_count;
|
||||
int start;
|
||||
|
||||
state->inserted++;
|
||||
|
||||
|
@ -505,28 +515,36 @@ _eina_inlist_sorted_state_insert(Eina_Inlist_Sorted_State *state,
|
|||
state->jump_table[index] = state->jump_table[index]->prev;
|
||||
}
|
||||
|
||||
last = state->jump_table[state->jump_limit - 1];
|
||||
for (jump_count = 0; last != NULL; last = last->next)
|
||||
jump_count++;
|
||||
start = state->jump_limit - 3;
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
|
||||
if (jump_count == state->jump_div + 1)
|
||||
last = state->jump_table[start];
|
||||
start++;
|
||||
|
||||
/* Correctly rebuild end of list */
|
||||
for (jump_count = 0; last->next != NULL; last = last->next, jump_count++)
|
||||
{
|
||||
if (jump_count == state->jump_div)
|
||||
{
|
||||
if (state->jump_limit == start)
|
||||
{
|
||||
if (state->jump_limit == EINA_INLIST_JUMP_SIZE)
|
||||
{
|
||||
unsigned short i, j;
|
||||
|
||||
/* compress the jump table */
|
||||
state->jump_div *= 2;
|
||||
state->jump_limit /= 2;
|
||||
|
||||
for (i = 2, j = 1;
|
||||
i < EINA_INLIST_JUMP_SIZE;
|
||||
i += 2, j++)
|
||||
state->jump_table[j] = state->jump_table[i];
|
||||
_eina_inlist_sorted_state_compact(state);
|
||||
start = state->jump_limit - 1;
|
||||
continue ;
|
||||
}
|
||||
state->jump_table[state->jump_limit] = state->jump_table[0]->last;
|
||||
else
|
||||
{
|
||||
state->jump_limit++;
|
||||
}
|
||||
}
|
||||
|
||||
state->jump_table[start++] = last;
|
||||
jump_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Eina_Inlist *
|
||||
|
@ -539,7 +557,7 @@ eina_inlist_sorted_insert(Eina_Inlist *list,
|
|||
int cmp = 0;
|
||||
int inf, sup;
|
||||
int cur = 0;
|
||||
int count = 0;
|
||||
int count;
|
||||
|
||||
if (!list) return eina_inlist_append(NULL, item);
|
||||
|
||||
|
@ -554,7 +572,7 @@ eina_inlist_sorted_insert(Eina_Inlist *list,
|
|||
|
||||
state.jump_div = 1;
|
||||
state.jump_limit = 0;
|
||||
eina_inlist_sorted_state_init(&state, list);
|
||||
count = eina_inlist_sorted_state_init(&state, list);
|
||||
|
||||
/*
|
||||
* now do a dychotomic search directly inside the jump_table.
|
||||
|
@ -600,8 +618,8 @@ eina_inlist_sorted_insert(Eina_Inlist *list,
|
|||
* Now do a dychotomic search between two entries inside the jump_table
|
||||
*/
|
||||
cur *= state.jump_div;
|
||||
inf = cur - state.jump_div;
|
||||
sup = cur + state.jump_div;
|
||||
inf = cur - state.jump_div - 1;
|
||||
sup = cur + state.jump_div + 1;
|
||||
|
||||
if (sup > count - 1) sup = count - 1;
|
||||
if (inf < 0) inf = 0;
|
||||
|
@ -632,7 +650,7 @@ eina_inlist_sorted_insert(Eina_Inlist *list,
|
|||
break;
|
||||
}
|
||||
|
||||
if (cmp < 0)
|
||||
if (cmp <= 0)
|
||||
return eina_inlist_append_relative(list, item, ct);
|
||||
return eina_inlist_prepend_relative(list, item, ct);
|
||||
}
|
||||
|
@ -647,7 +665,7 @@ eina_inlist_sorted_state_insert(Eina_Inlist *list,
|
|||
int cmp = 0;
|
||||
int inf, sup;
|
||||
int cur = 0;
|
||||
int count = 0;
|
||||
int count;
|
||||
unsigned short head;
|
||||
unsigned int offset;
|
||||
|
||||
|
@ -676,6 +694,8 @@ eina_inlist_sorted_state_insert(Eina_Inlist *list,
|
|||
return eina_inlist_prepend(list, item);
|
||||
}
|
||||
|
||||
count = state->inserted;
|
||||
|
||||
/*
|
||||
* now do a dychotomic search directly inside the jump_table.
|
||||
*/
|
||||
|
@ -728,12 +748,11 @@ eina_inlist_sorted_state_insert(Eina_Inlist *list,
|
|||
* Now do a dychotomic search between two entries inside the jump_table
|
||||
*/
|
||||
cur *= state->jump_div;
|
||||
inf = cur - state->jump_div;
|
||||
sup = cur + state->jump_div;
|
||||
inf = cur - state->jump_div - 1;
|
||||
sup = cur + state->jump_div + 1;
|
||||
|
||||
if (sup > count - 1) sup = count - 1;
|
||||
if (inf < 0)
|
||||
inf = 0;
|
||||
if (inf < 0) inf = 0;
|
||||
|
||||
while (inf <= sup)
|
||||
{
|
||||
|
@ -761,20 +780,20 @@ eina_inlist_sorted_state_insert(Eina_Inlist *list,
|
|||
break;
|
||||
}
|
||||
|
||||
if (cmp < 0)
|
||||
if (cmp <= 0)
|
||||
{
|
||||
cur++;
|
||||
head = cur / state->jump_div;
|
||||
offset = cur % state->jump_div;
|
||||
|
||||
ct = eina_inlist_append_relative(list, item, ct);
|
||||
_eina_inlist_sorted_state_insert(state, head, offset);
|
||||
return ct;
|
||||
}
|
||||
else
|
||||
{
|
||||
ct = eina_inlist_prepend_relative(list, item, ct);
|
||||
}
|
||||
|
||||
head = cur / state->jump_div;
|
||||
offset = cur % state->jump_div;
|
||||
|
||||
ct = eina_inlist_prepend_relative(list, item, ct);
|
||||
_eina_inlist_sorted_state_insert(state, head, offset);
|
||||
return ct;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ START_TEST(eina_inlist_simple)
|
|||
Eina_Test_Inlist *prev;
|
||||
int i = 0;
|
||||
|
||||
fail_if(!eina_init());
|
||||
|
||||
tmp = _eina_test_inlist_build(42);
|
||||
lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp));
|
||||
fail_if(!lst);
|
||||
|
@ -132,6 +134,8 @@ START_TEST(eina_inlist_simple)
|
|||
|
||||
while (lst)
|
||||
lst = eina_inlist_remove(lst, lst);
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
@ -172,9 +176,11 @@ START_TEST(eina_inlist_sorted)
|
|||
Eina_Inlist *sorted = NULL;
|
||||
int i;
|
||||
|
||||
fail_if(!eina_init());
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
for (i = 0; i < 1000; ++i)
|
||||
for (i = 0; i < 2000; ++i)
|
||||
{
|
||||
tmp = malloc(sizeof (Eina_Test_Inlist_Sorted));
|
||||
if (!tmp) continue ;
|
||||
|
@ -203,6 +209,39 @@ START_TEST(eina_inlist_sorted)
|
|||
}
|
||||
|
||||
_eina_test_inlist_check(sorted);
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eina_inlist_sorted_state)
|
||||
{
|
||||
Eina_Test_Inlist_Sorted *tmp;
|
||||
Eina_Inlist_Sorted_State *state;
|
||||
Eina_Inlist *list = NULL;
|
||||
int i;
|
||||
|
||||
fail_if(!eina_init());
|
||||
|
||||
state = eina_inlist_sorted_state_new();
|
||||
fail_if(!state);
|
||||
|
||||
for (i = 0; i < 2000; ++i)
|
||||
{
|
||||
tmp = malloc(sizeof (Eina_Test_Inlist_Sorted));
|
||||
if (!tmp) continue ;
|
||||
|
||||
tmp->value = rand();
|
||||
|
||||
list = eina_inlist_sorted_state_insert(list, EINA_INLIST_GET(tmp), _eina_test_inlist_cmp, state);
|
||||
_eina_test_inlist_check(list);
|
||||
}
|
||||
|
||||
_eina_test_inlist_check(list);
|
||||
|
||||
eina_inlist_sorted_state_free(state);
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
@ -211,4 +250,5 @@ eina_test_inlist(TCase *tc)
|
|||
{
|
||||
tcase_add_test(tc, eina_inlist_simple);
|
||||
tcase_add_test(tc, eina_inlist_sorted);
|
||||
tcase_add_test(tc, eina_inlist_sorted_state);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue