xref: /php-src/ext/dom/lexbor/lexbor/core/array_obj.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_obj.h"
8 
9 
10 lexbor_array_obj_t *
lexbor_array_obj_create(void)11 lexbor_array_obj_create(void)
12 {
13     return lexbor_calloc(1, sizeof(lexbor_array_obj_t));
14 }
15 
16 lxb_status_t
lexbor_array_obj_init(lexbor_array_obj_t * array,size_t size,size_t struct_size)17 lexbor_array_obj_init(lexbor_array_obj_t *array,
18                       size_t size, size_t struct_size)
19 {
20     if (array == NULL) {
21         return LXB_STATUS_ERROR_OBJECT_IS_NULL;
22     }
23 
24     if (size == 0 || struct_size == 0) {
25         return LXB_STATUS_ERROR_TOO_SMALL_SIZE;
26     }
27 
28     array->length = 0;
29     array->size = size;
30     array->struct_size = struct_size;
31 
32     array->list = lexbor_malloc(sizeof(uint8_t *)
33                                 * (array->size * struct_size));
34     if (array->list == NULL) {
35         return LXB_STATUS_ERROR_MEMORY_ALLOCATION;
36     }
37 
38     return LXB_STATUS_OK;
39 }
40 
41 void
lexbor_array_obj_clean(lexbor_array_obj_t * array)42 lexbor_array_obj_clean(lexbor_array_obj_t *array)
43 {
44     if (array != NULL) {
45         array->length = 0;
46     }
47 }
48 
49 lexbor_array_obj_t *
lexbor_array_obj_destroy(lexbor_array_obj_t * array,bool self_destroy)50 lexbor_array_obj_destroy(lexbor_array_obj_t *array, bool self_destroy)
51 {
52     if (array == NULL)
53         return NULL;
54 
55     if (array->list) {
56         array->length = 0;
57         array->size = 0;
58         array->list = lexbor_free(array->list);
59     }
60 
61     if (self_destroy) {
62         return lexbor_free(array);
63     }
64 
65     return array;
66 }
67 
68 uint8_t *
lexbor_array_obj_expand(lexbor_array_obj_t * array,size_t up_to)69 lexbor_array_obj_expand(lexbor_array_obj_t *array, size_t up_to)
70 {
71     uint8_t *list;
72     size_t new_size;
73 
74     if (array->length > (SIZE_MAX - up_to)) {
75         return NULL;
76     }
77 
78     new_size = array->length + up_to;
79 
80     list = lexbor_realloc(array->list, sizeof(uint8_t *)
81                           * (new_size * array->struct_size));
82     if (list == NULL) {
83         return NULL;
84     }
85 
86     array->list = list;
87     array->size = new_size;
88 
89     return list;
90 }
91 
92 void *
lexbor_array_obj_push(lexbor_array_obj_t * array)93 lexbor_array_obj_push(lexbor_array_obj_t *array)
94 {
95     void *entry;
96 
97     if (array->length >= array->size)
98     {
99         if ((lexbor_array_obj_expand(array, 128) == NULL)) {
100             return NULL;
101         }
102     }
103 
104     entry = array->list + (array->length * array->struct_size);
105     array->length++;
106 
107     memset(entry, 0, array->struct_size);
108 
109     return entry;
110 }
111 
112 void *
lexbor_array_obj_push_wo_cls(lexbor_array_obj_t * array)113 lexbor_array_obj_push_wo_cls(lexbor_array_obj_t *array)
114 {
115     void *entry;
116 
117     if (array->length >= array->size) {
118         if ((lexbor_array_obj_expand(array, 128) == NULL)) {
119             return NULL;
120         }
121     }
122 
123     entry = array->list + (array->length * array->struct_size);
124     array->length++;
125 
126     return entry;
127 }
128 
129 void *
lexbor_array_obj_push_n(lexbor_array_obj_t * array,size_t count)130 lexbor_array_obj_push_n(lexbor_array_obj_t *array, size_t count)
131 {
132     void *entry;
133 
134     if ((array->length + count) > array->size) {
135         if ((lexbor_array_obj_expand(array, count + 128) == NULL)) {
136             return NULL;
137         }
138     }
139 
140     entry = array->list + (array->length * array->struct_size);
141     array->length += count;
142 
143     return entry;
144 }
145 
146 void *
lexbor_array_obj_pop(lexbor_array_obj_t * array)147 lexbor_array_obj_pop(lexbor_array_obj_t *array)
148 {
149     if (array->length == 0) {
150         return NULL;
151     }
152 
153     array->length--;
154     return array->list + (array->length * array->struct_size);
155 }
156 
157 void
lexbor_array_obj_delete(lexbor_array_obj_t * array,size_t begin,size_t length)158 lexbor_array_obj_delete(lexbor_array_obj_t *array, size_t begin, size_t length)
159 {
160     if (begin >= array->length || length == 0) {
161         return;
162     }
163 
164     size_t end_len = begin + length;
165 
166     if (end_len >= array->length) {
167         array->length = begin;
168         return;
169     }
170 
171     memmove(&array->list[ begin * array->struct_size ],
172             &array->list[ end_len * array->struct_size ],
173             sizeof(uint8_t *)
174             * ((array->length - end_len) * array->struct_size));
175 
176     array->length -= length;
177 }
178 
179 /*
180  * No inline functions.
181  */
182 void
lexbor_array_obj_erase_noi(lexbor_array_obj_t * array)183 lexbor_array_obj_erase_noi(lexbor_array_obj_t *array)
184 {
185     lexbor_array_obj_erase(array);
186 }
187 
188 void *
lexbor_array_obj_get_noi(lexbor_array_obj_t * array,size_t idx)189 lexbor_array_obj_get_noi(lexbor_array_obj_t *array, size_t idx)
190 {
191     return lexbor_array_obj_get(array, idx);
192 }
193 
194 size_t
lexbor_array_obj_length_noi(lexbor_array_obj_t * array)195 lexbor_array_obj_length_noi(lexbor_array_obj_t *array)
196 {
197     return lexbor_array_obj_length(array);
198 }
199 
200 size_t
lexbor_array_obj_size_noi(lexbor_array_obj_t * array)201 lexbor_array_obj_size_noi(lexbor_array_obj_t *array)
202 {
203     return lexbor_array_obj_size(array);
204 }
205 
206 size_t
lexbor_array_obj_struct_size_noi(lexbor_array_obj_t * array)207 lexbor_array_obj_struct_size_noi(lexbor_array_obj_t *array)
208 {
209     return lexbor_array_obj_struct_size(array);
210 }
211 
212 void *
lexbor_array_obj_last_noi(lexbor_array_obj_t * array)213 lexbor_array_obj_last_noi(lexbor_array_obj_t *array)
214 {
215     return lexbor_array_obj_last(array);
216 }
217