bb1aa22d12ea9604bb88bc80c441354c91f34d0c
[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 = __name##_zero;\
59 }\
60 static C_ARRAY_INLINE \
61         void __name##_clear(\
62                         __name##_p a) \
63 {\
64         if (!a) return;\
65         a->count = 0;\
66 }\
67 static C_ARRAY_INLINE \
68         void __name##_realloc(\
69                         __name##_p a, __name##_count_t size) \
70 {\
71         if (!a || a->size == size) return; \
72         a->e = realloc(a->e, size * sizeof(__name##_element_t));\
73         a->size = size; \
74 }\
75 static C_ARRAY_INLINE \
76         void __name##_trim(\
77                         __name##_p a) \
78 {\
79         if (!a) return;\
80         __name##_count_t n = a->count + __name##_page_size;\
81         n -= (n % __name##_page_size);\
82         if (n != a->size)\
83                 __name##_realloc(a, n);\
84 }\
85 static C_ARRAY_INLINE \
86         __name##_element_t * __name##_get_ptr(\
87                         __name##_p a, __name##_count_t index) \
88 {\
89         if (!a) return NULL;\
90         if (index > a->count) index = a->count;\
91         return index < a->count ? a->e + index : NULL;\
92 }\
93 static C_ARRAY_INLINE \
94         __name##_count_t __name##_add(\
95                         __name##_p a, __name##_element_t e) \
96 {\
97         if (!a) return 0;\
98         if (a->count + 1 >= a->size)\
99                 __name##_realloc(a, a->size + __name##_page_size);\
100         a->e[a->count++] = e;\
101         return a->count;\
102 }\
103 static C_ARRAY_INLINE \
104         __name##_count_t __name##_insert(\
105                         __name##_p a, __name##_count_t index, \
106                         __name##_element_t * e, __name##_count_t count) \
107 {\
108         if (!a) return 0;\
109         if (index > a->count) index = a->count;\
110         if (a->count + count >= a->size) \
111                 __name##_realloc(a, (((a->count + count) / __name##_page_size)+1) * __name##_page_size);\
112         if (index < a->count)\
113                 memmove(&a->e[index + count], &a->e[index], \
114                                 (a->count - index + count) * sizeof(__name##_element_t));\
115         memmove(&a->e[index], e, count * sizeof(__name##_element_t));\
116         a->count += count;\
117         return a->count;\
118 }\
119 static C_ARRAY_INLINE \
120         __name##_count_t __name##_delete(\
121                         __name##_p a, __name##_count_t index, __name##_count_t count) \
122 {\
123         if (!a) return 0;\
124         if (index > a->count) index = a->count;\
125         if (index + count > a->count) \
126                 count = a->count - index;\
127         if (count && a->count - index) { \
128                 memmove(&a->e[index], &a->e[index + count], \
129                                 (a->count - index - count) * sizeof(__name##_element_t));\
130         }\
131         a->count -= count;\
132         return a->count;\
133 }
134
135 #endif /* __C_ARRAY_H___ */