Add first try for an accessor and iterator API, comment welcome (lack inlist and list currently).

Rewrite EINA_ARRAY_ITER_NEXT, still fast, need one more parameter, but no more EINA_ARRAY_ITER_END.


SVN revision: 35438
This commit is contained in:
Cedric BAIL 2008-08-11 16:30:16 +00:00
parent ea0fb7d1b5
commit 43cc2dca6f
22 changed files with 979 additions and 75 deletions

View File

@ -18,7 +18,9 @@ eina_counter.h \
eina_inline_array.x \
eina_magic.h \
eina_stringshare.h \
eina_inline_list.x
eina_inline_list.x \
eina_accessor.h \
eina_iterator.h
installed_mainheaderdir = $(prefix)/include/eina-@VMAJ@
installed_mainheader_DATA = Eina.h

View File

@ -0,0 +1,38 @@
/* 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/>.
*/
#ifndef EINA_ACCESSOR_H__
#define EINA_ACCESSOR_H__
#include "eina_types.h"
#include "eina_error.h"
typedef struct _Eina_Accessor Eina_Accessor;
EAPI void eina_accessor_free (Eina_Accessor *accessor);
EAPI void *eina_accessor_data_get (Eina_Accessor *accessor, unsigned int position);
EAPI void *eina_accessor_container_get (Eina_Accessor *accessor);
EAPI void eina_accessor_over (Eina_Accessor *accessor,
Eina_Each cb,
unsigned int start,
unsigned int end,
const void *fdata);
#endif

View File

@ -22,8 +22,12 @@
#include <stdlib.h>
#include "eina_types.h"
#include "eina_iterator.h"
#include "eina_accessor.h"
typedef struct _Eina_Array Eina_Array; /**< A generic vector */
typedef void** Eina_Array_Iterator;
struct _Eina_Array /** An array of data */
{
void **data; /**< Pointer to a vector of pointer to payload */
@ -42,16 +46,17 @@ EAPI void eina_array_clean (Eina_Array *array);
EAPI void eina_array_flush (Eina_Array *array);
EAPI void eina_array_remove (Eina_Array *array, Eina_Bool (*keep)(void *data, void *gdata), void *gdata);
static inline void * eina_array_get (Eina_Array *array, unsigned int index);
EAPI Eina_Iterator *eina_array_iterator_new(const Eina_Array *array);
EAPI Eina_Accessor *eina_array_accessor_new(const Eina_Array *array);
static inline void * eina_array_get (const Eina_Array *array, unsigned int index);
static inline void eina_array_append (Eina_Array *array, void *data);
static inline unsigned int eina_array_count (Eina_Array *array);
static inline unsigned int eina_array_count (const Eina_Array *array);
#define EINA_ARRAY_ITER_NEXT(array, index, item) \
for ((index) = 0; (index) < eina_array_count(array); ++(index)) \
{ \
(item) = eina_array_get((array), (index));
#define EINA_ARRAY_ITER_END }
#define EINA_ARRAY_ITER_NEXT(array, index, item, iterator) \
for (index = 0, iterator = (array)->data, item = iterator != NULL ? *(iterator) : NULL; \
index < eina_array_count(array); \
++(index), item = *(++(iterator)))
#include "eina_inline_array.x"

View File

@ -21,11 +21,21 @@
#define EINA_HASH_H_
#include "eina_types.h"
#include "eina_iterator.h"
/**
*
*/
typedef struct _Eina_Hash Eina_Hash;
typedef struct _Eina_Hash_Tuple Eina_Hash_Tuple;
struct _Eina_Hash_Tuple
{
const void *key;
void *data;
unsigned int key_length;
};
typedef unsigned int (*Eina_Key_Length)(const void *key);
#define EINA_KEY_LENGTH(Function) ((Eina_Key_Length)Function)
typedef int (*Eina_Key_Cmp)(const void *key1, int key1_length,
@ -66,7 +76,10 @@ EAPI void * eina_hash_modify_by_hash(Eina_Hash *hash,
const void *key, int key_length, int key_hash,
const void *data);
/* FIXME: Should go with iterator support. */
EAPI Eina_Iterator * eina_hash_iterator_key_new(const Eina_Hash *hash);
EAPI Eina_Iterator * eina_hash_iterator_data_new(const Eina_Hash *hash);
EAPI Eina_Iterator * eina_hash_iterator_tuple_new(const Eina_Hash *hash);
typedef Eina_Bool (*Eina_Foreach)(const Eina_Hash *hash, const void *key, void *data, void *fdata);
EAPI void eina_hash_foreach(const Eina_Hash *hash,
Eina_Foreach cb,

View File

@ -0,0 +1,38 @@
/* 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/>.
*/
#ifndef EINA_ITERATOR_H__
#define EINA_ITERATOR_H__
#include "eina_types.h"
#include "eina_error.h"
typedef struct _Eina_Iterator Eina_Iterator;
EAPI void eina_iterator_free (Eina_Iterator *iterator);
EAPI void *eina_iterator_data_get (Eina_Iterator *iterator);
EAPI void *eina_iterator_container_get (Eina_Iterator *iterator);
EAPI Eina_Error eina_iterator_next (Eina_Iterator *iterator);
EAPI void eina_iterator_foreach (Eina_Iterator *iterator,
Eina_Each callback,
const void *fdata);
#endif

View File

@ -39,6 +39,9 @@
#include <assert.h>
#include "eina_iterator.h"
#include "eina_accessor.h"
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
@ -111,5 +114,41 @@ typedef struct _Eina_Mempool_Backend
void (*shutdown)(void *data);
} Eina_Mempool_Backend;
/* Iterator/accessor private type */
typedef Eina_Bool (*Eina_Iterator_Next_Callback)(Eina_Iterator *it);
typedef void *(*Eina_Iterator_Get_Content_Callback)(Eina_Iterator *it);
typedef void *(*Eina_Iterator_Get_Container_Callback)(Eina_Iterator *it);
typedef void (*Eina_Iterator_Free_Callback)(Eina_Iterator *it);
#define FUNC_ITERATOR_NEXT(Function) ((Eina_Iterator_Next_Callback)Function)
#define FUNC_ITERATOR_GET_CONTENT(Function) ((Eina_Iterator_Get_Content_Callback)Function)
#define FUNC_ITERATOR_GET_CONTAINER(Function) ((Eina_Iterator_Get_Container_Callback)Function)
#define FUNC_ITERATOR_FREE(Function) ((Eina_Iterator_Free_Callback)Function)
typedef Eina_Bool (*Eina_Accessor_Jump_At_Callback)(Eina_Accessor *it, unsigned int index);
typedef void *(*Eina_Accessor_Get_Content_Callback)(Eina_Accessor *it);
typedef void *(*Eina_Accessor_Get_Container_Callback)(Eina_Accessor *it);
typedef void (*Eina_Accessor_Free_Callback)(Eina_Accessor *it);
#define FUNC_ACCESSOR_JUMP_AT(Function) ((Eina_Accessor_Jump_At_Callback)Function)
#define FUNC_ACCESSOR_GET_CONTENT(Function) ((Eina_Accessor_Get_Content_Callback)Function)
#define FUNC_ACCESSOR_GET_CONTAINER(Function) ((Eina_Accessor_Get_Container_Callback)Function)
#define FUNC_ACCESSOR_FREE(Function) ((Eina_Accessor_Free_Callback)Function)
struct _Eina_Iterator
{
Eina_Iterator_Next_Callback next;
Eina_Iterator_Get_Content_Callback get_content;
Eina_Iterator_Get_Container_Callback get_container;
Eina_Iterator_Free_Callback free;
};
struct _Eina_Accessor
{
Eina_Accessor_Jump_At_Callback jump_at;
Eina_Accessor_Get_Content_Callback get_content;
Eina_Accessor_Get_Container_Callback get_container;
Eina_Accessor_Free_Callback free;
};
#endif /* EINA_PRIVATE_H_ */

View File

@ -20,6 +20,8 @@ eina_array.c \
eina_magic.c \
eina_main.c \
eina_counter.c \
eina_iterator.c \
eina_accessor.c \
eina_stringshare.c
libeina_la_LIBADD = -ldl -lrt @COVERAGE_LIBS@

View File

@ -0,0 +1,76 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
/* EINA - EFL data type library
* Copyright (C) 2002-2008 Carsten Haitzler, Jorge Luis Zapata Muga, 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 "eina_accessor.h"
#include "eina_private.h"
EAPI void
eina_accessor_free(Eina_Accessor *accessor)
{
if (accessor) accessor->free(accessor);
}
EAPI void *
eina_accessor_data_get(Eina_Accessor *accessor, unsigned int position)
{
if (!accessor) return NULL;
if (accessor->jump_at(accessor, position) != EINA_TRUE) return NULL;
return accessor->get_content(accessor);
}
EAPI void *
eina_accessor_container_get(Eina_Accessor *accessor)
{
if (!accessor) return NULL;
return accessor->get_container(accessor);
}
EAPI void
eina_accessor_over(Eina_Accessor *accessor,
Eina_Each cb,
unsigned int start,
unsigned int end,
const void *fdata)
{
void *container;
void *data;
unsigned int i = start;
if (!accessor) return ;
if (!(start < end)) return ;
if (accessor->jump_at(accessor, start) != EINA_TRUE) return ;
container = accessor->get_container(accessor);
do {
data = accessor->get_content(accessor);
if (cb(container, data, (void*) fdata) != EINA_TRUE) return ;
++i;
} while (i < end && accessor->jump_at(accessor, i) == EINA_TRUE);
}

View File

@ -30,6 +30,7 @@
#include "eina_error.h"
#include "eina_array.h"
#include "eina_inline_array.x"
#include "eina_private.h"
EAPI int
eina_array_init(void)
@ -170,3 +171,129 @@ eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data, void *gdata),
array->data = tmp;
array->count = total;
}
typedef struct _Eina_Iterator_Array Eina_Iterator_Array;
struct _Eina_Iterator_Array
{
Eina_Iterator iterator;
const Eina_Array *array;
unsigned int index;
};
static Eina_Bool
eina_array_iterator_next(Eina_Iterator_Array *it)
{
if (!(it->index + 1 < eina_array_count(it->array)))
return EINA_FALSE;
it->index++;
return EINA_TRUE;
}
static void *
eina_array_iterator_get_content(Eina_Iterator_Array *it)
{
if (!(it->index < eina_array_count(it->array)))
return NULL;
return eina_array_get(it->array, it->index);
}
static Eina_Array *
eina_array_iterator_get_container(Eina_Iterator_Array *it)
{
return (Eina_Array *) it->array;
}
static void
eina_array_iterator_free(Eina_Iterator_Array *it)
{
free(it);
}
EAPI Eina_Iterator *
eina_array_iterator_new(const Eina_Array *array)
{
Eina_Iterator_Array *it;
if (!array) return NULL;
if (eina_array_count(array) <= 0) return NULL;
eina_error_set(0);
it = calloc(1, sizeof (Eina_Iterator_Array));
if (!it) {
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
return NULL;
}
it->array = array;
it->iterator.next = FUNC_ITERATOR_NEXT(eina_array_iterator_next);
it->iterator.get_content = FUNC_ITERATOR_GET_CONTENT(eina_array_iterator_get_content);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(eina_array_iterator_get_container);
it->iterator.free = FUNC_ITERATOR_FREE(eina_array_iterator_free);
return &it->iterator;
}
typedef struct _Eina_Accessor_Array Eina_Accessor_Array;
struct _Eina_Accessor_Array
{
Eina_Accessor accessor;
const Eina_Array *array;
unsigned int index;
};
static Eina_Bool
eina_array_accessor_jump_at(Eina_Accessor_Array *it, unsigned int index)
{
if (!(index < eina_array_count(it->array)))
return EINA_FALSE;
it->index = index;
return EINA_TRUE;
}
static void *
eina_array_accessor_get_content(Eina_Accessor_Array *it)
{
if (!(it->index < eina_array_count(it->array)))
return NULL;
return eina_array_get(it->array, it->index);
}
static Eina_Array *
eina_array_accessor_get_container(Eina_Accessor_Array *it)
{
return (Eina_Array *) it->array;
}
static void
eina_array_accessor_free(Eina_Accessor_Array *it)
{
free(it);
}
EAPI Eina_Accessor *
eina_array_accessor_new(const Eina_Array *array)
{
Eina_Accessor_Array *it;
if (!array) return NULL;
eina_error_set(0);
it = calloc(1, sizeof (Eina_Accessor_Array));
if (!it) {
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
return NULL;
}
it->array = array;
it->accessor.jump_at = FUNC_ACCESSOR_JUMP_AT(eina_array_accessor_jump_at);
it->accessor.get_content = FUNC_ACCESSOR_GET_CONTENT(eina_array_accessor_get_content);
it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(eina_array_accessor_get_container);
it->accessor.free = FUNC_ACCESSOR_FREE(eina_array_accessor_free);
return &it->accessor;
}

View File

@ -32,6 +32,9 @@
* Local *
*============================================================================*/
typedef struct _Eina_Hash_El Eina_Hash_El;
typedef struct _Eina_Hash_Foreach Eina_Hash_Foreach;
typedef struct _Eina_Iterator_Hash Eina_Iterator_Hash;
struct _Eina_Hash
{
Eina_Key_Length key_length_cb;
@ -45,10 +48,25 @@ struct _Eina_Hash
struct _Eina_Hash_El
{
Eina_Inlist _list_data;
Eina_Hash_Tuple tuple;
};
void *data;
const void *key;
unsigned int length;
struct _Eina_Hash_Foreach
{
Eina_Foreach cb;
const void *fdata;
};
struct _Eina_Iterator_Hash
{
Eina_Iterator iterator;
const Eina_Hash *hash;
Eina_Inlist *current;
int bucket;
int index;
};
static int _eina_hash_init_count = 0;
@ -61,7 +79,7 @@ _eina_hash_find_by_hash(const Eina_Hash *hash, const char *key, int key_length,
key_hash &= 0xFF;
EINA_INLIST_ITER_NEXT(hash->buckets[key_hash], el)
if (!hash->key_cmp_cb(el->key, el->length, key, key_length)) return el;
if (!hash->key_cmp_cb(el->tuple.key, el->tuple.key_length, key, key_length)) return el;
return NULL;
}
@ -75,7 +93,7 @@ _eina_hash_find_by_data(const Eina_Hash *hash, const void *data, int *key_hash)
/* FIXME: Use an iterator for this stuff */
for (hash_num = 0; hash_num < 256; hash_num++)
EINA_INLIST_ITER_NEXT(hash->buckets[hash_num], el)
if (el->data == data)
if (el->tuple.data == data)
{
*key_hash = hash_num;
return el;
@ -110,6 +128,90 @@ _eina_string_key_cmp(const char *key1, __UNUSED__ int key1_length,
return strcmp(key1, key2);
}
static Eina_Bool
_eina_foreach_cb(const Eina_Hash *hash, Eina_Hash_Tuple *data, Eina_Hash_Foreach *fdata)
{
return fdata->cb((Eina_Hash *) hash, data->key, data->data, (void*) fdata->fdata);
}
static Eina_Bool
_eina_hash_iterator_next(Eina_Iterator_Hash *it)
{
Eina_Inlist *move;
int bucket;
if (!(it->index + 1 < it->hash->population)) return EINA_FALSE;
if (it->current == NULL)
{
move = NULL;
bucket = 0;
it->index = -1;
}
else
{
bucket = it->bucket;
move = it->current->next;
}
if (!move)
{
while (bucket < 256)
{
if (it->hash->buckets[bucket] != NULL)
{
move = it->hash->buckets[bucket];
break ;
}
++bucket;
}
}
it->index++;
it->bucket = bucket;
it->current = move;
return EINA_TRUE;
}
static void *
_eina_hash_iterator_data_get_content(Eina_Iterator_Hash *it)
{
Eina_Hash_El *stuff = (Eina_Hash_El *) it->current;
if (!stuff) return NULL;
return stuff->tuple.data;
}
static void *
_eina_hash_iterator_key_get_content(Eina_Iterator_Hash *it)
{
Eina_Hash_El *stuff = (Eina_Hash_El *) it->current;
if (!stuff) return NULL;
return (void *) stuff->tuple.key;
}
static Eina_Hash_Tuple *
_eina_hash_iterator_tuple_get_content(Eina_Iterator_Hash *it)
{
Eina_Hash_El *stuff = (Eina_Hash_El *) it->current;
if (!stuff) return NULL;
return &stuff->tuple;
}
static void *
_eina_hash_iterator_get_container(Eina_Iterator_Hash *it)
{
return (void *) it->hash;
}
static void
_eina_hash_iterator_free(Eina_Iterator_Hash *it)
{
free(it);
}
/*============================================================================*
* Global *
*============================================================================*/
@ -225,10 +327,10 @@ eina_hash_add_by_hash(Eina_Hash *hash,
if (!el) goto on_error;
/* Setup the element */
el->length = key_length;
el->data = (void *) data;
el->key = (char *) (el + 1);
memcpy((char *) el->key, key, key_length);
el->tuple.key_length = key_length;
el->tuple.data = (void *) data;
el->tuple.key = (char *) (el + 1);
memcpy((char *) el->tuple.key, key, key_length);
/* eina hash have 256 buckets. */
key_hash &= 0xFF;
@ -284,9 +386,9 @@ eina_hash_direct_add_by_hash(Eina_Hash *hash,
if (!el) goto on_error;
/* Setup the element */
el->length = key_length;
el->data = (void *) data;
el->key = key;
el->tuple.key_length = key_length;
el->tuple.data = (void *) data;
el->tuple.key = key;
/* eina hash have 256 buckets. */
key_hash &= 0xFF;
@ -459,7 +561,7 @@ eina_hash_find_by_hash(const Eina_Hash *hash, const void *key, int key_length, i
if (el)
{
_eina_hash_reorder((Eina_Hash *) hash, el, key_hash);
return el->data;
return el->tuple.data;
}
return NULL;
}
@ -510,8 +612,8 @@ eina_hash_modify_by_hash(Eina_Hash *hash, const void *key, int key_length, int k
if (el)
{
_eina_hash_reorder((Eina_Hash *) hash, el, key_hash);
old_data = el->data;
el->data = (void *) data;
old_data = el->tuple.data;
el->tuple.data = (void *) data;
}
return old_data;
@ -601,7 +703,9 @@ eina_hash_free(Eina_Hash *hash)
free(hash);
}
/* FIXME: Create a generic foreach function in the iterator implementation. */
/*============================================================================*
* Iterator *
*============================================================================*/
/**
* Call a function on every member stored in the hash table
* @param hash The hash table whose members will be walked
@ -635,29 +739,89 @@ eina_hash_free(Eina_Hash *hash)
* @endcode
* @ingroup Eina_Hash_General_Group
*/
EAPI void eina_hash_foreach(
const Eina_Hash *hash,
Eina_Foreach func,
const void *fdata)
EAPI void
eina_hash_foreach(const Eina_Hash *hash,
Eina_Foreach func,
const void *fdata)
{
int i;
Eina_Iterator *it;
Eina_Hash_Foreach foreach;
if (!hash) return;
for (i = 0; i < 256; i++)
{
Eina_Inlist *l, *next_l;
foreach.cb = func;
foreach.fdata = fdata;
for (l = hash->buckets[i]; l;)
{
Eina_Hash_El *el;
it = eina_hash_iterator_tuple_new(hash);
eina_iterator_foreach(it, EINA_EACH(_eina_foreach_cb), &foreach);
eina_iterator_free(it);
}
next_l = l->next;
el = (Eina_Hash_El *)l;
if (!func(hash, el->key, el->data, (void *)fdata))
return;
l = next_l;
}
}
EAPI Eina_Iterator *
eina_hash_iterator_data_new(const Eina_Hash *hash)
{
Eina_Iterator_Hash *it;
if (!hash) return NULL;
if (hash->population <= 0) return NULL;
it = calloc(1, sizeof (Eina_Iterator_Hash));
if (!it) return NULL;
it->hash = hash;
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
it->iterator.get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_data_get_content);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_hash_iterator_get_container);
it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
_eina_hash_iterator_next(it);
return &it->iterator;
}
EAPI Eina_Iterator *
eina_hash_iterator_key_new(const Eina_Hash *hash)
{
Eina_Iterator_Hash *it;
if (!hash) return NULL;
if (hash->population <= 0) return NULL;
it = calloc(1, sizeof (Eina_Iterator_Hash));
if (!it) return NULL;
it->hash = hash;
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
it->iterator.get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_key_get_content);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_hash_iterator_get_container);
it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
_eina_hash_iterator_next(it);
return &it->iterator;
}
EAPI Eina_Iterator *
eina_hash_iterator_tuple_new(const Eina_Hash *hash)
{
Eina_Iterator_Hash *it;
if (!hash) return NULL;
if (hash->population <= 0) return NULL;
it = calloc(1, sizeof (Eina_Iterator_Hash));
if (!it) return NULL;
it->hash = hash;
it->iterator.next = FUNC_ITERATOR_NEXT(_eina_hash_iterator_next);
it->iterator.get_content = FUNC_ITERATOR_GET_CONTENT(_eina_hash_iterator_tuple_get_content);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eina_hash_iterator_get_container);
it->iterator.free = FUNC_ITERATOR_FREE(_eina_hash_iterator_free);
_eina_hash_iterator_next(it);
return &it->iterator;
}
/* Common hash functions */

View File

@ -0,0 +1,72 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
/* EINA - EFL data type library
* Copyright (C) 2002-2008 Carsten Haitzler, Jorge Luis Zapata Muga, 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 "eina_iterator.h"
#include "eina_private.h"
EAPI void
eina_iterator_free(Eina_Iterator *iterator)
{
if (iterator) iterator->free(iterator);
}
EAPI void *
eina_iterator_data_get(Eina_Iterator *iterator)
{
if (!iterator) return NULL;
return iterator->get_content(iterator);
}
EAPI void *
eina_iterator_container_get(Eina_Iterator *iterator)
{
if (!iterator) return NULL;
return iterator->get_container(iterator);
}
EAPI Eina_Error
eina_iterator_next(Eina_Iterator *iterator)
{
if (!iterator) return EINA_FALSE;
return iterator->next(iterator);
}
EAPI void
eina_iterator_foreach(Eina_Iterator *iterator,
Eina_Each cb,
const void *fdata)
{
void *container;
void *data;
if (!iterator) return ;
container = iterator->get_container(iterator);
while ((data = iterator->get_content(iterator)) != NULL) {
if (cb(container, data, (void*) fdata) != EINA_TRUE) return ;
if (iterator->next(iterator) != EINA_TRUE)
break ;
}
}

View File

@ -66,14 +66,14 @@ EAPI const char*
eina_magic_string_get(Eina_Magic magic)
{
Eina_Magic_String *ems;
Eina_Array_Iterator it;
unsigned int i;
if (!strings) return NULL;
EINA_ARRAY_ITER_NEXT(strings, i, ems)
EINA_ARRAY_ITER_NEXT(strings, i, ems, it)
if (ems->magic == magic)
return ems->string;
EINA_ARRAY_ITER_END;
return NULL;
}
@ -82,11 +82,12 @@ EAPI void
eina_magic_string_set(Eina_Magic magic, const char *magic_name)
{
Eina_Magic_String *ems;
Eina_Array_Iterator it;
unsigned int i;
if (!strings) return ;
EINA_ARRAY_ITER_NEXT(strings, i, ems)
EINA_ARRAY_ITER_NEXT(strings, i, ems, it)
if (ems->magic == magic)
{
free(ems->string);
@ -96,7 +97,6 @@ eina_magic_string_set(Eina_Magic magic, const char *magic_name)
ems->string = NULL;
return ;
}
EINA_ARRAY_ITER_END;
ems = malloc(sizeof (Eina_Magic_String));
ems->magic = magic;

View File

@ -22,6 +22,8 @@ eina_test_main.c \
eina_test_counter.c \
eina_test_lalloc.c \
eina_test_hash.c \
eina_test_iterator.c \
eina_test_accessor.c \
eina_test_list.c
eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la

View File

@ -54,6 +54,7 @@ eina_bench_array_4evas_render_inline(int request)
{
Eina_Array *array;
Eina_Bench_Object *ebo;
Eina_Array_Iterator it;
unsigned int i;
unsigned int j;
@ -77,22 +78,86 @@ eina_bench_array_4evas_render_inline(int request)
if (i == 500)
{
EINA_ARRAY_ITER_NEXT(array, j, ebo)
EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
free(ebo);
EINA_ARRAY_ITER_END;
eina_array_clean(array);
}
else if (i % 30 == 0) eina_array_remove(array, keep, NULL);
EINA_ARRAY_ITER_NEXT(array, j, ebo)
EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
EINA_ARRAY_ITER_END;
}
EINA_ARRAY_ITER_NEXT(array, j, ebo)
EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
free(ebo);
EINA_ARRAY_ITER_END;
eina_array_free(array);
eina_array_shutdown();
}
static Eina_Bool
eina_iterator_ebo_free(__UNUSED__ const Eina_Array *array,
Eina_Bench_Object *ebo, __UNUSED__ void *fdata)
{
free(ebo);
return EINA_TRUE;
}
static Eina_Bool
eina_iterator_ebo_rand(__UNUSED__ const Eina_Array *array,
Eina_Bench_Object *ebo, __UNUSED__ void *fdata)
{
ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
return EINA_TRUE;
}
static void
eina_bench_array_4evas_render_iterator(int request)
{
Eina_Array *array;
Eina_Bench_Object *ebo;
Eina_Iterator *it;
unsigned int i;
unsigned int j;
srand(time(NULL));
eina_array_init();
array = eina_array_new(64);
for (i = 0; i < 1000; ++i)
{
for (j = 0; j < (unsigned int) request; ++j)
{
ebo = malloc(sizeof (Eina_Bench_Object));
if (!ebo) continue ;
ebo->keep = rand() < (RAND_MAX / 2) ? EINA_TRUE : EINA_FALSE;
eina_array_append(array, ebo);
}
if (i == 500)
{
it = eina_array_iterator_new(array);
eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_free), NULL);
eina_iterator_free(it);
eina_array_clean(array);
}
else if (i % 30 == 0) eina_array_remove(array, keep, NULL);
it = eina_array_iterator_new(array);
eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_rand), NULL);
eina_iterator_free(it);
}
it = eina_array_iterator_new(array);
eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_free), NULL);
eina_iterator_free(it);
eina_array_free(array);
@ -232,6 +297,7 @@ eina_bench_inlist_4evas_render(int request)
void eina_bench_array(Eina_Bench *bench)
{
eina_bench_register(bench, "array-inline", EINA_BENCH(eina_bench_array_4evas_render_inline), 200, 4000, 100);
eina_bench_register(bench, "array-iterator", EINA_BENCH(eina_bench_array_4evas_render_iterator), 200, 4000, 100);
eina_bench_register(bench, "list", EINA_BENCH(eina_bench_list_4evas_render), 200, 4000, 100);
eina_bench_register(bench, "inlist", EINA_BENCH(eina_bench_inlist_4evas_render), 200, 4000, 100);
}

View File

@ -31,6 +31,7 @@ eina_bench_lookup_superfast(int request)
Eina_Hash *hash = NULL;
Eina_Array *array = NULL;
int *tmp_val;
Eina_Array_Iterator it;
unsigned int i;
array = eina_array_new(1000);
@ -66,9 +67,8 @@ eina_bench_lookup_superfast(int request)
eina_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
EINA_ARRAY_ITER_END;
eina_array_free(array);
}
@ -79,6 +79,7 @@ eina_bench_lookup_djb2(int request)
Eina_Hash *hash = NULL;
Eina_Array *array = NULL;
int *tmp_val;
Eina_Array_Iterator it;
unsigned int i;
array = eina_array_new(1000);
@ -114,9 +115,8 @@ eina_bench_lookup_djb2(int request)
eina_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
EINA_ARRAY_ITER_END;
eina_array_free(array);
}
@ -127,6 +127,7 @@ eina_bench_lookup_djb2_inline(int request)
Eina_Hash *hash = NULL;
Eina_Array *array = NULL;
int *tmp_val;
Eina_Array_Iterator it;
unsigned int i;
array = eina_array_new(1000);
@ -164,9 +165,8 @@ eina_bench_lookup_djb2_inline(int request)
eina_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
EINA_ARRAY_ITER_END;
eina_array_free(array);
}

View File

@ -29,6 +29,7 @@ eina_bench_stringshare_job(int request)
{
const char *tmp;
Eina_Array *ea;
Eina_Array_Iterator it;
unsigned int j;
int i;
@ -60,9 +61,8 @@ eina_bench_stringshare_job(int request)
eina_array_append(ea, tmp);
}
EINA_ARRAY_ITER_NEXT(ea, j, tmp)
EINA_ARRAY_ITER_NEXT(ea, j, tmp, it)
eina_stringshare_del(tmp);
EINA_ARRAY_ITER_END;
eina_array_shutdown();
eina_stringshare_shutdown();

View File

@ -36,6 +36,8 @@ static const Eina_Test_Case etc[] = {
{ "Counter", eina_test_counter },
{ "Hash", eina_test_hash },
{ "List", eina_test_list },
{ "Iterator", eina_test_iterator },
{ "Accessor", eina_test_accessor },
{ NULL, NULL }
};

View File

@ -35,5 +35,7 @@ void eina_test_main(TCase *tc);
void eina_test_counter(TCase *tc);
void eina_test_hash(TCase *tc);
void eina_test_list(TCase *tc);
void eina_test_iterator(TCase *tc);
void eina_test_accessor(TCase *tc);
#endif /* EINA_SUITE_H_ */

View File

@ -0,0 +1,85 @@
/* 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 <stdio.h>
#include "eina_suite.h"
#include "eina_array.h"
#include "eina_private.h"
static Eina_Bool
eina_accessor_check(__UNUSED__ const Eina_Array *array,
int *data, int *fdata)
{
fail_if(*fdata > *data);
*fdata = *data;
return EINA_TRUE;
}
START_TEST(eina_accessor_array_simple)
{
Eina_Accessor *it;
Eina_Array *ea;
int *tmp;
int i;
eina_array_init();
ea = eina_array_new(11);
fail_if(!ea);
for (i = 0; i < 200; ++i)
{
tmp = malloc(sizeof(int));
fail_if(!tmp);
*tmp = i;
eina_array_append(ea, tmp);
}
it = eina_array_accessor_new(ea);
fail_if(!it);
tmp = eina_accessor_data_get(it, 100);
fail_if(!tmp);
fail_if(*tmp != 100);
i = 50;
eina_accessor_over(it, EINA_EACH(eina_accessor_check), 50, 100, &i);
fail_if(i != 99);
fail_if(eina_accessor_container_get(it) != ea);
eina_accessor_free(it);
eina_array_free(ea);
eina_array_shutdown();
}
END_TEST
void
eina_test_accessor(TCase *tc)
{
tcase_add_test(tc, eina_accessor_array_simple);
}

View File

@ -25,6 +25,7 @@ START_TEST(eina_array_simple)
{
Eina_Array *ea;
char *tmp;
Eina_Array_Iterator it;
unsigned int i;
eina_array_init();
@ -44,10 +45,11 @@ START_TEST(eina_array_simple)
fail_if(eina_array_get(ea, 10) == NULL);
fail_if(atoi(eina_array_get(ea, 10)) != 10);
EINA_ARRAY_ITER_NEXT(ea, i, tmp)
fail_if((unsigned int) atoi(tmp) != i);
free(tmp);
EINA_ARRAY_ITER_END
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if((unsigned int) atoi(tmp) != i);
free(tmp);
}
fail_if(i != 200);
@ -63,6 +65,7 @@ START_TEST(eina_array_static)
{
Eina_Array sea = { NULL, 0, 0, 0 };
char *tmp;
Eina_Array_Iterator it;
unsigned int i;
eina_array_init();
@ -81,10 +84,11 @@ START_TEST(eina_array_static)
fail_if(eina_array_get(&sea, 10) == NULL);
fail_if(atoi(eina_array_get(&sea, 10)) != 10);
EINA_ARRAY_ITER_NEXT(&sea, i, tmp)
fail_if((unsigned int) atoi(tmp) != i);
free(tmp);
EINA_ARRAY_ITER_END
EINA_ARRAY_ITER_NEXT(&sea, i, tmp, it)
{
fail_if((unsigned int) atoi(tmp) != i);
free(tmp);
}
fail_if(i != 200);
@ -111,6 +115,7 @@ START_TEST(eina_array_remove_stuff)
{
Eina_Array *ea;
int *tmp;
Eina_Array_Iterator it;
unsigned int i;
eina_array_init();
@ -137,9 +142,8 @@ START_TEST(eina_array_remove_stuff)
eina_array_remove(ea, keep_int, NULL);
fail_if(eina_array_count(ea) != 990);
EINA_ARRAY_ITER_NEXT(ea, i, tmp)
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
fail_if(*tmp == 0);
EINA_ARRAY_ITER_END;
// Remove the last items
for (i = 980; i < 990; ++i)
@ -152,12 +156,11 @@ START_TEST(eina_array_remove_stuff)
// Remove all items
fail_if(eina_array_count(ea) != 980);
EINA_ARRAY_ITER_NEXT(ea, i, tmp)
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if(*tmp == 0);
*tmp = 0;
}
EINA_ARRAY_ITER_END;
eina_array_remove(ea, keep_int, NULL);

View File

@ -16,6 +16,10 @@
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
@ -35,6 +39,20 @@ START_TEST(eina_hash_init_shutdown)
}
END_TEST
static Eina_Bool
eina_foreach_check(__UNUSED__ const Eina_Hash *hash, const void *key, void *data, __UNUSED__ void *fdata)
{
int *j = data;
int i;
if (strlen(key) <= 0) return EINA_TRUE;
i = atoi(key);
fail_if(i != *j);
return EINA_TRUE;
}
START_TEST(eina_hash_simple)
{
Eina_Hash *hash = NULL;
@ -60,6 +78,8 @@ START_TEST(eina_hash_simple)
fail_if(!test);
fail_if(*test != 42);
eina_hash_foreach(hash, eina_foreach_check, NULL);
test = eina_hash_modify(hash, "5", &array[4]);
fail_if(!test);
fail_if(*test != 5);

View File

@ -0,0 +1,148 @@
/* 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 <stdio.h>
#include "eina_suite.h"
#include "eina_array.h"
#include "eina_hash.h"
#include "eina_private.h"
static Eina_Bool
eina_iterator_array_check(__UNUSED__ const Eina_Array *array,
int *data, int *fdata)
{
fail_if(*fdata > *data);
*fdata = *data;
return EINA_TRUE;
}
START_TEST(eina_iterator_array_simple)
{
Eina_Iterator *it;
Eina_Array *ea;
int *tmp;
int i;
eina_array_init();
ea = eina_array_new(11);
fail_if(!ea);
for (i = 0; i < 200; ++i)
{
tmp = malloc(sizeof(int));
fail_if(!tmp);
*tmp = i;
eina_array_append(ea, tmp);
}
it = eina_array_iterator_new(ea);
fail_if(!it);
tmp = eina_iterator_data_get(it);
fail_if(!tmp);
fail_if(*tmp != 0);
i = -1;
eina_iterator_foreach(it, EINA_EACH(eina_iterator_array_check), &i);
fail_if(i != 199);
fail_if(eina_iterator_container_get(it) != ea);
fail_if(eina_iterator_next(it) != EINA_FALSE);
eina_iterator_free(it);
eina_array_free(ea);
eina_array_shutdown();
}
END_TEST
static Eina_Bool
eina_iterator_hash_key_check(const Eina_Hash *hash, const char *key, __UNUSED__ void *fdata)
{
fail_if(eina_hash_find(hash, key) == NULL);
return EINA_TRUE;
}
static Eina_Bool
eina_iterator_hash_data_check(const Eina_Hash *hash, int *data, __UNUSED__ void *fdata)
{
char tmp[10];
snprintf(tmp, 10, "%i", *data);
fail_if(eina_hash_find(hash, tmp) != data);
return EINA_TRUE;
}
static Eina_Bool
eina_iterator_hash_tuple_check(__UNUSED__ const Eina_Hash *hash, Eina_Hash_Tuple *tuple, __UNUSED__ void *fdata)
{
fail_if(atoi((char*) tuple->key) != *((int*) tuple->data));
return EINA_TRUE;
}
START_TEST(eina_iterator_hash_simple)
{
Eina_Iterator *it;
Eina_Hash *hash;
int array[] = { 1, 42, 7, 8, 6 };
eina_hash_init();
hash = eina_hash_string_superfast_new();
fail_if(hash == NULL);
fail_if(eina_hash_add(hash, "1", &array[0]) != EINA_TRUE);
fail_if(eina_hash_add(hash, "42", &array[1]) != EINA_TRUE);
fail_if(eina_hash_add(hash, "7", &array[2]) != EINA_TRUE);
fail_if(eina_hash_add(hash, "8", &array[3]) != EINA_TRUE);
fail_if(eina_hash_add(hash, "6", &array[4]) != EINA_TRUE);
it = eina_hash_iterator_key_new(hash);
eina_iterator_foreach(it, EINA_EACH(eina_iterator_hash_key_check), NULL);
eina_iterator_free(it);
it = eina_hash_iterator_data_new(hash);
eina_iterator_foreach(it, EINA_EACH(eina_iterator_hash_data_check), NULL);
eina_iterator_free(it);
it = eina_hash_iterator_tuple_new(hash);
eina_iterator_foreach(it, EINA_EACH(eina_iterator_hash_tuple_check), NULL);
eina_iterator_free(it);
eina_hash_free(hash);
eina_hash_shutdown();
}
END_TEST
void
eina_test_iterator(TCase *tc)
{
tcase_add_test(tc, eina_iterator_array_simple);
tcase_add_test(tc, eina_iterator_hash_simple);
}