EFL 1.7 svn doobies
[profile/ivi/eina.git] / src / lib / eina_inarray.c
1 /* EINA - EFL data type library
2  * Copyright (C) 2012 - ProFUSION embedded systems
3  *
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.
8  *
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.
13  *
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/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "eina_config.h"
27 #include "eina_private.h"
28 #include "eina_error.h"
29 #include "eina_log.h"
30
31 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
32 #include "eina_safety_checks.h"
33 #include "eina_inarray.h"
34
35 /*============================================================================*
36 *                                  Local                                     *
37 *============================================================================*/
38
39 /**
40  * @cond LOCAL
41  */
42
43 static const char EINA_MAGIC_INARRAY_STR[] = "Eina Inline Array";
44 static const char EINA_MAGIC_INARRAY_ITERATOR_STR[] = "Eina Inline Array Iterator";
45 static const char EINA_MAGIC_INARRAY_ACCESSOR_STR[] = "Eina Inline Array Accessor";
46
47 typedef struct _Eina_Iterator_Inarray Eina_Iterator_Inarray;
48 typedef struct _Eina_Accessor_Inarray Eina_Accessor_Inarray;
49
50 struct _Eina_Iterator_Inarray
51 {
52    Eina_Iterator iterator;
53    const Eina_Inarray *array;
54    unsigned int pos;
55    EINA_MAGIC
56 };
57
58 struct _Eina_Accessor_Inarray
59 {
60    Eina_Accessor accessor;
61    const Eina_Inarray *array;
62    EINA_MAGIC
63 };
64
65 static int _eina_inarray_log_dom = -1;
66
67 #ifdef ERR
68 #undef ERR
69 #endif
70 #define ERR(...) EINA_LOG_DOM_ERR(_eina_inarray_log_dom, __VA_ARGS__)
71
72 #ifdef DBG
73 #undef DBG
74 #endif
75 #define DBG(...) EINA_LOG_DOM_DBG(_eina_inarray_log_dom, __VA_ARGS__)
76
77 #define EINA_MAGIC_CHECK_INARRAY(d, ...)                \
78   do                                                    \
79     {                                                   \
80        if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY))    \
81          {                                              \
82             EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY);     \
83             return __VA_ARGS__;                         \
84          }                                              \
85        eina_error_set(0);                               \
86     }                                                   \
87   while(0)
88
89 #define EINA_MAGIC_CHECK_INARRAY_ITERATOR(d, ...)               \
90   do                                                            \
91     {                                                           \
92        if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ITERATOR))   \
93          {                                                      \
94             EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ITERATOR);    \
95             return __VA_ARGS__;                                 \
96          }                                                      \
97        eina_error_set(0);                                       \
98     }                                                           \
99   while(0)
100
101 #define EINA_MAGIC_CHECK_INARRAY_ACCESSOR(d, ...)               \
102   do                                                            \
103     {                                                           \
104        if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_INARRAY_ACCESSOR))   \
105          {                                                      \
106             EINA_MAGIC_FAIL(d, EINA_MAGIC_INARRAY_ACCESSOR);    \
107             return __VA_ARGS__;                                 \
108          }                                                      \
109        eina_error_set(0);                                       \
110     }                                                           \
111   while(0)
112
113 static void
114 _eina_inarray_setup(Eina_Inarray *array, unsigned int member_size, unsigned int step)
115 {
116    EINA_MAGIC_SET(array, EINA_MAGIC_INARRAY);
117    array->version = EINA_ARRAY_VERSION;
118    array->member_size = member_size;
119    array->len = 0;
120    array->max = 0;
121    array->step = (step > 0) ? step : 32;
122    array->members = NULL;
123 }
124
125 static Eina_Bool
126 _eina_inarray_resize(Eina_Inarray *array, unsigned int new_size)
127 {
128    unsigned int new_max;
129    void *tmp;
130
131    if (new_size < array->max) /* don't change this behaviour as eina_inarray_pop rely on it */
132      return EINA_TRUE;
133
134    if (new_size % array->step == 0)
135      new_max = new_size;
136    else
137      new_max = ((new_size / array->step) + 1) * array->step;
138
139    tmp = realloc(array->members, new_max * array->member_size);
140    if ((!tmp) && (new_max > 0))
141      {
142         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
143         return EINA_FALSE;
144      }
145
146    array->members = tmp;
147    array->max = new_max;
148    return EINA_TRUE;
149 }
150
151 static inline void *
152 _eina_inarray_get(const Eina_Inarray *array, unsigned int position)
153 {
154    unsigned int offset = position * array->member_size;
155    return (unsigned char *)array->members + offset;
156 }
157
158 static int
159 _eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
160 {
161    const unsigned char *start, *found;
162    start = array->members;
163    found = bsearch(data, start, array->len, array->member_size, compare);
164    if (!found)
165      return -1;
166    return (found - start) / array->member_size;
167 }
168
169 static unsigned int
170 _eina_inarray_search_sorted_near(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare, int *cmp)
171 {
172    unsigned int start, last, middle;
173
174    if (array->len == 0)
175      {
176         *cmp = -1;
177         return 0;
178      }
179    else if (array->len == 1)
180      {
181         *cmp = compare(data, array->members);
182         return 0;
183      }
184
185    start = 0;
186    last = array->len - 1; /* inclusive */
187    do
188      {
189         void *p;
190         middle = start + (last - start) / 2; /* avoid overflow */
191         p = _eina_inarray_get(array, middle);
192         *cmp = compare(data, p);
193         if (*cmp == 0)
194           return middle;
195         else if (*cmp > 0)
196           start = middle + 1;
197         else if (middle > 0)
198           last = middle - 1;
199         else
200           break;
201      }
202    while (start <= last);
203    return middle;
204 }
205
206
207 static Eina_Bool
208 _eina_inarray_iterator_next(Eina_Iterator_Inarray *it, void **data)
209 {
210    EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE);
211
212    if (it->pos >= it->array->len)
213      return EINA_FALSE;
214
215    *data = _eina_inarray_get(it->array, it->pos);
216    it->pos++;
217
218    return EINA_TRUE;
219 }
220
221 static Eina_Bool
222 _eina_inarray_iterator_prev(Eina_Iterator_Inarray *it, void **data)
223 {
224    EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, EINA_FALSE);
225
226    if (it->pos == 0)
227      return EINA_FALSE;
228
229    it->pos--;
230    *data = _eina_inarray_get(it->array, it->pos);
231
232    return EINA_TRUE;
233 }
234
235 static Eina_Inarray *
236 _eina_inarray_iterator_get_container(Eina_Iterator_Inarray *it)
237 {
238    EINA_MAGIC_CHECK_INARRAY_ITERATOR(it, NULL);
239    return (Eina_Inarray *)it->array;
240 }
241
242 static void
243 _eina_inarray_iterator_free(Eina_Iterator_Inarray *it)
244 {
245    EINA_MAGIC_CHECK_INARRAY_ITERATOR(it);
246    MAGIC_FREE(it);
247 }
248
249 static Eina_Bool
250 _eina_inarray_accessor_get_at(Eina_Accessor_Inarray *it, unsigned int pos, void **data)
251 {
252    EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, EINA_FALSE);
253
254    if (pos >= it->array->len)
255      return EINA_FALSE;
256
257    *data = _eina_inarray_get(it->array, pos);
258    return EINA_TRUE;
259 }
260
261 static Eina_Inarray *
262 _eina_inarray_accessor_get_container(Eina_Accessor_Inarray *it)
263 {
264    EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it, NULL);
265    return (Eina_Inarray *)it->array;
266 }
267
268 static void
269 _eina_inarray_accessor_free(Eina_Accessor_Inarray *it)
270 {
271    EINA_MAGIC_CHECK_INARRAY_ACCESSOR(it);
272    MAGIC_FREE(it);
273 }
274
275 /**
276  * @endcond
277  */
278
279
280 /*============================================================================*
281 *                                 Global                                     *
282 *============================================================================*/
283
284 /**
285  * @internal
286  * @brief Initialize the inline array module.
287  *
288  * @return #EINA_TRUE on success, #EINA_FALSE on failure.
289  *
290  * This function sets up the inline array module of Eina. It is called
291  * by eina_init().
292  *
293  * @see eina_init()
294  */
295 Eina_Bool
296 eina_inarray_init(void)
297 {
298    _eina_inarray_log_dom = eina_log_domain_register("eina_inarray",
299                                                     EINA_LOG_COLOR_DEFAULT);
300    if (_eina_inarray_log_dom < 0)
301      {
302         EINA_LOG_ERR("Could not register log domain: eina_inarray");
303         return EINA_FALSE;
304      }
305
306 #define EMS(n) eina_magic_string_static_set(n, n ## _STR)
307    EMS(EINA_MAGIC_INARRAY);
308    EMS(EINA_MAGIC_INARRAY_ITERATOR);
309    EMS(EINA_MAGIC_INARRAY_ACCESSOR);
310 #undef EMS
311
312    return EINA_TRUE;
313 }
314
315 /**
316  * @internal
317  * @brief Shut down the inline array module.
318  *
319  * @return #EINA_TRUE on success, #EINA_FALSE on failure.
320  *
321  * This function shuts down the inline array module set up by
322  * eina_inarray_init(). It is called by eina_shutdown().
323  *
324  * @see eina_shutdown()
325  */
326 Eina_Bool
327 eina_inarray_shutdown(void)
328 {
329    eina_log_domain_unregister(_eina_inarray_log_dom);
330    _eina_inarray_log_dom = -1;
331    return EINA_TRUE;
332 }
333
334 /*============================================================================*
335 *                                   API                                      *
336 *============================================================================*/
337 EAPI Eina_Inarray *
338 eina_inarray_new(unsigned int member_size, unsigned int step)
339 {
340    Eina_Inarray *ret;
341
342    EINA_SAFETY_ON_TRUE_RETURN_VAL(member_size == 0, NULL);
343
344    ret = malloc(sizeof(*ret));
345    if (!ret)
346      {
347         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
348         return NULL;
349      }
350    eina_error_set(0);
351    _eina_inarray_setup(ret, member_size, step);
352    return ret;
353 }
354
355 EAPI void
356 eina_inarray_free(Eina_Inarray *array)
357 {
358    if (!array)
359      return;
360
361    EINA_MAGIC_CHECK_INARRAY(array);
362    free(array->members);
363    free(array);
364 }
365
366 EAPI void
367 eina_inarray_step_set(Eina_Inarray *array,
368                       unsigned int sizeof_eina_inarray,
369                       unsigned int member_size,
370                       unsigned int step)
371 {
372    EINA_SAFETY_ON_NULL_RETURN(array);
373    EINA_SAFETY_ON_TRUE_RETURN(member_size == 0);
374
375    if (sizeof (Eina_Inarray) != sizeof_eina_inarray)
376      {
377         ERR("Unknow Eina_Inarray size ! Got %i, expected %i\n",
378             sizeof_eina_inarray,
379             (int) sizeof (Eina_Inarray));
380         /* Force memory to zero to provide a small layer of security */
381         memset(array, 0, sizeof_eina_inarray);
382         return ;
383      }
384
385    _eina_inarray_setup(array, member_size, step);
386 }
387
388 EAPI void
389 eina_inarray_flush(Eina_Inarray *array)
390 {
391    EINA_MAGIC_CHECK_INARRAY(array);
392    free(array->members);
393    array->len = 0;
394    array->max = 0;
395    array->members = NULL;
396 }
397
398 EAPI int
399 eina_inarray_push(Eina_Inarray *array, const void *data)
400 {
401    void *p;
402
403    EINA_MAGIC_CHECK_INARRAY(array, -1);
404    EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
405
406    if (!_eina_inarray_resize(array, array->len + 1))
407      return -1;
408
409    p = _eina_inarray_get(array, array->len);
410    memcpy(p, data, array->member_size);
411
412    array->len++;
413    return array->len - 1;
414 }
415
416 EAPI int
417 eina_inarray_insert(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
418 {
419    const unsigned char *itr, *itr_end;
420    unsigned int sz;
421
422    EINA_MAGIC_CHECK_INARRAY(array, -1);
423    EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
424    EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
425
426    sz = array->member_size;
427    itr = array->members;
428    itr_end = itr + array->len * sz;
429    for (; itr < itr_end; itr += sz)
430      {
431       unsigned int offset, position;
432       int cmp = compare(itr, data);
433       if (cmp <= 0)
434         continue;
435
436       offset = itr - (unsigned char *)array->members;
437       position = offset / sz;
438       if (!eina_inarray_insert_at(array, position, data))
439         return -1;
440       return position;
441    }
442    return eina_inarray_push(array, data);
443 }
444
445 EAPI int
446 eina_inarray_insert_sorted(Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
447 {
448    unsigned int pos;
449    int cmp;
450
451    EINA_MAGIC_CHECK_INARRAY(array, -1);
452    EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
453    EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
454
455    pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp);
456    if (cmp > 0)
457      pos++;
458
459    if (!eina_inarray_insert_at(array, pos, data))
460      return -1;
461    return pos;
462 }
463
464 EAPI int
465 eina_inarray_remove(Eina_Inarray *array, const void *data)
466 {
467    const unsigned char *itr, *itr_end;
468    unsigned int position, sz;
469
470    EINA_MAGIC_CHECK_INARRAY(array, -1);
471    EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
472
473    sz = array->member_size;
474    if ((data >= array->members) &&
475        (data < _eina_inarray_get(array, array->len)))
476      {
477         unsigned int offset = ((unsigned char *)data -
478                                (unsigned char *)array->members);
479         position = offset / sz;
480         goto found;
481      }
482
483    itr = array->members;
484    itr_end = itr + array->len * sz;
485    for (; itr < itr_end; itr += sz)
486      {
487         if (memcmp(data, itr, sz) == 0)
488           {
489              unsigned int offset = itr - (unsigned char *)array->members;
490              position = offset / sz;
491              goto found;
492           }
493      }
494    return -1;
495
496 found:
497    if (!eina_inarray_remove_at(array, position))
498      return -1;
499    return position;
500 }
501
502 EAPI void *
503 eina_inarray_pop(Eina_Inarray *array)
504 {
505    EINA_MAGIC_CHECK_INARRAY(array, NULL);
506    EINA_SAFETY_ON_TRUE_RETURN_VAL(array->len == 0, NULL);
507    if (!_eina_inarray_resize(array, array->len - 1))
508      return NULL;
509    array->len--;
510    return _eina_inarray_get(array, array->len + 1);
511 }
512
513 EAPI void *
514 eina_inarray_nth(const Eina_Inarray *array, unsigned int position)
515 {
516    EINA_MAGIC_CHECK_INARRAY(array, NULL);
517    EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, NULL);
518    return _eina_inarray_get(array, position);
519 }
520
521 EAPI Eina_Bool
522 eina_inarray_insert_at(Eina_Inarray *array, unsigned int position, const void *data)
523 {
524    unsigned int sz;
525    unsigned char *p;
526
527    EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
528    EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, EINA_FALSE);
529
530    if (!_eina_inarray_resize(array, array->len + 1))
531      return EINA_FALSE;
532
533    p = _eina_inarray_get(array, position);
534    sz = array->member_size;
535    if (array->len > position)
536      memmove(p + sz, p, (array->len - position) * sz);
537    memcpy(p, data, sz);
538
539    array->len++;
540    return EINA_TRUE;
541 }
542
543 EAPI void *
544 eina_inarray_alloc_at(Eina_Inarray *array, unsigned int position, unsigned int member_count)
545 {
546    unsigned int sz;
547    unsigned char *p;
548
549    EINA_MAGIC_CHECK_INARRAY(array, NULL);
550    EINA_SAFETY_ON_TRUE_RETURN_VAL(position > array->len, NULL);
551    EINA_SAFETY_ON_TRUE_RETURN_VAL(member_count == 0, NULL);
552
553    if (!_eina_inarray_resize(array, array->len + member_count))
554      return NULL;
555
556    p = _eina_inarray_get(array, position);
557    sz = array->member_size;
558    if (array->len > position)
559      memmove(p + member_count * sz, p, (array->len - position) * sz);
560
561    array->len += member_count;
562    return p;
563 }
564
565 EAPI Eina_Bool
566 eina_inarray_replace_at(Eina_Inarray *array, unsigned int position, const void *data)
567 {
568    unsigned char *p;
569
570    EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
571    EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE);
572
573    p = _eina_inarray_get(array, position);
574    memcpy(p, data, array->member_size);
575
576    return EINA_TRUE;
577 }
578
579 EAPI Eina_Bool
580 eina_inarray_remove_at(Eina_Inarray *array, unsigned int position)
581 {
582    EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
583    EINA_SAFETY_ON_TRUE_RETURN_VAL(position >= array->len, EINA_FALSE);
584
585    if (position + 1 < array->len)
586      {
587         unsigned int sz = array->member_size;
588         unsigned char *p = _eina_inarray_get(array, position);
589         memmove(p, p + sz, (array->len - position - 1) * sz);
590      }
591
592    _eina_inarray_resize(array, array->len - 1);
593    array->len--;
594    return EINA_TRUE;
595 }
596
597 EAPI void
598 eina_inarray_reverse(Eina_Inarray *array)
599 {
600    size_t sz;
601    unsigned char *fwd, *rev, *fwd_end;
602    void *tmp;
603
604    EINA_MAGIC_CHECK_INARRAY(array);
605
606    if (array->len < 2)
607      return;
608
609    sz = array->member_size;
610
611    tmp = alloca(sz);
612    EINA_SAFETY_ON_NULL_RETURN(tmp);
613
614    fwd = array->members;
615    fwd_end = fwd + (array->len / 2) * sz;
616
617    rev = fwd + (array->len - 1) * sz;
618
619    for (; fwd < fwd_end; fwd += sz, rev -= sz)
620      {
621         memcpy(tmp, fwd, sz);
622         memcpy(fwd, rev, sz);
623         memcpy(rev, tmp, sz);
624      }
625 }
626
627 EAPI void
628 eina_inarray_sort(Eina_Inarray *array, Eina_Compare_Cb compare)
629 {
630    EINA_MAGIC_CHECK_INARRAY(array);
631    EINA_SAFETY_ON_NULL_RETURN(compare);
632    qsort(array->members, array->len, array->member_size, compare);
633 }
634
635 EAPI int
636 eina_inarray_search(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
637 {
638    EINA_MAGIC_CHECK_INARRAY(array, -1);
639    EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
640    EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
641    return _eina_inarray_search(array, data, compare);
642 }
643
644 EAPI int
645 eina_inarray_search_sorted(const Eina_Inarray *array, const void *data, Eina_Compare_Cb compare)
646 {
647    unsigned int pos;
648    int cmp;
649
650    EINA_MAGIC_CHECK_INARRAY(array, -1);
651    EINA_SAFETY_ON_NULL_RETURN_VAL(data, -1);
652    EINA_SAFETY_ON_NULL_RETURN_VAL(compare, -1);
653
654    pos = _eina_inarray_search_sorted_near(array, data, compare, &cmp);
655    if (cmp == 0)
656      return pos;
657    return -1;
658 }
659
660 EAPI Eina_Bool
661 eina_inarray_foreach(const Eina_Inarray *array, Eina_Each_Cb function, const void *user_data)
662 {
663    unsigned char *itr, *itr_end;
664    unsigned int sz;
665    Eina_Bool ret = EINA_TRUE;
666
667    EINA_MAGIC_CHECK_INARRAY(array, EINA_FALSE);
668    EINA_SAFETY_ON_NULL_RETURN_VAL(function, EINA_FALSE);
669
670    sz = array->member_size;
671    itr = array->members;
672    itr_end = itr + array->len * sz;
673    for (; (itr < itr_end) && (ret); itr += sz)
674      ret = function(array, itr, (void *)user_data);
675    return ret;
676 }
677
678 EAPI int
679 eina_inarray_foreach_remove(Eina_Inarray *array, Eina_Each_Cb match, const void *user_data)
680 {
681    unsigned int i = 0, count = 0;
682
683    EINA_MAGIC_CHECK_INARRAY(array, -1);
684    EINA_SAFETY_ON_NULL_RETURN_VAL(match, -1);
685
686    while (i < array->len)
687      {
688         void *p = _eina_inarray_get(array, i);
689         if (match(array, p, (void *)user_data) == EINA_FALSE)
690           {
691              i++;
692              continue;
693           }
694
695         eina_inarray_remove_at(array, i);
696         count++;
697      }
698
699    return count;
700 }
701
702 EAPI unsigned int
703 eina_inarray_count(const Eina_Inarray *array)
704 {
705    EINA_MAGIC_CHECK_INARRAY(array, 0);
706    return array->len;
707 }
708
709 EAPI Eina_Iterator *
710 eina_inarray_iterator_new(const Eina_Inarray *array)
711 {
712    Eina_Iterator_Inarray *it;
713
714    EINA_MAGIC_CHECK_INARRAY(array, NULL);
715
716    eina_error_set(0);
717    it = calloc(1, sizeof(Eina_Iterator_Inarray));
718    if (!it)
719      {
720         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
721         return NULL;
722      }
723
724    EINA_MAGIC_SET(it,            EINA_MAGIC_INARRAY_ITERATOR);
725    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
726
727    it->array = array;
728
729    it->iterator.version = EINA_ITERATOR_VERSION;
730    it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_next);
731    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER
732      (_eina_inarray_iterator_get_container);
733    it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free);
734
735    return &it->iterator;
736 }
737
738 EAPI Eina_Iterator *
739 eina_inarray_iterator_reversed_new(const Eina_Inarray *array)
740 {
741    Eina_Iterator_Inarray *it;
742
743    EINA_MAGIC_CHECK_INARRAY(array, NULL);
744
745    eina_error_set(0);
746    it = calloc(1, sizeof(Eina_Iterator_Inarray));
747    if (!it)
748      {
749         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
750         return NULL;
751      }
752
753    EINA_MAGIC_SET(it,            EINA_MAGIC_INARRAY_ITERATOR);
754    EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
755
756    it->array = array;
757    it->pos = array->len;
758
759    it->iterator.version = EINA_ITERATOR_VERSION;
760    it->iterator.next = FUNC_ITERATOR_NEXT(_eina_inarray_iterator_prev);
761    it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER
762      (_eina_inarray_iterator_get_container);
763    it->iterator.free = FUNC_ITERATOR_FREE(_eina_inarray_iterator_free);
764
765    return &it->iterator;
766 }
767
768 EAPI Eina_Accessor *
769 eina_inarray_accessor_new(const Eina_Inarray *array)
770 {
771    Eina_Accessor_Inarray *ac;
772
773    EINA_MAGIC_CHECK_INARRAY(array, NULL);
774
775    eina_error_set(0);
776    ac = calloc(1, sizeof(Eina_Accessor_Inarray));
777    if (!ac)
778      {
779         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
780         return NULL;
781      }
782
783    EINA_MAGIC_SET(ac,            EINA_MAGIC_INARRAY_ACCESSOR);
784    EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
785
786    ac->array = array;
787
788    ac->accessor.version = EINA_ACCESSOR_VERSION;
789    ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(_eina_inarray_accessor_get_at);
790    ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER
791      (_eina_inarray_accessor_get_container);
792    ac->accessor.free = FUNC_ACCESSOR_FREE(_eina_inarray_accessor_free);
793
794    return &ac->accessor;
795 }