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