1 /*
2 * Copyright (C) 2018 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
7 #include "lexbor/core/array.h"
8
9
10 lexbor_array_t *
lexbor_array_create(void)11 lexbor_array_create(void)
12 {
13 return lexbor_calloc(1, sizeof(lexbor_array_t));
14 }
15
16 lxb_status_t
lexbor_array_init(lexbor_array_t * array,size_t size)17 lexbor_array_init(lexbor_array_t *array, size_t size)
18 {
19 if (array == NULL) {
20 return LXB_STATUS_ERROR_OBJECT_IS_NULL;
21 }
22
23 if (size == 0) {
24 return LXB_STATUS_ERROR_TOO_SMALL_SIZE;
25 }
26
27 array->length = 0;
28 array->size = size;
29
30 array->list = lexbor_malloc(sizeof(void *) * size);
31 if (array->list == NULL) {
32 return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
33 }
34
35 return LXB_STATUS_OK;
36 }
37
38 void
lexbor_array_clean(lexbor_array_t * array)39 lexbor_array_clean(lexbor_array_t *array)
40 {
41 if (array != NULL) {
42 array->length = 0;
43 }
44 }
45
46 lexbor_array_t *
lexbor_array_destroy(lexbor_array_t * array,bool self_destroy)47 lexbor_array_destroy(lexbor_array_t *array, bool self_destroy)
48 {
49 if (array == NULL)
50 return NULL;
51
52 if (array->list) {
53 array->length = 0;
54 array->size = 0;
55 array->list = lexbor_free(array->list);
56 }
57
58 if (self_destroy) {
59 return lexbor_free(array);
60 }
61
62 return array;
63 }
64
65 void **
lexbor_array_expand(lexbor_array_t * array,size_t up_to)66 lexbor_array_expand(lexbor_array_t *array, size_t up_to)
67 {
68 void **list;
69 size_t new_size;
70
71 if (array->length > (SIZE_MAX - up_to))
72 return NULL;
73
74 new_size = array->length + up_to;
75 list = lexbor_realloc(array->list, sizeof(void *) * new_size);
76
77 if (list == NULL)
78 return NULL;
79
80 array->list = list;
81 array->size = new_size;
82
83 return list;
84 }
85
86 lxb_status_t
lexbor_array_push(lexbor_array_t * array,void * value)87 lexbor_array_push(lexbor_array_t *array, void *value)
88 {
89 if (array->length >= array->size) {
90 if ((lexbor_array_expand(array, 128) == NULL)) {
91 return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
92 }
93 }
94
95 array->list[ array->length ] = value;
96 array->length++;
97
98 return LXB_STATUS_OK;
99 }
100
101 void *
lexbor_array_pop(lexbor_array_t * array)102 lexbor_array_pop(lexbor_array_t *array)
103 {
104 if (array->length == 0) {
105 return NULL;
106 }
107
108 array->length--;
109 return array->list[ array->length ];
110 }
111
112 lxb_status_t
lexbor_array_insert(lexbor_array_t * array,size_t idx,void * value)113 lexbor_array_insert(lexbor_array_t *array, size_t idx, void *value)
114 {
115 if (idx >= array->length) {
116 size_t up_to = (idx - array->length) + 1;
117
118 if (idx >= array->size) {
119 if ((lexbor_array_expand(array, up_to) == NULL)) {
120 return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
121 }
122 }
123
124 memset(&array->list[array->length], 0, sizeof(void *) * up_to);
125
126 array->list[ idx ] = value;
127 array->length += up_to;
128
129 return LXB_STATUS_OK;
130 }
131
132 if (array->length >= array->size) {
133 if ((lexbor_array_expand(array, 32) == NULL)) {
134 return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
135 }
136 }
137
138 memmove(&array->list[idx + 1], &array->list[idx],
139 sizeof(void *) * (array->length - idx));
140
141 array->list[ idx ] = value;
142 array->length++;
143
144 return LXB_STATUS_OK;
145 }
146
147 lxb_status_t
lexbor_array_set(lexbor_array_t * array,size_t idx,void * value)148 lexbor_array_set(lexbor_array_t *array, size_t idx, void *value)
149 {
150 if (idx >= array->length) {
151 size_t up_to = (idx - array->length) + 1;
152
153 if (idx >= array->size) {
154 if ((lexbor_array_expand(array, up_to) == NULL)) {
155 return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
156 }
157 }
158
159 memset(&array->list[array->length], 0, sizeof(void *) * up_to);
160
161 array->length += up_to;
162 }
163
164 array->list[idx] = value;
165
166 return LXB_STATUS_OK;
167 }
168
169 void
lexbor_array_delete(lexbor_array_t * array,size_t begin,size_t length)170 lexbor_array_delete(lexbor_array_t *array, size_t begin, size_t length)
171 {
172 if (begin >= array->length || length == 0) {
173 return;
174 }
175
176 size_t end_len = begin + length;
177
178 if (end_len >= array->length) {
179 array->length = begin;
180 return;
181 }
182
183 memmove(&array->list[begin], &array->list[end_len],
184 sizeof(void *) * (array->length - end_len));
185
186 array->length -= length;
187 }
188
189 /*
190 * No inline functions.
191 */
192 void *
lexbor_array_get_noi(lexbor_array_t * array,size_t idx)193 lexbor_array_get_noi(lexbor_array_t *array, size_t idx)
194 {
195 return lexbor_array_get(array, idx);
196 }
197
198 size_t
lexbor_array_length_noi(lexbor_array_t * array)199 lexbor_array_length_noi(lexbor_array_t *array)
200 {
201 return lexbor_array_length(array);
202 }
203
204 size_t
lexbor_array_size_noi(lexbor_array_t * array)205 lexbor_array_size_noi(lexbor_array_t *array)
206 {
207 return lexbor_array_size(array);
208 }
209