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