xref: /php-src/ext/dom/lexbor/lexbor/core/array.c (revision bffab33a)
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