1 /* $Id$ */
2 /* Copyright (c) 2005-2015 Pierre Pronchery <khorben@defora.org> */
3 /* This file is part of DeforaOS System libSystem */
4 /* This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, version 3 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include "System/error.h"
23 #include "System/object.h"
24 #include "System/array.h"
25
26
27 /* Array */
28 /* protected */
29 /* types */
30 struct _Array
31 {
32 uint32_t count;
33 uint32_t size;
34 char * value;
35 };
36
37
38 /* public */
39 /* array_new */
array_new(size_t size)40 Array * array_new(size_t size)
41 {
42 Array * array;
43 uint64_t s = size;
44
45 if((array = object_new(sizeof(*array))) == NULL)
46 return NULL;
47 array->count = 0;
48 array->size = size;
49 array->value = NULL;
50 /* check for overflows */
51 if(array->size != s)
52 {
53 object_delete(array);
54 return NULL;
55 }
56 return array;
57 }
58
59
60 /* array_delete */
array_delete(Array * array)61 void array_delete(Array * array)
62 {
63 free(array->value);
64 object_delete(array);
65 }
66
67
68 /* accessors */
69 /* array_count */
array_count(Array * array)70 size_t array_count(Array * array)
71 {
72 return array->count;
73 }
74
75
76 /* array_get */
array_get(Array * array,size_t pos)77 void * array_get(Array * array, size_t pos)
78 {
79 uint64_t offset;
80
81 if(pos >= array->count)
82 return NULL;
83 offset = pos * array->size;
84 return &array->value[offset];
85 }
86
87
88 /* array_get_copy */
array_get_copy(Array * array,size_t pos,void * value)89 int array_get_copy(Array * array, size_t pos, void * value)
90 {
91 uint64_t offset;
92
93 if(pos >= array->count)
94 return 1;
95 offset = pos * array->size;
96 memcpy(value, &array->value[offset], array->size);
97 return 0;
98 }
99
100
101 /* array_set */
array_set(Array * array,size_t pos,void * value)102 int array_set(Array * array, size_t pos, void * value)
103 {
104 uint32_t p = pos + 1;
105 uint64_t offset;
106 uint64_t curpos;
107 size_t size;
108 void * q;
109
110 /* check for overflows */
111 if(p != pos + 1)
112 return -error_set_code(1, "%s", strerror(ERANGE));
113 offset = pos * array->size;
114 if(array->count < p)
115 {
116 /* grow the array */
117 size = offset + array->size;
118 if(size != offset + array->size)
119 return -error_set_code(-ERANGE, "%s", strerror(ERANGE));
120 if((q = realloc(array->value, offset + array->size)) == NULL)
121 return -error_set_code(-errno, "%s", strerror(errno));
122 array->value = q;
123 curpos = array->count * array->size;
124 memset(&array->value[curpos], 0, offset - curpos);
125 array->count = pos + 1;
126 }
127 /* set the value */
128 memcpy(&array->value[offset], value, array->size);
129 return 0;
130 }
131
132
133 /* useful */
134 /* array_append */
array_append(Array * array,void * value)135 int array_append(Array * array, void * value)
136 {
137 char * p;
138 uint64_t offset = array->size * array->count;
139
140 if((p = realloc(array->value, offset + array->size)) == NULL)
141 return error_set_code(-errno, "%s", strerror(errno));
142 array->value = p;
143 memcpy(&p[offset], value, array->size);
144 array->count++;
145 return 0;
146 }
147
148
149 /* array_remove_pos */
array_remove_pos(Array * array,size_t pos)150 int array_remove_pos(Array * array, size_t pos)
151 {
152 if(pos >= array->count)
153 return 1;
154 array->count--; /* FIXME resize array? */
155 memmove(&array->value[pos * array->size],
156 &array->value[(pos + 1) * array->size],
157 (array->count - pos) * array->size);
158 return 0;
159 }
160
161
162 /* array_foreach */
array_foreach(Array * array,ArrayForeach func,void * data)163 void array_foreach(Array * array, ArrayForeach func, void * data)
164 {
165 uint32_t i;
166 uint64_t offset;
167
168 for(i = 0, offset = 0; i < array->count; i++, offset += array->size)
169 func(array->value + offset, data);
170 }
171