diff --git a/legacy/eina/AUTHORS b/legacy/eina/AUTHORS new file mode 100644 index 0000000000..9e8b8f022a --- /dev/null +++ b/legacy/eina/AUTHORS @@ -0,0 +1,2 @@ +Jorge Luis "turran" Zapata +Carsten Haitzler diff --git a/legacy/eina/COPYING b/legacy/eina/COPYING new file mode 100644 index 0000000000..e69de29bb2 diff --git a/legacy/eina/ChangeLog b/legacy/eina/ChangeLog new file mode 100644 index 0000000000..e69de29bb2 diff --git a/legacy/eina/Doxyfile b/legacy/eina/Doxyfile new file mode 100644 index 0000000000..73c5bc70c9 --- /dev/null +++ b/legacy/eina/Doxyfile @@ -0,0 +1,139 @@ +PROJECT_NAME = Eina +PROJECT_NUMBER = +OUTPUT_DIRECTORY = doc +INPUT = ./src/lib +IMAGE_PATH = doc/img +OUTPUT_LANGUAGE = English +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +ENUM_VALUES_PER_LINE = 1 +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 2 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = NO +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +FILE_PATTERNS = +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = YES +GENERATE_XML = NO +XML_SCHEMA = +XML_DTD = +GENERATE_AUTOGEN_DEF = NO +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = NO +COLLABORATION_GRAPH = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 512 +MAX_DOT_GRAPH_HEIGHT = 512 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +SEARCHENGINE = NO diff --git a/legacy/eina/INSTALL b/legacy/eina/INSTALL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/legacy/eina/Makefile.am b/legacy/eina/Makefile.am new file mode 100644 index 0000000000..5f5ae10ffc --- /dev/null +++ b/legacy/eina/Makefile.am @@ -0,0 +1,32 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = src + +MAINTAINERCLEANFILES = \ +Makefile.in \ +aclocal.m4 \ +config.guess \ +config.h.in \ +config.sub \ +configure \ +install-sh \ +ltconfig \ +ltmain.sh \ +missing mkinstalldirs \ +stamp-h.in \ +build-stamp \ +configure-stamp \ +depcomp \ +eina.pc \ +eina_docs.tar.gz + +EXTRA_DIST = \ +AUTHORS \ +COPYING \ +gendoc \ +Doxyfile \ +README \ +eina.pc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = eina.pc diff --git a/legacy/eina/NEWS b/legacy/eina/NEWS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/legacy/eina/README b/legacy/eina/README new file mode 100644 index 0000000000..e69de29bb2 diff --git a/legacy/eina/autogen.sh b/legacy/eina/autogen.sh new file mode 100755 index 0000000000..7aeabb6a79 --- /dev/null +++ b/legacy/eina/autogen.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f aclocal.m4 ltmain.sh + +echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1 +echo "Running autoheader..." ; autoheader || exit 1 +echo "Running autoconf..." ; autoconf || exit 1 +echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 +echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 + +if [ -z "$NOCONFIGURE" ]; then + ./configure "$@" +fi diff --git a/legacy/eina/configure.in b/legacy/eina/configure.in new file mode 100644 index 0000000000..da8a54050d --- /dev/null +++ b/legacy/eina/configure.in @@ -0,0 +1,92 @@ +# get rid of that stupid cache mechanism +rm -f config.cache + +AC_INIT(eina, 0.0.1, enlightenment-devel@lists.sourceforge.net) +AC_PREREQ(2.52) +AC_CONFIG_SRCDIR(configure.in) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_ISC_POSIX + +AM_INIT_AUTOMAKE(1.6 dist-bzip2) +AM_CONFIG_HEADER(config.h) + +AC_LIBTOOL_WIN32_DLL +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl +define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl +AC_PROG_LIBTOOL + +VMAJ=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $1);}'` +VMIN=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $2);}'` +VMIC=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $3);}'` +SNAP=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $4);}'` +version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN" +AC_SUBST(version_info) + +# Checks for programs +AC_PROG_CC + +# Checks for libraries + +# Checks for header files +AC_HEADER_ASSERT +AC_HEADER_DIRENT +AC_HEADER_TIME + +# Checks for types + +# Checks for structures + +# Checks for compiler characteristics +AC_C_CONST +AC_C_BIGENDIAN +AC_PROG_CC_STDC + +if ! test "${VMIC}" = "x" ; then + CFLAGS="${CFLAGS} -Wall -W -Wextra" # -Werror +fi + +# Checks for linker characteristics +lt_enable_auto_import="" +case "$host_os" in + mingw*|cegcc*) + lt_enable_auto_import="-Wl,--enable-auto-import" + ;; +esac +AC_SUBST(lt_enable_auto_import) + +# Checks for library functions + +## Make the debug preprocessor configurable + +AC_CONFIG_FILES([ +Makefile +eina.pc +src/Makefile +src/include/Makefile +src/lib/Makefile +src/modules/Makefile +src/modules/mm_policies/Makefile +]) + +AC_OUTPUT + +##################################################################### +## Info + +echo +echo +echo +echo "------------------------------------------------------------------------" +echo "$PACKAGE $VERSION" +echo "------------------------------------------------------------------------" +echo +echo +echo "Configuration Options Summary:" +echo +echo "Installation Path.........: $prefix" +echo +echo "Now type 'make' ('gmake' on some systems) to compile $PACKAGE," +echo "and then afterwards as root (or the user who will install this), type" +echo "'make install'. Change users with 'su' or 'sudo' appropriately." +echo diff --git a/legacy/eina/eina.pc.in b/legacy/eina/eina.pc.in new file mode 100644 index 0000000000..7dc5465abf --- /dev/null +++ b/legacy/eina/eina.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Eina +Description: Eina +Requires: +Version: @VERSION@ +Libs: -L${libdir} -leina +Libs.private: -lm -ldl +Cflags: -I${includedir} -I${includedir}/eina diff --git a/legacy/eina/gendoc b/legacy/eina/gendoc new file mode 100755 index 0000000000..d141024697 --- /dev/null +++ b/legacy/eina/gendoc @@ -0,0 +1,9 @@ +#!/bin/sh +rm -rf ./doc/html ./doc/latex ./doc/man +mkdir -p ./doc/html ./doc/latex ./doc/man 2>/dev/null +doxygen +#cp doc/img/*.png doc/html/ +rm -f edata_docs.tar ecore_docs.tar.gz +tar -cvf edata_docs.tar doc/html doc/man doc/latex +gzip -9f edata_docs.tar +exit 0 diff --git a/legacy/eina/src/Makefile.am b/legacy/eina/src/Makefile.am new file mode 100644 index 0000000000..7e99d0bc11 --- /dev/null +++ b/legacy/eina/src/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = lib include modules + +MAINTAINERCLEANFILES = Makefile.in diff --git a/legacy/eina/src/include/Eina.h b/legacy/eina/src/include/Eina.h new file mode 100644 index 0000000000..776cdc50e0 --- /dev/null +++ b/legacy/eina/src/include/Eina.h @@ -0,0 +1,33 @@ +#ifndef EINA_H_ +#define EINA_H_ + +/** + * @mainpage Eina + * @file Eina.h + * @brief Contains list, hash, debugging and tree functions. + * TODO add debug functions, magic functions, etc + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "eina_types.h" +#include "eina_f16p16.h" +#include "eina_rectangle.h" +#include "eina_inlist.h" +#include "eina_file.h" +#include "eina_list.h" +#include "eina_hash.h" +#include "eina_lalloc.h" +#include "eina_module.h" +#include "eina_mempool.h" +#include "eina_error.h" + +#ifdef __cplusplus +} +#endif + +#endif /* EINA_H */ diff --git a/legacy/eina/src/include/Makefile.am b/legacy/eina/src/include/Makefile.am new file mode 100644 index 0000000000..cddfaad1a5 --- /dev/null +++ b/legacy/eina/src/include/Makefile.am @@ -0,0 +1,20 @@ +MAINTAINERCLEANFILES = Makefile.in + +EINAHEADERS = \ +eina_error.h \ +eina_f16p16.h \ +eina_hash.h \ +eina_lalloc.h \ +eina_inlist.h \ +eina_list.h \ +eina_file.h \ +eina_mempool.h \ +eina_module.h \ +eina_rectangle.h \ +eina_types.h + +include_HEADERS = \ +Eina.h + +installed_headersdir = $(prefix)/include/eina +installed_headers_DATA = $(EINAHEADERS) diff --git a/legacy/eina/src/include/eina_error.h b/legacy/eina/src/include/eina_error.h new file mode 100644 index 0000000000..9534f2737a --- /dev/null +++ b/legacy/eina/src/include/eina_error.h @@ -0,0 +1,33 @@ +#ifndef EINA_ERROR_H_ +#define EINA_ERROR_H_ + +#define EINA_ERROR_PERR(fmt, ...) \ + eina_error_print(EINA_ERROR_LEVEL_ERR, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) + +#define EINA_ERROR_PINFO(fmt, ...) \ + eina_error_print(EINA_ERROR_LEVEL_INFO, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) + +#define EINA_ERROR_PWARN(fmt, ...) \ + eina_error_print(EINA_ERROR_LEVEL_WARN, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) + +#define EINA_ERROR_PDBG(fmt, ...) \ + eina_error_print(EINA_ERROR_LEVEL_DBG, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) + +typedef enum _Eina_Error_Level +{ + EINA_ERROR_LEVEL_ERR, + EINA_ERROR_LEVEL_WARN, + EINA_ERROR_LEVEL_INFO, + EINA_ERROR_LEVEL_DBG, + EINA_ERROR_LEVELS +} Eina_Error_Level; + +EAPI int eina_error_init(void); +EAPI int eina_error_shutdown(void); +EAPI int eina_error_register(const char *msg); +EAPI const char * eina_error_msg_get(int error); +EAPI void eina_error_print(Eina_Error_Level level, const char *file, + const char *function, int line, const char *fmt, ...); +EAPI void eina_error_log_level_set(Eina_Error_Level level); + +#endif /*EINA_ERROR_H_*/ diff --git a/legacy/eina/src/include/eina_f16p16.h b/legacy/eina/src/include/eina_f16p16.h new file mode 100644 index 0000000000..b40907c52d --- /dev/null +++ b/legacy/eina/src/include/eina_f16p16.h @@ -0,0 +1,105 @@ +#ifndef EINA_F16P16_H_ +#define EINA_F16P16_H_ + +/** + * To be documented + * FIXME: To be fixed + */ +typedef int32_t Eina_F16p16; + +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_F16p16 eina_f16p16_int_from(int32_t v) +{ + return v << 16; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline int32_t eina_f16p16_int_to(Eina_F16p16 v) +{ + return v >> 16; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_F16p16 eina_f16p16_float_from(float v) +{ + Eina_F16p16 r; + r = (Eina_F16p16)(v * 65536.0 + (v < 0 ? -0.5 : 0.5)); + return r; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline float eina_f16p16_float_to(Eina_F16p16 v) +{ + float r; + r = v / 65536.0; + return r; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_F16p16 eina_f16p16_add(Eina_F16p16 a, Eina_F16p16 b) +{ + return a + b; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_F16p16 eina_f16p16_sub(Eina_F16p16 a, Eina_F16p16 b) +{ + return a - b; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_F16p16 eina_f16p16_mul(Eina_F16p16 a, Eina_F16p16 b) +{ + return (a * b) >> 16; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_F16p16 eina_f16p16_sqrt(Eina_F16p16 a) +{ + unsigned int root, remHi, remLo, testDiv, count; + + root = 0; /* Clear root */ + remHi = 0; /* Clear high part of partial remainder */ + remLo = a; /* Get argument into low part of partial remainder */ + count = (15 + (16 >> 1)); /* Load loop counter */ + do + { + remHi = (remHi << 2) | (remLo >> 30); + remLo <<= 2; /* get 2 bits of arg */ + root <<= 1; /* Get ready for the next bit in the root */ + testDiv = (root << 1) + 1; /* Test radical */ + if (remHi >= testDiv) + { + remHi -= testDiv; + root++; + } + } while (count-- != 0); + return (root); +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline unsigned int eina_f16p16_fracc_get(Eina_F16p16 v) +{ + return (v & 0xffff); +} + +#endif /*EINA_F16P16_H_*/ diff --git a/legacy/eina/src/include/eina_file.h b/legacy/eina/src/include/eina_file.h new file mode 100644 index 0000000000..d74167b4a8 --- /dev/null +++ b/legacy/eina/src/include/eina_file.h @@ -0,0 +1,16 @@ +#ifndef EINA_FILE_H_ +#define EINA_FILE_H_ + +/** + * @defgroup File_Group Memory File + * @{ + */ + +typedef void (*Eina_File_Dir_List_Cb)(const char *name, const char *path, void *data); + +EAPI void eina_file_dir_list(const char *dir, int recursive, Eina_File_Dir_List_Cb cb, void *data); +EAPI void eina_file_path_nth_get(const char *path, int n, char **left, char **right); + +/** @} */ + +#endif /*EINA_FILE_H_*/ diff --git a/legacy/eina/src/include/eina_hash.h b/legacy/eina/src/include/eina_hash.h new file mode 100644 index 0000000000..36bbd43886 --- /dev/null +++ b/legacy/eina/src/include/eina_hash.h @@ -0,0 +1,19 @@ +#ifndef EINA_HASH_H_ +#define EINA_HASH_H_ + +/** + * + */ +typedef struct _Eina_Hash Eina_Hash; + +EAPI Eina_Hash *eina_hash_add (Eina_Hash *hash, const char *key, const void *data); +EAPI Eina_Hash *eina_hash_direct_add (Eina_Hash *hash, const char *key, const void *data); +EAPI Eina_Hash *eina_hash_del (Eina_Hash *hash, const char *key, const void *data); +EAPI void *eina_hash_find(const Eina_Hash *hash, const char *key); +EAPI void *eina_hash_modify(Eina_Hash *hash, const char *key, const void *data); +EAPI int eina_hash_size(const Eina_Hash *hash); +EAPI void eina_hash_free(Eina_Hash *hash); +EAPI void eina_hash_foreach(const Eina_Hash *hash, Eina_Bool (*func) (const Eina_Hash *hash, const char *key, void *data, void *fdata), + const void *fdata); + +#endif /*EINA_HASH_H_*/ diff --git a/legacy/eina/src/include/eina_inlist.h b/legacy/eina/src/include/eina_inlist.h new file mode 100644 index 0000000000..0fc7eb7562 --- /dev/null +++ b/legacy/eina/src/include/eina_inlist.h @@ -0,0 +1,33 @@ +#ifndef EINA_INLIST_H_ +#define EINA_INLIST_H_ + +/** + * @defgroup Inline_List_Group Inline List + * @{ + */ + +/* TODO change the prototype to use an Eina_Inlist */ +typedef struct _Eina_Inlist Eina_Inlist; + +struct _Eina_Inlist +{ + Eina_Inlist *next; + Eina_Inlist *prev; + Eina_Inlist *last; +}; + +EAPI void * eina_inlist_append(void *in_list, void *in_item); +EAPI void * eina_inlist_prepend(void *in_list, void *in_item); +EAPI void * eina_inlist_append_relative(void *in_list, void *in_item, void *in_relative); +EAPI void * eina_inlist_prepend_relative(void *in_list, void *in_item, void *in_relative); +EAPI void * eina_inlist_remove(void *in_list, void *in_item); +EAPI void * eina_inlist_find(void *in_list, void *in_item); + +//typedef Eina_Bool (*Eina_Iterator_Func)(Eina_Inlist *l, void *data); + +#define EINA_ITER_NEXT(list, l) for (l = (Eina_Inlist *)list; l; l = l->next) +#define EINA_ITER_LAST(list, l) for (l = ((Eina_Inlist *)list)->last; l; l = l->prev) + +/** @} */ + +#endif /*EINA_INLIST_H_*/ diff --git a/legacy/eina/src/include/eina_lalloc.h b/legacy/eina/src/include/eina_lalloc.h new file mode 100644 index 0000000000..9d57930c59 --- /dev/null +++ b/legacy/eina/src/include/eina_lalloc.h @@ -0,0 +1,22 @@ +#ifndef EINA_LALLOC_H_ +#define EINA_LALLOC_H_ + +/** + * @defgroup Array_Group Array + * @{ + */ + +typedef void (*Eina_Array_Alloc) (void *user_data, int num); +#define EINA_ARRAY_ALLOC(function) ((Eina_Array_Alloc)function) +typedef void (*Eina_Array_Free) (void *user_data); +#define EINA_ARRAY_FREE(function) ((Eina_Array_Free)function) + +typedef struct _Eina_Array Eina_Array; +EAPI void eina_array_free(Eina_Array *a); +EAPI Eina_Array *eina_array_new(void *data, Eina_Array_Alloc alloc_cb, Eina_Array_Free free_cb, int num_init); +EAPI void eina_array_elements_add(Eina_Array *a, int num); +EAPI void eina_array_element_add(Eina_Array *a); + +/** @} */ + +#endif diff --git a/legacy/eina/src/include/eina_list.h b/legacy/eina/src/include/eina_list.h new file mode 100644 index 0000000000..64fd78011b --- /dev/null +++ b/legacy/eina/src/include/eina_list.h @@ -0,0 +1,37 @@ +#ifndef EINA_LIST_H_ +#define EINA_LIST_H_ + +/** + * @defgroup List_Group List + * @{ + */ + +typedef struct _Eina_List Eina_List; + +EAPI Eina_List *eina_list_append (Eina_List *list, const void *data); +EAPI Eina_List *eina_list_prepend (Eina_List *list, const void *data); +EAPI Eina_List *eina_list_append_relative (Eina_List *list, const void *data, const void *relative); +EAPI Eina_List *eina_list_append_relative_list (Eina_List *list, const void *data, Eina_List *relative); +EAPI Eina_List *eina_list_prepend_relative (Eina_List *list, const void *data, const void *relative); +EAPI Eina_List *eina_list_prepend_relative_list (Eina_List *list, const void *data, Eina_List *relative); +EAPI Eina_List *eina_list_remove (Eina_List *list, const void *data); +EAPI Eina_List *eina_list_remove_list (Eina_List *list, Eina_List *remove_list); +EAPI Eina_List *eina_list_promote_list (Eina_List *list, Eina_List *move_list); +EAPI void *eina_list_find(const Eina_List *list, const void *data); +EAPI Eina_List *eina_list_find_list (const Eina_List *list, const void *data); +EAPI Eina_List *eina_list_free (Eina_List *list); +EAPI Eina_List *eina_list_last (const Eina_List *list); +EAPI Eina_List *eina_list_next (const Eina_List *list); +EAPI Eina_List *eina_list_prev (const Eina_List *list); +EAPI void *eina_list_data(const Eina_List *list); +EAPI int eina_list_count(const Eina_List *list); +EAPI void *eina_list_nth(const Eina_List *list, int n); +EAPI Eina_List *eina_list_nth_list (const Eina_List *list, int n); +EAPI Eina_List *eina_list_reverse (Eina_List *list); +EAPI Eina_List *eina_list_sort (Eina_List *list, int size, int(*func)(void*,void*)); +EAPI int eina_list_alloc_error(void); + + +/** @} */ + +#endif /* EINA_LIST_H_ */ diff --git a/legacy/eina/src/include/eina_mempool.h b/legacy/eina/src/include/eina_mempool.h new file mode 100644 index 0000000000..efca921a5f --- /dev/null +++ b/legacy/eina/src/include/eina_mempool.h @@ -0,0 +1,23 @@ +#ifndef EINA_MEMPOOL_H_ +#define EINA_MEMPOOL_H_ + +/** + * @defgroup Memory_Pool_Group Memory Pool + * @{ + */ +typedef struct _Eina_Mempool Eina_Mempool; + +EAPI int eina_mempool_init(void); +EAPI int eina_mempool_shutdown(void); +EAPI void eina_mempool_delete(Eina_Mempool *mp); +EAPI Eina_Mempool * eina_mempool_new_from_buffer(const char *name, void *buffer, + unsigned int size, const char *options, ...); +EAPI Eina_Mempool * eina_mempool_new(const char *name, unsigned int size, const char + *options, ...); +EAPI void * eina_mempool_realloc(Eina_Mempool *mp, void *element, unsigned int size); +EAPI void * eina_mempool_alloc(Eina_Mempool *mp, unsigned int size); +EAPI void eina_mempool_free(Eina_Mempool *mp, void *element); + +/** @} */ + +#endif /* EINA_MEMPOOL_H_ */ diff --git a/legacy/eina/src/include/eina_module.h b/legacy/eina/src/include/eina_module.h new file mode 100644 index 0000000000..2c938dd7f4 --- /dev/null +++ b/legacy/eina/src/include/eina_module.h @@ -0,0 +1,27 @@ +#ifndef EINA_MODULE_H_ +#define EINA_MODULE_H_ + +/** + * @defgroup Module_Group Module + * @{ + */ + +typedef struct _Eina_Module Eina_Module; + +typedef int (*Eina_Module_Cb)(Eina_Module *m, void *data); + +EAPI Eina_Module * eina_module_new(const char *file); +EAPI void eina_module_free(Eina_Module *m); +EAPI void eina_module_unload(Eina_Module *m); +EAPI char * eina_module_path_get(Eina_Module *m); +EAPI char * eina_module_name_get(Eina_Module *m); +EAPI void * eina_module_symbol_get(Eina_Module *m, const char *symbol); + +EAPI Eina_List * eina_module_list_get(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data); +EAPI void eina_module_list_load(Eina_List *list); +EAPI void eina_module_list_unload(Eina_List *list); +EAPI void eina_module_list_free(Eina_List *list); + +/** @} */ + +#endif /*EINA_MODULE_H_*/ diff --git a/legacy/eina/src/include/eina_private.h b/legacy/eina/src/include/eina_private.h new file mode 100644 index 0000000000..b84ad964e9 --- /dev/null +++ b/legacy/eina/src/include/eina_private.h @@ -0,0 +1,148 @@ +#ifndef EINA_PRIVATE_H_ +#define EINA_PRIVATE_H_ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DEBUG +#include + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +#ifndef MIN +# define MIN(x, y) (((x) > (y)) ? (y) : (x)) +#endif + +#ifndef MAX +# define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif + +#ifndef ABS +# define ABS(x) ((x) < 0 ? -(x) : (x)) +#endif + +#ifndef CLAMP +# define CLAMP(x, min, max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x))) +#endif + +#define READBUFSIZ 65536 + +#define EINA_MAGIC_NONE 0x1234fedc +#define EINA_MAGIC_EXE 0xf7e812f5 +#define EINA_MAGIC_TIMER 0xf7d713f4 +#define EINA_MAGIC_IDLER 0xf7c614f3 +#define EINA_MAGIC_IDLE_ENTERER 0xf7b515f2 +#define EINA_MAGIC_IDLE_EXITER 0xf7601afd +#define EINA_MAGIC_FD_HANDLER 0xf7a416f1 +#define EINA_MAGIC_EVENT_HANDLER 0xf79317f0 +#define EINA_MAGIC_EVENT_FILTER 0xf78218ff +#define EINA_MAGIC_EVENT 0xf77119fe +#define EINA_MAGIC_ANIMATOR 0xf7643ea5 + +#define EINA_MAGIC Eina_Magic __magic + +#define EINA_MAGIC_SET(d, m) (d)->__magic = (m) +#define EINA_MAGIC_CHECK(d, m) ((d) && ((d)->__magic == (m))) +#define EINA_MAGIC_FAIL(d, m, fn) _eina_magic_fail((d), (d) ? (d)->__magic : 0, (m), (fn)); + +/* undef the following, we want out version */ +#undef FREE +#define FREE(ptr) free(ptr); ptr = NULL; + +#undef IF_FREE +#define IF_FREE(ptr) if (ptr) free(ptr); ptr = NULL; + +#undef IF_FN_DEL +#define IF_FN_DEL(_fn, ptr) if (ptr) { _fn(ptr); ptr = NULL; } + +inline void eina_print_warning(const char *function, const char *sparam); + +/* convenience macros for checking pointer parameters for non-NULL */ +#undef CHECK_PARAM_POINTER_RETURN +#define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \ + if (!(param)) \ + { \ + eina_print_warning(__FUNCTION__, sparam); \ + return ret; \ + } + +#undef CHECK_PARAM_POINTER +#define CHECK_PARAM_POINTER(sparam, param) \ + if (!(param)) \ + { \ + eina_print_warning(__FUNCTION__, sparam); \ + return; \ + } + +typedef unsigned int Eina_Magic; + +typedef struct _Eina_List2 Eina_List2; +typedef struct _Eina_List2_Data Eina_List2_Data; + +struct _Eina_List2 +{ + Eina_List2 *next, *prev; + Eina_List2 *last; +}; + +struct _Eina_List2_Data +{ + Eina_List2 __list_data; + void *data; +}; + +#ifndef EINA_H + +#endif + +EAPI void _eina_magic_fail(void *d, Eina_Magic m, Eina_Magic req_m, const char *fname); + +EAPI void *_eina_list2_append (void *in_list, void *in_item); +EAPI void *_eina_list2_prepend (void *in_list, void *in_item); +EAPI void *_eina_list2_append_relative (void *in_list, void *in_item, void *in_relative); +EAPI void *_eina_list2_prepend_relative (void *in_list, void *in_item, void *in_relative); +EAPI void *_eina_list2_remove (void *in_list, void *in_item); +EAPI void *_eina_list2_find (void *in_list, void *in_item); + +void _eina_fps_debug_init(void); +void _eina_fps_debug_shutdown(void); +void _eina_fps_debug_runtime_add(double t); + + + +extern int _eina_fps_debug; + + +/* old code finish */ +/* mp */ +typedef struct _Eina_Mempool_Backend +{ + void *(*init)(void *buffer, unsigned int size, const char *options, va_list args); + void (*free)(void *data, void *element); + void *(*alloc)(void *data, unsigned int size); + void *(*realloc)(void *data, void *element, unsigned int size); + void (*garbage_collect)(void); + void (*statistics)(void); + void (*shutdown)(void *data); +} Eina_Mempool_Backend; + + +#endif /* EINA_PRIVATE_H_ */ diff --git a/legacy/eina/src/include/eina_rectangle.h b/legacy/eina/src/include/eina_rectangle.h new file mode 100644 index 0000000000..839e8715bb --- /dev/null +++ b/legacy/eina/src/include/eina_rectangle.h @@ -0,0 +1,196 @@ +#ifndef EINA_RECTANGLE_H_ +#define EINA_RECTANGLE_H_ + +/** + * @file + * @{ + */ + +/** + * To be documented + * FIXME: To be fixed + */ +typedef struct _Eina_Rectangle +{ + int x; + int y; + int w; + int h; +} Eina_Rectangle; + +/** + * To be documented + * FIXME: To be fixed + * Is it needed?? + */ +static inline int +eina_spans_intersect(int c1, int l1, int c2, int l2) +{ + return (!(((c2 + l2) <= c1) || (c2 >= (c1 + l1)))); +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_is_empty(Eina_Rectangle *r) +{ + return ((r->w < 1) || (r->h < 1)); +} + +/** + * To be documented + * FIXME: To be fixed + */ +static inline void +eina_rectangle_coords_from(Eina_Rectangle *r, int x, int y, int w, int h) +{ + r->x = x; + r->y = y; + r->w = w; + r->h = h; +} + +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangles_intersect(Eina_Rectangle *r1, Eina_Rectangle *r2) +{ + return (eina_spans_intersect(r1->x, r1->w, r2->x, r2->w) && eina_spans_intersect(r1->y, r1->h, r2->y, r2->h)); +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_hspan_inside(Eina_Rectangle *r, int x, int l) +{ + +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_vspan_inside(Eina_Rectangle *r, int y, int l) +{ + +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_xcoord_inside(Eina_Rectangle *r, int x) +{ + return ((x >= r->x) && (x < (r->x + r->w))); +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_ycoord_inside(Eina_Rectangle *r, int y) +{ + return ((y >= r->y) && (y < (r->y + r->h))); +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_coords_inside(Eina_Rectangle *r, int x, int y) +{ + return (eina_rectangle_xcoord_inside(r, x) && eina_rectangle_ycoord_inside(r, y)); +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline void +eina_rectangle_union(Eina_Rectangle *dst, Eina_Rectangle *src) +{ + /* left */ + if (dst->x > src->x) + { + dst->w += dst->x - src->x; + dst->x = src->x; + } + /* right */ + if ((dst->x + dst->w) < (src->x + src->w)) + dst->w = src->x + src->w; + /* top */ + if (dst->y > src->y) + { + dst->h += dst->y - src->y; + dst->y = src->y; + } + /* bottom */ + if ((dst->y + dst->h) < (src->y + src->h)) + dst->h = src->y + src->h; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline Eina_Bool +eina_rectangle_intersection(Eina_Rectangle *dst, Eina_Rectangle *src) +{ + if (!(eina_rectangles_intersect(dst, src))) + return EINA_FALSE; + + /* left */ + if (dst->x < src->x) + { + dst->w += dst->x - src->x; + dst->x = src->x; + if (dst->w < 0) + dst->w = 0; + } + /* right */ + if ((dst->x + dst->w) > (src->x + src->w)) + dst->w = src->x + src->w - dst->x; + /* top */ + if (dst->y < src->y) + { + dst->h += dst->y - src->y; + dst->y = src->y; + if (dst->h < 0) + dst->h = 0; + } + /* bottom */ + if ((dst->y + dst->h) > (src->y + src->h)) + dst->h = src->y + src->h - dst->y; + + return EINA_TRUE; +} + +/** + * Rescale the coordinates from @in as if it where relative to @out + */ +static inline void +eina_rectangle_rescale_in(Eina_Rectangle *out, Eina_Rectangle *in, Eina_Rectangle *res) +{ + res->x = in->x - out->x; + res->y = in->y - out->y; + res->w = in->w; + res->h = in->h; +} +/** + * To be documented + * FIXME: To be fixed + */ +static inline void +eina_rectangle_rescale_out(Eina_Rectangle *out, Eina_Rectangle *in, Eina_Rectangle *res) +{ + res->x = out->x + in->x; + res->y = out->y + in->y; + res->w = out->w; + res->h = out->h; +} + +/** @} */ + +#endif /*_ENESIM_RECTANGLE_H_*/ diff --git a/legacy/eina/src/include/eina_types.h b/legacy/eina/src/include/eina_types.h new file mode 100644 index 0000000000..9dc7164e11 --- /dev/null +++ b/legacy/eina/src/include/eina_types.h @@ -0,0 +1,62 @@ +#ifndef EINA_TYPES_H_ +#define EINA_TYPES_H_ + +#ifdef EAPI +# undef EAPI +#endif + +#ifdef _WIN32 +# ifdef EFL_EINA_BUILD +# ifdef DLL_EXPORT +# define EAPI __declspec(dllexport) +# else +# define EAPI +# endif /* ! DLL_EXPORT */ +# else +# define EAPI __declspec(dllimport) +# endif /* ! EFL_EINA_BUILD */ +#else +# ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +# else +# define EAPI +# endif +#endif + +/* remove this TRUE/FALSE redifinitions */ + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +typedef enum { + EINA_FALSE = 0, + EINA_TRUE = 1 +} Eina_Bool; + +EAPI extern const unsigned int eina_prime_table[]; + +#define EINA_SORT_MIN 0 +#define EINA_SORT_MAX 1 + +typedef void (*Eina_For_Each) (void *value, void *user_data); +#define EINA_FOR_EACH(function) ((Eina_For_Each)function) + +typedef void (*Eina_Free_Cb) (void *data); +#define EINA_FREE_CB(func) ((Eina_Free_Cb)func) + +typedef unsigned int (*Eina_Hash_Cb) (const void *key); +#define EINA_HASH_CB(function) ((Eina_Hash_Cb)function) + +typedef int (*Eina_Compare_Cb) (const void *data1, const void *data2); +#define EINA_COMPARE_CB(function) ((Eina_Compare_Cb)function) + +#endif /*EINA_TYPES_H_*/ diff --git a/legacy/eina/src/lib/Makefile.am b/legacy/eina/src/lib/Makefile.am new file mode 100644 index 0000000000..666aed8612 --- /dev/null +++ b/legacy/eina/src/lib/Makefile.am @@ -0,0 +1,21 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_srcdir)/src/include + +lib_LTLIBRARIES = libeina.la + +libeina_la_SOURCES = \ +eina_error.c \ +eina_hash.c \ +eina_lalloc.c \ +eina_inlist.c \ +eina_file.c \ +eina_mempool.c \ +eina_list.c \ +eina_module.c \ +eina_value.c + +libeina_la_LIBADD = -ldl +libeina_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ +libeina_la_DEPENDENCIES = $(top_builddir)/config.h diff --git a/legacy/eina/src/lib/eina_error.c b/legacy/eina/src/lib/eina_error.c new file mode 100644 index 0000000000..b4e10dbcf2 --- /dev/null +++ b/legacy/eina/src/lib/eina_error.c @@ -0,0 +1,153 @@ +#include "Eina.h" +#include "eina_private.h" +/* TODO + * + printing errors to stdout or stderr can be implemented + * using a queue, usful for multiple threads printing + * + add a wapper for assert? + * + add common error numbers, messages + * + add a calltrace of erros, not only store the last error but a list of them + * and also store the function that set it + */ +/*============================================================================* + * Local * + *============================================================================*/ +static int _curr = 1; +static int _init_count = 0; +static Eina_List *_error_list; +static int _err; + +#define RED "\033[31;1m" +#define GREEN "\033[32;1m" +#define YELLOW "\033[33;1m" +#define WHITE "\033[37;1m" +#define NOTHING "\033[0m" + + +#ifdef DEBUG +static _error_level = EINA_ERROR_LEVEL_DBG; +#else +static _error_level = EINA_ERROR_LEVEL_ERR; +#endif + +static char *_colors[EINA_ERROR_LEVELS] = { + [EINA_ERROR_LEVEL_ERR] = RED, + [EINA_ERROR_LEVEL_WARN] = YELLOW, + [EINA_ERROR_LEVEL_INFO] = NOTHING, + [EINA_ERROR_LEVEL_DBG] = GREEN, +}; + +static void _error_print(Eina_Error_Level level, const char *file, + const char *fnc, int line, const char *fmt, va_list args) +{ + if (level <= _error_level) + { + printf("%s", _colors[level]); + printf("[%s:%d] %s() ", file, line, fnc); + printf("%s", _colors[EINA_ERROR_LEVEL_INFO]); + vprintf(fmt, args); + } +} +/*============================================================================* + * Global * + *============================================================================*/ +void eina_error_magic_check(unsigned int magic, unsigned int cmp) +{ + assert(magic == cmp); +} +/*============================================================================* + * API * + *============================================================================*/ +/** + * + */ +EAPI int eina_error_init(void) +{ + if (!_init_count) + { + char *level; + /* TODO register the eina's basic errors */ + /* TODO load the environment variable for getting the log level */ + if (level = getenv("EINA_ERROR_LEVEL")) + { + _error_level = atoi(level); + } + } + /* get all the modules */ + return ++_init_count; +} +/** + * + */ +EAPI int eina_error_shutdown(void) +{ + if (!_init_count) + return _init_count; + _init_count--; + if (!_init_count) + { + /* remove the error strings */ + while (_error_list) + { + free(eina_list_data(_error_list)); + _error_list = eina_list_free(_error_list); + } + } + return _init_count; +} + +/** + * Register a new error type + * @param str The description of the error + * @return The unique number identifier for this error + */ +EAPI int eina_error_register(const char *msg) +{ + char *str; + + str = strdup(msg); + _error_list = eina_list_append(_error_list, str); + + return ++_curr; +} +/** + * + */ +EAPI int eina_error_get(void) +{ + return _err; +} +/** + * + */ +EAPI int eina_error_set(int err) +{ + _err = err; +} +/** + * Given an error number return the description of it + * @param error The error number + * @return The description of the error + */ +EAPI const char * eina_error_msg_get(int error) +{ + return eina_list_nth(_error_list, error); +} +/** + * + */ +EAPI void eina_error_print(Eina_Error_Level level, const char *file, + const char *fnc, int line, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + _error_print(level, file, fnc, line, fmt, args); + va_end(args); +} +/** + * + */ +EAPI void eina_error_log_level_set(Eina_Error_Level level) +{ + _error_level = level; +} diff --git a/legacy/eina/src/lib/eina_file.c b/legacy/eina/src/lib/eina_file.c new file mode 100644 index 0000000000..a69db84545 --- /dev/null +++ b/legacy/eina/src/lib/eina_file.c @@ -0,0 +1,84 @@ +#include "Eina.h" +#include "eina_private.h" +/*============================================================================* + * API * + *============================================================================*/ +/** + * Lis all files on the directory calling the function for every file found + * @param recursive Iterate recursively in the directory + */ +EAPI void eina_file_dir_list(const char *dir, int recursive, Eina_File_Dir_List_Cb cb, void *data) +{ + struct dirent *de; + DIR *d; + + assert(cb); + + d = opendir(dir); + if (!d) + return; + + while (de = readdir(d)) + { + int length; + + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + cb(de->d_name, dir, data); + /* d_type is only available on linux and bsd (_BSD_SOURCE) */ + if ((recursive) && (de->d_type == DT_DIR)) + { + char path[PATH_MAX]; + + snprintf(path, PATH_MAX, "%s/%s", dir, de->d_name); + eina_file_dir_list(path, recursive, cb, data); + } + } + closedir(d); +} +/** + * + */ +EAPI void eina_file_path_nth_get(const char *path, int n, char **left, char **right) +{ + char *p; + char *end; + char *tmp; + char *delim; + int inc; + int num = 0; + + if (!left && !right) + return; + + if (n > 0) + { + p = (char *)path; + inc = 1; + end = (char *)path + strlen(path); + } + else + { + p = (char *)path + strlen(path); + inc = -1; + end = (char *)path; + } + for (tmp = p; tmp != end, num != n; tmp += inc) + { + if (*tmp == '/') + { + num += inc; + delim = tmp; + } + } + if (left) + { + *left = strndup(path, delim - path + 1); + } + if (right) + { + *right = strdup(delim + 1); + } +} + diff --git a/legacy/eina/src/lib/eina_hash.c b/legacy/eina/src/lib/eina_hash.c new file mode 100644 index 0000000000..b897ba4f55 --- /dev/null +++ b/legacy/eina/src/lib/eina_hash.c @@ -0,0 +1,473 @@ +#include "Eina.h" +#include "eina_private.h" +/*============================================================================* + * Local * + *============================================================================*/ +typedef struct _Eina_Hash_El Eina_Hash_El; + +struct _Eina_Hash +{ + int population; + Eina_Inlist *buckets[256]; +}; + +struct _Eina_Hash_El +{ + Eina_Inlist _list_data; + const char *key; + void *data; +}; + +static inline int _eina_hash_gen(const char *key); + +static int _eina_hash_alloc_error = 0; + +static inline int _eina_hash_gen(const char *key) +{ + unsigned int hash_num = 5381; + const unsigned char *ptr; + + if (!key) + return 0; + for (ptr = (unsigned char *)key; *ptr; ptr++) + hash_num = (hash_num * 33) ^ *ptr; + + hash_num &= 0xff; + return (int)hash_num; +} +/*============================================================================* + * Global * + *============================================================================*/ +/*============================================================================* + * API * + *============================================================================*/ +/** + * Adds an entry to the given hash table. + * + * @p key is expected to be a unique string within the hash table. + * Otherwise, you cannot be sure which inserted data pointer will be + * accessed with @ref eina_hash_find , and removed with + * @ref eina_hash_del . + * + * Key strings are case sensitive. + * + * @ref eina_hash_alloc_error should be used to determine if an + * allocation error occurred during this function. + * + * @param hash The given hash table. Can be @c NULL, in which case a + * new hash table is allocated and returned. + * @param key A unique string. Can be @c NULL. + * @param data Data to associate with the string given by @p key. + * @return Either the given hash table, or if the given value for @p + * hash is @c NULL, then a new one. @c NULL will be returned + * if memory could not be allocated for a new table. + */ +EAPI Eina_Hash * +eina_hash_add(Eina_Hash *hash, const char *key, const void *data) +{ + int hash_num; + Eina_Hash_El *el; + + if ((!key) || (!data)) return hash; + _eina_hash_alloc_error = 0; + if (!hash) + { + hash = calloc(1, sizeof(struct _Eina_Hash)); + if (!hash) + { + _eina_hash_alloc_error = 1; + return NULL; + } + } + if (!(el = malloc(sizeof(struct _Eina_Hash_El) + strlen(key) + 1))) + { + if (hash->population <= 0) + { + free(hash); + hash = NULL; + } + _eina_hash_alloc_error = 1; + return hash; + }; + el->key = ((char *)el) + sizeof(struct _Eina_Hash_El); + strcpy((char *) el->key, key); + el->data = (void *)data; + hash_num = _eina_hash_gen(key); + hash->buckets[hash_num] = eina_inlist_prepend(hash->buckets[hash_num], el); + if (eina_list_alloc_error()) + { + _eina_hash_alloc_error = 1; + free(el); + return hash; + } + hash->population++; + return hash; +} +/** + * Adds an entry to the given hash table and does not duplicate the string key. + * + * @p key is expected to be a unique string within the hash table. + * Otherwise, you cannot be sure which inserted data pointer will be + * accessed with @ref eina_hash_find , and removed with + * @ref eina_hash_del . This call does not make a copy of the key so it must + * be a string constant or stored elsewhere (in the object being added) etc. + * + * Key strings are case sensitive. + * + * @ref eina_hash_alloc_error should be used to determine if an + * allocation error occurred during this function. + * + * @param hash The given hash table. Can be @c NULL, in which case a + * new hash table is allocated and returned. + * @param key A unique string. Can be @c NULL. + * @param data Data to associate with the string given by @p key. + * @return Either the given hash table, or if the given value for @p + * hash is @c NULL, then a new one. @c NULL will be returned + * if memory could not be allocated for a new table. + * @ingroup Eina_Hash_Data + */ +EAPI Eina_Hash * +eina_hash_direct_add(Eina_Hash *hash, const char *key, const void *data) +{ + int hash_num; + Eina_Hash_El *el; + + if ((!key) || (!data)) return hash; + _eina_hash_alloc_error = 0; + if (!hash) + { + hash = calloc(1, sizeof(struct _Eina_Hash)); + if (!hash) + { + _eina_hash_alloc_error = 1; + return NULL; + } + } + if (!(el = malloc(sizeof(struct _Eina_Hash_El)))) + { + if (hash->population <= 0) + { + free(hash); + hash = NULL; + } + _eina_hash_alloc_error = 1; + return hash; + }; + el->key = key; + el->data = (void *)data; + hash_num = _eina_hash_gen(key); + hash->buckets[hash_num] = eina_inlist_prepend(hash->buckets[hash_num], el); + if (eina_list_alloc_error()) + { + _eina_hash_alloc_error = 1; + free(el); + return hash; + } + hash->population++; + return hash; +} + +/** + * Removes the entry identified by @p key or @p data from the given + * hash table. + * + * If @p key is @c NULL, then @p data is used to find a match to + * remove. + * + * @param hash The given hash table. + * @param key The key string. Can be @c NULL. + * @param data The data pointer to remove if @p key is @c NULL. + * Otherwise, not required and can be @c NULL. + * @return The modified hash table. If there are no entries left, the + * hash table will be freed and @c NULL will be returned. + * @ingroup Eina_Hash_Data + */ +EAPI Eina_Hash * +eina_hash_del(Eina_Hash *hash, const char *key, const void *data) +{ + int hash_num; + Eina_Hash_El *el; + Eina_Inlist *l; + + if (!hash) return NULL; + if (!key) + { + int hash_num; + + for (hash_num = 0; hash_num < 256; hash_num++) + { + for (l = hash->buckets[hash_num]; l; l = l->next) + { + el = (Eina_Hash_El *)l; + if (el->data == data) + { + hash->buckets[hash_num] = eina_inlist_remove(hash->buckets[hash_num], el); + free(el); + hash->population--; + if (hash->population <= 0) + { + free(hash); + hash = NULL; + } + return hash; + } + } + } + } + else + { + hash_num = _eina_hash_gen(key); + for (l = hash->buckets[hash_num]; l; l = l->next) + { + el = (Eina_Hash_El *)l; + if (!strcmp(el->key, key)) + { + hash->buckets[hash_num] = eina_inlist_remove(hash->buckets[hash_num], el); + free(el); + hash->population--; + if (hash->population <= 0) + { + free(hash); + hash = NULL; + } + return hash; + } + } + } + return hash; +} + +/** + * Retrieves a specific entry in the given hash table. + * @param hash The given hash table. + * @param key The key string of the entry to find. + * @return The data pointer for the stored entry, or @c NULL if not + * found. + * @ingroup Eina_Hash_Data + */ +EAPI void * eina_hash_find(const Eina_Hash *hash, const char *key) +{ + int hash_num; + Eina_Hash_El *el; + Eina_Inlist *l; + + _eina_hash_alloc_error = 0; + if ((!hash) || (!key)) + return NULL; + hash_num = _eina_hash_gen(key); + for (l = hash->buckets[hash_num]; l; l = l->next) { + el = (Eina_Hash_El *)l; + if (!strcmp(el->key, key)) { + if (l != hash->buckets[hash_num]) { + Eina_Inlist *bucket; + + bucket = hash->buckets[hash_num]; + bucket = eina_inlist_remove(bucket, el); + bucket = eina_inlist_prepend(bucket, el); + ((Eina_Hash *)hash)->buckets[hash_num] + = bucket; + } + return el->data; + } + } + return NULL; +} + +/** + * Modifies the entry pointer at the specified key and returns the old entry + * @param hash The given hash table. + * @param key The key string of the entry to modify. + * @param data The data to replace the old entry, if it exists. + * @return The data pointer for the old stored entry, or @c NULL if not + * found. If an existing entry is not found, nothing is added to the + * hash. + * @ingroup Eina_Hash_Data + */ +EAPI void * eina_hash_modify(Eina_Hash *hash, const char *key, const void *data) +{ + int hash_num; + Eina_Hash_El *el; + Eina_Inlist *l; + + _eina_hash_alloc_error = 0; + if (!hash) + return NULL; + hash_num = _eina_hash_gen(key); + for (l = hash->buckets[hash_num]; l; l = l->next) { + el = (Eina_Hash_El *)l; + if ((key) && (!strcmp(el->key, key))) { + void *old_data; + + if (l != hash->buckets[hash_num]) { + hash->buckets[hash_num] + = eina_inlist_remove( + hash->buckets[hash_num], + el); + hash->buckets[hash_num] + = eina_inlist_prepend( + hash->buckets[hash_num], + el); + } + old_data = el->data; + el->data = (void *) data; + return old_data; + } + } + return NULL; +} + +/** + * @defgroup Eina_Hash_General_Group Hash General Functions + * + * Miscellaneous functions that operate on hash objects. + */ + +/** + * Retrieves the number of buckets available in the given hash table. + * @param hash The given hash table. + * @return @c 256 if @p hash is not @c NULL. @c 0 otherwise. + * @ingroup Eina_Hash_General_Group + */ +EAPI int eina_hash_size(const Eina_Hash *hash) +{ + if (!hash) + return 0; + return 256; +} + +/** + * @todo Complete polishing documentation for eina_hash.c. The + * functions' docs may be grouped, but they need some simplification. + */ + +/** + * Free an entire hash table + * @param hash The hash table to be freed + * + * This function frees up all the memory allocated to storing the specified + * hash tale pointed to by @p hash. Any entries in the table that the program + * has no more pointers for elsewhere may now be lost, so this should only be + * called if the program has lready freed any allocated data in the hash table + * or has the pointers for data in teh table stored elswehere as well. + * + * Example: + * @code + * extern Eina_Hash *hash; + * + * eina_hash_free(hash); + * hash = NULL; + * @endcode + * @ingroup Eina_Hash_General_Group + */ +EAPI void eina_hash_free(Eina_Hash *hash) +{ + int i, size; + + if (!hash) + return; + size = eina_hash_size(hash); + for (i = 0; i < size; i++) { + while (hash->buckets[i]) { + Eina_Hash_El *el; + + el = (Eina_Hash_El *)hash->buckets[i]; + hash->buckets[i] = eina_inlist_remove( + hash->buckets[i], el); + free(el); + } + } + free(hash); +} + +/** + * Call a function on every member stored in the hash table + * @param hash The hash table whose members will be walked + * @param func The function to call on each parameter + * @param fdata The data pointer to pass to the function being called + * + * This function goes through every entry in the hash table @p hash and calls + * the function @p func on each member. The function should NOT modify the + * hash table contents if it returns 1. IF the hash table contents are + * modified by this function or the function wishes to stop processing it must + * return 0, otherwise return 1 to keep processing. + * + * Example: + * @code + * extern Eina_Hash *hash; + * + * Eina_Bool hash_fn(Eina_Hash *hash, const char *key, void *data, void *fdata) + * { + * printf("Func data: %s, Hash entry: %s / %p\n", fdata, key, data); + * return 1; + * } + * + * int main(int argc, char **argv) + * { + * char *hash_fn_data; + * + * hash_fn_data = strdup("Hello World"); + * eina_hash_foreach(hash, hash_fn, hash_fn_data); + * free(hash_fn_data); + * } + * @endcode + * @ingroup Eina_Hash_General_Group + */ +EAPI void eina_hash_foreach( + const Eina_Hash *hash, + Eina_Bool (*func) (const Eina_Hash *hash, const char *key, void *data, void *fdata), + const void *fdata) +{ + int i, size; + + if (!hash) + return; + size = eina_hash_size(hash); + for (i = 0; i < size; i++) { + Eina_Inlist *l, *next_l; + + for (l = hash->buckets[i]; l;) { + Eina_Hash_El *el; + + next_l = l->next; + el = (Eina_Hash_El *)l; + if (!func(hash, el->key, el->data, (void *)fdata)) + return; + l = next_l; + } + } +} + +/** + * Return memory allocation failure flag after an function requiring allocation + * @return The state of the allocation flag + * + * This function returns the state of the memory allocation flag. This flag is + * set if memory allocations fail during eina_hash_add() calls. If they do, 1 + * will be returned, otherwise 0 will be returned. The flag will remain in its + * current state until the next call that requires allocation is called, and + * is then reset. + * + * Example: + * @code + * Eina_Hash *hash = NULL; + * extern void *my_data; + * + * hash = eina_hash_add(hash, "My Data", my_data); + * if (eina_hash_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. Hash allocation failed.\n"); + * exit(-1); + * } + * if (eina_hash_find(hash, "My Data") == my_data) + * { + * printf("My Data inserted and successfully found.\n"); + * } + * @endcode + * @ingroup Eina_Hash_General_Group + */ +EAPI int eina_hash_alloc_error(void) +{ + return _eina_hash_alloc_error; +} + +/* Common hash functions */ diff --git a/legacy/eina/src/lib/eina_inlist.c b/legacy/eina/src/lib/eina_inlist.c new file mode 100644 index 0000000000..582a714df4 --- /dev/null +++ b/legacy/eina/src/lib/eina_inlist.c @@ -0,0 +1,161 @@ +#include "Eina.h" +#include "eina_private.h" + +/* TODO please, refactor this :) */ + +/*============================================================================* + * API * + *============================================================================*/ +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_inlist_append(void *in_list, void *in_item) { + Eina_Inlist *l, *new_l; + Eina_Inlist *list; + + list = in_list; + new_l = in_item; + new_l->next = NULL; + if (!list) { + new_l->prev = NULL; + new_l->last = new_l; + return new_l; + } + if (list->last) + l = list->last; + else + for (l = list; (l) && (l->next); l = l->next) + ; + l->next = new_l; + new_l->prev = l; + list->last = new_l; + return list; +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_inlist_prepend(void *in_list, void *in_item) { + Eina_Inlist *new_l; + Eina_Inlist *list; + + list = in_list; + new_l = in_item; + new_l->prev = NULL; + if (!list) { + new_l->next = NULL; + new_l->last = new_l; + return new_l; + } + new_l->next = list; + list->prev = new_l; + new_l->last = list->last; + list->last = NULL; + return new_l; +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_inlist_append_relative(void *in_list, void *in_item, + void *in_relative) { + Eina_Inlist *list, *relative, *new_l; + + list = in_list; + new_l = in_item; + relative = in_relative; + if (relative) { + if (relative->next) { + new_l->next = relative->next; + relative->next->prev = new_l; + } else + new_l->next = NULL; + relative->next = new_l; + new_l->prev = relative; + if (!new_l->next) + list->last = new_l; + return list; + } + return eina_inlist_append(list, new_l); +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_inlist_prepend_relative(void *in_list, void *in_item, + void *in_relative) { + Eina_Inlist *list, *relative, *new_l; + + list = in_list; + new_l = in_item; + relative = in_relative; + if (relative) { + new_l->prev = relative->prev; + new_l->next = relative; + relative->prev = new_l; + if (new_l->prev) { + new_l->prev->next = new_l; + if (!new_l->next) + list->last = new_l; + return list; + } else { + if (!new_l->next) + new_l->last = new_l; + else { + new_l->last = list->last; + list->last = NULL; + } + return new_l; + } + } + return eina_inlist_prepend(list, new_l); +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_inlist_remove(void *in_list, void *in_item) { + Eina_Inlist *return_l; + Eina_Inlist *list, *item; + + /* checkme */ + if (!in_list) + return in_list; + + list = in_list; + item = in_item; + if (!item) + return list; + if (item->next) + item->next->prev = item->prev; + if (item->prev) { + item->prev->next = item->next; + return_l = list; + } else { + return_l = item->next; + if (return_l) + return_l->last = list->last; + } + if (item == list->last) + list->last = item->prev; + item->next = NULL; + item->prev = NULL; + return return_l; +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_inlist_find(void *in_list, void *in_item) { + Eina_Inlist *l; + Eina_Inlist *list, *item; + + list = in_list; + item = in_item; + for (l = list; l; l = l->next) { + if (l == item) + return item; + } + return NULL; +} diff --git a/legacy/eina/src/lib/eina_lalloc.c b/legacy/eina/src/lib/eina_lalloc.c new file mode 100644 index 0000000000..f2ce80d442 --- /dev/null +++ b/legacy/eina/src/lib/eina_lalloc.c @@ -0,0 +1,78 @@ +#include "Eina.h" +#include "eina_private.h" + +struct _Eina_Array +{ + void *data; + int num_allocated; + int num_elements; + int acc; + Eina_Array_Alloc alloc_cb; + Eina_Array_Free free_cb; +}; + +/** + * To be documented + * FIXME: To be fixed + */ +EAPI Eina_Array * eina_array_new(void *data, Eina_Array_Alloc alloc_cb, Eina_Array_Free free_cb, int num_init) +{ + Eina_Array *a; + + a = calloc(1, sizeof(Eina_Array)); + a->data = data; + a->alloc_cb = alloc_cb; + a->free_cb = free_cb; + if (num_init > 0) + { + a->num_allocated = num_init; + a->alloc_cb(a->data, a->num_allocated); + } + return a; +} + +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void eina_array_element_add(Eina_Array *a) +{ + if (a->num_elements == a->num_allocated) + { + a->num_allocated = (1 << a->acc); + a->acc++; + a->alloc_cb(a->data, a->num_allocated); + } + a->num_elements++; +} + +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void eina_array_elements_add(Eina_Array *a, int num) +{ + int tmp; + + tmp = a->num_elements + num; + if (tmp > a->num_allocated) + { + while (tmp > a->num_allocated) + { + a->num_allocated = (1 << a->acc); + a->acc++; + } + a->alloc_cb(a->data, a->num_allocated); + } + a->num_elements += num; +} + +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void eina_array_free(Eina_Array *a) +{ + a->free_cb(a->data); + free(a); +} diff --git a/legacy/eina/src/lib/eina_list.c b/legacy/eina/src/lib/eina_list.c new file mode 100644 index 0000000000..0a5a627cef --- /dev/null +++ b/legacy/eina/src/lib/eina_list.c @@ -0,0 +1,1052 @@ +#include "Eina.h" +#include "eina_private.h" + +struct _Eina_List /** A linked list node */ +{ + void *data; /**< Pointer to list element payload */ + Eina_List *next; /**< Next member in the list */ + Eina_List *prev; /**< Previous member in the list */ + struct _Eina_List_Accounting *accounting; /**< Private list accounting info - don't touch */ +}; + +typedef struct _Eina_List_Accounting Eina_List_Accounting; + +struct _Eina_List_Accounting +{ + Eina_List *last; + int count; +}; + +static int _eina_list_alloc_error = 0; + +typedef struct _Eina_Mempool2 Eina_Mempool2; + +struct _Eina_Mempool2 +{ + int item_size; + int pool_size; + int usage; + void *first, *last; +}; + +void *_mempool2_malloc(Eina_Mempool2 *pool, int size) +{ + return malloc(size); +} +void _mempool2_free(Eina_Mempool2 *pool, void *ptr) +{ + free(ptr); +} +void *_mempool2_calloc(Eina_Mempool2 *pool, int size) +{ + return calloc(1, size); +} + +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 +}; + +/** + * @defgroup Eina_List_Data_Group Linked List Creation Functions + * + * Functions that add data to an Eina_List. + */ + +/** + * Appends the given data to the given linked list. + * + * 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); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * @endcode + * + * @param list The given list. If @c NULL is given, then a new list + * is created. + * @param data The data to append. + * @return A new list pointer that should be used in place of the one + * given to this function if successful. Otherwise, the old + * pointer is returned. + * @ingroup Eina_List_Data_Group + */ +EAPI Eina_List * +eina_list_append(Eina_List *list, const void *data) +{ + Eina_List *l, *new_l; + + _eina_list_alloc_error = 0; + new_l = _mempool2_malloc(&_eina_list_mempool, sizeof(Eina_List)); + if (!new_l) + { + _eina_list_alloc_error = 1; + return list; + } + new_l->next = NULL; + new_l->data = (void *)data; + if (!list) + { + new_l->prev = NULL; + new_l->accounting = _mempool2_malloc(&_eina_list_accounting_mempool, sizeof(Eina_List_Accounting)); + if (!new_l->accounting) + { + _eina_list_alloc_error = 1; + _mempool2_free(&_eina_list_mempool, new_l); + return list; + } + new_l->accounting->last = new_l; + new_l->accounting->count = 1; + return new_l; + } + l = list->accounting->last; + l->next = new_l; + new_l->prev = l; + new_l->accounting = list->accounting; + list->accounting->last = new_l; + list->accounting->count++; + return list; +} + +/** + * Prepends the given data to the given linked list. + * + * 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); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * @endcode + * + * @param list The given list. + * @param data The given data. + * @return A new list pointer that should be used in place of the one + * given to this function, if successful. Otherwise, the old + * pointer is returned. + * @ingroup Eina_List_Data_Group + */ +EAPI Eina_List * +eina_list_prepend(Eina_List *list, const void *data) +{ + Eina_List *new_l; + + _eina_list_alloc_error = 0; + new_l = _mempool2_malloc(&_eina_list_mempool, sizeof(Eina_List)); + if (!new_l) + { + _eina_list_alloc_error = 1; + return list; + } + new_l->prev = NULL; + new_l->data = (void *)data; + if (!list) + { + new_l->next = NULL; + new_l->accounting = _mempool2_malloc(&_eina_list_accounting_mempool, sizeof(Eina_List_Accounting)); + if (!new_l->accounting) + { + _eina_list_alloc_error = 1; + _mempool2_free(&_eina_list_mempool, new_l); + return list; + } + new_l->accounting->last = new_l; + new_l->accounting->count = 1; + return new_l; + } + new_l->next = list; + list->prev = new_l; + new_l->accounting = list->accounting; + list->accounting->count++; + return new_l; +} + +/** + * Inserts the given data into the given linked list after the specified data. + * + * If @p relative is not in the list, @p data is appended to the end of the + * list. If there are multiple instances of @p relative in the list, + * @p data is inserted after the first instance. + * + * 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); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * list = eina_list_append_relative(list, my_data, relative_member); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * @endcode + * + * @param list The given linked list. + * @param data The given data. + * @param relative The data to insert after. + * @return A new list pointer that should be used in place of the one + * given to this function if successful. Otherwise, the old pointer + * is returned. + * @ingroup Eina_List_Data_Group + */ +EAPI Eina_List * +eina_list_append_relative(Eina_List *list, const void *data, const void *relative) +{ + Eina_List *l; + + for (l = list; l; l = l->next) + { + if (l->data == relative) + return eina_list_append_relative_list(list, data, l); + } + return eina_list_append(list, data); +} + +EAPI Eina_List * +eina_list_append_relative_list(Eina_List *list, const void *data, Eina_List *relative) +{ + Eina_List *new_l; + + if ((!list) || (!relative)) return eina_list_append(list, data); + _eina_list_alloc_error = 0; + new_l = _mempool2_malloc(&_eina_list_mempool, sizeof(Eina_List)); + if (!new_l) + { + _eina_list_alloc_error = 1; + return list; + } + new_l->data = (void *)data; + if (relative->next) + { + new_l->next = relative->next; + relative->next->prev = new_l; + } + else + new_l->next = NULL; + + relative->next = new_l; + new_l->prev = relative; + new_l->accounting = list->accounting; + list->accounting->count++; + if (!new_l->next) + new_l->accounting->last = new_l; + return list; +} + +/** + * Prepend a data pointer to a linked list before the memeber specified + * @param list The list handle to prepend @p data too + * @param data The data pointer to prepend to list @p list before @p relative + * @param relative The data pointer before which to insert @p data + * @return A new list handle to replace the old one + + * Inserts the given data into the given linked list before the member + * specified. + * + * If @p relative is not in the list, @p data is prepended to the + * start of the list. If there are multiple instances of @p relative + * in the list, @p data is inserted before the first instance. + * + * 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); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * list = eina_list_prepend_relative(list, my_data, relative_member); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * @endcode + * + * @param list The given linked list. + * @param data The given data. + * @param relative The data to insert before. + * @return A new list pointer that should be used in place of the one + * given to this function if successful. Otherwise the old pointer + * is returned. + * @ingroup Eina_List_Data_Group + */ +EAPI Eina_List * +eina_list_prepend_relative(Eina_List *list, const void *data, const void *relative) +{ + Eina_List *l; + + _eina_list_alloc_error = 0; + for (l = list; l; l = l->next) + { + if (l->data == relative) + return eina_list_prepend_relative_list(list, data, l); + } + return eina_list_prepend(list, data); +} + +EAPI Eina_List * +eina_list_prepend_relative_list(Eina_List *list, const void *data, Eina_List *relative) +{ + Eina_List *new_l; + + if ((!list) || (!relative)) return eina_list_prepend(list, data); + _eina_list_alloc_error = 0; + new_l = _mempool2_malloc(&_eina_list_mempool, sizeof(Eina_List)); + if (!new_l) + { + _eina_list_alloc_error = 1; + return list; + } + new_l->data = (void *)data; + new_l->prev = relative->prev; + new_l->next = relative; + if (relative->prev) relative->prev->next = new_l; + relative->prev = new_l; + new_l->accounting = list->accounting; + list->accounting->count++; + if (new_l->prev) + return list; + return new_l; +} + +/** + * @defgroup Eina_List_Remove_Group Linked List Remove Functions + * + * Functions that remove data from linked lists. + */ + +/** + * Removes the first instance of the specified data from the given list. + * + * If the specified data is not in the given list, nothing is done. + * + * @param list The given list. + * @param data The specified data. + * @return A new list pointer that should be used in place of the one + * passed to this functions. + * @ingroup Eina_List_Remove_Group + */ +EAPI Eina_List * +eina_list_remove(Eina_List *list, const void *data) +{ + Eina_List *l; + + for (l = list; l; l = l->next) + { + if (l->data == data) + return eina_list_remove_list(list, l); + } + return list; +} + +/** + * Removes the specified data + * + * Remove a specified member from a list + * @param list The list handle to remove @p remove_list from + * @param remove_list The list node which is to be removed + * @return A new list handle to replace the old one + * + * Calling this function takes the list node @p remove_list and removes it + * from the list @p list, freeing the list node structure @p remove_list. + * + * Example: + * @code + * extern Eina_List *list; + * Eina_List *l; + * extern void *my_data; + * + * for (l = list; l; l= l->next) + * { + * if (l->data == my_data) + * { + * list = eina_list_remove_list(list, l); + * break; + * } + * } + * @endcode + * @ingroup Eina_List_Remove_Group + */ +EAPI Eina_List * +eina_list_remove_list(Eina_List *list, Eina_List *remove_list) +{ + Eina_List *return_l; + + if (!list) return NULL; + if (!remove_list) return list; + if (remove_list->next) remove_list->next->prev = remove_list->prev; + if (remove_list->prev) + { + remove_list->prev->next = remove_list->next; + return_l = list; + } + else + return_l = remove_list->next; + if (remove_list == list->accounting->last) + list->accounting->last = remove_list->prev; + list->accounting->count--; + if (list->accounting->count == 0) + _mempool2_free(&_eina_list_accounting_mempool, list->accounting); + _mempool2_free(&_eina_list_mempool, remove_list); + return return_l; +} + +/** + * Moves the specified data to the head of the list + * + * Move a specified member to the head of the list + * @param list The list handle to move @p inside + * @param move_list The list node which is to be moved + * @return A new list handle to replace the old one + * + * Calling this function takes the list node @p move_list and moves it + * to the front of the @p list. + * + * Example: + * @code + * extern Eina_List *list; + * Eina_List *l; + * extern void *my_data; + * + * for (l = list; l; l= l->next) + * { + * if (l->data == my_data) + * { + * list = eina_list_promote_list(list, l); + * break; + * } + * } + * @endcode + * @ingroup Eina_List_Promote_Group + */ +EAPI Eina_List * +eina_list_promote_list(Eina_List *list, Eina_List *move_list) +{ + Eina_List *return_l; + + if (!list) return NULL; + if (!move_list) return list; + if (move_list == list) return list; + if (move_list->next) move_list->next->prev = move_list->prev; + if (move_list->prev) + { + move_list->prev->next = move_list->next; + return_l = list; + } + else + return_l = move_list->next; + if (move_list == list->accounting->last) + list->accounting->last = move_list->prev; + move_list->prev = return_l->prev; + if (return_l->prev) + return_l->prev->next = move_list; + return_l->prev = move_list; + move_list->next = return_l; + return move_list; +} + + + +/** + * @defgroup Eina_List_Find_Group Linked List Find Functions + * + * Functions that find specified data in a linked list. + */ + +/** + * Find a member of a list and return the member + * @param list The list handle to search for @p data + * @param data The data pointer to find in the list @p list + * @return The found member data pointer + * + * A call to this function will search the list @p list from beginning to end + * for the first member whose data pointer is @p data. If it is found, @p data + * will be returned, otherwise NULL will be returned. + * + * Example: + * @code + * extern Eina_List *list; + * extern void *my_data; + * + * if (eina_list_find(list, my_data) == my_data) + * { + * printf("Found member %p\n", my_data); + * } + * @endcode + * @ingroup Eina_List_Find_Group + */ +EAPI void * +eina_list_find(const Eina_List *list, const void *data) +{ + const Eina_List *l; + + for (l = list; l; l = l->next) + { + if (l->data == data) return (void *)data; + } + return NULL; +} + +/** + * Find a member of a list and return the list node containing that member + * @param list The list handle to search for @p data + * @param data The data pointer to find in the list @p list + * @return The found members list node + * + * A call to this function will search the list @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 will be returned, otherwise NULL + * will be returned. + * + * Example: + * @code + * extern Eina_List *list; + * extern void *my_data; + * Eina_List *found_node; + * + * found_node = eina_list_find_list(list, my_data); + * if (found_node) + * { + * printf("Found member %p\n", found_node->data); + * } + * @endcode + * @ingroup Eina_List_Find_Group + */ +EAPI Eina_List * +eina_list_find_list(const Eina_List *list, const void *data) +{ + const Eina_List *l; + + for (l = list; l; l = l->next) + { + if (l->data == data) return (Eina_List *)l; + } + return NULL; +} + +/** + * Free an entire list and all the nodes, ignoring the data contained + * @param list The list to free + * @return A NULL pointer + * + * This function will free all the list nodes in list specified by @p list. + * + * Example: + * @code + * extern Eina_List *list; + * + * list = eina_list_free(list); + * @endcode + * @ingroup Eina_List_Remove_Group + */ +EAPI Eina_List * +eina_list_free(Eina_List *list) +{ + Eina_List *l, *free_l; + + if (!list) return NULL; + _mempool2_free(&_eina_list_accounting_mempool, list->accounting); + for (l = list; l;) + { + free_l = l; + l = l->next; + _mempool2_free(&_eina_list_mempool, free_l); + } + return NULL; +} + +/** + * @defgroup Eina_List_Traverse_Group Linked List Traverse Functions + * + * Functions that you can use to traverse a linked list. + */ + +/** + * Get the last list node in the list + * @param list The list to get the last list node from + * @return The last list node in the list @p list + * + * This function will return the last list node in the list (or NULL if the + * list is empty). + * + * NB: This is a order-1 operation (it takes the same short time regardless of + * the length of the list). + * + * Example: + * @code + * extern Eina_List *list; + * Eina_List *last, *l; + * + * last = eina_list_last(list); + * printf("The list in reverse:\n"); + * for (l = last; l; l = l->prev) + * { + * printf("%p\n", l->data); + * } + * @endcode + * @ingroup Eina_List_Traverse_Group + */ +EAPI Eina_List * +eina_list_last(const Eina_List *list) +{ + if (!list) return NULL; + return list->accounting->last; +} + +/** + * Get the next list node after the specified list node + * @param list The list node to get the next list node from + * @return The next list node, or NULL if no next list node exists + * + * This function returns the next list node after the current one. It is + * equivalent to list->next. + * + * Example: + * @code + * extern Eina_List *list; + * Eina_List *l; + * + * printf("The list:\n"); + * for (l = list; l; l = eina_list_next(l)) + * { + * printf("%p\n", l->data); + * } + * @endcode + * @ingroup Eina_List_Traverse_Group + */ +EAPI Eina_List * +eina_list_next(const Eina_List *list) +{ + if (!list) return NULL; + return list->next; +} + +/** + * Get the previous list node before the specified list node + * @param list The list node to get the previous list node from + * @return The previous list node, or NULL if no previous list node exists + * + * This function returns the previous list node before the current one. It is + * equivalent to list->prev. + * + * Example: + * @code + * extern Eina_List *list; + * Eina_List *last, *l; + * + * last = eina_list_last(list); + * printf("The list in reverse:\n"); + * for (l = last; l; l = eina_list_prev(l)) + * { + * printf("%p\n", l->data); + * } + * @endcode + * @ingroup Eina_List_Traverse_Group + */ +EAPI Eina_List * +eina_list_prev(const Eina_List *list) +{ + if (!list) return NULL; + return list->prev; +} + +/** + * @defgroup Eina_List_General_Group Linked List General Functions + * + * Miscellaneous functions that work on linked lists. + */ + +/** + * Get the list node data member + * @param list The list node to get the data member of + * @return The data member from the list node @p list + * + * This function returns the data member of the specified list node @p list. + * It is equivalent to list->data. + * + * Example: + * @code + * extern Eina_List *list; + * Eina_List *l; + * + * printf("The list:\n"); + * for (l = list; l; l = eina_list_next(l)) + * { + * printf("%p\n", eina_list_data(l)); + * } + * @endcode + * @ingroup Eina_List_General_Group + */ +EAPI void * +eina_list_data(const Eina_List *list) +{ + if (!list) return NULL; + return list->data; +} + +/** + * Get the count of the number of items in a list + * @param list The list whose count to return + * @return The number of members in the list @p list + * + * This function returns how many members in the specified list: @p list. If + * the list is empty (NULL), 0 is returned. + * + * NB: This is an order-1 operation and takes the same tiem regardless of the + * length of the list. + * + * Example: + * @code + * extern Eina_List *list; + * + * printf("The list has %i members\n", eina_list_count(list)); + * @endcode + * @ingroup Eina_List_General_Group + */ +EAPI int +eina_list_count(const Eina_List *list) +{ + if (!list) return 0; + return list->accounting->count; +} + +/** + * Get the nth member's data pointer in a list + * @param list The list to get member number @p n from + * @param n The number of the element (0 being the first) + * @return The data pointer stored in the specified element + * + * This function returns the data pointer of element number @p n, in the list + * @p list. The first element in the array is element number 0. If the element + * number @p n does not exist, NULL will be returned. + * + * Example: + * @code + * extern Eina_List *list; + * extern int number; + * void *data; + * + * data = eina_list_nth(list, number); + * if (data) + * printf("Element number %i has data %p\n", number, data); + * @endcode + * @ingroup Eina_List_Find_Group + */ +EAPI void * +eina_list_nth(const Eina_List *list, int n) +{ + Eina_List *l; + + l = eina_list_nth_list(list, n); + return l ? l->data : NULL; +} + +/** + * Get the nth member's list node in a list + * @param list The list to get member number @p n 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 the list + * @p list. The first element in the array is element number 0. If the element + * number @p n does not exist, NULL will be returned. + * + * Example: + * @code + * extern Eina_List *list; + * extern int number; + * Eina_List *nth_list; + * + * nth_list = eina_list_nth_list(list, number); + * if (nth_list) + * printf("Element number %i has data %p\n", number, nth_list->data); + * @endcode + * @ingroup Eina_List_Find_Group + */ +EAPI Eina_List * +eina_list_nth_list(const Eina_List *list, int n) +{ + int i; + const Eina_List *l; + + /* check for non-existing nodes */ + if ((!list) || (n < 0) || + (n > (list->accounting->count - 1))) + return NULL; + + /* 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)) + { + for (i = list->accounting->count - 1, + l = list->accounting->last; + l; + l = l->prev, i--) + { + if (i == n) return (Eina_List *)l; + } + } + else + { + for (i = 0, l = list; l; l = l->next, i++) + { + if (i == n) return (Eina_List *)l; + } + } + return NULL; +} + +/** + * @defgroup Eina_List_Ordering_Group Linked List Ordering Functions + * + * Functions that change the ordering of data in a linked list. + */ + +/** + * Reverse all the elements in the list + * @param list The list to reverse + * @return The list after it has been reversed + * + * This takes a list @p list, and reverses the order of all elements in the + * list, so the last member is now first, and so on. + * + * Example: + * @code + * extern Eina_List *list; + * + * list = eina_list_reverse(list); + * @endcode + * @ingroup Eina_List_Ordering_Group + */ +EAPI Eina_List * +eina_list_reverse(Eina_List *list) +{ + Eina_List *l1, *l2; + + if (!list) return NULL; + l1 = list; + l2 = list->accounting->last; + while (l1 != l2) + { + void *data; + + data = l1->data; + l1->data = l2->data; + l2->data = data; + l1 = l1->next; + if (l1 == l2) break; + l2 = l2->prev; + } + + return list; +} + +/** + * 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 + * @param func A function pointer that can handle comparing the list data + * nodes + * @return A new sorted list + * + * This function sorts your list. The data in your nodes can be arbitrary, + * you just have to be smart enough to know what kind of data is in your + * lists + * + * 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 *list; + * + * list = eina_list_sort(list, eina_list_count(list), sort_cb); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List Sorting failed.\n"); + * exit(-1); + * } + * @endcode + * @ingroup Eina_List_Ordering_Group + */ +EAPI Eina_List * +eina_list_sort(Eina_List *list, int size, int (*func)(void *, void *)) +{ + Eina_List* last; + unsigned int list_number; + unsigned int middle; + int list_size; + + if (!list || !func) + return NULL; + + /* if the caller specified an invalid size, sort the whole list */ + if ((size <= 0) || + (size > list->accounting->count)) + size = list->accounting->count; + + last = list->accounting->last; + middle = size - size / 2; + + for (list_number = middle, list_size = 1; + list_size < middle * 2; + list_number >>= 1, list_size <<= 1) + { + Eina_List *head1 = list; + unsigned int limit = size; + unsigned int process_list; + unsigned int pass_number; + unsigned int split_size = list_size; + + for (process_list = 0; process_list < list_number + 1; ++process_list) + { + Eina_List *head2; + unsigned int size_sum; + int size1, size2; + int i; + + size1 = limit < split_size ? limit : split_size; + limit -= size1; + + size2 = limit < split_size ? limit : split_size; + limit -= size2; + + size_sum = size1 + size2; + + for (head2 = head1, i = 0; i < size1; ++i) + head2 = eina_list_next (head2); + + for (pass_number = 0; pass_number < size_sum; ++pass_number) + { + Eina_List *next; + Eina_List *prev1; + Eina_List *prev2; + + if (size1 == 0 || head1 == NULL) /* List1 is empty, head1 is already at the end of the list. So only need to update head2 */ + { + for (; pass_number < size_sum; ++pass_number) + head2 = eina_list_next (head2); + break; + } + else + if (size2 == 0 || head2 == NULL) /* List2 is empty, just leave */ + break; + else + if (func (head1->data, head2->data) < 0) + { + head1 = eina_list_next (head1); + --size1; + } + else + { + next = eina_list_next (head2); + prev1 = eina_list_prev (head1); + prev2 = eina_list_prev (head2); + + if (next) + next->prev = prev2; + if (prev1) + prev1->next = head2; + if (prev2) + prev2->next = next; + + head2->prev = prev1; + head2->next = head1; + head1->prev = head2; + + --size2; + + if (head1 == list) + list = head2; + if (head2 == last) + last = prev2; + + head2 = next; + } + } + head1 = head2; + } + } + + list->accounting->last = last; + return list; +} +/** + * Return the memory allocation failure flag after any operation needin allocation + * @return The state of the allocation flag + * + * This function returns the state of the memory allocation flag. This flag is + * set if memory allocations during eina_list_append(), eina_list_prepend(), + * eina_list_append_relative(), or eina_list_prepend_relative() fail. If they + * do fail, 1 will be returned, otherwise 0 will be returned. The flag will + * remain in its current state until the next call that requires allocation + * is called, and is then reset. + * + * Example: + * @code + * Eina_List *list = NULL; + * extern void *my_data; + * + * list = eina_list_append(list, my_data); + * if (eina_list_alloc_error()) + * { + * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n"); + * exit(-1); + * } + * @endcode + * @ingroup Eina_List_General_Group + */ +EAPI int +eina_list_alloc_error(void) +{ + return _eina_list_alloc_error; +} diff --git a/legacy/eina/src/lib/eina_mempool.c b/legacy/eina/src/lib/eina_mempool.c new file mode 100644 index 0000000000..7d377e74e0 --- /dev/null +++ b/legacy/eina/src/lib/eina_mempool.c @@ -0,0 +1,151 @@ +#include "Eina.h" +#include "eina_private.h" +/*============================================================================* + * Local * + *============================================================================*/ +static Eina_List *_modules; +static int _init_count = 0; + +struct _Eina_Mempool +{ +#ifdef DEBUG + unsigned int magic; +#endif + Eina_Module *module; + Eina_Mempool_Backend *backend; + void *backend_data; +}; +static Eina_Mempool * _new_from_buffer(const char *name, void *buffer, + unsigned int size, const char *options, va_list args) +{ + Eina_List *l; + + /* load the module with filename == name */ + for (l = _modules; l; l = eina_list_next(l)) + { + Eina_Module *m; + + m = eina_list_data(l); + /* check if the requested module name exists */ + if (!strncmp(eina_module_name_get(m), name, strlen(name))) + { + Eina_Mempool *mp; + + mp = malloc(sizeof(Eina_Mempool)); + eina_module_load(m); + mp->module = m; + mp->backend = eina_module_symbol_get(m, "mp_backend"); + mp->backend_data = mp->backend->init(buffer, size, options, args); + + return mp; + } + } + return NULL; +} +/*============================================================================* + * API * + *============================================================================*/ +/** + * + */ +EAPI int eina_mempool_init(void) +{ + if (!_init_count) + { + _modules = eina_module_list_get("/usr/local/lib/eina/mm_policies", 0, NULL, NULL); + } + /* get all the modules */ + return ++_init_count; +} +/** + * + */ +EAPI int eina_mempool_shutdown(void) +{ + if (!_init_count) + return _init_count; + _init_count--; + if (!_init_count) + { + /* remove the list of modules */ + eina_module_list_free(_modules); + } + return _init_count; +} +/** + * + */ +EAPI Eina_Mempool * eina_mempool_new_from_buffer(const char *name, void *buffer, + unsigned int size, const char *options, ...) +{ + Eina_Mempool *mp; + va_list args; + + assert(name); + assert(buffer); + + va_start(args, options); + mp = _new_from_buffer(name, buffer, size, options, args); + va_end(args); + + return mp; +} +/** + * + */ +EAPI Eina_Mempool * eina_mempool_new(const char *name, unsigned int size, const char + *options, ...) +{ + Eina_Mempool *mp; + void *buffer; + va_list args; + + assert(name); + + buffer = malloc(sizeof(char) * size); + va_start(args, options); + mp = _new_from_buffer(name, buffer, size, options, args); + va_end(args); + + return mp; +} +/** + * + */ +EAPI void eina_mempool_delete(Eina_Mempool *mp) +{ + Eina_List *l; + + assert(mp); + + mp->backend->shutdown(mp->backend_data); + eina_module_unload(mp->module); + free(mp); +} +/** + * + */ +EAPI void * eina_mempool_realloc(Eina_Mempool *mp, void *element, unsigned int size) +{ + +} +/** + * + */ +EAPI void * eina_mempool_alloc(Eina_Mempool *mp, unsigned int size) +{ + assert(mp); + assert(mp->backend->alloc); + + return mp->backend->alloc(mp->backend_data, size); +} +/** + * + */ +EAPI void eina_mempool_free(Eina_Mempool *mp, void *element) +{ + assert(mp); + assert(mp->backend->free); + + mp->backend->free(mp->backend_data, element); +} diff --git a/legacy/eina/src/lib/eina_module.c b/legacy/eina/src/lib/eina_module.c new file mode 100644 index 0000000000..11f38fff0b --- /dev/null +++ b/legacy/eina/src/lib/eina_module.c @@ -0,0 +1,280 @@ +#include "Eina.h" +#include "eina_private.h" + +#include +#include +#include +/*============================================================================* + * Local * + *============================================================================*/ +struct _Eina_Module +{ +#ifdef DEBUG + unsigned int magic; +#endif + void *handle; + char *file; +}; + +#define MODULE_EXTENSION ".so" + + +typedef struct _Dir_List_Get_Cb_Data +{ + Eina_Module_Cb cb; + void *data; + Eina_List *list; +} Dir_List_Get_Cb_Data; + +typedef struct _Dir_List_Cb_Data +{ + Eina_Module_Cb cb; + void *data; +} Dir_List_Cb_Data; + +static int _dir_list_get_cb(Eina_Module *m, void *data) +{ + Dir_List_Get_Cb_Data *cb_data = data; + int ret = 1; + + if (cb_data->cb) + { + ret = cb_data->cb(m, cb_data->data); + } + if (ret) + { + cb_data->list = eina_list_append(cb_data->list, m); + } +} + +static void _dir_list_cb(const char *name, const char *path, void *data) +{ + Dir_List_Cb_Data *cb_data = data; + int length; + + length = strlen(name); + if (length < strlen(MODULE_EXTENSION) + 1) /* x.so */ + return; + if (!strcmp(name + length - strlen(MODULE_EXTENSION), + MODULE_EXTENSION)) + { + char file[PATH_MAX]; + Eina_Module *m; + + snprintf(file, PATH_MAX, "%s/%s", path, name); + m = eina_module_new(file); + if (!m) + return; + /* call the user provided cb on this module */ + cb_data->cb(m, cb_data->data); + } +} +/*============================================================================* + * API * + *============================================================================*/ +/** + * Calls the cb function for every module found on the directory path + * + * @param path The directory's path to search for modules + * @param recursive Iterate recursively on the path + * @param cb Callback function to call + * @param data Data passed to the callback function + */ +EAPI void eina_module_list(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data) +{ + Dir_List_Cb_Data cb_data; + + assert(path); + + cb_data.cb = cb; + cb_data.data = data; + eina_file_dir_list(path, recursive, &_dir_list_cb, &cb_data); +} +/** + * Gets a list of modules found on the directory path + * + * @param path The directory's path to search for modules + * @param recursive Iterate recursively on the path + * @param cb Callback function to call, if the return value of the callback is zero + * it won't be added to the list, if it is one, it will. + * @param data Data passed to the callback function + */ +EAPI Eina_List * eina_module_list_get(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data) +{ + Dir_List_Get_Cb_Data list_get_cb_data; + Dir_List_Cb_Data list_cb_data; + + assert(path); + + list_get_cb_data.list = NULL; + list_get_cb_data.cb = cb; + list_get_cb_data.data = data; + + list_cb_data.cb = &_dir_list_get_cb; + list_cb_data.data = &list_get_cb_data; + + eina_file_dir_list(path, recursive, &_dir_list_cb, &list_cb_data); + + return list_get_cb_data.list; +} +/** + * Load every module on the list of modules + * @param list The list of modules + */ +EAPI void eina_module_list_load(Eina_List *list) +{ + Eina_List *l; + + for (l = list; l; l = eina_list_next(l)) + { + Eina_Module *m; + + m = eina_list_data(l); + eina_module_load(m); + } +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void eina_module_list_unload(Eina_List *list) +{ + Eina_List *l; + + for (l = list; l; l = eina_list_next(l)) + { + Eina_Module *m; + + m = eina_list_data(l); + eina_module_unload(m); + } +} +/** + * Helper function that iterates over the list of modules and calls + * eina_module_delete on each + * + */ +EAPI void eina_module_list_free(Eina_List *list) +{ + Eina_List *l; + + for (l = list; l; l = eina_list_next(l)) + { + Eina_Module *m; + + m = eina_list_data(l); + eina_module_free(m); + } +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI int eina_module_load(Eina_Module *m) +{ + void *dl_handle; + + assert(m); + + if (m->handle) return 1; + + dl_handle = dlopen(m->file, RTLD_LAZY); + if (!dl_handle) return 0; + + m->handle = dl_handle; + return 1; +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI Eina_Module * eina_module_new(const char *file) +{ + Eina_Module *m; + + assert(file); + /* TODO check that the file exists */ + + m = malloc(sizeof(Eina_Module)); +#ifdef DEBUG + /* TODO add the magic */ +#endif + m->file = strdup(file); + m->handle = NULL; + + return m; +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void eina_module_free(Eina_Module *m) +{ + assert(m); + +#ifdef DEBUG + /* TODO check the magic */ +#endif + if (m->handle) + eina_module_unload(m); + free(m->file); + free(m); +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void eina_module_unload(Eina_Module *m) +{ + assert(m); +#ifdef DEBUG + /* TODO check the magic */ +#endif + if (!m->handle) + return; + dlclose(m->handle); +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI void * eina_module_symbol_get(Eina_Module *m, const char *symbol) +{ + assert(m); +#ifdef DEBUG + /* TODO check the magic */ +#endif + return dlsym(m->handle, symbol); +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI char * eina_module_path_get(Eina_Module *m) +{ + char *path; + + assert(m); +#ifdef DEBUG + /* TODO check the magic */ +#endif + eina_file_path_nth_get(m->file, -1, &path, NULL); + + return path; +} +/** + * To be documented + * FIXME: To be fixed + */ +EAPI char * eina_module_name_get(Eina_Module *m) +{ + char *name; + + assert(m); +#ifdef DEBUG + /* TODO check the magic */ +#endif + eina_file_path_nth_get(m->file, -1, NULL, &name); + + return name; +} diff --git a/legacy/eina/src/lib/eina_value.c b/legacy/eina/src/lib/eina_value.c new file mode 100644 index 0000000000..6a5a4aca1b --- /dev/null +++ b/legacy/eina/src/lib/eina_value.c @@ -0,0 +1,46 @@ +/* eina_value.c + +Copyright (C) 2001 Christopher Rosendahl + Nathan Ingersoll + +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 documentation and acknowledgment shall be +given in the documentation and software packages that this Software was +used. + +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. + +*/ + +#include "Eina.h" +#include "eina_private.h" + +EAPI const unsigned int eina_prime_table[] = +{ + 17, 31, 61, 127, 257, 509, 1021, + 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, + 2097143, 4194301, 8388617, 16777213 +}; + +inline void eina_print_warning(const char *function, const char *sparam) +{ + fprintf(stderr, "***** Developer Warning ***** :\n" + "\tThis program is calling:\n\n" + "\t%s();\n\n" + "\tWith the parameter:\n\n" + "\t%s\n\n" + "\tbeing NULL. Please fix your program.\n", function, sparam); + fflush(stderr); +} diff --git a/legacy/eina/src/modules/Makefile.am b/legacy/eina/src/modules/Makefile.am new file mode 100644 index 0000000000..38cd2048d3 --- /dev/null +++ b/legacy/eina/src/modules/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = mm_policies + +MAINTAINERCLEANFILES = \ +Makefile.in \ No newline at end of file diff --git a/legacy/eina/src/modules/mm_policies/Makefile.am b/legacy/eina/src/modules/mm_policies/Makefile.am new file mode 100644 index 0000000000..6e0b57f924 --- /dev/null +++ b/legacy/eina/src/modules/mm_policies/Makefile.am @@ -0,0 +1,23 @@ +MAINTAINERCLEANFILES = \ +Makefile.in + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/include + +controllerdir = $(libdir)/eina/mm_policies +controller_LTLIBRARIES = fixed.la ememoa.la + +fixed_la_SOURCES = \ +fixed.c + +fixed_la_LIBADD = $(top_builddir)/src/lib/libeina.la +fixed_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +fixed_la_DEPENDENCIES = $(top_builddir)/src/lib/libeina.la + +ememoa_la_SOURCES = \ +ememoa.c + +ememoa_la_LIBADD = $(top_builddir)/src/lib/libeina.la +ememoa_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +ememoa_la_DEPENDENCIES = $(top_builddir)/src/lib/libeina.la diff --git a/legacy/eina/src/modules/mm_policies/ememoa.c b/legacy/eina/src/modules/mm_policies/ememoa.c new file mode 100644 index 0000000000..58874ad2f8 --- /dev/null +++ b/legacy/eina/src/modules/mm_policies/ememoa.c @@ -0,0 +1,830 @@ +#include "Eina.h" +#include "eina_private.h" + +#include "mempool_struct.h" +/*============================================================================* + * Local * + *============================================================================*/ +#define EMEMOA_MAGIC 0xDEAD5007 + +#ifdef DEBUG +#define EMEMOA_CHECK_MAGIC(Memory) \ + assert(Memory->magic == EMEMOA_MAGIC); +#else +#define EMEMOA_CHECK_MAGIC(Memory) ; +#endif + +static int total = 0; + +/** + * @defgroup Ememoa_Mempool_Base_64m Static buffer allocator. + * + */ + +/** + * Global context for the static buffer allocator. + * @ingroup Ememoa_Mempool_Base_64m + * TODO this context is mempool relative + */ +//static struct ememoa_memory_base_s *base_64m = NULL; + +/** + * Remove an item from the base_64m free block list. + * + * @param index Item to be removed. + * @return Will never fail. + * @ingroup Ememoa_Mempool_Base_64m + */ +static void ememoa_memory_base_remove_from_list(struct ememoa_memory_base_s *base_64m, uint16_t index) +{ + uint16_t prev = base_64m->chunks[index].prev; + uint16_t next = base_64m->chunks[index].next; + + if (prev != 0xFFFF) + base_64m->chunks[prev].next = next; + if (next != 0xFFFF) + base_64m->chunks[next].prev = prev; + if (base_64m->start == index) + base_64m->start = next; + if (base_64m->over == index) + base_64m->over = prev; + + base_64m->chunks[index].prev = 0xFFFF; + base_64m->chunks[index].next = 0xFFFF; +} + +/** + * Insert an item in the base_64m free block list. + * + * @param index Item to be inserted. + * @return Will break completely if the item is already in the list. + * @ingroup Ememoa_Mempool_Base_64m + */ +static void ememoa_memory_base_insert_in_list(struct ememoa_memory_base_s *base_64m, uint16_t index) +{ + uint16_t length = base_64m->chunks[index].length; + uint16_t prev = 0xFFFF; + uint16_t next; + + if (base_64m->chunks[index].start == 0xFFFF) + return; + + for (next = base_64m->start; next != 0xFFFF + && base_64m->chunks[next].length > length; next + = base_64m->chunks[next].next) + prev = next; + + assert(index != next); + assert(index != prev); + + base_64m->chunks[index].next = next; + base_64m->chunks[index].prev = prev; + + if (next != 0xFFFF) + base_64m->chunks[next].prev = index; + else + base_64m->over = index; + + if (prev != 0xFFFF) + base_64m->chunks[prev].next = index; + else + base_64m->start = index; +} + +/** + * Merge two chunk of memory together. Choose the index of the resulting + * chunk as the one requiring less effort for committing the change. No + * requirement on parameters order or any other characteristic exist. + * + * @param one First part of the chunk to be merged. + * @param two Second part of the chunk to be merged. + * @return Index of the new chunk. + * @ingroup Ememoa_Mempool_Base_64m + */ +static uint16_t ememoa_memory_base_merge_64m(struct ememoa_memory_base_s *base_64m, uint16_t one, uint16_t two) +{ + uint16_t index; + uint16_t tmp; + + if (base_64m->chunks[one].length < base_64m->chunks[two].length) + { + tmp = one; + one = two; + two = tmp; + } + + /* All page refering to 'two' now refere to 'one'. */ + for (index = base_64m->chunks[two].start; index + != base_64m->chunks[two].end; ++index) + base_64m->pages[index] = one; + base_64m->pages[index] = one; + + if (base_64m->chunks[one].start < base_64m->chunks[two].start) + base_64m->chunks[one].end = base_64m->chunks[two].end; + else + base_64m->chunks[one].start = base_64m->chunks[two].start; + + base_64m->chunks[one].length += base_64m->chunks[two].length; + + base_64m->chunks[two].start = 0xFFFF; + base_64m->chunks[two].use = 0; + if (base_64m->jump > two) + base_64m->jump = two; + + return one; +} + +/** + * Split a chunk in two, allocating a new one on the fly and doing as few as possible + * memory update. The new allocated chunk could be used as the left or right part of + * the splitted chunk depending on the fastest strategie. You will need to guess by your + * self what was our choice. + * + * @param index The item to split. + * @param length The required size for one of the two resulting chunk. + * @return 0xFFFF, if the chunk already has the right size otherwise the new allocated chunk. + * @ingroup Ememoa_Mempool_Base_64m + */ +static uint16_t ememoa_memory_base_split_64m(struct ememoa_memory_base_s *base_64m, uint16_t index, unsigned int length) +{ + if (base_64m->chunks[index].length != length) + { + struct ememoa_memory_base_chunck_s a; + struct ememoa_memory_base_chunck_s b; + uint16_t i; + uint16_t splitted; + + while (!(base_64m->chunks[base_64m->jump].start == 0xFFFF + && base_64m->chunks[base_64m->jump].prev + == 0xFFFF + && base_64m->chunks[base_64m->jump].next + == 0xFFFF)) + base_64m->jump++; + + splitted = base_64m->jump++; + ememoa_memory_base_remove_from_list(base_64m, index); + + a = base_64m->chunks[index]; + + b.length = a.length - length; + b.end = a.end; + b.start = a.start + length; + b.next = 0xFFFF; + b.prev = 0xFFFF; + b.use = 0; + + a.length = length; + a.end = a.start + length - 1; + a.use = 1; + + if (a.length < b.length) + { + base_64m->chunks[index] = b; + base_64m->chunks[splitted] = a; + ememoa_memory_base_insert_in_list(base_64m, index); + } else + { + base_64m->chunks[index] = a; + base_64m->chunks[splitted] = b; + ememoa_memory_base_insert_in_list(base_64m, splitted); + } + + for (i = base_64m->chunks[splitted].start; i + != base_64m->chunks[splitted].end; ++i) + base_64m->pages[i] = splitted; + base_64m->pages[i] = splitted; + + return splitted; + } + return 0xFFFF; +} + +/** + * @defgroup Ememoa_Mempool_Base_Resize_List Function enabling manipulation of array with linked list properties. + * + */ +#define RESIZE_POOL_SIZE 128 +struct ememoa_memory_base_resize_list_pool_s { + struct ememoa_memory_base_resize_list_pool_s *next; + + unsigned int count; +#ifdef USE64 + uint64_t map[2]; +#else + uint32_t map[4]; +#endif + struct ememoa_memory_base_resize_list_s array[RESIZE_POOL_SIZE]; +}; + +static struct ememoa_memory_base_resize_list_pool_s *resize_pool = NULL; +#if 0 + +/** + * Allocate a new resizable list (it's an array now). It currently use to much memory + * when using the base_64m allocator, it could be fixed if really usefull (Not high priority at this time). + * + * @param size items size inside the list. + * @return Will return a pointer to the base array. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +struct ememoa_memory_base_resize_list_s* ememoa_memory_base_resize_list_new( + unsigned int size) +{ + struct ememoa_memory_base_resize_list_s *tmp; + struct ememoa_memory_base_resize_list_pool_s *over; + unsigned int i; + int pos; + + if (size == 0) + return NULL; + + for (over = resize_pool; over && over->count == RESIZE_POOL_SIZE; over + = over->next) + ; + + if (!over) + { + over + = ememoa_memory_base_alloc(sizeof(struct ememoa_memory_base_resize_list_pool_s)); + if (!over) + return NULL; + + over->next = resize_pool; + over->count = 0; + +#ifdef USE64 + for (i = 0; i < 2; ++i) +#else + for (i = 0; i < 4; ++i) +#endif + over->map[i] = ~0; + + resize_pool = over; + } + +#ifdef USE64 + for (i = 0, pos = 0; i < 2 && pos == 0; ++i) +#else + for (i = 0, pos = 0; i < 4 && pos == 0; ++i) +#endif +#ifdef USE64 + pos = ffsll (over->map[i]); +#else + pos = ffs(over->map[i]); +#endif + + over->count++; + pos--; + i--; + +#ifdef USE64 + assert(i >= 0 && i < 2); + assert(pos >= 0 && pos < 64); + tmp = over->array + pos + i * 64; +#else + assert(i >= 0 && i < 4); + assert(pos >= 0 && pos < 32); + tmp = over->array + pos + i * 32; +#endif + + over->map[i] &= ~(1 << pos); + + bzero(tmp, sizeof(struct ememoa_memory_base_resize_list_s)); + tmp->size = size; + +#ifdef DEBUG + tmp->magic = EMEMOA_MAGIC; +#endif + + return tmp; +} +#endif +/** + * Clean a list and all it's item. + * + * @param base List + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +void ememoa_memory_base_resize_list_clean( + struct ememoa_memory_base_resize_list_s* base) +{ + struct ememoa_memory_base_resize_list_pool_s *over; + int index; + + if (!base) + return; + + EMEMOA_CHECK_MAGIC(base); + + ememoa_memory_base_free(base->pool); + ememoa_memory_base_free(base->bitmap); + +#ifdef DEBUG + if (base->actif != 0) + fprintf(stderr, "Warning some element where not freed from this list.\n"); +#endif + +#ifdef DEBUG + base->magic = 0; +#endif + + for (over = resize_pool; over && !(over->array <= base && base + < over->array + RESIZE_POOL_SIZE); over = over->next) + ; + + assert(over != NULL); + + index = base - over->array; + +#ifdef USE64 + over->map[index / 64] |= (1 << (index % 64)); +#else + over->map[index / 32] |= (1 << (index % 32)); +#endif +} +#if 0 +/** + * Allocate a new item in the list "base". + * + * @param base Pointer to a valid and activ list. + * @return Will return the new item index. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +int ememoa_memory_base_resize_list_new_item( + struct ememoa_memory_base_resize_list_s *base) +{ + int i; + + if (base == NULL) + return -1; + + EMEMOA_CHECK_MAGIC(base); + + if (base->count < base->actif + 1) + { + unsigned int count; + uint32_t *tmp_bitmap; + void *tmp_pool; + + count = base->count + 32; + + tmp_pool = ememoa_memory_base_realloc(base->pool, count + * base->size); + if (!tmp_pool) + return -1; + base->pool = tmp_pool; + + tmp_bitmap = ememoa_memory_base_realloc(base->bitmap, (count + >> 5) * sizeof(uint32_t)); + if (!tmp_bitmap) + return -1; + base->bitmap = tmp_bitmap; + + base->bitmap[base->count >> 5] = 0xFFFFFFFF; + +#ifdef DEBUG + memset ((uint8_t*) tmp_pool + base->count * base->size, 43, base->size * 32); +#endif + base->count = count; + + } + + for (; base->jump < (base->count >> 5) && base->bitmap[base->jump] == 0; ++base->jump) + ; + + assert(base->jump < (base->count >> 5)); + + i = ffs(base->bitmap[base->jump]) - 1; + + assert(i >= 0 && i < 32); + + base->bitmap[base->jump] &= ~(1 << i); + base->actif++; + + return (base->jump << 5) + i; +} +#endif +/** + * Give the pointer corresponding to an item index. + * + * @param base Pointer to a valid and activ list. + * @param index Item index given by ememoa_memory_base_resize_list_new_item. + * @return Will return a pointer to the item. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +void* ememoa_memory_base_resize_list_get_item( + struct ememoa_memory_base_resize_list_s *base, int index) +{ + EMEMOA_CHECK_MAGIC(base); + + if (index < 0) + return NULL; + + return (void*) ((uint8_t*) base->pool + index * base->size); +} + +/** + * Give back an item to the list. + * + * @param base Pointer to a valid and activ list. + * @param index Item index given by ememoa_memory_base_resize_list_new_item. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +void ememoa_memory_base_resize_list_back( + struct ememoa_memory_base_resize_list_s *base, int index) +{ + unsigned int shift; + unsigned int i; + + EMEMOA_CHECK_MAGIC(base); + + if (index < 0) + return; + + shift = index >> 5; + i = index & 0x1F; + + base->bitmap[shift] |= (1 << i); + base->actif--; + + if (shift < base->jump) + base->jump = shift; + +#ifdef DEBUG + memset ((uint8_t*) base->pool + base->size * index, 44, base->size); +#endif +} +#if 0 +/** + * Make some attempt to resize the size of the list. + * + * @param base Pointer to a valid and activ list. + * @return Will 0 is nothing where freed, -1 if not enought memory + * is available for the operation and anything else if successfull. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +int ememoa_memory_base_resize_list_garbage_collect( + struct ememoa_memory_base_resize_list_s *base) +{ + uint32_t *tmp_bitmap; + void *tmp_pool; + unsigned int count; + + EMEMOA_CHECK_MAGIC(base); + + count = base->count; + + for (; base->count > 0 && base->bitmap[(base->count >> 5)] == 0xFFFFFFFF; base->count -= 32) + ; + + tmp_pool = ememoa_memory_base_realloc(base->pool, base->count + * base->size); + if (!tmp_pool) + return -1; + base->pool = tmp_pool; + + tmp_bitmap = ememoa_memory_base_realloc(base->bitmap, + (base->count >> 5) * sizeof(uint32_t)); + if (!tmp_bitmap) + return -1; + base->bitmap = tmp_bitmap; + + return count != base->count; +} +#endif +/** + * Call fct on all allocated item of the list and return the sum of fct result. + * + * @param base Pointer to a valid and activ list. + * @param start Index to start at. + * @param end Index to end the walk. + * @param fct The callback function. + * @param ctx An obscure pointer that will be directly passed, without any + * check/change to each fct call. + * @return Will return the sum of fct result. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +int ememoa_memory_base_resize_list_walk_over( + struct ememoa_memory_base_resize_list_s *base, int start, + int end, int (*fct)(void *ctx, int index, void *data), void *ctx) +{ + int bitmap; + int first; + int end_shift; + int end_i; + int shift; + int i; + int result = 0; + + EMEMOA_CHECK_MAGIC(base); + + i = start & 0x1F; + + if (end < 0) + end = base->count - 1; + + if (end == -1) + return 0; + + end_shift = end >> 5; + end_i = end & 0x1F; + + for (shift = start >> 5; shift < end_shift; ++shift) + { + bitmap = ~base->bitmap[shift]; + first = ffs(bitmap) - 1; + + i = i > first ? i : first; + for (bitmap >>= i; i < 32; ++i, bitmap >>= 1, ++start) + if (bitmap & 0x1) + result += fct(ctx, start, base->pool + start + * base->size); + i = 0; + } + + bitmap = ~base->bitmap[shift]; + for (bitmap >>= i; i < end_i; ++i, bitmap >>= 1, ++start) + if (bitmap & 0x1) + result += fct(ctx, start, base->pool + start + * base->size); + + return result; +} + +/** + * Call fct as long as fct doesn't return a value different from 0. + * + * @param base Pointer to a valid and activ list. + * @param start Index to start at. + * @param end Index to end the walk. + * @param fct The callback function. + * @param ctx An obscure pointer that will be directly passed, without any + * check/change to each fct call. + * @param index If different from NULL, put the index on which we stop in it. + * @return Will return a pointer to the item where we stop the search. + * @ingroup Ememoa_Mempool_Base_Resize_List + */ +void* ememoa_memory_base_resize_list_search_over( + struct ememoa_memory_base_resize_list_s *base, int start, + int end, int (*fct)(void *ctx, int index, void *data), void *ctx, + int *index) +{ + int bitmap; + int first; + int end_shift; + int end_i; + int shift; + int i; + + EMEMOA_CHECK_MAGIC(base); + + i = start & 0x1F; + + if (end < 0) + end = base->count - 1; + + if (end == -1) + return NULL; + + end_shift = end >> 5; + end_i = end & 0x1F; + + for (shift = start >> 5; shift < end_shift; ++shift) + { + bitmap = ~base->bitmap[shift]; + first = ffs(bitmap) - 1; + + i = i > first ? i : first; + for (bitmap >>= i; i < 32; ++i, bitmap >>= 1, ++start) + if (bitmap & 0x1) + if (fct(ctx, start, base->pool + start + * base->size)) + goto found; + i = 0; + } + + bitmap = ~base->bitmap[shift]; + for (bitmap >>= i; i < end_i; ++i, bitmap >>= 1, ++start) + if (bitmap & 0x1) + if (fct(ctx, start, base->pool + start * base->size)) + goto found; + + if (index) + *index = 0; + return NULL; + + found: if (index) + *index = start; + return base->pool + start * base->size; +} + +static void ememoa_free(void *data, void *element) +{ + struct ememoa_memory_base_s *base_64m = data; + unsigned int delta = element - base_64m->base; + uint16_t index; + uint16_t chunk_index; + uint16_t prev_chunk_index; + uint16_t next_chunk_index; + + if (element == NULL) + return; + + assert(element > base_64m->base); + + index = delta >> 12; + chunk_index = base_64m->pages[index]; + + total -= base_64m->chunks[chunk_index].length; +#ifdef ALLOC_REPORT + fprintf(stderr, "free %i [%i] => %p\n", base_64m->chunks[chunk_index].length, total << 12, ptr); +#endif + + prev_chunk_index = base_64m->pages[index - 1]; + next_chunk_index + = base_64m->pages[base_64m->chunks[chunk_index].end + 1]; + + if (index > 0 && prev_chunk_index < base_64m->chunks_count) + if (base_64m->chunks[prev_chunk_index].use == 0) + { + ememoa_memory_base_remove_from_list(base_64m, prev_chunk_index); + chunk_index = ememoa_memory_base_merge_64m(base_64m, chunk_index, + prev_chunk_index); + } + + if (base_64m->chunks[chunk_index].end < base_64m->chunks_count + && next_chunk_index < base_64m->chunks_count) + if (base_64m->chunks[next_chunk_index].use == 0) + { + ememoa_memory_base_remove_from_list(base_64m, next_chunk_index); + chunk_index = ememoa_memory_base_merge_64m(base_64m, chunk_index, + next_chunk_index); + } + + ememoa_memory_base_insert_in_list(base_64m, chunk_index); + base_64m->chunks[chunk_index].use = 0; +} +static void * ememoa_alloc(void *data, unsigned int size) +{ + struct ememoa_memory_base_s *base_64m = data; + uint16_t real = (size >> 12) + (size & 0xFFF ? 1 : 0); + uint16_t jump = base_64m->start; + uint16_t prev = 0xFFFF; + + while (jump != 0xFFFF && base_64m->chunks[jump].length > real) + { + prev = jump; + jump = base_64m->chunks[jump].next; + } + + if (prev != 0xFFFF) + { + uint16_t splitted = ememoa_memory_base_split_64m(base_64m, prev, real); + uint16_t allocated; + uint16_t empty; + + /* Guess who is who */ + allocated = base_64m->chunks[prev].use == 1 ? prev : splitted; + empty = base_64m->chunks[prev].use == 1 ? splitted : prev; + + total += real; +#ifdef ALLOC_REPORT + fprintf(stderr, "alloc %i(%i) [%i] => %p\n", real << 12, size, total << 12, ((uint8_t*) base_64m->base) + (base_64m->chunks[allocated].start << 12)); +#endif + return ((uint8_t*) base_64m->base) + + (base_64m->chunks[allocated].start << 12); + } + return NULL; +} + +static void *ememoa_realloc(void *data, void *element, unsigned int size) +{ + struct ememoa_memory_base_s *base_64m = data; + void* tmp; + unsigned int delta = element - base_64m->base; + uint16_t real = (size >> 12) + (size & 0xFFF ? 1 : 0); + uint16_t index; + uint16_t chunk_index; + uint16_t next_chunk_index; + + if (element == NULL) + return ememoa_alloc(base_64m, size); + + assert(element > base_64m->base); + + index = delta >> 12; + chunk_index = base_64m->pages[index]; + + /* FIXME: Not resizing when the size is big enough */ + if (real <= base_64m->chunks[chunk_index].length) + return element; + + next_chunk_index + = base_64m->pages[base_64m->chunks[chunk_index].end + 1]; + + if (base_64m->chunks[next_chunk_index].use == 0) + if (real <= base_64m->chunks[next_chunk_index].length + + base_64m->chunks[chunk_index].length) + { + uint16_t splitted; + uint16_t allocated; + int tmp; + + total -= base_64m->chunks[chunk_index].length; + tmp = base_64m->chunks[chunk_index].length; + + ememoa_memory_base_remove_from_list(base_64m, next_chunk_index); + chunk_index = ememoa_memory_base_merge_64m(base_64m, chunk_index, + next_chunk_index); + splitted = ememoa_memory_base_split_64m(base_64m, chunk_index, + real); + + allocated + = base_64m->chunks[chunk_index].use + == 1 ? chunk_index + : splitted; + + ememoa_memory_base_remove_from_list(base_64m, allocated); + + total += real; +#ifdef ALLOC_REPORT + fprintf(stderr, "realloc %i(%i) [%i] => %p\n", (real - tmp) << 12, size, total << 12, ((uint8_t*) base_64m->base) + (base_64m->chunks[allocated].start << 12)); +#endif + + return ((uint8_t*) base_64m->base) + + (base_64m->chunks[allocated].start + << 12); + } + + tmp = ememoa_alloc(base_64m, size); + if (!tmp) + return NULL; + + memcpy(tmp, element, base_64m->chunks[chunk_index].length << 12); + ememoa_memory_base_free_64m(element); + + return tmp; +} + +static void *ememoa_init(void *buffer, unsigned int size, const char *options, va_list args) +{ + struct ememoa_memory_base_s *new_64m = buffer; + unsigned int temp_size; + + temp_size = (size - sizeof(struct ememoa_memory_base_s)) >> 12; + if (temp_size <= 1) + { + /* TODO handle an error */ + return NULL; + } + +#ifdef DEBUG + new_64m->magic = EMEMOA_MAGIC; +#endif + new_64m->chunks + = (struct ememoa_memory_base_chunck_s*) ((struct ememoa_memory_base_s*) new_64m + + 1); + new_64m->pages + = (uint16_t*)((struct ememoa_memory_base_chunck_s*) new_64m->chunks + + temp_size + 1); + new_64m->base = ((uint16_t*) new_64m->pages + temp_size + 1); + new_64m->start = 0; + + new_64m->chunks_count + = (size - sizeof(struct ememoa_memory_base_s) + - temp_size + * (sizeof(struct ememoa_memory_base_chunck_s) + + sizeof(uint16_t))) + / 4096; + + memset(new_64m->chunks, 0xFF, + sizeof(struct ememoa_memory_base_chunck_s) * temp_size); + memset(new_64m->pages, 0, sizeof(uint16_t) * temp_size); + + new_64m->chunks[0].start = 0; + new_64m->chunks[0].end = new_64m->chunks_count - 1; + new_64m->chunks[0].length = new_64m->chunks_count; + new_64m->chunks[0].next = 0xFFFF; + new_64m->chunks[0].prev = 0xFFFF; + new_64m->chunks[0].use = 0; + new_64m->over = 0; + new_64m->start = 0; + new_64m->jump = 1; + + return new_64m; +} + +static void ememoa_shutdown(void *data) +{ + +} +/*============================================================================* + * API * + *============================================================================*/ +Eina_Mempool_Backend mp_backend = { + .init = &ememoa_init, + .shutdown = &ememoa_shutdown, + .realloc = &ememoa_realloc, + .alloc = &ememoa_alloc, + .free = &ememoa_free, +}; diff --git a/legacy/eina/src/modules/mm_policies/ememoa_memory_base.h b/legacy/eina/src/modules/mm_policies/ememoa_memory_base.h new file mode 100644 index 0000000000..516bbc539d --- /dev/null +++ b/legacy/eina/src/modules/mm_policies/ememoa_memory_base.h @@ -0,0 +1,54 @@ +/* +** Copyright Cedric BAIL, 2006 +** contact: cedric.bail@free.fr +** +*/ + +#ifndef EMEMOA_MEMORY_BASE_H__ +# define EMEMOA_MEMORY_BASE_H__ + +#include + +struct ememoa_memory_base_resize_list_s +{ +#ifdef DEBUG + unsigned int magic; +#endif + + void *pool; + uint32_t *bitmap; + + unsigned int jump; + unsigned int count; + unsigned int actif; + unsigned int size; +}; + +/* Direct use of this two function is most of the time a bad idea. */ +//extern void* (*ememoa_memory_base_alloc)(unsigned int size); +//extern void (*ememoa_memory_base_free)(void *ptr); +//extern void* (*ememoa_memory_base_realloc)(void* ptr, unsigned int size); + +int ememoa_memory_base_init_64m(void* buffer, unsigned int size); + +struct ememoa_memory_base_resize_list_s* ememoa_memory_base_resize_list_new (unsigned int size); +void ememoa_memory_base_resize_list_clean (struct ememoa_memory_base_resize_list_s* base); +int ememoa_memory_base_resize_list_new_item (struct ememoa_memory_base_resize_list_s *base); +void* ememoa_memory_base_resize_list_get_item (struct ememoa_memory_base_resize_list_s *base, int index); +void ememoa_memory_base_resize_list_back (struct ememoa_memory_base_resize_list_s *base, int index); +int ememoa_memory_base_resize_list_walk_over (struct ememoa_memory_base_resize_list_s *base, + int start, + int end, + int (*fct)(void *ctx, int index, void *data), + void *ctx); +void* ememoa_memory_base_resize_list_search_over (struct ememoa_memory_base_resize_list_s *base, + int start, + int end, + int (*fct)(void *ctx, int index, void *data), + void *ctx, + int *index); + +/* Be carefull when you call this function, you will loose all index mapping after this call. */ +int ememoa_memory_base_resize_list_garbage_collect (struct ememoa_memory_base_resize_list_s *base); + +#endif /* EMEMOA_MEMORY_BASE_H__ */ diff --git a/legacy/eina/src/modules/mm_policies/ememoa_mempool_error.h b/legacy/eina/src/modules/mm_policies/ememoa_mempool_error.h new file mode 100644 index 0000000000..ca4c8f377a --- /dev/null +++ b/legacy/eina/src/modules/mm_policies/ememoa_mempool_error.h @@ -0,0 +1,29 @@ +/* +** Copyright Cedric BAIL, 2006 +** contact: cedric.bail@free.fr +** +*/ + +#ifndef EMEMOA_MEMPOOL_ERROR_H__ +# define EMEMOA_MEMPOOL_ERROR_H__ + +typedef enum _ememoa_mempool_error_e + { + EMEMOA_NO_ERROR, + EMEMOA_ERROR_INIT_ALREADY_DONE, + EMEMOA_ERROR_REALLOC_AVAILABLE_OBJECTS_FAILED, + EMEMOA_ERROR_REALLOC_OBJECTS_USE_FAILED, + EMEMOA_ERROR_REALLOC_JUMP_OBJECT_FAILED, + EMEMOA_ERROR_REALLOC_OBJECTS_POOL_FAILED, + EMEMOA_ERROR_MALLOC_NEW_POOL, + EMEMOA_ERROR_PUSH_ADDRESS_NOT_FOUND, + EMEMOA_NO_EMPTY_POOL, + EMEMOA_DOUBLE_PUSH, + EMEMOA_NO_MORE_MEMORY, + EMEMOA_INVALID_MEMPOOL + } ememoa_mempool_error_t; + +const char* +ememoa_mempool_error2string (ememoa_mempool_error_t error_code); + +#endif /* EMEMOA_MEMPOOL_ERROR_H__ */ diff --git a/legacy/eina/src/modules/mm_policies/fixed.c b/legacy/eina/src/modules/mm_policies/fixed.c new file mode 100644 index 0000000000..0f37954738 --- /dev/null +++ b/legacy/eina/src/modules/mm_policies/fixed.c @@ -0,0 +1,29 @@ +#include "Eina.h" +#include "eina_private.h" + +static void push(void *data, void *element) +{ + +} +static void * pop(void *data, unsigned int size) +{ + return NULL; +} + +static void *init(unsigned int size) +{ + return NULL; +} + +static void shutdown(void *data) +{ + +} + +Eina_Mempool_Backend mp_backend = { + .init = &init, + .shutdown = &shutdown, + .alloc = &pop, + .free = &push, +}; + diff --git a/legacy/eina/src/modules/mm_policies/mempool_struct.h b/legacy/eina/src/modules/mm_policies/mempool_struct.h new file mode 100644 index 0000000000..2c2128a090 --- /dev/null +++ b/legacy/eina/src/modules/mm_policies/mempool_struct.h @@ -0,0 +1,50 @@ +/* +** Copyright Cedric BAIL, 2006 +** contact: cedric.bail@free.fr +** +*/ + +#ifndef MEMPOOL_STRUCT_H__ +# define MEMPOOL_STRUCT_H__ + +#include "config.h" + +#include + +#ifdef HAVE_PTHREAD +# include +#endif + +#include "ememoa_memory_base.h" +//#include "ememoa_mempool_error.h" + +struct ememoa_memory_base_chunck_s +{ + uint16_t start; + uint16_t end; + uint16_t length; + + uint16_t next; + uint16_t prev; + + uint8_t use; +}; + +struct ememoa_memory_base_s +{ +#ifdef DEBUG + unsigned int magic; +#endif + void *base; + + struct ememoa_memory_base_chunck_s *chunks; + uint16_t *pages; + + unsigned int chunks_count; + + uint16_t start; + uint16_t over; + uint16_t jump; +}; + +#endif /* MEMPOOL_STRUCT_H__ */