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