libc3: c_array tweaks
[simavr] / examples / shared / libc3 / src / c_array.h
1 /*
2         c_array.h
3
4         Copyright 2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of gcodepp.
7
8         gcodepp is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         gcodepp is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with gcodepp.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22
23 #ifndef __C_ARRAY_H___
24 #define __C_ARRAY_H___
25
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifndef C_ARRAY_INLINE
31 #define C_ARRAY_INLINE inline
32 #endif
33 #ifndef C_ARRAY_SIZE_TYPE
34 #define C_ARRAY_SIZE_TYPE uint32_t
35 #endif
36
37 #define DECLARE_C_ARRAY(__type, __name, __page, __args...) \
38 enum { __name##_page_size = __page }; \
39 typedef __type __name##_element_t; \
40 typedef C_ARRAY_SIZE_TYPE __name##_count_t; \
41 typedef struct __name##_t {\
42         volatile __name##_count_t count;\
43         volatile __name##_count_t size;\
44         __name##_element_t * e;\
45         __args ;\
46 } __name##_t, *__name##_p;
47
48 #define C_ARRAY_NULL { 0, 0, NULL }
49
50 #define IMPLEMENT_C_ARRAY(__name) \
51 static const __name##_t __name##_zero = C_ARRAY_NULL; \
52 static C_ARRAY_INLINE \
53         void __name##_free(\
54                         __name##_p a) \
55 {\
56         if (!a) return;\
57         if (a->e) free(a->e);\
58         a->count = a->size = 0;\
59         a->e = NULL;\
60 }\
61 static C_ARRAY_INLINE \
62         void __name##_clear(\
63                         __name##_p a) \
64 {\
65         if (!a) return;\
66         a->count = 0;\
67 }\
68 static C_ARRAY_INLINE \
69         void __name##_realloc(\
70                         __name##_p a, __name##_count_t size) \
71 {\
72         if (!a || a->size == size) return; \
73         if (size == 0) { if (a->e) free(a->e); a->e = NULL; } \
74         else a->e = realloc(a->e, size * sizeof(__name##_element_t));\
75         a->size = size; \
76 }\
77 static C_ARRAY_INLINE \
78         void __name##_trim(\
79                         __name##_p a) \
80 {\
81         if (!a) return;\
82         __name##_count_t n = a->count + __name##_page_size;\
83         n -= (n % __name##_page_size);\
84         if (n != a->size)\
85                 __name##_realloc(a, n);\
86 }\
87 static C_ARRAY_INLINE \
88         __name##_element_t * __name##_get_ptr(\
89                         __name##_p a, __name##_count_t index) \
90 {\
91         if (!a) return NULL;\
92         if (index > a->count) index = a->count;\
93         return index < a->count ? a->e + index : NULL;\
94 }\
95 static C_ARRAY_INLINE \
96         __name##_count_t __name##_add(\
97                         __name##_p a, __name##_element_t e) \
98 {\
99         if (!a) return 0;\
100         if (a->count + 1 >= a->size)\
101                 __name##_realloc(a, a->size + __name##_page_size);\
102         a->e[a->count++] = e;\
103         return a->count;\
104 }\
105 static C_ARRAY_INLINE \
106         __name##_count_t __name##_insert(\
107                         __name##_p a, __name##_count_t index, \
108                         __name##_element_t * e, __name##_count_t count) \
109 {\
110         if (!a) return 0;\
111         if (index > a->count) index = a->count;\
112         if (a->count + count >= a->size) \
113                 __name##_realloc(a, (((a->count + count) / __name##_page_size)+1) * __name##_page_size);\
114         if (index < a->count)\
115                 memmove(&a->e[index + count], &a->e[index], \
116                                 (a->count - index + count) * sizeof(__name##_element_t));\
117         memmove(&a->e[index], e, count * sizeof(__name##_element_t));\
118         a->count += count;\
119         return a->count;\
120 }\
121 static C_ARRAY_INLINE \
122         __name##_count_t __name##_delete(\
123                         __name##_p a, __name##_count_t index, __name##_count_t count) \
124 {\
125         if (!a) return 0;\
126         if (index > a->count) index = a->count;\
127         if (index + count > a->count) \
128                 count = a->count - index;\
129         if (count && a->count - index) { \
130                 memmove(&a->e[index], &a->e[index + count], \
131                                 (a->count - index - count) * sizeof(__name##_element_t));\
132         }\
133         a->count -= count;\
134         return a->count;\
135 }
136
137 #endif /* __C_ARRAY_H___ */