2009-11-01 11:50:18 -08:00
|
|
|
// vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
|
|
|
2008-08-06 11:15:24 -07:00
|
|
|
/* EINA - EFL data type library
|
|
|
|
* Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, Tilman Sauerbeck,
|
|
|
|
* Vincent Torri, Cedric Bail, Jorge Luis Zapata Muga,
|
2008-09-26 06:45:30 -07:00
|
|
|
* Corey Donohoe, Arnaud de Turckheim, Alexandre Becoulet
|
2008-08-06 11:15:24 -07:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following copyright and
|
|
|
|
* permission notice:
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004 ncn
|
|
|
|
* Copyright (C) 2006 Sebastian Dransfeld
|
|
|
|
* Copyright (C) 2007 Christopher Michael
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies of the Software and its Copyright notices. In addition publicly
|
|
|
|
* documented acknowledgment must be given that this software has been used if no
|
|
|
|
* source code of this software is made available publicly. This includes
|
|
|
|
* acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
|
|
|
|
* documents or any documentation provided with any product containing this
|
|
|
|
* software. This License does not apply to any software that links to the
|
|
|
|
* libraries provided by this software (statically or dynamically), but only to
|
|
|
|
* the software provided.
|
|
|
|
|
|
|
|
* Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
|
|
|
|
* and it's intent.
|
|
|
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2008-09-22 22:17:49 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @page tutorial_list_page List Tutorial
|
|
|
|
*
|
|
|
|
* to be written...
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2008-10-29 16:12:56 -07:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2008-10-16 14:31:51 -07:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
2009-06-08 01:27:33 -07:00
|
|
|
#include "eina_config.h"
|
2009-08-28 05:03:34 -07:00
|
|
|
#include "eina_private.h"
|
2008-08-07 06:09:09 -07:00
|
|
|
#include "eina_error.h"
|
2008-09-30 09:48:28 -07:00
|
|
|
#include "eina_mempool.h"
|
2008-12-26 10:31:14 -08:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
|
|
|
#include "eina_safety_checks.h"
|
|
|
|
#include "eina_list.h"
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Local *
|
|
|
|
*============================================================================*/
|
2008-08-27 23:31:18 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
2009-09-06 20:32:22 -07:00
|
|
|
static const char EINA_MAGIC_LIST_STR[] = "Eina List";
|
|
|
|
static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator";
|
|
|
|
static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor";
|
|
|
|
static const char EINA_MAGIC_LIST_ACCOUNTING_STR[] = "Eina List Accounting";
|
|
|
|
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
#define EINA_MAGIC_CHECK_LIST(d, ...) \
|
|
|
|
do { \
|
|
|
|
if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \
|
|
|
|
{ \
|
|
|
|
EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST); \
|
|
|
|
return __VA_ARGS__; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define EINA_MAGIC_CHECK_LIST_ITERATOR(d, ...) \
|
|
|
|
do { \
|
|
|
|
if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ITERATOR)) \
|
|
|
|
{ \
|
|
|
|
EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ITERATOR); \
|
|
|
|
return __VA_ARGS__; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define EINA_MAGIC_CHECK_LIST_ACCESSOR(d, ...) \
|
|
|
|
do { \
|
|
|
|
if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCESSOR)) \
|
|
|
|
{ \
|
|
|
|
EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCESSOR); \
|
|
|
|
return __VA_ARGS__; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define EINA_MAGIC_CHECK_LIST_ACCOUNTING(d) \
|
|
|
|
do { \
|
|
|
|
if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCOUNTING)) \
|
|
|
|
{ \
|
|
|
|
EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCOUNTING); \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-09-26 06:45:30 -07:00
|
|
|
#define EINA_LIST_SORT_STACK_SIZE 32
|
|
|
|
|
2008-08-13 02:19:34 -07:00
|
|
|
typedef struct _Eina_Iterator_List Eina_Iterator_List;
|
|
|
|
typedef struct _Eina_Accessor_List Eina_Accessor_List;
|
|
|
|
|
|
|
|
struct _Eina_Iterator_List
|
|
|
|
{
|
|
|
|
Eina_Iterator iterator;
|
|
|
|
|
|
|
|
const Eina_List *head;
|
|
|
|
const Eina_List *current;
|
2008-12-05 22:53:14 -08:00
|
|
|
|
* eina/src/include/eina_array.h,
* eina/src/include/eina_f16p16.h,
* eina/src/include/eina_accessor.h,
* eina/src/include/eina_list.h,
* eina/src/include/eina_iterator.h,
* eina/src/lib/eina_rectangle.c,
* eina/src/lib/eina_list.c,
* eina/src/lib/eina_array.c,
* eina/src/lib/eina_hash.c,
* eina/src/lib/eina_module.c,
* eina/src/lib/eina_stringshare.c,
* eina/src/lib/eina_benchmark.c: Fix for windows compilation.
SVN revision: 38663
2009-01-20 07:56:48 -08:00
|
|
|
EINA_MAGIC
|
2008-08-13 02:19:34 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _Eina_Accessor_List
|
|
|
|
{
|
|
|
|
Eina_Accessor accessor;
|
|
|
|
|
|
|
|
const Eina_List *head;
|
|
|
|
const Eina_List *current;
|
|
|
|
|
|
|
|
unsigned int index;
|
2008-12-05 22:53:14 -08:00
|
|
|
|
* eina/src/include/eina_array.h,
* eina/src/include/eina_f16p16.h,
* eina/src/include/eina_accessor.h,
* eina/src/include/eina_list.h,
* eina/src/include/eina_iterator.h,
* eina/src/lib/eina_rectangle.c,
* eina/src/lib/eina_list.c,
* eina/src/lib/eina_array.c,
* eina/src/lib/eina_hash.c,
* eina/src/lib/eina_module.c,
* eina/src/lib/eina_stringshare.c,
* eina/src/lib/eina_benchmark.c: Fix for windows compilation.
SVN revision: 38663
2009-01-20 07:56:48 -08:00
|
|
|
EINA_MAGIC
|
2008-08-13 02:19:34 -07:00
|
|
|
};
|
|
|
|
|
2008-09-30 09:48:28 -07:00
|
|
|
static Eina_Mempool *_eina_list_mp = NULL;
|
|
|
|
static Eina_Mempool *_eina_list_accounting_mp = NULL;
|
2009-09-03 18:43:50 -07:00
|
|
|
static int _eina_list_log_dom = -1;
|
|
|
|
|
2009-09-06 21:23:05 -07:00
|
|
|
#ifdef ERR
|
|
|
|
#undef ERR
|
|
|
|
#endif
|
2009-09-03 18:43:50 -07:00
|
|
|
#define ERR(...) EINA_LOG_DOM_ERR(_eina_list_log_dom, __VA_ARGS__)
|
2009-09-06 21:23:05 -07:00
|
|
|
|
|
|
|
#ifdef DBG
|
|
|
|
#undef DBG
|
|
|
|
#endif
|
2009-09-03 18:43:50 -07:00
|
|
|
#define DBG(...) EINA_LOG_DOM_DBG(_eina_list_log_dom, __VA_ARGS__)
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
static inline Eina_List_Accounting *
|
2008-08-07 06:09:09 -07:00
|
|
|
_eina_list_mempool_accounting_new(__UNUSED__ Eina_List *list)
|
|
|
|
{
|
|
|
|
Eina_List_Accounting *tmp;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
tmp =
|
|
|
|
eina_mempool_malloc(_eina_list_accounting_mp,
|
|
|
|
sizeof (Eina_List_Accounting));
|
|
|
|
if (!tmp)
|
|
|
|
return NULL;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST_ACCOUNTING);
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
static inline void
|
|
|
|
_eina_list_mempool_accounting_free(Eina_List_Accounting *accounting)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ACCOUNTING(accounting);
|
|
|
|
|
2008-09-30 09:48:28 -07:00
|
|
|
EINA_MAGIC_SET(accounting, EINA_MAGIC_NONE);
|
|
|
|
eina_mempool_free(_eina_list_accounting_mp, accounting);
|
2008-08-07 06:09:09 -07:00
|
|
|
}
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
static inline Eina_List *
|
2008-08-07 06:09:09 -07:00
|
|
|
_eina_list_mempool_list_new(__UNUSED__ Eina_List *list)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2008-08-07 06:09:09 -07:00
|
|
|
Eina_List *tmp;
|
|
|
|
|
2009-06-24 09:56:49 -07:00
|
|
|
tmp = eina_mempool_malloc(_eina_list_mp, sizeof (Eina_List));
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!tmp)
|
|
|
|
return NULL;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST);
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
return tmp;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-08-07 06:09:09 -07:00
|
|
|
static inline void
|
|
|
|
_eina_list_mempool_list_free(Eina_List *list)
|
|
|
|
{
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list);
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
list->accounting->count--;
|
|
|
|
if (list->accounting->count == 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_list_mempool_accounting_free(list->accounting);
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-09-30 09:48:28 -07:00
|
|
|
EINA_MAGIC_SET(list, EINA_MAGIC_NONE);
|
|
|
|
eina_mempool_free(_eina_list_mp, list);
|
2008-08-07 06:09:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_List *
|
|
|
|
_eina_list_setup_accounting(Eina_List *list)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
list->accounting = _eina_list_mempool_accounting_new(list);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list->accounting)
|
|
|
|
goto on_error;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
|
|
|
list->accounting->last = list;
|
|
|
|
list->accounting->count = 1;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
on_error:
|
2008-08-07 06:09:09 -07:00
|
|
|
_eina_list_mempool_list_free(list);
|
|
|
|
return NULL;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-08-07 06:09:09 -07:00
|
|
|
|
|
|
|
static inline void
|
|
|
|
_eina_list_update_accounting(Eina_List *list, Eina_List *new_list)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list);
|
|
|
|
EINA_MAGIC_CHECK_LIST(new_list);
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
list->accounting->count++;
|
|
|
|
new_list->accounting = list->accounting;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
#if 0
|
2008-07-30 05:46:55 -07:00
|
|
|
static Eina_Mempool2 _eina_list_mempool =
|
|
|
|
{
|
|
|
|
sizeof(Eina_List),
|
|
|
|
320,
|
|
|
|
0, NULL, NULL
|
|
|
|
};
|
|
|
|
static Eina_Mempool2 _eina_list_accounting_mempool =
|
|
|
|
{
|
|
|
|
sizeof(Eina_List_Accounting),
|
|
|
|
80,
|
|
|
|
0, NULL, NULL
|
|
|
|
};
|
2008-08-07 06:09:09 -07:00
|
|
|
#endif
|
|
|
|
|
2008-08-13 02:19:34 -07:00
|
|
|
static Eina_Bool
|
|
|
|
eina_list_iterator_next(Eina_Iterator_List *it, void **data)
|
|
|
|
{
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (it->current == NULL)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2009-08-25 14:05:00 -07:00
|
|
|
*data = eina_list_data_get(it->current);
|
2008-08-13 02:19:34 -07:00
|
|
|
|
|
|
|
it->current = eina_list_next(it->current);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2009-03-17 05:52:38 -07:00
|
|
|
static Eina_Bool
|
|
|
|
eina_list_iterator_prev(Eina_Iterator_List *it, void **data)
|
|
|
|
{
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (it->current == NULL)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2009-08-25 14:05:00 -07:00
|
|
|
*data = eina_list_data_get(it->current);
|
2009-03-17 05:52:38 -07:00
|
|
|
|
|
|
|
it->current = eina_list_prev(it->current);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-08-13 02:19:34 -07:00
|
|
|
static Eina_List *
|
|
|
|
eina_list_iterator_get_container(Eina_Iterator_List *it)
|
|
|
|
{
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ITERATOR(it, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
return (Eina_List *)it->head;
|
2008-08-13 02:19:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
eina_list_iterator_free(Eina_Iterator_List *it)
|
|
|
|
{
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ITERATOR(it);
|
|
|
|
|
|
|
|
MAGIC_FREE(it);
|
2008-08-13 02:19:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2010-01-23 11:53:27 -08:00
|
|
|
eina_list_accessor_get_at(Eina_Accessor_List *it, unsigned int idx, void **data)
|
2008-08-13 02:19:34 -07:00
|
|
|
{
|
|
|
|
const Eina_List *over;
|
|
|
|
unsigned int middle;
|
|
|
|
unsigned int i;
|
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ACCESSOR(it, EINA_FALSE);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (idx >= eina_list_count(it->head))
|
|
|
|
return EINA_FALSE;
|
2008-08-13 02:19:34 -07:00
|
|
|
|
2010-01-23 11:53:27 -08:00
|
|
|
if (it->index == idx)
|
2010-07-27 19:37:05 -07:00
|
|
|
over = it->current;
|
2010-01-23 11:53:27 -08:00
|
|
|
else if (idx > it->index)
|
2008-08-13 02:19:34 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
/* After current position. */
|
|
|
|
middle = ((eina_list_count(it->head) - it->index) >> 1) + it->index;
|
|
|
|
|
|
|
|
if (idx > middle)
|
|
|
|
/* Go backward from the end. */
|
|
|
|
for (i = eina_list_count(it->head) - 1,
|
|
|
|
over = eina_list_last(it->head);
|
|
|
|
i > idx && over != NULL;
|
|
|
|
--i, over = eina_list_prev(over))
|
|
|
|
;
|
|
|
|
else
|
|
|
|
/* Go forward from current. */
|
|
|
|
for (i = it->index, over = it->current;
|
|
|
|
i < idx && over != NULL;
|
|
|
|
++i, over = eina_list_next(over))
|
|
|
|
;
|
2008-08-13 02:19:34 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
/* Before current position. */
|
|
|
|
middle = it->index >> 1;
|
|
|
|
|
|
|
|
if (idx > middle)
|
|
|
|
/* Go backward from current. */
|
|
|
|
for (i = it->index, over = it->current;
|
|
|
|
i > idx && over != NULL;
|
|
|
|
--i, over = eina_list_prev(over))
|
|
|
|
;
|
|
|
|
else
|
|
|
|
/* Go forward from start. */
|
|
|
|
for (i = 0, over = it->head;
|
|
|
|
i < idx && over != NULL;
|
|
|
|
++i, over = eina_list_next(over))
|
|
|
|
;
|
2008-08-13 02:19:34 -07:00
|
|
|
}
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (over == NULL)
|
|
|
|
return EINA_FALSE;
|
2008-08-13 02:19:34 -07:00
|
|
|
|
|
|
|
it->current = over;
|
2010-01-23 11:53:27 -08:00
|
|
|
it->index = idx;
|
2008-08-13 02:19:34 -07:00
|
|
|
|
2009-08-25 14:05:00 -07:00
|
|
|
*data = eina_list_data_get(it->current);
|
2008-08-13 02:19:34 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_List *
|
|
|
|
eina_list_accessor_get_container(Eina_Accessor_List *it)
|
|
|
|
{
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ACCESSOR(it, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
return (Eina_List *)it->head;
|
2008-08-13 02:19:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
eina_list_accessor_free(Eina_Accessor_List *it)
|
|
|
|
{
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST_ACCESSOR(it);
|
|
|
|
|
|
|
|
MAGIC_FREE(it);
|
2008-08-13 02:19:34 -07:00
|
|
|
}
|
|
|
|
|
2008-10-01 09:30:30 -07:00
|
|
|
static Eina_List *
|
2008-09-26 06:45:30 -07:00
|
|
|
eina_list_sort_rebuild_prev(Eina_List *list)
|
|
|
|
{
|
2008-10-01 09:30:30 -07:00
|
|
|
Eina_List *prev = NULL;
|
2008-09-26 06:45:30 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-26 06:45:30 -07:00
|
|
|
|
|
|
|
for (; list; list = list->next)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
list->prev = prev;
|
|
|
|
prev = list;
|
2008-09-26 06:45:30 -07:00
|
|
|
}
|
2008-10-01 09:30:30 -07:00
|
|
|
|
|
|
|
return prev;
|
2008-09-26 06:45:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_List *
|
|
|
|
eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func)
|
|
|
|
{
|
|
|
|
Eina_List *first, *last;
|
|
|
|
|
|
|
|
if (func(a->data, b->data) < 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
a = (last = first = a)->next;
|
2008-09-26 06:45:30 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
b = (last = first = b)->next;
|
2008-09-26 06:45:30 -07:00
|
|
|
|
|
|
|
while (a && b)
|
2010-07-27 19:37:05 -07:00
|
|
|
if (func(a->data, b->data) < 0)
|
|
|
|
a = (last = last->next = a)->next;
|
|
|
|
else
|
|
|
|
b = (last = last->next = b)->next;
|
2008-09-26 06:45:30 -07:00
|
|
|
|
|
|
|
last->next = a ? a : b;
|
|
|
|
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/**
|
|
|
|
* @endcond
|
|
|
|
*/
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Global *
|
|
|
|
*============================================================================*/
|
2008-08-28 00:46:42 -07:00
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/**
|
2009-09-06 15:21:56 -07:00
|
|
|
* @internal
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Initialize the list module.
|
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
2008-09-22 22:17:49 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* This function sets up the list module of Eina. It is called by
|
|
|
|
* eina_init().
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* This function creates mempool to speed up list node and accounting
|
|
|
|
* management, using EINA_MEMPOOL environment variable if it is set to
|
|
|
|
* choose the memory pool type to use.
|
2009-06-22 13:03:58 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @see eina_init()
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
2009-09-06 15:21:56 -07:00
|
|
|
Eina_Bool
|
2008-08-07 06:09:09 -07:00
|
|
|
eina_list_init(void)
|
|
|
|
{
|
2009-09-06 15:21:56 -07:00
|
|
|
const char *choice, *tmp;
|
2008-10-06 07:47:09 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_list_log_dom = eina_log_domain_register("eina_list",
|
|
|
|
EINA_LOG_COLOR_DEFAULT);
|
2009-09-06 15:21:56 -07:00
|
|
|
if (_eina_list_log_dom < 0)
|
2008-09-25 07:46:16 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_LOG_ERR("Could not register log domain: eina_list");
|
|
|
|
return EINA_FALSE;
|
2009-09-06 15:21:56 -07:00
|
|
|
}
|
2008-09-30 09:48:28 -07:00
|
|
|
|
2008-10-06 07:47:09 -07:00
|
|
|
#ifdef EINA_DEFAULT_MEMPOOL
|
2009-09-06 15:21:56 -07:00
|
|
|
choice = "pass_through";
|
2008-10-06 07:47:09 -07:00
|
|
|
#else
|
2009-09-06 15:21:56 -07:00
|
|
|
choice = "chained_mempool";
|
2008-10-06 07:47:09 -07:00
|
|
|
#endif
|
2009-09-06 15:21:56 -07:00
|
|
|
tmp = getenv("EINA_MEMPOOL");
|
|
|
|
if (tmp && tmp[0])
|
2010-07-27 19:37:05 -07:00
|
|
|
choice = tmp;
|
2008-10-06 07:47:09 -07:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
_eina_list_mp = eina_mempool_add
|
2010-07-27 19:37:05 -07:00
|
|
|
(choice, "list", NULL, sizeof(Eina_List), 320);
|
2009-09-06 15:21:56 -07:00
|
|
|
if (!_eina_list_mp)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
ERR("ERROR: Mempool for list cannot be allocated in list init.");
|
|
|
|
goto on_init_fail;
|
2009-09-06 15:21:56 -07:00
|
|
|
}
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
_eina_list_accounting_mp = eina_mempool_add
|
2010-07-27 19:37:05 -07:00
|
|
|
(choice, "list_accounting", NULL, sizeof(Eina_List_Accounting), 80);
|
2009-09-06 15:21:56 -07:00
|
|
|
if (!_eina_list_accounting_mp)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
ERR(
|
|
|
|
"ERROR: Mempool for list accounting cannot be allocated in list init.");
|
|
|
|
eina_mempool_del(_eina_list_mp);
|
|
|
|
goto on_init_fail;
|
2008-09-25 07:46:16 -07:00
|
|
|
}
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
|
2009-09-06 20:32:22 -07:00
|
|
|
EMS(EINA_MAGIC_LIST);
|
|
|
|
EMS(EINA_MAGIC_LIST_ITERATOR);
|
|
|
|
EMS(EINA_MAGIC_LIST_ACCESSOR);
|
|
|
|
EMS(EINA_MAGIC_LIST_ACCOUNTING);
|
|
|
|
#undef EMS
|
2009-09-06 15:21:56 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
2009-06-04 02:02:29 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
on_init_fail:
|
2009-09-03 18:43:50 -07:00
|
|
|
eina_log_domain_unregister(_eina_list_log_dom);
|
|
|
|
_eina_list_log_dom = -1;
|
2009-09-06 15:21:56 -07:00
|
|
|
return EINA_FALSE;
|
2008-08-07 06:09:09 -07:00
|
|
|
}
|
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/**
|
2009-09-06 15:21:56 -07:00
|
|
|
* @internal
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Shut down the list module.
|
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
2008-09-22 22:17:49 -07:00
|
|
|
*
|
2009-09-06 15:21:56 -07:00
|
|
|
* This function shuts down the list module set up by
|
|
|
|
* eina_list_init(). It is called by eina_shutdown().
|
|
|
|
*
|
|
|
|
* @see eina_shutdown()
|
2008-08-27 23:31:18 -07:00
|
|
|
*/
|
2009-09-06 15:21:56 -07:00
|
|
|
Eina_Bool
|
2008-08-07 06:09:09 -07:00
|
|
|
eina_list_shutdown(void)
|
|
|
|
{
|
2009-09-06 15:21:56 -07:00
|
|
|
eina_mempool_del(_eina_list_accounting_mp);
|
|
|
|
eina_mempool_del(_eina_list_mp);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2009-09-06 15:21:56 -07:00
|
|
|
eina_log_domain_unregister(_eina_list_log_dom);
|
|
|
|
_eina_list_log_dom = -1;
|
|
|
|
return EINA_TRUE;
|
2008-08-07 06:09:09 -07:00
|
|
|
}
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2009-12-27 00:45:30 -08:00
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* API *
|
|
|
|
*============================================================================*/
|
2009-12-27 00:45:30 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @addtogroup Eina_List_Group List
|
|
|
|
*
|
|
|
|
* @brief These functions provide double linked list management.
|
|
|
|
*
|
|
|
|
* For more information, you can look at the @ref tutorial_list_page.
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Append the given data to the given linked list.
|
|
|
|
*
|
|
|
|
* @param list The given list.
|
|
|
|
* @param data The data to append.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
2008-12-26 10:31:14 -08:00
|
|
|
* This function appends @p data to @p list. If @p list is @c NULL, a
|
2008-09-22 22:17:49 -07:00
|
|
|
* new list is returned. On success, a new list pointer that should be
|
|
|
|
* used in place of the one given to this function is
|
|
|
|
* returned. Otherwise, the old pointer is returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
|
|
|
* The following example code demonstrates how to ensure that the
|
|
|
|
* given data has been successfully appended.
|
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* Eina_List *list = NULL;
|
|
|
|
* extern void *my_data;
|
|
|
|
*
|
|
|
|
* list = eina_list_append(list, my_data);
|
2008-09-22 22:17:49 -07:00
|
|
|
* if (eina_error_get())
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
|
|
|
|
* exit(-1);
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_append(Eina_List *list, const void *data)
|
|
|
|
{
|
|
|
|
Eina_List *l, *new_l;
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
eina_error_set(0);
|
|
|
|
new_l = _eina_list_mempool_list_new(list);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!new_l)
|
|
|
|
return list;
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
new_l->next = NULL;
|
|
|
|
new_l->data = (void *)data;
|
|
|
|
if (!list)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
new_l->prev = NULL;
|
|
|
|
return _eina_list_setup_accounting(new_l);
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
l = list->accounting->last;
|
2008-08-07 06:09:09 -07:00
|
|
|
list->accounting->last = new_l;
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
l->next = new_l;
|
|
|
|
new_l->prev = l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
|
|
|
_eina_list_update_accounting(list, new_l);
|
2008-07-30 05:46:55 -07:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Prepends the given data to the given linked list.
|
|
|
|
*
|
|
|
|
* @param list The given list.
|
|
|
|
* @param data The data to prepend.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
2008-12-26 10:31:14 -08:00
|
|
|
* This function prepends @p data to @p list. If @p list is @c NULL, a
|
2008-09-22 22:17:49 -07:00
|
|
|
* new list is returned. On success, a new list pointer that should be
|
|
|
|
* used in place of the one given to this function is
|
|
|
|
* returned. Otherwise, the old pointer is returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
|
|
|
* The following example code demonstrates how to ensure that the
|
|
|
|
* given data has been successfully prepended.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* Eina_List *list = NULL;
|
|
|
|
* extern void *my_data;
|
|
|
|
*
|
|
|
|
* list = eina_list_prepend(list, my_data);
|
2008-09-22 22:17:49 -07:00
|
|
|
* if (eina_error_get())
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
|
|
|
|
* exit(-1);
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_prepend(Eina_List *list, const void *data)
|
|
|
|
{
|
|
|
|
Eina_List *new_l;
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
eina_error_set(0);
|
|
|
|
new_l = _eina_list_mempool_list_new(list);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!new_l)
|
|
|
|
return list;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
new_l->prev = NULL;
|
|
|
|
new_l->next = list;
|
2008-08-07 06:09:09 -07:00
|
|
|
new_l->data = (void *)data;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return _eina_list_setup_accounting(new_l);
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
list->prev = new_l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
|
|
|
_eina_list_update_accounting(list, new_l);
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return new_l;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Insert the given data into the given linked list after the specified data.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* @param list The given linked list.
|
|
|
|
* @param data The data to insert.
|
|
|
|
* @param relative The data to insert after.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
|
|
|
* This function inserts @p data to @p list after @p relative. If
|
|
|
|
* @p relative is not in the list, @p data is appended to the end of
|
|
|
|
* the list. If @p list is @c NULL, a new list is returned. If there
|
|
|
|
* are multiple instances of @p relative in the list, @p data is
|
|
|
|
* inserted after the first instance.On success, a new list pointer
|
|
|
|
* that should be used in place of the one given to this function is
|
|
|
|
* returned. Otherwise, the old pointer is returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
|
|
|
* The following example code demonstrates how to ensure that the
|
|
|
|
* given data has been successfully inserted.
|
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* Eina_List *list = NULL;
|
|
|
|
* extern void *my_data;
|
|
|
|
* extern void *relative_member;
|
|
|
|
*
|
|
|
|
* list = eina_list_append(list, relative_member);
|
2008-09-22 22:17:49 -07:00
|
|
|
* if (eina_error_get())
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
|
|
|
|
* exit(-1);
|
|
|
|
* }
|
|
|
|
* list = eina_list_append_relative(list, my_data, relative_member);
|
2008-09-22 22:17:49 -07:00
|
|
|
* if (eina_error_get())
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
|
|
|
|
* exit(-1);
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_append_relative(Eina_List *list,
|
|
|
|
const void *data,
|
|
|
|
const void *relative)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
|
|
|
Eina_List *l;
|
2008-09-25 07:46:16 -07:00
|
|
|
void *list_data;
|
2009-03-25 02:24:56 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (list)
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2008-10-21 05:49:29 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, list_data)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
if (list_data == relative)
|
|
|
|
return eina_list_append_relative_list(list, data, l);
|
|
|
|
}
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return eina_list_append(list, data);
|
|
|
|
}
|
|
|
|
|
2008-09-22 22:17:49 -07:00
|
|
|
/**
|
|
|
|
* @brief Append a list node to a linked list after the specified member
|
|
|
|
*
|
|
|
|
* @param list The given linked list.
|
|
|
|
* @param data The data to insert.
|
|
|
|
* @param relative The list node to insert after.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
|
|
|
* This function inserts @p data to @p list after the list node
|
|
|
|
* @p relative. If @p list or @p relative are @c NULL, @p data is just
|
|
|
|
* appended to @p list using eina_list_append(). If @p list is
|
|
|
|
* @c NULL, a new list is returned. If there are multiple instances
|
|
|
|
* of @p relative in the list, @p data is inserted after the first
|
|
|
|
* instance. On success, a new list pointer that should be used in
|
|
|
|
* place of the one given to this function is returned. Otherwise, the
|
|
|
|
* old pointer is returned.
|
|
|
|
*/
|
2008-07-30 05:46:55 -07:00
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_append_relative_list(Eina_List *list,
|
|
|
|
const void *data,
|
|
|
|
Eina_List *relative)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
|
|
|
Eina_List *new_l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if ((!list) || (!relative))
|
|
|
|
return eina_list_append(list, data);
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
eina_error_set(0);
|
|
|
|
new_l = _eina_list_mempool_list_new(list);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!new_l)
|
|
|
|
return list;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(relative, NULL);
|
2008-08-07 06:09:09 -07:00
|
|
|
new_l->next = relative->next;
|
2008-07-30 05:46:55 -07:00
|
|
|
new_l->data = (void *)data;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
if (relative->next)
|
2010-07-27 19:37:05 -07:00
|
|
|
relative->next->prev = new_l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
relative->next = new_l;
|
|
|
|
new_l->prev = relative;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
|
|
|
_eina_list_update_accounting(list, new_l);
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
if (!new_l->next)
|
2010-07-27 19:37:05 -07:00
|
|
|
new_l->accounting->last = new_l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Prepend a data pointer to a linked list before the specified member
|
|
|
|
*
|
|
|
|
* @param list The given linked list.
|
|
|
|
* @param data The data to insert.
|
|
|
|
* @param relative The data to insert before.
|
|
|
|
* @return A list pointer.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function inserts @p data to @p list before @p relative. If
|
|
|
|
* @p relative is not in the list, @p data is prepended to the list
|
|
|
|
* with eina_list_prepend(). If @p list is @c NULL, a new list is
|
|
|
|
* returned. If there are multiple instances of @p relative in the
|
|
|
|
* list, @p data is inserted before the first instance. On success, a
|
|
|
|
* new list pointer that should be used in place of the one given to
|
|
|
|
* this function is returned. Otherwise, the old pointer is returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
|
|
|
* The following code example demonstrates how to ensure that the
|
|
|
|
* given data has been successfully inserted.
|
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* Eina_List *list = NULL;
|
|
|
|
* extern void *my_data;
|
|
|
|
* extern void *relative_member;
|
|
|
|
*
|
|
|
|
* list = eina_list_append(list, relative_member);
|
2008-09-22 22:17:49 -07:00
|
|
|
* if (eina_error_get_error())
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
|
|
|
|
* exit(-1);
|
|
|
|
* }
|
|
|
|
* list = eina_list_prepend_relative(list, my_data, relative_member);
|
2008-09-22 22:17:49 -07:00
|
|
|
* if (eina_error_get())
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
|
|
|
|
* exit(-1);
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_prepend_relative(Eina_List *list,
|
|
|
|
const void *data,
|
|
|
|
const void *relative)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
|
|
|
Eina_List *l;
|
2008-09-25 07:46:16 -07:00
|
|
|
void *list_data;
|
2009-03-25 02:24:56 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (list)
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-10-21 05:49:29 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, list_data)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
if (list_data == relative)
|
|
|
|
return eina_list_prepend_relative_list(list, data, l);
|
|
|
|
}
|
2008-07-30 05:46:55 -07:00
|
|
|
return eina_list_prepend(list, data);
|
|
|
|
}
|
|
|
|
|
2008-09-22 22:17:49 -07:00
|
|
|
/**
|
|
|
|
* @brief Prepend a list node to a linked list before the specified member
|
|
|
|
*
|
|
|
|
* @param list The given linked list.
|
|
|
|
* @param data The data to insert.
|
|
|
|
* @param relative The list node to insert before.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
|
|
|
* This function inserts @p data to @p list before the list node
|
|
|
|
* @p relative. If @p list or @p relative are @c NULL, @p data is just
|
|
|
|
* prepended to @p list using eina_list_prepend(). If @p list is
|
|
|
|
* @c NULL, a new list is returned. If there are multiple instances
|
|
|
|
* of @p relative in the list, @p data is inserted before the first
|
|
|
|
* instance. On success, a new list pointer that should be used in
|
|
|
|
* place of the one given to this function is returned. Otherwise, the
|
|
|
|
* old pointer is returned.
|
|
|
|
*/
|
2008-07-30 05:46:55 -07:00
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_prepend_relative_list(Eina_List *list,
|
|
|
|
const void *data,
|
|
|
|
Eina_List *relative)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
|
|
|
Eina_List *new_l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if ((!list) || (!relative))
|
|
|
|
return eina_list_prepend(list, data);
|
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
eina_error_set(0);
|
|
|
|
new_l = _eina_list_mempool_list_new(list);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!new_l)
|
|
|
|
return list;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(relative, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
new_l->prev = relative->prev;
|
|
|
|
new_l->next = relative;
|
2008-08-07 06:09:09 -07:00
|
|
|
new_l->data = (void *)data;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (relative->prev)
|
|
|
|
relative->prev->next = new_l;
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
relative->prev = new_l;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
|
|
|
_eina_list_update_accounting(list, new_l);
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
if (new_l->prev)
|
2010-07-27 19:37:05 -07:00
|
|
|
return list;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return new_l;
|
|
|
|
}
|
|
|
|
|
2009-08-06 15:31:45 -07:00
|
|
|
/**
|
|
|
|
* @brief Insert a new node into a sorted list.
|
|
|
|
*
|
|
|
|
* @param list The given linked list, @b must be sorted.
|
2009-12-27 00:45:30 -08:00
|
|
|
* @param func The function called for the sort.
|
2009-08-06 15:31:45 -07:00
|
|
|
* @param data The data to insert sorted.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
|
|
|
* This function inserts values into a linked list assuming it was
|
|
|
|
* sorted and the result will be sorted. If @p list is @c NULLL, a new
|
|
|
|
* list is returned. On success, a new list pointer that should be
|
|
|
|
* used in place of the one given to this function is
|
|
|
|
* returned. Otherwise, the old pointer is returned. See eina_error_get().
|
|
|
|
*
|
2009-12-27 00:45:30 -08:00
|
|
|
* @note O(log2(n)) comparisons (calls to @p func) average/worst case
|
2009-08-06 18:35:16 -07:00
|
|
|
* performance as it uses eina_list_search_sorted_near_list() and thus
|
|
|
|
* is bounded to that. As said in eina_list_search_sorted_near_list(),
|
|
|
|
* lists do not have O(1) access time, so walking to the correct node
|
|
|
|
* can be costly, consider worst case to be almost O(n) pointer
|
|
|
|
* dereference (list walk).
|
2009-08-06 15:31:45 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data)
|
|
|
|
{
|
|
|
|
Eina_List *lnear;
|
|
|
|
int cmp;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return eina_list_append(NULL, data);
|
2009-08-06 15:31:45 -07:00
|
|
|
|
|
|
|
lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
|
|
|
|
if (cmp < 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
return eina_list_append_relative_list(list, data, lnear);
|
2009-08-06 15:31:45 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
return eina_list_prepend_relative_list(list, data, lnear);
|
2009-08-06 15:31:45 -07:00
|
|
|
}
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Remove the first instance of the specified data from the given list.
|
|
|
|
*
|
|
|
|
* @param list The given list.
|
|
|
|
* @param data The specified data.
|
|
|
|
* @return A list pointer.
|
|
|
|
*
|
|
|
|
* This function removes the first instance of @p data from
|
|
|
|
* @p list. If the specified data is not in the given list (tihis
|
|
|
|
* include the case where @p data is @c NULL), nothing is done. If
|
|
|
|
* @p list is @c NULL, @c NULL is returned, otherwise a new list
|
|
|
|
* pointer that should be used in place of the one passed to this
|
|
|
|
* function.
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_remove(Eina_List *list, const void *data)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (list)
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2009-02-25 02:46:14 -08:00
|
|
|
l = eina_list_data_find_list(list, data);
|
2009-08-15 17:47:23 -07:00
|
|
|
return eina_list_remove_list(list, l);
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Remove the specified data.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* @param list The given linked list.
|
|
|
|
* @param remove_list The list node which is to be removed.
|
|
|
|
* @return A list pointer.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function removes the list node @p remove_list from @p list and
|
|
|
|
* frees the list node structure @p remove_list. If @p list is
|
|
|
|
* @c NULL, this function returns @c NULL. If @p remove_list is
|
|
|
|
* @c NULL, it returns @p list, otherwise, a new list pointer that
|
|
|
|
* should be used in place of the one passed to this function.
|
|
|
|
*
|
2009-08-15 17:47:23 -07:00
|
|
|
* The following code gives an example (notice we use EINA_LIST_FOREACH
|
|
|
|
* instead of EINA_LIST_FOREACH_SAFE because we stop the loop after
|
|
|
|
* removing the current node).
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
|
|
|
* @code
|
|
|
|
* extern Eina_List *list;
|
|
|
|
* Eina_List *l;
|
|
|
|
* extern void *my_data;
|
2008-09-25 07:46:16 -07:00
|
|
|
* void *data
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-10-21 05:49:29 -07:00
|
|
|
* EINA_LIST_FOREACH(list, l, data)
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
2008-09-25 07:46:16 -07:00
|
|
|
* if (data == my_data)
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* list = eina_list_remove_list(list, l);
|
|
|
|
* break;
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_remove_list(Eina_List *list, Eina_List *remove_list)
|
|
|
|
{
|
|
|
|
Eina_List *return_l;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!remove_list)
|
|
|
|
return list;
|
|
|
|
|
|
|
|
EINA_MAGIC_CHECK_LIST(remove_list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (remove_list->next)
|
|
|
|
remove_list->next->prev = remove_list->prev;
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
if (remove_list->prev)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
remove_list->prev->next = remove_list->next;
|
|
|
|
return_l = list;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
return_l = remove_list->next;
|
|
|
|
|
2009-02-25 02:46:14 -08:00
|
|
|
if (remove_list == remove_list->accounting->last)
|
2008-09-25 07:46:16 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
|
|
|
list->accounting->last = remove_list->prev;
|
2008-09-25 07:46:16 -07:00
|
|
|
}
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
_eina_list_mempool_list_free(remove_list);
|
2008-07-30 05:46:55 -07:00
|
|
|
return return_l;
|
|
|
|
}
|
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Free an entire list and all the nodes, ignoring the data contained.
|
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
* @param list The list to free
|
|
|
|
* @return A NULL pointer
|
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function frees all the nodes of @p list. It does not free the
|
2009-04-11 09:59:39 -07:00
|
|
|
* data of the nodes. To free them, use #EINA_LIST_FREE.
|
2008-08-27 23:31:18 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_free(Eina_List *list)
|
|
|
|
{
|
|
|
|
Eina_List *l, *free_l;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
for (l = list; l; )
|
2008-08-27 23:31:18 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
free_l = l;
|
|
|
|
l = l->next;
|
2008-08-27 23:31:18 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_list_mempool_list_free(free_l);
|
2008-08-27 23:31:18 -07:00
|
|
|
}
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Move the specified data to the head of the list.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* @param list The list handle to move the data.
|
|
|
|
* @param move_list The list node to move.
|
2008-07-30 05:46:55 -07:00
|
|
|
* @return A new list handle to replace the old one
|
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function move @p move_list to the front of @p list. If list is
|
|
|
|
* @c NULL, @c NULL is returned. If @p move_list is @c NULL,
|
|
|
|
* @p list is returned. Otherwise, a new list pointer that should be
|
|
|
|
* used in place of the one passed to this function.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* extern Eina_List *list;
|
|
|
|
* Eina_List *l;
|
|
|
|
* extern void *my_data;
|
2008-09-25 07:46:16 -07:00
|
|
|
* void *data;
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-10-21 05:49:29 -07:00
|
|
|
* EINA_LIST_FOREACH(list, l, data)
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
2008-09-25 07:46:16 -07:00
|
|
|
* if (data == my_data)
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* list = eina_list_promote_list(list, l);
|
|
|
|
* break;
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_promote_list(Eina_List *list, Eina_List *move_list)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!move_list)
|
2010-07-27 19:48:11 -07:00
|
|
|
return list; /* Promoting head to be head. */
|
2010-07-27 19:37:05 -07:00
|
|
|
|
|
|
|
if (move_list == list)
|
|
|
|
return list;
|
|
|
|
|
|
|
|
if (move_list->next == list)
|
|
|
|
return move_list;
|
|
|
|
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
|
|
|
EINA_MAGIC_CHECK_LIST(move_list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-08-07 06:09:09 -07:00
|
|
|
/* Remove the promoted item from the list. */
|
2009-01-26 06:46:02 -08:00
|
|
|
if (!move_list->prev)
|
|
|
|
move_list->next->prev = NULL;
|
|
|
|
else
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
move_list->prev->next = move_list->next;
|
|
|
|
if (move_list == list->accounting->last)
|
|
|
|
list->accounting->last = move_list->prev;
|
|
|
|
else
|
|
|
|
move_list->next->prev = move_list->prev;
|
2009-01-26 06:46:02 -08:00
|
|
|
}
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2009-01-26 06:46:02 -08:00
|
|
|
/* Add the promoted item in the list. */
|
|
|
|
move_list->next = list;
|
2008-08-07 06:09:09 -07:00
|
|
|
move_list->prev = list->prev;
|
|
|
|
list->prev = move_list;
|
2009-01-26 06:46:02 -08:00
|
|
|
if (move_list->prev)
|
|
|
|
move_list->prev->next = move_list;
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return move_list;
|
|
|
|
}
|
|
|
|
|
2009-01-26 06:46:02 -08:00
|
|
|
/**
|
|
|
|
* @brief Move the specified data to the tail of the list.
|
|
|
|
*
|
|
|
|
* @param list The list handle to move the data.
|
|
|
|
* @param move_list The list node to move.
|
|
|
|
* @return A new list handle to replace the old one
|
|
|
|
*
|
|
|
|
* This function move @p move_list to the back of @p list. If list is
|
|
|
|
* @c NULL, @c NULL is returned. If @p move_list is @c NULL,
|
|
|
|
* @p list is returned. Otherwise, a new list pointer that should be
|
|
|
|
* used in place of the one passed to this function.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* extern Eina_List *list;
|
|
|
|
* Eina_List *l;
|
|
|
|
* extern void *my_data;
|
|
|
|
* void *data;
|
|
|
|
*
|
|
|
|
* EINA_LIST_FOREACH(list, l, data)
|
|
|
|
* {
|
|
|
|
* if (data == my_data)
|
|
|
|
* {
|
|
|
|
* list = eina_list_demote_list(list, l);
|
|
|
|
* break;
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_demote_list(Eina_List *list, Eina_List *move_list)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
2009-01-26 06:46:02 -08:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!move_list)
|
2010-07-27 19:48:11 -07:00
|
|
|
return list; /* Demoting tail to be tail. */
|
2010-07-27 19:37:05 -07:00
|
|
|
|
|
|
|
if (move_list == list->accounting->last)
|
|
|
|
return list;
|
|
|
|
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
|
|
|
EINA_MAGIC_CHECK_LIST(move_list, NULL);
|
2009-01-26 06:46:02 -08:00
|
|
|
|
|
|
|
/* Update pointer list if necessary. */
|
|
|
|
if (list == move_list)
|
2010-07-27 19:48:11 -07:00
|
|
|
list = move_list->next; /* Remove the demoted item from the list. */
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2009-01-26 06:46:02 -08:00
|
|
|
if (move_list->prev)
|
|
|
|
move_list->prev->next = move_list->next;
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2009-01-26 06:46:02 -08:00
|
|
|
move_list->next->prev = move_list->prev;
|
|
|
|
/* Add the demoted item in the list. */
|
|
|
|
move_list->prev = list->accounting->last;
|
|
|
|
move_list->prev->next = move_list;
|
|
|
|
move_list->next = NULL;
|
|
|
|
list->accounting->last = move_list;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Find a member of a list and return the member.
|
|
|
|
*
|
|
|
|
* @param list The list to search for a data.
|
|
|
|
* @param data The data pointer to find in the list.
|
|
|
|
* @return The found member data pointer if foun, @c NULL otherwise.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function searches in @p list from beginning to end for the
|
|
|
|
* first member whose data pointer is @p data. If it is found, @p data
|
2008-07-30 05:46:55 -07:00
|
|
|
* will be returned, otherwise NULL will be returned.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* extern Eina_List *list;
|
|
|
|
* extern void *my_data;
|
|
|
|
*
|
2008-09-25 07:46:16 -07:00
|
|
|
* if (eina_list_data_find(list, my_data) == my_data)
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
|
|
|
* printf("Found member %p\n", my_data);
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI void *
|
2008-09-25 07:46:16 -07:00
|
|
|
eina_list_data_find(const Eina_List *list, const void *data)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (eina_list_data_find_list(list, data))
|
|
|
|
return (void *)data;
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Find a member of a list and return the list node containing that member.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* @param list The list to search for data.
|
|
|
|
* @param data The data pointer to find in the list.
|
|
|
|
* @return The found members list node on success, @c NULL otherwise.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function searches in @p list from beginning to end for the
|
|
|
|
* first member whose data pointer is @p data. If it is found, the
|
|
|
|
* list node containing the specified member is returned, otherwise
|
|
|
|
* @c NULL is returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
2008-09-25 07:46:16 -07:00
|
|
|
eina_list_data_find_list(const Eina_List *list, const void *data)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
|
|
|
const Eina_List *l;
|
2008-09-25 07:46:16 -07:00
|
|
|
void *list_data;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (list)
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, list_data)
|
|
|
|
{
|
|
|
|
if (list_data == data)
|
|
|
|
return (Eina_List *)l;
|
|
|
|
}
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Get the nth member's data pointer in a list.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* @param list The list to get the specified member number from.
|
|
|
|
* @param n The number of the element (0 being the first).
|
|
|
|
* @return The data pointer stored in the specified element.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function returns the data pointer of element number @p n, in
|
|
|
|
* the @p list. The first element in the array is element number 0. If
|
|
|
|
* the element number @p n does not exist, @c NULL is
|
|
|
|
* returned. Otherwise, the data of the found element is returned.
|
2008-08-27 23:31:18 -07:00
|
|
|
*/
|
|
|
|
EAPI void *
|
|
|
|
eina_list_nth(const Eina_List *list, unsigned int n)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
|
|
|
|
l = eina_list_nth_list(list, n);
|
|
|
|
return l ? l->data : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Get the nth member's list node in a list.
|
|
|
|
*
|
|
|
|
* @param list The list to get the specfied member number from.
|
|
|
|
* @param n The number of the element (0 being the first).
|
|
|
|
* @return The list node stored in the numbered element.
|
|
|
|
*
|
|
|
|
* This function returns the list node of element number @p n, in
|
|
|
|
* @ list. The first element in the array is element number 0. If the
|
|
|
|
* element number @p n does not exist or @p list is @c NULL or @p n is
|
|
|
|
* greater than the count of elements in @p list minus 1, @c NULL is
|
|
|
|
* returned. Otherwise the list node stored in the numbered element is
|
|
|
|
* returned.
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
2008-08-27 23:31:18 -07:00
|
|
|
eina_list_nth_list(const Eina_List *list, unsigned int n)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2008-08-27 23:31:18 -07:00
|
|
|
const Eina_List *l;
|
|
|
|
unsigned int i;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (list)
|
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/* check for non-existing nodes */
|
|
|
|
if ((!list) || (n > (list->accounting->count - 1)))
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2008-08-07 06:09:09 -07:00
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/* if the node is in the 2nd half of the list, search from the end
|
|
|
|
* else, search from the beginning.
|
|
|
|
*/
|
|
|
|
if (n > (list->accounting->count / 2))
|
2010-07-27 19:37:05 -07:00
|
|
|
for (i = list->accounting->count - 1,
|
|
|
|
l = list->accounting->last;
|
|
|
|
l;
|
|
|
|
l = l->prev, i--)
|
|
|
|
{
|
|
|
|
if (i == n)
|
|
|
|
return (Eina_List *)l;
|
|
|
|
}
|
2008-08-27 23:31:18 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
for (i = 0, l = list; l; l = l->next, i++)
|
|
|
|
{
|
|
|
|
if (i == n)
|
|
|
|
return (Eina_List *)l;
|
|
|
|
}
|
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
abort();
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Reverse all the elements in the list.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* @param list The list to reverse.
|
2009-03-17 05:52:38 -07:00
|
|
|
* @return The list head after it has been reversed.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function reverses the order of all elements in @p list, so the
|
|
|
|
* last member is now first, and so on. If @p list is @c NULL, this
|
|
|
|
* functon returns @c NULL.
|
2009-03-17 05:52:38 -07:00
|
|
|
*
|
|
|
|
* @note @b in-place: this will change the given list, so you should
|
|
|
|
* now point to the new list head that is returned by this function.
|
|
|
|
*
|
|
|
|
* @see eina_list_reverse_clone()
|
|
|
|
* @see eina_list_iterator_reversed_new()
|
2008-07-30 05:46:55 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_reverse(Eina_List *list)
|
|
|
|
{
|
|
|
|
Eina_List *l1, *l2;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
l1 = list;
|
|
|
|
l2 = list->accounting->last;
|
|
|
|
while (l1 != l2)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
void *data;
|
|
|
|
|
|
|
|
data = l1->data;
|
|
|
|
l1->data = l2->data;
|
|
|
|
l2->data = data;
|
|
|
|
l1 = l1->next;
|
|
|
|
if (l1 == l2)
|
|
|
|
break;
|
|
|
|
|
|
|
|
l2 = l2->prev;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2009-03-17 05:52:38 -07:00
|
|
|
/**
|
|
|
|
* @brief Clone (copy) all the elements in the list in reverse order.
|
|
|
|
*
|
|
|
|
* @param list The list to reverse.
|
|
|
|
* @return The new list that has been reversed.
|
|
|
|
*
|
|
|
|
* This function reverses the order of all elements in @p list, so the
|
|
|
|
* last member is now first, and so on. If @p list is @c NULL, this
|
|
|
|
* functon returns @c NULL. This returns a copy of the given list.
|
|
|
|
*
|
|
|
|
* @note @b copy: this will copy the list and you should then
|
|
|
|
* eina_list_free() when it is not required anymore.
|
|
|
|
*
|
|
|
|
* @see eina_list_reverse()
|
|
|
|
* @see eina_list_clone()
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_reverse_clone(const Eina_List *list)
|
|
|
|
{
|
|
|
|
const Eina_List *l;
|
2010-01-24 11:51:22 -08:00
|
|
|
Eina_List *lclone;
|
2009-03-17 05:52:38 -07:00
|
|
|
void *data;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2010-01-24 11:51:22 -08:00
|
|
|
lclone = NULL;
|
2009-03-17 05:52:38 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, data)
|
2010-07-27 19:37:05 -07:00
|
|
|
lclone = eina_list_prepend(lclone, data);
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2010-01-24 11:51:22 -08:00
|
|
|
return lclone;
|
2009-03-17 05:52:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Clone (copy) all the elements in the list in exact order.
|
|
|
|
*
|
|
|
|
* @param list The list to clone.
|
|
|
|
* @return The new list that has been cloned.
|
|
|
|
*
|
|
|
|
* This function clone in order of all elements in @p list. If @p list
|
|
|
|
* is @c NULL, this functon returns @c NULL. This returns a copy of
|
|
|
|
* the given list.
|
|
|
|
*
|
|
|
|
* @note @b copy: this will copy the list and you should then
|
|
|
|
* eina_list_free() when it is not required anymore.
|
|
|
|
*
|
|
|
|
* @see eina_list_reverse_clone()
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_clone(const Eina_List *list)
|
|
|
|
{
|
|
|
|
const Eina_List *l;
|
2010-01-24 11:51:22 -08:00
|
|
|
Eina_List *lclone;
|
2009-03-17 05:52:38 -07:00
|
|
|
void *data;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2010-01-24 11:51:22 -08:00
|
|
|
lclone = NULL;
|
2009-03-17 05:52:38 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, data)
|
2010-07-27 19:37:05 -07:00
|
|
|
lclone = eina_list_append(lclone, data);
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2010-01-24 11:51:22 -08:00
|
|
|
return lclone;
|
2009-03-17 05:52:38 -07:00
|
|
|
}
|
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/**
|
2008-09-22 22:17:49 -07:00
|
|
|
* @brief Sort a list according to the ordering func will return.
|
|
|
|
*
|
|
|
|
* @param list The list handle to sort.
|
|
|
|
* @param size The length of the list to sort.
|
2008-07-30 05:46:55 -07:00
|
|
|
* @param func A function pointer that can handle comparing the list data
|
2008-09-22 22:17:49 -07:00
|
|
|
* nodes.
|
2009-03-17 05:52:38 -07:00
|
|
|
* @return the new head of list.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2008-09-22 22:17:49 -07:00
|
|
|
* This function sorts @p list. @p size if the number of the first
|
|
|
|
* element to sort. If @p size is 0 or greater than the number of
|
2009-10-27 03:26:20 -07:00
|
|
|
* elements in @p list, all the elements are sorted. @p func is used to
|
2008-09-22 22:17:49 -07:00
|
|
|
* compare two elements of @p list. If @p list or @p func are @c NULL,
|
|
|
|
* this function returns @c NULL.
|
2008-07-30 05:46:55 -07:00
|
|
|
*
|
2009-03-17 05:52:38 -07:00
|
|
|
* @note @b in-place: this will change the given list, so you should
|
|
|
|
* now point to the new list head that is returned by this function.
|
|
|
|
*
|
2009-08-06 18:35:16 -07:00
|
|
|
* @note worst case is O(n * log2(n)) comparisons (calls to func()),
|
|
|
|
* O(n) comparisons average case. That means that for 1,000,000 list
|
|
|
|
* elements, sort will usually do 1,000,000 comparisons, but may do up
|
|
|
|
* to 20,000,000.
|
2009-08-06 08:50:19 -07:00
|
|
|
*
|
2008-07-30 05:46:55 -07:00
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* int
|
2008-10-23 17:37:09 -07:00
|
|
|
* sort_cb(const void *d1, const void *d2)
|
2008-07-30 05:46:55 -07:00
|
|
|
* {
|
2008-10-23 17:37:09 -07:00
|
|
|
* const char *txt = NULL;
|
2008-07-30 05:46:55 -07:00
|
|
|
* const char *txt2 = NULL;
|
|
|
|
*
|
|
|
|
* if(!d1) return(1);
|
|
|
|
* if(!d2) return(-1);
|
|
|
|
*
|
|
|
|
* return(strcmp((const char*)d1, (const char*)d2));
|
|
|
|
* }
|
|
|
|
* extern Eina_List *list;
|
|
|
|
*
|
|
|
|
* list = eina_list_sort(list, eina_list_count(list), sort_cb);
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
2008-09-25 05:41:49 -07:00
|
|
|
eina_list_sort(Eina_List *list, unsigned int size, Eina_Compare_Cb func)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2008-09-26 06:45:30 -07:00
|
|
|
unsigned int i = 0;
|
|
|
|
unsigned int n = 0;
|
|
|
|
Eina_List *tail = list;
|
2008-09-30 07:16:18 -07:00
|
|
|
Eina_List *unsort = NULL;
|
2008-09-26 06:45:30 -07:00
|
|
|
Eina_List *stack[EINA_LIST_SORT_STACK_SIZE];
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2008-12-26 10:31:14 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(func, list);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
|
|
|
|
2009-03-25 02:24:56 -07:00
|
|
|
EINA_MAGIC_CHECK_LIST(list, NULL);
|
2008-09-25 07:46:16 -07:00
|
|
|
|
2008-07-30 05:46:55 -07:00
|
|
|
/* if the caller specified an invalid size, sort the whole list */
|
2008-08-13 02:19:34 -07:00
|
|
|
if ((size == 0) ||
|
2008-07-30 05:46:55 -07:00
|
|
|
(size > list->accounting->count))
|
2010-07-27 19:37:05 -07:00
|
|
|
size = list->accounting->count;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2008-09-30 07:16:18 -07:00
|
|
|
if (size != list->accounting->count)
|
2008-09-26 06:45:30 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
unsort = eina_list_nth_list(list, size);
|
|
|
|
if (unsort)
|
|
|
|
unsort->prev->next = NULL;
|
2008-09-26 06:45:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
while (tail)
|
2008-07-30 05:46:55 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
unsigned int idx, tmp;
|
2008-09-30 07:16:18 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_List *a = tail;
|
|
|
|
Eina_List *b = tail->next;
|
2008-09-26 06:45:30 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!b)
|
|
|
|
{
|
|
|
|
stack[i++] = a;
|
|
|
|
break;
|
|
|
|
}
|
2008-09-26 06:45:30 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
tail = b->next;
|
2008-09-30 07:16:18 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (func(a->data, b->data) < 0)
|
|
|
|
((stack[i++] = a)->next = b)->next = 0;
|
|
|
|
else
|
|
|
|
((stack[i++] = b)->next = a)->next = 0;
|
2008-09-26 06:45:30 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
tmp = n++;
|
|
|
|
for (idx = n ^ tmp; idx &= idx - 1; i--)
|
|
|
|
stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func);
|
2008-09-26 06:45:30 -07:00
|
|
|
}
|
2008-07-30 05:46:55 -07:00
|
|
|
|
2008-09-26 06:45:30 -07:00
|
|
|
while (i-- > 1)
|
2010-07-27 19:37:05 -07:00
|
|
|
stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func);
|
2008-09-30 07:16:18 -07:00
|
|
|
|
2008-09-26 06:45:30 -07:00
|
|
|
list = stack[0];
|
2008-10-01 09:30:30 -07:00
|
|
|
tail = eina_list_sort_rebuild_prev(list);
|
2008-09-26 06:45:30 -07:00
|
|
|
|
|
|
|
if (unsort)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
tail->next = unsort;
|
|
|
|
unsort->prev = tail;
|
2008-07-30 05:46:55 -07:00
|
|
|
}
|
2008-09-26 06:45:30 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
list->accounting->last = tail;
|
2008-07-30 05:46:55 -07:00
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
2008-08-13 02:19:34 -07:00
|
|
|
|
2008-10-21 04:28:38 -07:00
|
|
|
/**
|
|
|
|
* @brief Merge two list.
|
|
|
|
*
|
|
|
|
* @param left Head list to merge.
|
|
|
|
* @param right Tail list to merge.
|
|
|
|
* @return A new merged list.
|
|
|
|
*
|
|
|
|
* This function put right at the end of left and return the head.
|
|
|
|
*
|
|
|
|
* Both left and right does not exist anymore after the merge.
|
|
|
|
*
|
2009-08-06 11:35:53 -07:00
|
|
|
* @note merge cost is O(n), being @b n the size of the smallest
|
|
|
|
* list. This is due the need to fix accounting of that segment,
|
|
|
|
* making count and last access O(1).
|
2008-10-21 04:28:38 -07:00
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_merge(Eina_List *left, Eina_List *right)
|
|
|
|
{
|
2009-08-06 11:35:53 -07:00
|
|
|
unsigned int n_left, n_right;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!left)
|
|
|
|
return right;
|
|
|
|
|
|
|
|
if (!right)
|
|
|
|
return left;
|
2008-10-21 04:28:38 -07:00
|
|
|
|
|
|
|
left->accounting->last->next = right;
|
|
|
|
right->prev = left->accounting->last;
|
|
|
|
|
2009-08-06 11:35:53 -07:00
|
|
|
n_left = left->accounting->count;
|
|
|
|
n_right = right->accounting->count;
|
|
|
|
|
|
|
|
if (n_left >= n_right)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_List *itr = right;
|
|
|
|
left->accounting->last = right->accounting->last;
|
|
|
|
left->accounting->count += n_right;
|
|
|
|
|
|
|
|
_eina_list_mempool_accounting_free(right->accounting);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
itr->accounting = left->accounting;
|
|
|
|
itr = itr->next;
|
|
|
|
}
|
|
|
|
while (itr);
|
2009-08-06 11:35:53 -07:00
|
|
|
}
|
|
|
|
else
|
2008-10-21 04:28:38 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_List *itr = left->accounting->last;
|
|
|
|
right->accounting->count += n_left;
|
2009-08-06 11:35:53 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_list_mempool_accounting_free(left->accounting);
|
2009-08-06 11:35:53 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
do
|
|
|
|
{
|
|
|
|
itr->accounting = right->accounting;
|
|
|
|
itr = itr->prev;
|
|
|
|
}
|
|
|
|
while (itr);
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
2009-10-27 03:26:20 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Split a list into 2 lists.
|
|
|
|
*
|
|
|
|
* @param list List to split.
|
|
|
|
* @param relative The list will be split after @p relative.
|
|
|
|
* @param right The head of the new right list.
|
|
|
|
* @return The new left list
|
|
|
|
*
|
2009-11-01 11:50:18 -08:00
|
|
|
* This function split @p list into two lists ( left and right ) after the node @p relative. @p Relative
|
|
|
|
* will become the last node of the left list. If @p list or @p right are NULL list is returns.
|
2009-10-27 03:26:20 -07:00
|
|
|
* If @p relative is NULL right is set to @p list and NULL is returns.
|
|
|
|
* If @p relative is the last node of @p list list is returns and @p right is set to NULL.
|
|
|
|
*
|
|
|
|
* list does not exist anymore after the split.
|
|
|
|
*
|
|
|
|
*/
|
2010-07-27 19:37:05 -07:00
|
|
|
EAPI Eina_List *
|
2009-10-27 03:26:20 -07:00
|
|
|
eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
|
|
|
|
{
|
|
|
|
Eina_List *next;
|
|
|
|
Eina_List *itr;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if(!right)
|
|
|
|
return list;
|
|
|
|
|
2009-10-27 03:26:20 -07:00
|
|
|
*right = NULL;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!list)
|
|
|
|
return NULL;
|
|
|
|
|
2009-10-27 03:26:20 -07:00
|
|
|
if (!relative)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
*right = list;
|
|
|
|
return NULL;
|
2009-10-27 03:26:20 -07:00
|
|
|
}
|
2010-07-27 19:37:05 -07:00
|
|
|
|
|
|
|
if (relative == eina_list_last(list))
|
|
|
|
return list;
|
2009-10-27 03:26:20 -07:00
|
|
|
|
2009-11-01 11:50:18 -08:00
|
|
|
next = eina_list_next(relative);
|
2009-10-27 03:26:20 -07:00
|
|
|
next->prev = NULL;
|
|
|
|
next->accounting = _eina_list_mempool_accounting_new(next);
|
|
|
|
next->accounting->last = list->accounting->last;
|
|
|
|
*right = next;
|
|
|
|
|
|
|
|
itr = next;
|
|
|
|
do
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
itr->accounting = next->accounting;
|
|
|
|
next->accounting->count++;
|
|
|
|
itr = itr->next;
|
2009-10-27 03:26:20 -07:00
|
|
|
}
|
2009-11-01 11:50:18 -08:00
|
|
|
while (itr);
|
2009-10-27 03:26:20 -07:00
|
|
|
|
|
|
|
relative->next = NULL;
|
2009-11-01 11:50:18 -08:00
|
|
|
list->accounting->last = relative;
|
2009-10-27 03:26:20 -07:00
|
|
|
list->accounting->count = list->accounting->count - next->accounting->count;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2008-10-21 04:28:38 -07:00
|
|
|
/**
|
|
|
|
* @brief Merge two sorted list according to the ordering func will return.
|
|
|
|
*
|
|
|
|
* @param left First list to merge.
|
|
|
|
* @param right Second list to merge.
|
|
|
|
* @param func A function pointer that can handle comparing the list data
|
|
|
|
* nodes.
|
|
|
|
* @return A new sorted list.
|
|
|
|
*
|
|
|
|
* This function compare the head of @p left and @p right, and choose the
|
|
|
|
* smallest one to be head of the returned list. It will continue this process
|
|
|
|
* for all entry of both list.
|
|
|
|
*
|
|
|
|
* Both left and right does not exist anymore after the merge.
|
|
|
|
* If @p func is NULL, it will return NULL.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* int
|
|
|
|
* sort_cb(void *d1, void *d2)
|
|
|
|
* {
|
|
|
|
* const char *txt = NULL;
|
|
|
|
* const char *txt2 = NULL;
|
|
|
|
*
|
|
|
|
* if(!d1) return(1);
|
|
|
|
* if(!d2) return(-1);
|
|
|
|
*
|
|
|
|
* return(strcmp((const char*)d1, (const char*)d2));
|
|
|
|
* }
|
|
|
|
* extern Eina_List *sorted1;
|
|
|
|
* extern Eina_List *sorted2;
|
|
|
|
*
|
|
|
|
* list = eina_list_sorted_merge(sorted1, sorted2, sort_cb);
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI Eina_List *
|
|
|
|
eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func)
|
|
|
|
{
|
|
|
|
Eina_List *ret;
|
|
|
|
Eina_List *current;
|
|
|
|
|
2008-12-26 10:31:14 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!left)
|
|
|
|
return right;
|
|
|
|
|
|
|
|
if (!right)
|
|
|
|
return left;
|
2008-10-21 04:28:38 -07:00
|
|
|
|
|
|
|
if (func(left->data, right->data) < 0)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
ret = left;
|
|
|
|
current = left;
|
|
|
|
left = left->next;
|
|
|
|
ret->accounting->count += right->accounting->count;
|
2008-10-21 04:28:38 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_list_mempool_accounting_free(right->accounting);
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
ret = right;
|
|
|
|
current = right;
|
|
|
|
right = right->next;
|
|
|
|
ret->accounting->count += left->accounting->count;
|
2008-10-21 04:28:38 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_list_mempool_accounting_free(left->accounting);
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
while (left && right)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (func(left->data, right->data) < 0)
|
|
|
|
{
|
|
|
|
current->next = left;
|
|
|
|
left->prev = current;
|
|
|
|
left = left->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
current->next = right;
|
|
|
|
right->prev = current;
|
|
|
|
right = right->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
current = current->next;
|
|
|
|
current->accounting = ret->accounting;
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (left)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
current->next = left;
|
|
|
|
left->prev = current;
|
|
|
|
current->accounting = ret->accounting;
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (right)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
current->next = right;
|
|
|
|
right->prev = current;
|
|
|
|
current->accounting = ret->accounting;
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
while (current->next)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
current = current->next;
|
|
|
|
current->accounting = ret->accounting;
|
2008-10-21 04:28:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ret->accounting->last = current;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-08-06 08:50:19 -07:00
|
|
|
/**
|
|
|
|
* @brief Returns node nearest to data is in the sorted list.
|
|
|
|
*
|
|
|
|
* @param list The list to search for data, @b must be sorted.
|
|
|
|
* @param func A function pointer that can handle comparing the list data nodes.
|
|
|
|
* @param data reference value to search.
|
2009-08-06 12:01:47 -07:00
|
|
|
* @param result_cmp if provided returns the result of
|
|
|
|
* func(node->data, data) node being the last (returned) node. If node
|
|
|
|
* was found (exact match), then it is 0. If returned node is smaller
|
|
|
|
* than requested data, it is less than 0 and if it's bigger it's
|
|
|
|
* greater than 0. It is the last value returned by func().
|
2009-08-06 08:50:19 -07:00
|
|
|
* @return the nearest node, NULL if not found.
|
|
|
|
*
|
|
|
|
* This can be used to check if some value is inside the list and get
|
|
|
|
* the nearest container node in this case. It should be used when list is
|
|
|
|
* known to be sorted as it will do binary search for results.
|
|
|
|
*
|
|
|
|
* Example: imagine user gives a string, you check if it's in the list
|
|
|
|
* before duplicating its contents, otherwise you want to insert it
|
|
|
|
* sorted. In this case you get the result of this function and either
|
|
|
|
* append or prepend the value.
|
|
|
|
*
|
|
|
|
* @note O(log2(n)) average/worst case performance, for 1,000,000
|
|
|
|
* elements it will do a maximum of 20 comparisons. This is much
|
|
|
|
* faster than the 1,000,000 comparisons made naively walking the list
|
|
|
|
* from head to tail, so depending on the number of searches and
|
|
|
|
* insertions, it may be worth to eina_list_sort() the list and do he
|
2009-08-06 18:35:16 -07:00
|
|
|
* searches later. As lists do not have O(1) access time, walking to
|
|
|
|
* the correct node can be costly, consider worst case to be almost
|
|
|
|
* O(n) pointer dereference (list walk).
|
2009-08-06 08:50:19 -07:00
|
|
|
*
|
|
|
|
* @see eina_list_search_sorted_list()
|
|
|
|
* @see eina_list_sort()
|
|
|
|
* @see eina_list_sorted_merge()
|
|
|
|
*/
|
2009-03-18 06:29:36 -07:00
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_search_sorted_near_list(const Eina_List *list,
|
|
|
|
Eina_Compare_Cb func,
|
|
|
|
const void *data,
|
|
|
|
int *result_cmp)
|
2009-01-26 06:46:02 -08:00
|
|
|
{
|
2009-03-18 06:29:36 -07:00
|
|
|
const Eina_List *ct;
|
2009-08-06 15:31:45 -07:00
|
|
|
unsigned int inf, sup, cur;
|
|
|
|
int cmp;
|
2009-01-26 06:46:02 -08:00
|
|
|
|
2009-08-06 12:01:47 -07:00
|
|
|
if (!list)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (result_cmp)
|
|
|
|
*result_cmp = 0;
|
|
|
|
|
|
|
|
return NULL;
|
2009-08-06 12:01:47 -07:00
|
|
|
}
|
2009-07-21 08:21:46 -07:00
|
|
|
|
2009-08-06 15:31:45 -07:00
|
|
|
if (list->accounting->count == 1)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (result_cmp)
|
|
|
|
*result_cmp = func(list->data, data);
|
|
|
|
|
|
|
|
return (Eina_List *)list;
|
2009-08-06 15:31:45 -07:00
|
|
|
}
|
2009-08-06 12:01:47 -07:00
|
|
|
|
2009-08-06 15:31:45 -07:00
|
|
|
/* list walk is expensive, do quick check: tail */
|
|
|
|
ct = list->accounting->last;
|
|
|
|
cmp = func(ct->data, data);
|
|
|
|
if (cmp <= 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
goto end;
|
2009-08-06 15:31:45 -07:00
|
|
|
|
|
|
|
/* list walk is expensive, do quick check: head */
|
|
|
|
ct = list;
|
|
|
|
cmp = func(ct->data, data);
|
|
|
|
if (cmp >= 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
goto end;
|
2009-08-06 15:31:45 -07:00
|
|
|
|
|
|
|
/* inclusive bounds */
|
|
|
|
inf = 1;
|
|
|
|
sup = list->accounting->count - 2;
|
|
|
|
cur = 1;
|
|
|
|
ct = list->next;
|
|
|
|
|
|
|
|
/* no loop, just compare if comparison value is important to caller */
|
|
|
|
if (inf > sup)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (result_cmp)
|
|
|
|
cmp = func(ct->data, data);
|
|
|
|
|
|
|
|
goto end;
|
2009-08-06 15:31:45 -07:00
|
|
|
}
|
2009-01-26 06:46:02 -08:00
|
|
|
|
2009-08-06 15:31:45 -07:00
|
|
|
while (inf <= sup)
|
2009-01-26 06:46:02 -08:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
unsigned int tmp = cur;
|
|
|
|
cur = inf + ((sup - inf) >> 1);
|
|
|
|
if (tmp < cur)
|
|
|
|
for (; tmp != cur; tmp++, ct = ct->next) ;
|
|
|
|
else if (tmp > cur)
|
|
|
|
for (; tmp != cur; tmp--, ct = ct->prev) ;
|
|
|
|
|
|
|
|
cmp = func(ct->data, data);
|
|
|
|
if (cmp == 0)
|
|
|
|
break;
|
|
|
|
else if (cmp < 0)
|
|
|
|
inf = cur + 1;
|
|
|
|
else if (cmp > 0)
|
|
|
|
{
|
|
|
|
if (cur > 0)
|
|
|
|
sup = cur - 1;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
2009-01-26 06:46:02 -08:00
|
|
|
}
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
end:
|
|
|
|
if (result_cmp)
|
|
|
|
*result_cmp = cmp;
|
|
|
|
|
2009-08-06 15:31:45 -07:00
|
|
|
return (Eina_List *)ct;
|
2009-01-26 06:46:02 -08:00
|
|
|
}
|
|
|
|
|
2009-08-06 08:50:19 -07:00
|
|
|
/**
|
|
|
|
* @brief Returns node if data is in the sorted list.
|
|
|
|
*
|
|
|
|
* @param list The list to search for data, @b must be sorted.
|
|
|
|
* @param func A function pointer that can handle comparing the list data nodes.
|
|
|
|
* @param data reference value to search.
|
|
|
|
* @return the node if func(node->data, data) == 0, NULL if not found.
|
|
|
|
*
|
|
|
|
* This can be used to check if some value is inside the list and get
|
|
|
|
* the container node in this case. It should be used when list is
|
|
|
|
* known to be sorted as it will do binary search for results.
|
|
|
|
*
|
|
|
|
* Example: imagine user gives a string, you check if it's in the list
|
|
|
|
* before duplicating its contents.
|
|
|
|
*
|
|
|
|
* @note O(log2(n)) average/worst case performance, for 1,000,000
|
|
|
|
* elements it will do a maximum of 20 comparisons. This is much
|
|
|
|
* faster than the 1,000,000 comparisons made by
|
|
|
|
* eina_list_search_unsorted_list(), so depending on the number of
|
|
|
|
* searches and insertions, it may be worth to eina_list_sort() the
|
2009-08-06 18:35:16 -07:00
|
|
|
* list and do he searches later. As said in
|
|
|
|
* eina_list_search_sorted_near_list(), lists do not have O(1) access
|
|
|
|
* time, so walking to the correct node can be costly, consider worst
|
|
|
|
* case to be almost O(n) pointer dereference (list walk).
|
2009-08-06 08:50:19 -07:00
|
|
|
*
|
|
|
|
* @see eina_list_search_sorted()
|
|
|
|
* @see eina_list_sort()
|
|
|
|
* @see eina_list_sorted_merge()
|
|
|
|
* @see eina_list_search_unsorted_list()
|
2009-08-06 18:35:16 -07:00
|
|
|
* @see eina_list_search_sorted_near_list()
|
2009-08-06 08:50:19 -07:00
|
|
|
*/
|
2009-03-18 08:00:52 -07:00
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_search_sorted_list(const Eina_List *list,
|
|
|
|
Eina_Compare_Cb func,
|
|
|
|
const void *data)
|
2009-03-18 08:00:52 -07:00
|
|
|
{
|
2009-03-22 05:22:39 -07:00
|
|
|
Eina_List *lnear;
|
2009-08-06 15:31:45 -07:00
|
|
|
int cmp;
|
2009-03-18 08:00:52 -07:00
|
|
|
|
2009-08-06 12:01:47 -07:00
|
|
|
lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!lnear)
|
|
|
|
return NULL;
|
|
|
|
|
2009-08-06 12:01:47 -07:00
|
|
|
if (cmp == 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
return lnear;
|
|
|
|
|
2009-03-18 08:00:52 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-08-06 08:50:19 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Returns node data if it is in the sorted list.
|
|
|
|
*
|
|
|
|
* @param list The list to search for data, @b must be sorted.
|
|
|
|
* @param func A function pointer that can handle comparing the list data nodes.
|
|
|
|
* @param data reference value to search.
|
|
|
|
* @return the node value (@c node->data) if func(node->data, data) == 0,
|
|
|
|
* NULL if not found.
|
|
|
|
*
|
|
|
|
* This can be used to check if some value is inside the list and get
|
|
|
|
* the existing instance in this case. It should be used when list is
|
|
|
|
* known to be sorted as it will do binary search for results.
|
|
|
|
*
|
|
|
|
* Example: imagine user gives a string, you check if it's in the list
|
|
|
|
* before duplicating its contents.
|
|
|
|
*
|
|
|
|
* @note O(log2(n)) average/worst case performance, for 1,000,000
|
|
|
|
* elements it will do a maximum of 20 comparisons. This is much
|
|
|
|
* faster than the 1,000,000 comparisons made by
|
|
|
|
* eina_list_search_unsorted(), so depending on the number of
|
|
|
|
* searches and insertions, it may be worth to eina_list_sort() the
|
2009-08-06 18:35:16 -07:00
|
|
|
* list and do he searches later. As said in
|
|
|
|
* eina_list_search_sorted_near_list(), lists do not have O(1) access
|
|
|
|
* time, so walking to the correct node can be costly, consider worst
|
|
|
|
* case to be almost O(n) pointer dereference (list walk).
|
2009-08-06 08:50:19 -07:00
|
|
|
*
|
|
|
|
* @see eina_list_search_sorted_list()
|
|
|
|
* @see eina_list_sort()
|
|
|
|
* @see eina_list_sorted_merge()
|
|
|
|
* @see eina_list_search_unsorted_list()
|
|
|
|
*/
|
2009-01-26 06:46:02 -08:00
|
|
|
EAPI void *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_search_sorted(const Eina_List *list,
|
|
|
|
Eina_Compare_Cb func,
|
|
|
|
const void *data)
|
2009-03-18 06:29:36 -07:00
|
|
|
{
|
|
|
|
return eina_list_data_get(eina_list_search_sorted_list(list, func, data));
|
|
|
|
}
|
|
|
|
|
2009-08-06 08:50:19 -07:00
|
|
|
/**
|
|
|
|
* @brief Returns node if data is in the unsorted list.
|
|
|
|
*
|
|
|
|
* @param list The list to search for data, may be unsorted.
|
|
|
|
* @param func A function pointer that can handle comparing the list data nodes.
|
|
|
|
* @param data reference value to search.
|
|
|
|
* @return the node if func(node->data, data) == 0, NULL if not found.
|
|
|
|
*
|
|
|
|
* This can be used to check if some value is inside the list and get
|
|
|
|
* the container node in this case.
|
|
|
|
*
|
|
|
|
* Example: imagine user gives a string, you check if it's in the list
|
|
|
|
* before duplicating its contents.
|
|
|
|
*
|
|
|
|
* @note this is expensive and may walk the whole list, it's order-N,
|
|
|
|
* that is for 1,000,000 elements list it may walk and compare
|
|
|
|
* 1,000,000 nodes.
|
|
|
|
*
|
|
|
|
* @see eina_list_search_sorted_list()
|
|
|
|
* @see eina_list_search_unsorted()
|
|
|
|
*/
|
2009-03-18 06:29:36 -07:00
|
|
|
EAPI Eina_List *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_search_unsorted_list(const Eina_List *list,
|
|
|
|
Eina_Compare_Cb func,
|
|
|
|
const void *data)
|
2009-01-26 06:46:02 -08:00
|
|
|
{
|
|
|
|
const Eina_List *l;
|
|
|
|
void *d;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(list, l, d)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
if (!func(d, data))
|
|
|
|
return (Eina_List *)l;
|
|
|
|
}
|
2009-01-26 06:46:02 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-08-06 08:50:19 -07:00
|
|
|
/**
|
|
|
|
* @brief Returns node data if it is in the unsorted list.
|
|
|
|
*
|
|
|
|
* @param list The list to search for data, may be unsorted.
|
|
|
|
* @param func A function pointer that can handle comparing the list data nodes.
|
|
|
|
* @param data reference value to search.
|
|
|
|
* @return the node value (@c node->data) if func(node->data, data) == 0,
|
|
|
|
* NULL if not found.
|
|
|
|
*
|
|
|
|
* This can be used to check if some value is inside the list and get
|
|
|
|
* the existing instance in this case.
|
|
|
|
*
|
|
|
|
* Example: imagine user gives a string, you check if it's in the list
|
|
|
|
* before duplicating its contents.
|
|
|
|
*
|
|
|
|
* @note this is expensive and may walk the whole list, it's order-N,
|
|
|
|
* that is for 1,000,000 elements list it may walk and compare
|
|
|
|
* 1,000,000 nodes.
|
|
|
|
*
|
|
|
|
* @see eina_list_search_sorted()
|
|
|
|
* @see eina_list_search_unsorted_list()
|
|
|
|
*/
|
2009-03-18 06:29:36 -07:00
|
|
|
EAPI void *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_list_search_unsorted(const Eina_List *list,
|
|
|
|
Eina_Compare_Cb func,
|
|
|
|
const void *data)
|
2009-03-18 06:29:36 -07:00
|
|
|
{
|
|
|
|
return eina_list_data_get(eina_list_search_unsorted_list(list, func, data));
|
|
|
|
}
|
|
|
|
|
2009-01-26 06:46:02 -08:00
|
|
|
|
2008-09-22 22:17:49 -07:00
|
|
|
/**
|
|
|
|
* @brief Returned a new iterator asociated to a list.
|
|
|
|
*
|
|
|
|
* @param list The list.
|
|
|
|
* @return A new iterator.
|
|
|
|
*
|
2009-02-27 08:32:22 -08:00
|
|
|
* This function returns a newly allocated iterator associated to @p
|
|
|
|
* list. If @p list is @c NULL or the count member of @p list is less
|
|
|
|
* or equal than 0, this function still returns a valid iterator that
|
|
|
|
* will always return false on eina_iterator_next(), thus keeping API
|
|
|
|
* sane.
|
|
|
|
*
|
|
|
|
* If the memory can not be allocated, NULL is returned and
|
|
|
|
* #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
|
|
|
|
* returned.
|
|
|
|
*
|
|
|
|
* @warning if the list structure changes then the iterator becomes
|
|
|
|
* invalid! That is, if you add or remove nodes this iterator
|
|
|
|
* behavior is undefined and your program may crash!
|
2008-09-22 22:17:49 -07:00
|
|
|
*/
|
2008-08-13 02:19:34 -07:00
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_list_iterator_new(const Eina_List *list)
|
|
|
|
{
|
|
|
|
Eina_Iterator_List *it;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_error_set(0);
|
2008-08-13 02:19:34 -07:00
|
|
|
it = calloc(1, sizeof (Eina_Iterator_List));
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!it)
|
|
|
|
{
|
|
|
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-13 02:19:34 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
2008-08-13 02:19:34 -07:00
|
|
|
it->head = list;
|
|
|
|
it->current = list;
|
|
|
|
|
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_next);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
eina_list_iterator_get_container);
|
2008-08-13 02:19:34 -07:00
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
|
|
|
}
|
|
|
|
|
2009-03-17 05:52:38 -07:00
|
|
|
/**
|
|
|
|
* @brief Returned a new reversed iterator asociated to a list.
|
|
|
|
*
|
|
|
|
* @param list The list.
|
|
|
|
* @return A new iterator.
|
|
|
|
*
|
|
|
|
* This function returns a newly allocated iterator associated to @p
|
|
|
|
* list. If @p list is @c NULL or the count member of @p list is less
|
|
|
|
* or equal than 0, this function still returns a valid iterator that
|
|
|
|
* will always return false on eina_iterator_next(), thus keeping API
|
|
|
|
* sane.
|
|
|
|
*
|
|
|
|
* Unlike eina_list_iterator_new(), this will walk the list backwards.
|
|
|
|
*
|
|
|
|
* If the memory can not be allocated, NULL is returned and
|
|
|
|
* #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
|
|
|
|
* returned.
|
|
|
|
*
|
|
|
|
* @warning if the list structure changes then the iterator becomes
|
|
|
|
* invalid! That is, if you add or remove nodes this iterator
|
|
|
|
* behavior is undefined and your program may crash!
|
|
|
|
*/
|
|
|
|
EAPI Eina_Iterator *
|
|
|
|
eina_list_iterator_reversed_new(const Eina_List *list)
|
|
|
|
{
|
|
|
|
Eina_Iterator_List *it;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_error_set(0);
|
2009-03-17 05:52:38 -07:00
|
|
|
it = calloc(1, sizeof (Eina_Iterator_List));
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!it)
|
|
|
|
{
|
|
|
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-03-17 05:52:38 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
|
2009-03-17 05:52:38 -07:00
|
|
|
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
|
|
|
|
|
|
|
|
it->head = eina_list_last(list);
|
|
|
|
it->current = it->head;
|
|
|
|
|
|
|
|
it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_prev);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
|
|
|
|
eina_list_iterator_get_container);
|
2009-03-17 05:52:38 -07:00
|
|
|
it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
|
|
|
|
|
|
|
|
return &it->iterator;
|
|
|
|
}
|
|
|
|
|
2008-09-22 22:17:49 -07:00
|
|
|
/**
|
|
|
|
* @brief Returned a new accessor asociated to a list.
|
|
|
|
*
|
|
|
|
* @param list The list.
|
|
|
|
* @return A new accessor.
|
|
|
|
*
|
|
|
|
* This function returns a newly allocated accessor associated to
|
|
|
|
* @p list. If @p list is @c NULL or the count member of @p list is
|
|
|
|
* less or equal than 0, this function returns NULL. If the memory can
|
|
|
|
* not be allocated, NULL is returned and #EINA_ERROR_OUT_OF_MEMORY is
|
|
|
|
* set. Otherwise, a valid accessor is returned.
|
|
|
|
*/
|
2008-08-13 02:19:34 -07:00
|
|
|
EAPI Eina_Accessor *
|
|
|
|
eina_list_accessor_new(const Eina_List *list)
|
|
|
|
{
|
|
|
|
Eina_Accessor_List *it;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_error_set(0);
|
2008-08-13 02:19:34 -07:00
|
|
|
it = calloc(1, sizeof (Eina_Accessor_List));
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!it)
|
|
|
|
{
|
|
|
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-08-13 02:19:34 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ACCESSOR);
|
2008-09-25 07:46:16 -07:00
|
|
|
EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
|
|
|
|
|
2008-08-13 02:19:34 -07:00
|
|
|
it->head = list;
|
|
|
|
it->current = list;
|
|
|
|
it->index = 0;
|
|
|
|
|
|
|
|
it->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_list_accessor_get_at);
|
2010-07-27 19:37:05 -07:00
|
|
|
it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(
|
|
|
|
eina_list_accessor_get_container);
|
2008-08-13 02:19:34 -07:00
|
|
|
it->accessor.free = FUNC_ACCESSOR_FREE(eina_list_accessor_free);
|
|
|
|
|
|
|
|
return &it->accessor;
|
|
|
|
}
|
|
|
|
|
2008-08-27 23:31:18 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|