1 /* EINA - EFL data type library
2 * Copyright (C) 2009 Gustavo Sverzut Barbieri
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
21 * @page tutorial_matrixsparse_page Sparse Matrix Tutorial
40 #include "eina_config.h"
41 #include "eina_private.h"
42 #include "eina_error.h"
44 #include "eina_magic.h"
45 #include "eina_mempool.h"
47 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
48 #include "eina_safety_checks.h"
49 #include "eina_matrixsparse.h"
52 /*============================================================================*
54 *============================================================================*/
60 static const char EINA_MAGIC_MATRIXSPARSE_STR[] = "Eina Matrixsparse";
61 static const char EINA_MAGIC_MATRIXSPARSE_ROW_STR[] = "Eina Matrixsparse Row";
62 static const char EINA_MAGIC_MATRIXSPARSE_CELL_STR[] = "Eina Matrixsparse Cell";
63 static const char EINA_MAGIC_MATRIXSPARSE_ITERATOR_STR[] =
64 "Eina Matrixsparse Iterator";
65 static const char EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR_STR[] =
66 "Eina Matrixsparse Row Accessor";
67 static const char EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR_STR[] =
68 "Eina Matrixsparse Row Iterator";
69 static const char EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR_STR[] =
70 "Eina Matrixsparse Cell Accessor";
71 static const char EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR_STR[] =
72 "Eina Matrixsparse Cell Iterator";
75 #define EINA_MAGIC_CHECK_MATRIXSPARSE(d, ...) \
77 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE)) \
79 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE); \
84 #define EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(d, ...) \
86 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_ROW)) \
88 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_ROW); \
93 #define EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(d, ...) \
95 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_CELL)) \
97 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_CELL); \
102 #define EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(d, ...) \
104 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_MATRIXSPARSE_ITERATOR)) \
106 EINA_MAGIC_FAIL(d, EINA_MAGIC_MATRIXSPARSE_ITERATOR); \
107 return __VA_ARGS__; \
111 struct _Eina_Matrixsparse_Cell
113 Eina_Matrixsparse_Cell *next;
114 Eina_Matrixsparse_Cell *prev;
119 Eina_Matrixsparse_Row *parent;
124 struct _Eina_Matrixsparse_Row
126 Eina_Matrixsparse_Row *next;
127 Eina_Matrixsparse_Row *prev;
129 Eina_Matrixsparse_Cell *cols;
130 Eina_Matrixsparse_Cell *last_col;
131 Eina_Matrixsparse_Cell *last_used; /* fast sequential access */
134 Eina_Matrixsparse *parent;
139 struct _Eina_Matrixsparse
141 Eina_Matrixsparse_Row *rows;
142 Eina_Matrixsparse_Row *last_row;
143 Eina_Matrixsparse_Row *last_used; /* fast sequential access */
153 void (*func)(void *user_data, void *cell_data);
160 typedef struct _Eina_Matrixsparse_Iterator Eina_Matrixsparse_Iterator;
161 typedef struct _Eina_Matrixsparse_Iterator_Complete
162 Eina_Matrixsparse_Iterator_Complete;
164 struct _Eina_Matrixsparse_Iterator
166 Eina_Iterator iterator;
168 const Eina_Matrixsparse *m;
171 const Eina_Matrixsparse_Row *row;
172 const Eina_Matrixsparse_Cell *col;
178 struct _Eina_Matrixsparse_Iterator_Complete
180 Eina_Iterator iterator;
182 const Eina_Matrixsparse *m;
185 const Eina_Matrixsparse_Row *row;
186 const Eina_Matrixsparse_Cell *col;
191 unsigned long row, col;
196 Eina_Matrixsparse_Row row;
197 Eina_Matrixsparse_Cell col;
204 * @todo Eina_Matrixsparse_Row_Iterator: iterator over rows in matrix
205 * @todo Eina_Matrixsparse_Row_Accessor: accessor over rows in matrix
206 * @todo Eina_Matrixsparse_Cell_Iterator: iterator over cells in row
207 * @todo Eina_Matrixsparse_Cell_Accessor: accessor over cells in row
210 static int _eina_matrixsparse_log_dom = -1;
215 #define ERR(...) EINA_LOG_DOM_ERR(_eina_matrixsparse_log_dom, __VA_ARGS__)
220 #define DBG(...) EINA_LOG_DOM_DBG(_eina_matrixsparse_log_dom, __VA_ARGS__)
222 static Eina_Mempool *_eina_matrixsparse_cell_mp = NULL;
223 static Eina_Mempool *_eina_matrixsparse_row_mp = NULL;
226 _eina_matrixsparse_cell_free(Eina_Matrixsparse_Cell *c, void (*free_func)(
228 void *), void *user_data)
231 free_func(user_data, c->data);
233 EINA_MAGIC_SET(c, EINA_MAGIC_NONE);
234 eina_mempool_free(_eina_matrixsparse_cell_mp, c);
238 _eina_matrixsparse_cell_unlink(Eina_Matrixsparse_Cell *c)
240 Eina_Matrixsparse_Row *r = c->parent;
242 if (r->last_used == c)
245 r->last_used = c->next;
247 r->last_used = c->prev;
250 if (r->last_col == c)
251 r->last_col = c->prev;
256 if (c->next && c->prev)
258 c->next->prev = c->prev;
259 c->prev->next = c->next;
262 c->next->prev = NULL;
264 c->prev->next = NULL;
268 _eina_matrixsparse_row_cells_free(Eina_Matrixsparse_Row *r, void (*free_func)(
270 void *), void *user_data)
272 Eina_Matrixsparse_Cell *c = r->cols;
275 Eina_Matrixsparse_Cell *c_aux = c;
277 _eina_matrixsparse_cell_free(c_aux, free_func, user_data);
282 _eina_matrixsparse_row_free(Eina_Matrixsparse_Row *r, void (*free_func)(void *,
286 _eina_matrixsparse_row_cells_free(r, free_func, user_data);
287 EINA_MAGIC_SET(r, EINA_MAGIC_NONE);
288 eina_mempool_free(_eina_matrixsparse_row_mp, r);
292 _eina_matrixsparse_row_unlink(Eina_Matrixsparse_Row *r)
294 Eina_Matrixsparse *m = r->parent;
296 if (m->last_used == r)
299 m->last_used = r->next;
301 m->last_used = r->prev;
304 if (m->last_row == r)
305 m->last_row = r->prev;
310 if (r->next && r->prev)
312 r->next->prev = r->prev;
313 r->prev->next = r->next;
316 r->next->prev = NULL;
318 r->prev->next = NULL;
322 _eina_matrixsparse_row_find_parms_get(const Eina_Matrixsparse *m,
324 Eina_Matrixsparse_Row **p_r,
327 Eina_Matrixsparse_Row *r;
331 dist = row - m->rows->row;
334 if (dist > m->last_row->row - row)
336 dist = m->last_row->row - row;
343 if (m->last_used->row < row)
345 if (dist > row - m->last_used->row)
347 /* dist = row = m->last_used->row; */
352 else if (dist > m->last_used->row - row)
354 /* dist = m->last_used->row - row; */
365 _eina_matrixsparse_row_cell_find_parms_get(const Eina_Matrixsparse_Row *r,
367 Eina_Matrixsparse_Cell **p_c,
370 Eina_Matrixsparse_Cell *c;
374 dist = col - r->cols->col;
377 if (dist > r->last_col->col - col)
379 dist = r->last_col->col - col;
386 if (r->last_used->col < col)
388 if (dist > col - r->last_used->col)
390 /* dist = col = r->last_used->col; */
395 else if (dist > r->last_used->col - col)
397 /* dist = r->last_used->col - col; */
407 static inline Eina_Matrixsparse_Row *
408 _eina_matrixsparse_row_idx_get(const Eina_Matrixsparse *m, unsigned long row)
410 Eina_Matrixsparse_Row *r;
416 if (m->rows->row == row)
418 else if (m->rows->row > row)
421 if (m->last_row->row == row)
423 else if (m->last_row->row < row)
426 if ((m->last_used) && (m->last_used->row == row))
429 _eina_matrixsparse_row_find_parms_get(m, row, &r, &dir);
433 for (; r; r = r->next)
436 ((Eina_Matrixsparse *)m)->last_used = r;
439 else if (r->row > row)
445 for (; r; r = r->prev)
448 ((Eina_Matrixsparse *)m)->last_used = r;
451 else if (r->row < row)
458 static inline Eina_Matrixsparse_Cell *
459 _eina_matrixsparse_row_cell_idx_get(const Eina_Matrixsparse_Row *r,
462 Eina_Matrixsparse_Cell *c;
468 if (r->cols->col == col)
470 else if (r->cols->col > col)
473 if (r->last_col->col == col)
475 else if (r->last_col->col < col)
478 if ((r->last_used) && (r->last_used->col == col))
481 _eina_matrixsparse_row_cell_find_parms_get(r, col, &c, &dir);
485 for (; r; c = c->next)
488 ((Eina_Matrixsparse_Row *)r)->last_used = c;
491 else if (c->col > col)
497 for (; r; c = c->prev)
500 ((Eina_Matrixsparse_Row *)r)->last_used = c;
503 else if (c->col < col)
510 static inline Eina_Matrixsparse_Cell *
511 _eina_matrixsparse_cell_idx_get(const Eina_Matrixsparse *m,
515 Eina_Matrixsparse_Row *r = _eina_matrixsparse_row_idx_get(m, row);
519 return _eina_matrixsparse_row_cell_idx_get(r, col);
523 _eina_matrixsparse_row_idx_siblings_find(const Eina_Matrixsparse *m,
525 Eina_Matrixsparse_Row **p_prev,
526 Eina_Matrixsparse_Row **p_next)
528 Eina_Matrixsparse_Row *r;
531 _eina_matrixsparse_row_find_parms_get(m, row, &r, &dir);
535 for (; r; r = r->next)
545 for (; r; r = r->prev)
556 _eina_matrixsparse_row_cell_idx_siblings_find(const Eina_Matrixsparse_Row *r,
558 Eina_Matrixsparse_Cell **p_prev,
559 Eina_Matrixsparse_Cell **p_next)
561 Eina_Matrixsparse_Cell *c;
564 _eina_matrixsparse_row_cell_find_parms_get(r, col, &c, &dir);
568 for (; c; c = c->next)
578 for (; c; c = c->prev)
588 static inline Eina_Matrixsparse_Row *
589 _eina_matrixsparse_row_idx_add(Eina_Matrixsparse *m, unsigned long row)
591 Eina_Matrixsparse_Row *r = eina_mempool_malloc
592 (_eina_matrixsparse_row_mp, sizeof(Eina_Matrixsparse_Row));
603 else if (row < m->rows->row)
610 else if (row > m->last_row->row)
612 r->prev = m->last_row;
613 m->last_row->next = r;
619 Eina_Matrixsparse_Row *prev = NULL, *next = NULL;
620 _eina_matrixsparse_row_idx_siblings_find(m, row, &prev, &next);
621 assert(prev != NULL);
622 assert(next != NULL);
634 EINA_MAGIC_SET(r, EINA_MAGIC_MATRIXSPARSE_ROW);
639 static inline Eina_Matrixsparse_Cell *
640 _eina_matrixsparse_row_cell_idx_add(Eina_Matrixsparse_Row *r,
644 Eina_Matrixsparse_Cell *c = eina_mempool_malloc
645 (_eina_matrixsparse_cell_mp, sizeof(Eina_Matrixsparse_Cell));
656 else if (col < r->cols->col)
663 else if (col > r->last_col->col)
665 c->prev = r->last_col;
666 r->last_col->next = c;
672 Eina_Matrixsparse_Cell *prev = NULL, *next = NULL;
673 _eina_matrixsparse_row_cell_idx_siblings_find(r, col, &prev, &next);
674 assert(prev != NULL);
675 assert(next != NULL);
682 c->data = (void *)data;
685 EINA_MAGIC_SET(c, EINA_MAGIC_MATRIXSPARSE_CELL);
690 static inline Eina_Bool
691 _eina_matrixsparse_cell_idx_add(Eina_Matrixsparse *m,
696 Eina_Matrixsparse_Row *r = _eina_matrixsparse_row_idx_get(m, row);
698 r = _eina_matrixsparse_row_idx_add(m, row);
703 if (_eina_matrixsparse_row_cell_idx_add(r, col, data))
709 _eina_matrixsparse_row_unlink(r);
710 _eina_matrixsparse_row_free(r, m->free.func, m->free.user_data);
714 /*============================================================================*
716 *============================================================================*/
718 _eina_matrixsparse_iterator_next(Eina_Matrixsparse_Iterator *it, void **data)
720 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, EINA_FALSE);
722 /* do not touch it->idx */
727 *data = (Eina_Matrixsparse_Cell *)it->ref.col;
729 it->ref.col = it->ref.col->next;
732 it->ref.row = it->ref.row->next;
734 it->ref.col = it->ref.row->cols;
740 static Eina_Matrixsparse *
741 _eina_matrixsparse_iterator_get_container(Eina_Matrixsparse_Iterator *it)
743 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, NULL);
744 return (Eina_Matrixsparse *)it->m;
748 _eina_matrixsparse_iterator_free(Eina_Matrixsparse_Iterator *it)
750 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it);
751 EINA_MAGIC_SET(it, EINA_MAGIC_NONE);
752 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE);
757 _eina_matrixsparse_iterator_complete_next(
758 Eina_Matrixsparse_Iterator_Complete *it,
761 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, EINA_FALSE);
763 if (it->idx.row >= it->m->size.rows)
766 if (it->dummy.col.data)
767 ERR("Last iterator call changed dummy cell!");
770 (it->ref.col->col == it->idx.col) &&
771 (it->ref.row->row == it->idx.row))
773 *data = (Eina_Matrixsparse_Cell *)it->ref.col;
774 it->ref.col = it->ref.col->next;
777 it->ref.row = it->ref.row->next;
779 it->ref.col = it->ref.row->cols;
784 it->dummy.col.data = NULL;
785 it->dummy.col.col = it->idx.col;
786 it->dummy.row.row = it->idx.row;
787 *data = &it->dummy.col;
791 if (it->idx.col == it->m->size.cols)
800 static Eina_Matrixsparse *
801 _eina_matrixsparse_iterator_complete_get_container(
802 Eina_Matrixsparse_Iterator_Complete *it)
804 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it, NULL);
805 return (Eina_Matrixsparse *)it->m;
809 _eina_matrixsparse_iterator_complete_free(
810 Eina_Matrixsparse_Iterator_Complete *it)
812 EINA_MAGIC_CHECK_MATRIXSPARSE_ITERATOR(it);
814 if (it->dummy.col.data)
815 ERR("Last iterator call changed dummy cell!");
817 EINA_MAGIC_SET(it, EINA_MAGIC_NONE);
818 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_NONE);
827 /*============================================================================*
829 *============================================================================*/
833 * @brief Initialize the matrixsparse module.
835 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
837 * This function sets up the matrixsparse module of Eina. It is called by
840 * This function creates mempool to speed up matrix rows and cells
841 * management, using EINA_MEMPOOL environment variable if it is set to
842 * choose the memory pool type to use.
847 eina_matrixsparse_init(void)
849 const char *choice, *tmp;
851 _eina_matrixsparse_log_dom = eina_log_domain_register("eina_matrixsparse",
852 EINA_LOG_COLOR_DEFAULT);
853 if (_eina_matrixsparse_log_dom < 0)
855 EINA_LOG_ERR("Could not register log domain: eina_matrixsparse");
859 #ifdef EINA_DEFAULT_MEMPOOL
860 choice = "pass_through";
862 choice = "chained_mempool";
864 tmp = getenv("EINA_MEMPOOL");
868 _eina_matrixsparse_cell_mp = eina_mempool_add
872 sizeof (Eina_Matrixsparse_Cell),
874 if (!_eina_matrixsparse_cell_mp)
877 "Mempool for matrixsparse_cell cannot be allocated in matrixsparse init.");
881 _eina_matrixsparse_row_mp = eina_mempool_add
882 (choice, "matrixsparse_row", NULL, sizeof (Eina_Matrixsparse_Row), 32);
883 if (!_eina_matrixsparse_row_mp)
886 "Mempool for matrixsparse_row cannot be allocated in matrixsparse init.");
890 #define EMS(n) eina_magic_string_static_set(n, n ## _STR)
891 EMS(EINA_MAGIC_MATRIXSPARSE);
892 EMS(EINA_MAGIC_MATRIXSPARSE_ROW);
893 EMS(EINA_MAGIC_MATRIXSPARSE_CELL);
894 EMS(EINA_MAGIC_MATRIXSPARSE_ITERATOR);
895 EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ACCESSOR);
896 EMS(EINA_MAGIC_MATRIXSPARSE_ROW_ITERATOR);
897 EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ACCESSOR);
898 EMS(EINA_MAGIC_MATRIXSPARSE_CELL_ITERATOR);
904 eina_log_domain_unregister(_eina_matrixsparse_log_dom);
905 _eina_matrixsparse_log_dom = -1;
911 * @brief Shut down the matrixsparse module.
913 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
915 * This function shuts down the matrixsparse module set up by
916 * eina_matrixsparse_init(). It is called by eina_shutdown().
918 * @see eina_shutdown()
921 eina_matrixsparse_shutdown(void)
923 eina_mempool_del(_eina_matrixsparse_row_mp);
924 eina_mempool_del(_eina_matrixsparse_cell_mp);
926 eina_log_domain_unregister(_eina_matrixsparse_log_dom);
927 _eina_matrixsparse_log_dom = -1;
931 /*============================================================================*
933 *============================================================================*/
935 EAPI Eina_Matrixsparse *
936 eina_matrixsparse_new(unsigned long rows, unsigned long cols, void (*free_func)(
938 void *cell_data), const void *user_data)
940 Eina_Matrixsparse *m;
942 EINA_SAFETY_ON_FALSE_RETURN_VAL(rows > 0, NULL);
943 EINA_SAFETY_ON_FALSE_RETURN_VAL(cols > 0, NULL);
945 m = malloc(sizeof(Eina_Matrixsparse));
948 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
952 EINA_MAGIC_SET(m, EINA_MAGIC_MATRIXSPARSE);
960 m->free.func = free_func;
961 m->free.user_data = (void *)user_data;
968 eina_matrixsparse_free(Eina_Matrixsparse *m)
970 void (*free_func)(void *, void *);
973 Eina_Matrixsparse_Row *r;
978 EINA_MAGIC_CHECK_MATRIXSPARSE(m);
980 free_func = m->free.func;
981 user_data = m->free.user_data;
986 Eina_Matrixsparse_Row *r_aux = r;
988 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
991 EINA_MAGIC_SET(m, EINA_MAGIC_NONE);
996 eina_matrixsparse_size_get(const Eina_Matrixsparse *m,
1006 EINA_MAGIC_CHECK_MATRIXSPARSE(m);
1008 *rows = m->size.rows;
1011 *cols = m->size.cols;
1015 eina_matrixsparse_size_set(Eina_Matrixsparse *m,
1019 Eina_Bool update_last_used_row;
1020 Eina_Matrixsparse_Row *r;
1021 void (*free_func)(void *, void *);
1024 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1025 EINA_SAFETY_ON_FALSE_RETURN_VAL(rows > 0, 0);
1026 EINA_SAFETY_ON_FALSE_RETURN_VAL(cols > 0, 0);
1028 if ((rows == m->size.rows) && (cols == m->size.cols))
1031 update_last_used_row = ((m->last_used) && (m->last_used->row >= rows));
1032 free_func = m->free.func;
1033 user_data = m->free.user_data;
1036 while (r && r->row >= rows)
1038 Eina_Matrixsparse_Row *r_aux = r;
1040 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
1047 else if (r != m->last_row)
1053 if (update_last_used_row)
1054 m->last_used = m->last_row;
1059 Eina_Matrixsparse_Cell *c = r->last_col;
1060 Eina_Bool update_last_used_col;
1061 update_last_used_col = ((r->last_used) && (r->last_used->col >= cols));
1062 while (c && c->col >= cols)
1064 Eina_Matrixsparse_Cell *c_aux = c;
1066 _eina_matrixsparse_cell_free(c_aux, free_func, user_data);
1070 Eina_Matrixsparse_Row *r_aux = r;
1074 r->next->prev = r->prev;
1076 m->last_row = r->prev;
1079 r->prev->next = r->next;
1084 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
1085 if ((update_last_used_row) && (m->last_used == r_aux))
1090 if (c != r->last_col)
1096 if (update_last_used_col)
1097 r->last_used = r->last_col;
1103 update_last_used_row = 0;
1107 update_last_used_row = m->last_used->row > m->last_row->row;
1109 update_last_used_row = 1;
1112 if (update_last_used_row)
1113 m->last_used = m->last_row;
1115 m->size.rows = rows;
1116 m->size.cols = cols;
1121 eina_matrixsparse_cell_idx_get(const Eina_Matrixsparse *m,
1124 Eina_Matrixsparse_Cell **cell)
1126 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1127 EINA_SAFETY_ON_NULL_RETURN_VAL(cell, 0);
1129 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1130 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1131 *cell = _eina_matrixsparse_cell_idx_get(m, row, col);
1136 eina_matrixsparse_cell_data_get(const Eina_Matrixsparse_Cell *cell)
1138 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, NULL);
1143 eina_matrixsparse_data_idx_get(const Eina_Matrixsparse *m,
1147 Eina_Matrixsparse_Cell *c;
1148 EINA_MAGIC_CHECK_MATRIXSPARSE(m, NULL);
1149 c = _eina_matrixsparse_cell_idx_get(m, row, col);
1157 eina_matrixsparse_cell_position_get(const Eina_Matrixsparse_Cell *cell,
1167 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1168 EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0);
1170 *row = cell->parent->row;
1179 eina_matrixsparse_cell_data_replace(Eina_Matrixsparse_Cell *cell,
1186 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1189 *p_old = cell->data;
1191 cell->data = (void *)data;
1196 eina_matrixsparse_cell_data_set(Eina_Matrixsparse_Cell *cell, const void *data)
1198 Eina_Matrixsparse *m;
1200 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1201 EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0);
1202 EINA_MAGIC_CHECK_MATRIXSPARSE(cell->parent->parent, 0);
1204 m = cell->parent->parent;
1207 m->free.func(m->free.user_data, cell->data);
1209 cell->data = (void *)data;
1214 eina_matrixsparse_data_idx_replace(Eina_Matrixsparse *m,
1220 Eina_Matrixsparse_Cell *cell;
1225 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1226 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1227 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1229 cell = _eina_matrixsparse_cell_idx_get(m, row, col);
1233 *p_old = cell->data;
1235 cell->data = (void *)data;
1239 return _eina_matrixsparse_cell_idx_add(m, row, col, data);
1243 eina_matrixsparse_data_idx_set(Eina_Matrixsparse *m,
1248 Eina_Matrixsparse_Cell *cell;
1250 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1251 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1252 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1254 cell = _eina_matrixsparse_cell_idx_get(m, row, col);
1258 m->free.func(m->free.user_data, cell->data);
1260 cell->data = (void *)data;
1264 return _eina_matrixsparse_cell_idx_add(m, row, col, data);
1268 eina_matrixsparse_row_idx_clear(Eina_Matrixsparse *m, unsigned long row)
1270 Eina_Matrixsparse_Row *r;
1272 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1273 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1275 r = _eina_matrixsparse_row_idx_get(m, row);
1279 _eina_matrixsparse_row_unlink(r);
1280 _eina_matrixsparse_row_free(r, m->free.func, m->free.user_data);
1286 eina_matrixsparse_column_idx_clear(Eina_Matrixsparse *m, unsigned long col)
1288 Eina_Matrixsparse_Row *r;
1289 void (*free_func)(void *, void *);
1292 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1293 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1295 free_func = m->free.func;
1296 user_data = m->free.user_data;
1298 for (r = m->rows; r; )
1300 Eina_Matrixsparse_Row *r_aux = r;
1301 Eina_Matrixsparse_Cell *c;
1303 c = _eina_matrixsparse_row_cell_idx_get(r, col);
1309 if ((r_aux->cols != c) || (r_aux->last_col != c))
1311 _eina_matrixsparse_cell_unlink(c);
1312 _eina_matrixsparse_cell_free(c, free_func, user_data);
1316 _eina_matrixsparse_row_unlink(r_aux);
1317 _eina_matrixsparse_row_free(r_aux, free_func, user_data);
1325 eina_matrixsparse_cell_idx_clear(Eina_Matrixsparse *m,
1329 Eina_Matrixsparse_Cell *c;
1331 EINA_MAGIC_CHECK_MATRIXSPARSE(m, 0);
1332 EINA_SAFETY_ON_FALSE_RETURN_VAL(row < m->size.rows, 0);
1333 EINA_SAFETY_ON_FALSE_RETURN_VAL(col < m->size.cols, 0);
1335 c = _eina_matrixsparse_cell_idx_get(m, row, col);
1339 _eina_matrixsparse_cell_unlink(c);
1340 _eina_matrixsparse_cell_free(c, m->free.func, m->free.user_data);
1346 eina_matrixsparse_cell_clear(Eina_Matrixsparse_Cell *cell)
1348 Eina_Matrixsparse *m;
1350 EINA_MAGIC_CHECK_MATRIXSPARSE_CELL(cell, 0);
1351 EINA_MAGIC_CHECK_MATRIXSPARSE_ROW(cell->parent, 0);
1352 EINA_MAGIC_CHECK_MATRIXSPARSE(cell->parent->parent, 0);
1354 m = cell->parent->parent;
1356 _eina_matrixsparse_cell_unlink(cell);
1357 _eina_matrixsparse_cell_free(cell, m->free.func, m->free.user_data);
1361 EAPI Eina_Iterator *
1362 eina_matrixsparse_iterator_new(const Eina_Matrixsparse *m)
1364 Eina_Matrixsparse_Iterator *it;
1366 it = calloc(1, sizeof(*it));
1369 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1373 EINA_MAGIC_SET(it, EINA_MAGIC_MATRIXSPARSE_ITERATOR);
1374 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1377 it->ref.row = m->rows;
1378 it->ref.col = m->rows ? m->rows->cols : NULL;
1380 it->iterator.version = EINA_ITERATOR_VERSION;
1381 it->iterator.next = FUNC_ITERATOR_NEXT(_eina_matrixsparse_iterator_next);
1382 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1383 _eina_matrixsparse_iterator_get_container);
1384 it->iterator.free = FUNC_ITERATOR_FREE(_eina_matrixsparse_iterator_free);
1385 return &it->iterator;
1388 EAPI Eina_Iterator *
1389 eina_matrixsparse_iterator_complete_new(const Eina_Matrixsparse *m)
1391 Eina_Matrixsparse_Iterator_Complete *it;
1393 it = calloc(1, sizeof(*it));
1396 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1400 EINA_MAGIC_SET(it, EINA_MAGIC_MATRIXSPARSE_ITERATOR);
1401 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1406 it->ref.row = m->rows;
1407 it->ref.col = m->rows ? m->rows->cols : NULL;
1409 it->dummy.row.next = it->dummy.row.prev = NULL;
1410 it->dummy.row.cols = it->dummy.row.last_col = it->dummy.row.last_used = NULL;
1411 it->dummy.row.parent = (Eina_Matrixsparse *)m;
1412 EINA_MAGIC_SET(&it->dummy.row, EINA_MAGIC_MATRIXSPARSE_ROW);
1414 it->dummy.col.next = it->dummy.col.prev = NULL;
1415 it->dummy.col.data = NULL;
1416 it->dummy.col.parent = &it->dummy.row;
1417 EINA_MAGIC_SET(&it->dummy.col, EINA_MAGIC_MATRIXSPARSE_CELL);
1419 it->iterator.version = EINA_ITERATOR_VERSION;
1420 it->iterator.next = FUNC_ITERATOR_NEXT(
1421 _eina_matrixsparse_iterator_complete_next);
1422 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1423 _eina_matrixsparse_iterator_complete_get_container);
1424 it->iterator.free = FUNC_ITERATOR_FREE(
1425 _eina_matrixsparse_iterator_complete_free);
1426 return &it->iterator;