1 /*
2  *    Copyright 2012 Peter Curtis
3  *
4  *    This file is part of libocad.
5  *
6  *    libocad is free software: you can redistribute it and/or modify
7  *    it under the terms of the GNU General Public License as published by
8  *    the Free Software Foundation, either version 3 of the License, or
9  *    (at your option) any later version.
10  *
11  *    libocad is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    GNU General Public License for more details.
15  *
16  *    You should have received a copy of the GNU General Public License
17  *    along with libocad.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "array.h"
24 
array_realloc(PtrArray * array,int minsize)25 static int array_realloc(PtrArray *array, int minsize) {
26 	int size = array->size;
27 	while (size < minsize) {
28 		if (size < 16) size = 16;
29 		else if (size < 1024) size *= 2;
30 		else size += 1024;
31 	}
32 	if (size > array->size) {
33 		void **newdata = (void **)realloc(array->data, size * sizeof(void *));
34 		if (newdata == NULL) return -1;
35 		memset(newdata + array->size, 0, (size - array->size) * sizeof(void *)); // NULL out the rest
36 		array->data = newdata;
37 		array->size = size;
38 	}
39 	return 0;
40 }
41 
array_shift(PtrArray * array,u32 start,u32 count)42 static int array_shift(PtrArray *array, u32 start, u32 count) {
43 	u32 size;
44 	int ret;
45 	if (start < 0) return -2;
46 	if (count == 0) return 0;
47 	size = array->size;
48 	ret = array_realloc(array, array->size + count);
49 	if (ret < 0) return ret;
50 	memmove(array->data + (start + count), array->data + start, (size - start) * sizeof(void *));
51 	array->count += count;
52 	return 0;
53 }
54 
array_init(PtrArray * array)55 int array_init(PtrArray *array) {
56 	array->count = 0;
57 	array->size = 0;
58 	array->data = NULL;
59 	return 0;
60 }
61 
array_clear(PtrArray * array)62 int array_clear(PtrArray *array) {
63 	if (array->data) free(array->data);
64 	return array_init(array);
65 }
66 
array_count(const PtrArray * array)67 u32 array_count(const PtrArray *array) {
68 	return array->count;
69 }
70 
array_get(const PtrArray * array,u32 index)71 void *array_get(const PtrArray *array, u32 index) {
72 	if (index < 0 || index >= array->count) return NULL;
73 	return array->data[index];
74 }
75 
array_set(PtrArray * array,u32 index,void * value)76 void *array_set(PtrArray *array, u32 index, void *value) {
77 	void *old_value;
78 	if (index < 0 || index >= array->count) return NULL; // out of bounds
79 //	int ret = 0;
80 //	if ((ret = array_realloc(array, index + 1))) return ret;
81 	old_value = array->data[index];
82 	array->data[index] = value;
83 	return old_value;
84 }
85 
array_remove(PtrArray * array,u32 index)86 void *array_remove(PtrArray *array, u32 index) {
87 	void *old_value;
88 	if (index < 0 || index >= array->count) return NULL; // out of bounds
89 	old_value = array->data[index];
90 	array_remove_range(array, index, 1);
91 	return old_value;
92 }
93 
array_remove_range(PtrArray * array,u32 start,u32 count)94 int array_remove_range(PtrArray *array, u32 start, u32 count) {
95 	u32 end;
96 	if (start < 0) return ARRAY_INDEX_OUT_OF_BOUNDS;
97 	if (count == 0) return ARRAY_OK;
98 	end = start + count;
99 	if (end > array->count) return ARRAY_INDEX_OUT_OF_BOUNDS;
100 	memmove(array->data + start, array->data + end, (array->count - end) * sizeof(void *));
101 	array->count -= count;
102 	return ARRAY_INDEX_OUT_OF_BOUNDS;
103 }
104 
array_add(PtrArray * array,void * value)105 int array_add(PtrArray *array, void *value) {
106 	return array_insert(array, array->count, value);
107 }
108 
array_insert(PtrArray * array,u32 index,void * value)109 int array_insert(PtrArray *array, u32 index, void *value) {
110 	int ret;
111 	if (index < 0 || index > array->count) return -2;
112 	ret = array_shift(array, index, 1);
113 	if (ret < 0) return ret;
114 	array->data[index] = value;
115 	return 0;
116 }
117 
array_splice(PtrArray * array,u32 start,u32 delete,const void ** data,u32 count)118 int array_splice(PtrArray *array, u32 start, u32 delete, const void **data, u32 count) {
119 	int ret = (count < delete) ?
120 		array_remove_range(array, start, delete - count) :
121 		array_shift(array, start, count - delete);
122 	if (ret < 0) return ret;
123 	memcpy(array->data + start, data, count * sizeof(void *));
124 	return 0;
125 }
126 
array_splice_array(PtrArray * array,u32 start,u32 delete,const PtrArray * data,u32 pos,u32 count)127 int array_splice_array(PtrArray *array, u32 start, u32 delete, const PtrArray *data, u32 pos, u32 count) {
128 	if (pos < 0) return -2;
129 	if ((pos + count) >= data->size) return -2;
130 	return array_splice(array, start, delete, (const void **)(data->data + pos), count);
131 }
132 
133 
134