eina: fix eina inlist sorted insert (with and without state)

SVN revision: 63398
This commit is contained in:
Cedric BAIL 2011-09-14 22:04:37 +00:00
parent d5a1614b2f
commit 60d03bc2d2
3 changed files with 105 additions and 45 deletions

View File

@ -674,13 +674,14 @@ EAPI Eina_Inlist_Sorted_State *eina_inlist_sorted_state_new(void);
* *
* @param state The state to update * @param state The state to update
* @param list The list to match * @param list The list to match
* @return The number of item in the actually in the list
* @since 1.1.0 * @since 1.1.0
* *
* See eina_inlist_sorted_state_insert() for more information. This function is * 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 * 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. * 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. * @brief Free an Eina_Inlist_Sorted_State.

View File

@ -190,6 +190,21 @@ eina_inlist_sort_rebuild_prev(Eina_Inlist *list)
return prev; 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 * @endcond
*/ */
@ -434,7 +449,7 @@ eina_inlist_count(const Eina_Inlist *list)
return i; return i;
} }
EAPI void EAPI int
eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list) eina_inlist_sorted_state_init(Eina_Inlist_Sorted_State *state, Eina_Inlist *list)
{ {
Eina_Inlist *ct = NULL; 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) if (state->jump_limit == EINA_INLIST_JUMP_SIZE)
{ {
unsigned short i, j; _eina_inlist_sorted_state_compact(state);
/* 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];
} }
state->jump_table[state->jump_limit] = ct; 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; jump_count = 0;
} }
} }
state->inserted = count;
return count;
} }
EAPI Eina_Inlist_Sorted_State * EAPI Eina_Inlist_Sorted_State *
@ -496,6 +505,7 @@ _eina_inlist_sorted_state_insert(Eina_Inlist_Sorted_State *state,
{ {
Eina_Inlist *last; Eina_Inlist *last;
int jump_count; int jump_count;
int start;
state->inserted++; state->inserted++;
@ -505,27 +515,35 @@ _eina_inlist_sorted_state_insert(Eina_Inlist_Sorted_State *state,
state->jump_table[index] = state->jump_table[index]->prev; state->jump_table[index] = state->jump_table[index]->prev;
} }
last = state->jump_table[state->jump_limit - 1]; start = state->jump_limit - 3;
for (jump_count = 0; last != NULL; last = last->next) if (start < 0)
jump_count++; 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 (state->jump_limit == EINA_INLIST_JUMP_SIZE) if (jump_count == state->jump_div)
{ {
unsigned short i, j; if (state->jump_limit == start)
{
if (state->jump_limit == EINA_INLIST_JUMP_SIZE)
{
_eina_inlist_sorted_state_compact(state);
start = state->jump_limit - 1;
continue ;
}
else
{
state->jump_limit++;
}
}
/* compress the jump table */ state->jump_table[start++] = last;
state->jump_div *= 2; jump_count = 0;
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];
} }
state->jump_table[state->jump_limit] = state->jump_table[0]->last;
state->jump_limit++;
} }
} }
@ -539,7 +557,7 @@ eina_inlist_sorted_insert(Eina_Inlist *list,
int cmp = 0; int cmp = 0;
int inf, sup; int inf, sup;
int cur = 0; int cur = 0;
int count = 0; int count;
if (!list) return eina_inlist_append(NULL, item); 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_div = 1;
state.jump_limit = 0; 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. * 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 * Now do a dychotomic search between two entries inside the jump_table
*/ */
cur *= state.jump_div; cur *= state.jump_div;
inf = cur - state.jump_div; inf = cur - state.jump_div - 1;
sup = cur + state.jump_div; sup = cur + state.jump_div + 1;
if (sup > count - 1) sup = count - 1; if (sup > count - 1) sup = count - 1;
if (inf < 0) inf = 0; if (inf < 0) inf = 0;
@ -632,7 +650,7 @@ eina_inlist_sorted_insert(Eina_Inlist *list,
break; break;
} }
if (cmp < 0) if (cmp <= 0)
return eina_inlist_append_relative(list, item, ct); return eina_inlist_append_relative(list, item, ct);
return eina_inlist_prepend_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 cmp = 0;
int inf, sup; int inf, sup;
int cur = 0; int cur = 0;
int count = 0; int count;
unsigned short head; unsigned short head;
unsigned int offset; unsigned int offset;
@ -676,6 +694,8 @@ eina_inlist_sorted_state_insert(Eina_Inlist *list,
return eina_inlist_prepend(list, item); return eina_inlist_prepend(list, item);
} }
count = state->inserted;
/* /*
* now do a dychotomic search directly inside the jump_table. * 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 * Now do a dychotomic search between two entries inside the jump_table
*/ */
cur *= state->jump_div; cur *= state->jump_div;
inf = cur - state->jump_div; inf = cur - state->jump_div - 1;
sup = cur + state->jump_div; sup = cur + state->jump_div + 1;
if (sup > count - 1) sup = count - 1; if (sup > count - 1) sup = count - 1;
if (inf < 0) if (inf < 0) inf = 0;
inf = 0;
while (inf <= sup) while (inf <= sup)
{ {
@ -761,20 +780,20 @@ eina_inlist_sorted_state_insert(Eina_Inlist *list,
break; break;
} }
if (cmp < 0) if (cmp <= 0)
{ {
cur++; cur++;
head = cur / state->jump_div;
offset = cur % state->jump_div;
ct = eina_inlist_append_relative(list, item, ct); 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; head = cur / state->jump_div;
offset = 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); _eina_inlist_sorted_state_insert(state, head, offset);
return ct; return ct;
} }

View File

@ -53,6 +53,8 @@ START_TEST(eina_inlist_simple)
Eina_Test_Inlist *prev; Eina_Test_Inlist *prev;
int i = 0; int i = 0;
fail_if(!eina_init());
tmp = _eina_test_inlist_build(42); tmp = _eina_test_inlist_build(42);
lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp)); lst = eina_inlist_append(lst, EINA_INLIST_GET(tmp));
fail_if(!lst); fail_if(!lst);
@ -132,6 +134,8 @@ START_TEST(eina_inlist_simple)
while (lst) while (lst)
lst = eina_inlist_remove(lst, lst); lst = eina_inlist_remove(lst, lst);
eina_shutdown();
} }
END_TEST END_TEST
@ -172,9 +176,11 @@ START_TEST(eina_inlist_sorted)
Eina_Inlist *sorted = NULL; Eina_Inlist *sorted = NULL;
int i; int i;
fail_if(!eina_init());
srand(time(NULL)); srand(time(NULL));
for (i = 0; i < 1000; ++i) for (i = 0; i < 2000; ++i)
{ {
tmp = malloc(sizeof (Eina_Test_Inlist_Sorted)); tmp = malloc(sizeof (Eina_Test_Inlist_Sorted));
if (!tmp) continue ; if (!tmp) continue ;
@ -203,6 +209,39 @@ START_TEST(eina_inlist_sorted)
} }
_eina_test_inlist_check(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 END_TEST
@ -211,4 +250,5 @@ eina_test_inlist(TCase *tc)
{ {
tcase_add_test(tc, eina_inlist_simple); tcase_add_test(tc, eina_inlist_simple);
tcase_add_test(tc, eina_inlist_sorted); tcase_add_test(tc, eina_inlist_sorted);
tcase_add_test(tc, eina_inlist_sorted_state);
} }