xref: /aosp_15_r20/external/libaom/third_party/vector/vector.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2 The MIT License(MIT)
3 Copyright(c) 2016 Peter Goldsborough
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of
6 this software and associated documentation files (the "Software"), to deal in
7 the Software without restriction, including without limitation the rights to
8 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 the Software, and to permit persons to whom the Software is furnished to do so,
10 subject to the following conditions :
11 
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
18 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22 
23 #define __STDC_WANT_LIB_EXT1__ 1
24 
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "third_party/vector/vector.h"
30 
31 /***** PRIVATE *****/
32 #define MAX(a, b) ((a) > (b) ? (a) : (b))
33 
_vector_should_grow(Vector * vector)34 static bool _vector_should_grow(Vector *vector) {
35   assert(vector->size <= vector->capacity);
36   return vector->size == vector->capacity;
37 }
38 
39 #if 0
40 static bool _vector_should_shrink(Vector *vector) {
41   assert(vector->size <= vector->capacity);
42   return vector->size == vector->capacity * VECTOR_SHRINK_THRESHOLD;
43 }
44 #endif  // 0
45 
_vector_offset(Vector * vector,size_t index)46 static void *_vector_offset(Vector *vector, size_t index) {
47   // return vector->data + (index * vector->element_size);
48   return (unsigned char *)vector->data + (index * vector->element_size);
49 }
50 
51 #if 0
52 static const void *_vector_const_offset(const Vector *vector, size_t index) {
53   // return vector->data + (index * vector->element_size);
54   return (unsigned char *)vector->data + (index * vector->element_size);
55 }
56 #endif  // 0
57 
_vector_assign(Vector * vector,size_t index,void * element)58 static void _vector_assign(Vector *vector, size_t index, void *element) {
59   /* Insert the element */
60   void *offset = _vector_offset(vector, index);
61   memcpy(offset, element, vector->element_size);
62 }
63 
64 #if 0
65 static int _vector_move_right(Vector *vector, size_t index) {
66   assert(vector->size < vector->capacity);
67 
68   /* The location where to start to move from. */
69   void *offset = _vector_offset(vector, index);
70 
71   /* How many to move to the right. */
72   size_t elements_in_bytes = (vector->size - index) * vector->element_size;
73 
74 #ifdef __STDC_LIB_EXT1__
75   size_t right_capacity_in_bytes =
76       (vector->capacity - (index + 1)) * vector->element_size;
77 
78   /* clang-format off */
79     int return_code =  memmove_s(
80         offset + vector->element_size,
81         right_capacity_in_bytes,
82         offset,
83         elements_in_bytes);
84 
85   /* clang-format on */
86 
87   return return_code == 0 ? VECTOR_SUCCESS : VECTOR_ERROR;
88 
89 #else
90   // memmove(offset + vector->element_size, offset, elements_in_bytes);
91   memmove((unsigned char *)offset + vector->element_size, offset,
92           elements_in_bytes);
93   return VECTOR_SUCCESS;
94 #endif
95 }
96 
97 static void _vector_move_left(Vector *vector, size_t index) {
98   size_t right_elements_in_bytes;
99   void *offset;
100 
101   /* The offset into the memory */
102   offset = _vector_offset(vector, index);
103 
104   /* How many to move to the left */
105   right_elements_in_bytes = (vector->size - index - 1) * vector->element_size;
106 
107   // memmove(offset, offset + vector->element_size, right_elements_in_bytes);
108   memmove(offset, (unsigned char *)offset + vector->element_size,
109           right_elements_in_bytes);
110 }
111 #endif  // 0
112 
_vector_reallocate(Vector * vector,size_t new_capacity)113 static int _vector_reallocate(Vector *vector, size_t new_capacity) {
114   size_t new_capacity_in_bytes;
115   void *old;
116   assert(vector != NULL);
117 
118   if (new_capacity < VECTOR_MINIMUM_CAPACITY) {
119     if (vector->capacity > VECTOR_MINIMUM_CAPACITY) {
120       new_capacity = VECTOR_MINIMUM_CAPACITY;
121     } else {
122       /* NO-OP */
123       return VECTOR_SUCCESS;
124     }
125   }
126 
127   new_capacity_in_bytes = new_capacity * vector->element_size;
128   old = vector->data;
129 
130   if ((vector->data = malloc(new_capacity_in_bytes)) == NULL) {
131     return VECTOR_ERROR;
132   }
133 
134 #ifdef __STDC_LIB_EXT1__
135   /* clang-format off */
136     if (memcpy_s(vector->data,
137                              new_capacity_in_bytes,
138                              old,
139                              aom_vector_byte_size(vector)) != 0) {
140         return VECTOR_ERROR;
141     }
142 /* clang-format on */
143 #else
144   memcpy(vector->data, old, aom_vector_byte_size(vector));
145 #endif
146 
147   vector->capacity = new_capacity;
148 
149   free(old);
150 
151   return VECTOR_SUCCESS;
152 }
153 
_vector_adjust_capacity(Vector * vector)154 static int _vector_adjust_capacity(Vector *vector) {
155   return _vector_reallocate(vector,
156                             MAX(1, vector->size * VECTOR_GROWTH_FACTOR));
157 }
158 
159 #if 0
160 static void _vector_swap(size_t *first, size_t *second) {
161   size_t temp = *first;
162   *first = *second;
163   *second = temp;
164 }
165 #endif  // 0
166 
aom_vector_setup(Vector * vector,size_t capacity,size_t element_size)167 int aom_vector_setup(Vector *vector, size_t capacity, size_t element_size) {
168   assert(vector != NULL);
169 
170   if (vector == NULL) return VECTOR_ERROR;
171 
172   vector->size = 0;
173   vector->capacity = MAX(VECTOR_MINIMUM_CAPACITY, capacity);
174   vector->element_size = element_size;
175   vector->data = malloc(vector->capacity * element_size);
176 
177   return vector->data == NULL ? VECTOR_ERROR : VECTOR_SUCCESS;
178 }
179 
180 #if 0
181 int aom_vector_copy(Vector *destination, Vector *source) {
182   assert(destination != NULL);
183   assert(source != NULL);
184   assert(aom_vector_is_initialized(source));
185   assert(!aom_vector_is_initialized(destination));
186 
187   if (destination == NULL) return VECTOR_ERROR;
188   if (source == NULL) return VECTOR_ERROR;
189   if (aom_vector_is_initialized(destination)) return VECTOR_ERROR;
190   if (!aom_vector_is_initialized(source)) return VECTOR_ERROR;
191 
192   /* Copy ALL the data */
193   destination->size = source->size;
194   destination->capacity = source->size * 2;
195   destination->element_size = source->element_size;
196 
197   /* Note that we are not necessarily allocating the same capacity */
198   destination->data = malloc(destination->capacity * source->element_size);
199   if (destination->data == NULL) return VECTOR_ERROR;
200 
201   memcpy(destination->data, source->data, aom_vector_byte_size(source));
202 
203   return VECTOR_SUCCESS;
204 }
205 
206 int aom_vector_copy_assign(Vector *destination, Vector *source) {
207   assert(destination != NULL);
208   assert(source != NULL);
209   assert(aom_vector_is_initialized(source));
210   assert(aom_vector_is_initialized(destination));
211 
212   if (destination == NULL) return VECTOR_ERROR;
213   if (source == NULL) return VECTOR_ERROR;
214   if (!aom_vector_is_initialized(destination)) return VECTOR_ERROR;
215   if (!aom_vector_is_initialized(source)) return VECTOR_ERROR;
216 
217   aom_vector_destroy(destination);
218 
219   return aom_vector_copy(destination, source);
220 }
221 
222 int aom_vector_move(Vector *destination, Vector *source) {
223   assert(destination != NULL);
224   assert(source != NULL);
225 
226   if (destination == NULL) return VECTOR_ERROR;
227   if (source == NULL) return VECTOR_ERROR;
228 
229   *destination = *source;
230   source->data = NULL;
231 
232   return VECTOR_SUCCESS;
233 }
234 
235 int aom_vector_move_assign(Vector *destination, Vector *source) {
236   aom_vector_swap(destination, source);
237   return aom_vector_destroy(source);
238 }
239 
240 int aom_vector_swap(Vector *destination, Vector *source) {
241   void *temp;
242 
243   assert(destination != NULL);
244   assert(source != NULL);
245   assert(aom_vector_is_initialized(source));
246   assert(aom_vector_is_initialized(destination));
247 
248   if (destination == NULL) return VECTOR_ERROR;
249   if (source == NULL) return VECTOR_ERROR;
250   if (!aom_vector_is_initialized(destination)) return VECTOR_ERROR;
251   if (!aom_vector_is_initialized(source)) return VECTOR_ERROR;
252 
253   _vector_swap(&destination->size, &source->size);
254   _vector_swap(&destination->capacity, &source->capacity);
255   _vector_swap(&destination->element_size, &source->element_size);
256 
257   temp = destination->data;
258   destination->data = source->data;
259   source->data = temp;
260 
261   return VECTOR_SUCCESS;
262 }
263 #endif  // 0
264 
aom_vector_destroy(Vector * vector)265 int aom_vector_destroy(Vector *vector) {
266   assert(vector != NULL);
267 
268   if (vector == NULL) return VECTOR_ERROR;
269 
270   free(vector->data);
271   vector->data = NULL;
272 
273   return VECTOR_SUCCESS;
274 }
275 
276 /* Insertion */
aom_vector_push_back(Vector * vector,void * element)277 int aom_vector_push_back(Vector *vector, void *element) {
278   assert(vector != NULL);
279   assert(element != NULL);
280 
281   if (_vector_should_grow(vector)) {
282     if (_vector_adjust_capacity(vector) == VECTOR_ERROR) {
283       return VECTOR_ERROR;
284     }
285   }
286 
287   _vector_assign(vector, vector->size, element);
288 
289   ++vector->size;
290 
291   return VECTOR_SUCCESS;
292 }
293 
294 #if 0
295 int aom_vector_push_front(Vector *vector, void *element) {
296   return aom_vector_insert(vector, 0, element);
297 }
298 
299 int aom_vector_insert(Vector *vector, size_t index, void *element) {
300   void *offset;
301 
302   assert(vector != NULL);
303   assert(element != NULL);
304   assert(index <= vector->size);
305 
306   if (vector == NULL) return VECTOR_ERROR;
307   if (element == NULL) return VECTOR_ERROR;
308   if (vector->element_size == 0) return VECTOR_ERROR;
309   if (index > vector->size) return VECTOR_ERROR;
310 
311   if (_vector_should_grow(vector)) {
312     if (_vector_adjust_capacity(vector) == VECTOR_ERROR) {
313       return VECTOR_ERROR;
314     }
315   }
316 
317   /* Move other elements to the right */
318   if (_vector_move_right(vector, index) == VECTOR_ERROR) {
319     return VECTOR_ERROR;
320   }
321 
322   /* Insert the element */
323   offset = _vector_offset(vector, index);
324   memcpy(offset, element, vector->element_size);
325   ++vector->size;
326 
327   return VECTOR_SUCCESS;
328 }
329 
330 int aom_vector_assign(Vector *vector, size_t index, void *element) {
331   assert(vector != NULL);
332   assert(element != NULL);
333   assert(index < vector->size);
334 
335   if (vector == NULL) return VECTOR_ERROR;
336   if (element == NULL) return VECTOR_ERROR;
337   if (vector->element_size == 0) return VECTOR_ERROR;
338   if (index >= vector->size) return VECTOR_ERROR;
339 
340   _vector_assign(vector, index, element);
341 
342   return VECTOR_SUCCESS;
343 }
344 
345 /* Deletion */
346 int aom_vector_pop_back(Vector *vector) {
347   assert(vector != NULL);
348   assert(vector->size > 0);
349 
350   if (vector == NULL) return VECTOR_ERROR;
351   if (vector->element_size == 0) return VECTOR_ERROR;
352 
353   --vector->size;
354 
355 #ifndef VECTOR_NO_SHRINK
356   if (_vector_should_shrink(vector)) {
357     _vector_adjust_capacity(vector);
358   }
359 #endif
360 
361   return VECTOR_SUCCESS;
362 }
363 
364 int aom_vector_pop_front(Vector *vector) { return aom_vector_erase(vector, 0); }
365 
366 int aom_vector_erase(Vector *vector, size_t index) {
367   assert(vector != NULL);
368   assert(index < vector->size);
369 
370   if (vector == NULL) return VECTOR_ERROR;
371   if (vector->element_size == 0) return VECTOR_ERROR;
372   if (index >= vector->size) return VECTOR_ERROR;
373 
374   /* Just overwrite */
375   _vector_move_left(vector, index);
376 
377 #ifndef VECTOR_NO_SHRINK
378   if (--vector->size == vector->capacity / 4) {
379     _vector_adjust_capacity(vector);
380   }
381 #endif
382 
383   return VECTOR_SUCCESS;
384 }
385 
386 int aom_vector_clear(Vector *vector) { return aom_vector_resize(vector, 0); }
387 
388 /* Lookup */
389 void *aom_vector_get(Vector *vector, size_t index) {
390   assert(vector != NULL);
391   assert(index < vector->size);
392 
393   if (vector == NULL) return NULL;
394   if (vector->element_size == 0) return NULL;
395   if (index >= vector->size) return NULL;
396 
397   return _vector_offset(vector, index);
398 }
399 
400 const void *aom_vector_const_get(const Vector *vector, size_t index) {
401   assert(vector != NULL);
402   assert(index < vector->size);
403 
404   if (vector == NULL) return NULL;
405   if (vector->element_size == 0) return NULL;
406   if (index >= vector->size) return NULL;
407 
408   return _vector_const_offset(vector, index);
409 }
410 
411 void *aom_vector_front(Vector *vector) { return aom_vector_get(vector, 0); }
412 
413 void *aom_vector_back(Vector *vector) {
414   return aom_vector_get(vector, vector->size - 1);
415 }
416 #endif  // 0
417 
418 /* Information */
419 
aom_vector_is_initialized(const Vector * vector)420 bool aom_vector_is_initialized(const Vector *vector) {
421   return vector->data != NULL;
422 }
423 
aom_vector_byte_size(const Vector * vector)424 size_t aom_vector_byte_size(const Vector *vector) {
425   return vector->size * vector->element_size;
426 }
427 
428 #if 0
429 size_t aom_vector_free_space(const Vector *vector) {
430   return vector->capacity - vector->size;
431 }
432 
433 bool aom_vector_is_empty(const Vector *vector) { return vector->size == 0; }
434 
435 /* Memory management */
436 int aom_vector_resize(Vector *vector, size_t new_size) {
437   if (new_size <= vector->capacity * VECTOR_SHRINK_THRESHOLD) {
438     vector->size = new_size;
439     if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1) {
440       return VECTOR_ERROR;
441     }
442   } else if (new_size > vector->capacity) {
443     if (_vector_reallocate(vector, new_size * VECTOR_GROWTH_FACTOR) == -1) {
444       return VECTOR_ERROR;
445     }
446   }
447 
448   vector->size = new_size;
449 
450   return VECTOR_SUCCESS;
451 }
452 
453 int aom_vector_reserve(Vector *vector, size_t minimum_capacity) {
454   if (minimum_capacity > vector->capacity) {
455     if (_vector_reallocate(vector, minimum_capacity) == VECTOR_ERROR) {
456       return VECTOR_ERROR;
457     }
458   }
459 
460   return VECTOR_SUCCESS;
461 }
462 
463 int aom_vector_shrink_to_fit(Vector *vector) {
464   return _vector_reallocate(vector, vector->size);
465 }
466 #endif  // 0
467 
468 /* Iterators */
aom_vector_begin(Vector * vector)469 Iterator aom_vector_begin(Vector *vector) { return aom_vector_iterator(vector, 0); }
470 
471 #if 0
472 Iterator aom_vector_end(Vector *vector) {
473   return aom_vector_iterator(vector, vector->size);
474 }
475 #endif  // 0
476 
aom_vector_iterator(Vector * vector,size_t index)477 Iterator aom_vector_iterator(Vector *vector, size_t index) {
478   Iterator iterator = { NULL, 0 };
479 
480   assert(vector != NULL);
481   assert(index <= vector->size);
482 
483   if (vector == NULL) return iterator;
484   if (index > vector->size) return iterator;
485   if (vector->element_size == 0) return iterator;
486 
487   iterator.pointer = _vector_offset(vector, index);
488   iterator.element_size = vector->element_size;
489 
490   return iterator;
491 }
492 
aom_iterator_get(Iterator * iterator)493 void *aom_iterator_get(Iterator *iterator) { return iterator->pointer; }
494 
495 #if 0
496 int aom_iterator_erase(Vector *vector, Iterator *iterator) {
497   size_t index = aom_iterator_index(vector, iterator);
498 
499   if (aom_vector_erase(vector, index) == VECTOR_ERROR) {
500     return VECTOR_ERROR;
501   }
502 
503   *iterator = aom_vector_iterator(vector, index);
504 
505   return VECTOR_SUCCESS;
506 }
507 #endif  // 0
508 
aom_iterator_increment(Iterator * iterator)509 void aom_iterator_increment(Iterator *iterator) {
510   assert(iterator != NULL);
511   // iterator->pointer += iterator->element_size;
512   iterator->pointer =
513       (unsigned char *)iterator->pointer + iterator->element_size;
514 }
515 
516 #if 0
517 void aom_iterator_decrement(Iterator *iterator) {
518   assert(iterator != NULL);
519   // iterator->pointer -= iterator->element_size;
520   iterator->pointer =
521       (unsigned char *)iterator->pointer - iterator->element_size;
522 }
523 
524 void *aom_iterator_next(Iterator *iterator) {
525   void *current = iterator->pointer;
526   aom_iterator_increment(iterator);
527 
528   return current;
529 }
530 
531 void *aom_iterator_previous(Iterator *iterator) {
532   void *current = iterator->pointer;
533   aom_iterator_decrement(iterator);
534 
535   return current;
536 }
537 
538 bool aom_iterator_equals(Iterator *first, Iterator *second) {
539   assert(first->element_size == second->element_size);
540   return first->pointer == second->pointer;
541 }
542 
543 bool aom_iterator_is_before(Iterator *first, Iterator *second) {
544   assert(first->element_size == second->element_size);
545   return first->pointer < second->pointer;
546 }
547 
548 bool aom_iterator_is_after(Iterator *first, Iterator *second) {
549   assert(first->element_size == second->element_size);
550   return first->pointer > second->pointer;
551 }
552 
553 size_t aom_iterator_index(Vector *vector, Iterator *iterator) {
554   assert(vector != NULL);
555   assert(iterator != NULL);
556   // return (iterator->pointer - vector->data) / vector->element_size;
557   return ((unsigned char *)iterator->pointer - (unsigned char *)vector->data) /
558          vector->element_size;
559 }
560 #endif  // 0
561