1 /* 2 * Copyright (c) 2012-2014 by Farsight Security, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <assert.h> 18 19 #include "my_alloc.h" 20 21 #define VECTOR_GENERATE(name, type) \ 22 typedef struct name##__vector { \ 23 type * _v; \ 24 type * _p; \ 25 size_t _n, _n_alloced, _hint; \ 26 } name; \ 27 __attribute__((unused)) \ 28 static inline name * \ 29 name##_init(unsigned hint) \ 30 { \ 31 name *vec; \ 32 vec = my_calloc(1, sizeof(name)); \ 33 if (hint == 0) hint = 1; \ 34 vec->_hint = vec->_n_alloced = hint; \ 35 vec->_v = my_malloc(vec->_n_alloced * sizeof(type)); \ 36 vec->_p = &(vec->_v[0]); \ 37 return (vec); \ 38 } \ 39 __attribute__((unused)) \ 40 static inline void \ 41 name##_reinit(unsigned hint, name *vec) \ 42 { \ 43 if (hint == 0) hint = 1; \ 44 vec->_hint = vec->_n_alloced = hint; \ 45 vec->_n = 0; \ 46 vec->_v = my_malloc(vec->_n_alloced * sizeof(type)); \ 47 vec->_p = &(vec->_v[0]); \ 48 } \ 49 __attribute__((unused)) \ 50 static inline void \ 51 name##_detach(name *vec, type **out, size_t *outsz) \ 52 { \ 53 *(out) = (vec)->_v; \ 54 *(outsz) = (vec)->_n; \ 55 (vec)->_n = 0; \ 56 (vec)->_n_alloced = (vec)->_hint; \ 57 (vec)->_v = my_malloc((vec)->_n_alloced * sizeof(type)); \ 58 (vec)->_p = &(vec->_v[0]); \ 59 } \ 60 __attribute__((unused)) \ 61 static inline void \ 62 name##_destroy(name **vec) \ 63 { \ 64 if (*vec) { \ 65 my_free((*vec)->_v); \ 66 my_free((*vec)); \ 67 } \ 68 } \ 69 __attribute__((unused)) \ 70 static inline void \ 71 name##_reserve(name *vec, size_t n_elems) \ 72 { \ 73 while ((n_elems) > ((vec)->_n_alloced - (vec)->_n)) { \ 74 (vec)->_n_alloced *= 2; \ 75 (vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced \ 76 * sizeof(type)); \ 77 (vec)->_p = &((vec)->_v[(vec)->_n]); \ 78 } \ 79 } \ 80 __attribute__((unused)) \ 81 static inline void \ 82 name##_add(name *vec, type elem) \ 83 { \ 84 while ((vec)->_n + 1 > (vec)->_n_alloced) { \ 85 (vec)->_n_alloced *= 2; \ 86 (vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced \ 87 * sizeof(type)); \ 88 (vec)->_p = &((vec)->_v[(vec)->_n]); \ 89 } \ 90 (vec)->_v[(vec)->_n] = elem; \ 91 (vec)->_n += 1; \ 92 (vec)->_p = &((vec)->_v[(vec)->_n]); \ 93 } \ 94 __attribute__((unused)) \ 95 static inline void \ 96 name##_append(name *vec, type const *elems, size_t n_elems) \ 97 { \ 98 name##_reserve(vec, n_elems); \ 99 memcpy((vec)->_v + (vec)->_n, elems, (n_elems) * sizeof(type)); \ 100 (vec)->_n += (n_elems); \ 101 (vec)->_p = &((vec)->_v[(vec)->_n]); \ 102 } \ 103 __attribute__((unused)) \ 104 static inline void \ 105 name##_extend(name *vec0, name *vec1) \ 106 { \ 107 name##_append(vec0, (vec1)->_v, (vec1)->_n); \ 108 } \ 109 __attribute__((unused)) \ 110 static inline void \ 111 name##_reset(name *vec) \ 112 { \ 113 (vec)->_n = 0; \ 114 if ((vec)->_n_alloced > (vec)->_hint) { \ 115 (vec)->_n_alloced = (vec)->_hint; \ 116 (vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced \ 117 * sizeof(type)); \ 118 } \ 119 (vec)->_p = &(vec->_v[0]); \ 120 } \ 121 __attribute__((unused)) \ 122 static inline void \ 123 name##_clip(name *vec, size_t n_elems) \ 124 { \ 125 if (n_elems < (vec)->_n) { \ 126 (vec)->_n = n_elems; \ 127 (vec)->_p = &((vec)->_v[(vec)->_n]); \ 128 } \ 129 } \ 130 __attribute__((unused)) \ 131 static inline size_t \ 132 name##_bytes(name *vec) \ 133 { \ 134 return ((vec)->_n * sizeof(type)); \ 135 } \ 136 __attribute__((unused)) \ 137 static inline size_t \ 138 name##_size(name *vec) \ 139 { \ 140 return ((vec)->_n); \ 141 } \ 142 __attribute__((unused)) \ 143 static inline type \ 144 name##_value(name *vec, size_t i) \ 145 { \ 146 assert(i < (vec)->_n); \ 147 return ((vec)->_v[i]); \ 148 } \ 149 __attribute__((unused)) \ 150 static inline type * \ 151 name##_ptr(name *vec) \ 152 { \ 153 return ((vec)->_p); \ 154 } \ 155 __attribute__((unused)) \ 156 static inline type * \ 157 name##_data(name *vec) \ 158 { \ 159 return ((vec)->_v); \ 160 } \ 161 __attribute__((unused)) \ 162 static inline void \ 163 name##_advance(name *vec, size_t x) \ 164 { \ 165 assert(x <= ((vec)->_n_alloced - (vec)->_n)); \ 166 (vec)->_n += x; \ 167 (vec)->_p = &((vec)->_v[(vec)->_n]); \ 168 } 169