1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 9 окт. 2017 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef DATA_CASTORAGE_H_ 23 #define DATA_CASTORAGE_H_ 24 25 #include <core/types.h> 26 #include <core/alloc.h> 27 #include <string.h> 28 29 namespace lsp 30 { 31 class basic_aligned_storage 32 { 33 protected: 34 uint8_t *vItems; 35 size_t nCapacity; 36 size_t nItems; 37 size_t nSizeOf; 38 size_t nAlign; 39 uint8_t *vData; 40 41 protected: realloc_capacity(size_t capacity)42 bool realloc_capacity(size_t capacity) 43 { 44 if (capacity < 32) 45 capacity = 32; 46 47 // Do aligned (re)allocation 48 size_t alloc = nSizeOf * capacity + nAlign; 49 50 uint8_t *ptr = lsp_trealloc(uint8_t, vData, alloc); 51 if (ptr == NULL) 52 return false; 53 else if (ptr == vData) 54 { 55 nCapacity = capacity; 56 return true; 57 } 58 59 uint8_t *p = ALIGN_PTR(ptr, nAlign); 60 size_t s_diff = vItems - vData; 61 size_t d_diff = p - ptr; 62 63 if (s_diff != d_diff) 64 ::memmove(&ptr[d_diff], &ptr[s_diff], nSizeOf * nCapacity); 65 66 // Update internal data 67 vData = ptr; 68 vItems = p; 69 nCapacity = capacity; 70 return true; 71 } 72 alloc_items(size_t n)73 uint8_t *alloc_items(size_t n) 74 { 75 if ((nItems + n) > nCapacity) 76 { 77 size_t dn = nCapacity + n; 78 if (!realloc_capacity(dn + (dn >> 1))) 79 return NULL; 80 } 81 82 uint8_t *ptr = &vItems[nItems * nSizeOf]; 83 nItems += n; 84 return ptr; 85 } 86 alloc_item()87 uint8_t *alloc_item() 88 { 89 if (nItems >= nCapacity) 90 { 91 if (!realloc_capacity(nCapacity + (nCapacity >> 1))) 92 return NULL; 93 } 94 95 return &vItems[(nItems++)*nSizeOf]; 96 } 97 insert_items(size_t index,size_t n)98 uint8_t *insert_items(size_t index, size_t n) 99 { 100 if ((index < 0) || (index > nItems)) 101 return NULL; 102 if ((nItems + n) > nCapacity) 103 { 104 size_t dn = nCapacity + n; 105 if (!realloc_capacity(dn + (dn >> 1))) 106 return NULL; 107 } 108 uint8_t *res = &vItems[index * nSizeOf]; 109 if (index < nItems) 110 ::memmove(&vItems[(index+n) * nSizeOf], res, (nItems - index)*nSizeOf); 111 nItems += n; 112 return res; 113 } 114 at(size_t index)115 uint8_t *at(size_t index) 116 { 117 return &vItems[index * nSizeOf]; 118 } 119 c_at(size_t index)120 uint8_t *c_at(size_t index) 121 { 122 return &vItems[(index % nItems) * nSizeOf]; 123 } 124 get_item(size_t index)125 uint8_t *get_item(size_t index) 126 { 127 return (index < nItems) ? &vItems[index * nSizeOf] : NULL; 128 } 129 c_get_item(size_t index)130 uint8_t *c_get_item(size_t index) 131 { 132 if (nItems == 0) 133 return NULL; 134 135 return &vItems[(index % nItems) * nSizeOf]; 136 } 137 first()138 uint8_t *first() 139 { 140 return (nItems > 0) ? vItems : NULL; 141 } 142 last()143 uint8_t *last() 144 { 145 return (nItems > 0) ? &vItems[(nItems-1)*nSizeOf] : NULL; 146 } 147 pop_last()148 uint8_t *pop_last() 149 { 150 return (nItems > 0) ? &vItems[(--nItems)*nSizeOf] : NULL; 151 } 152 do_swap_data(basic_aligned_storage * src)153 inline void do_swap_data(basic_aligned_storage *src) 154 { 155 uint8_t *_vItems = src->vItems; 156 size_t _nCapacity = src->nCapacity; 157 size_t _nItems = src->nItems; 158 size_t _nSizeOf = src->nSizeOf; 159 size_t _nAlign = src->nAlign; 160 uint8_t *_vData = src->vData; 161 162 src->vItems = vItems; 163 src->nCapacity = nCapacity; 164 src->nItems = nItems; 165 src->nSizeOf = nSizeOf; 166 src->nAlign = nAlign; 167 src->vData = vData; 168 169 vItems = _vItems; 170 nCapacity = _nCapacity; 171 nItems = _nItems; 172 nSizeOf = _nSizeOf; 173 nAlign = _nAlign; 174 vData = _vData; 175 } 176 177 public: basic_aligned_storage(size_t sz,size_t align)178 inline basic_aligned_storage(size_t sz, size_t align) 179 { 180 vItems = NULL; 181 nCapacity = 0; 182 nItems = 0; 183 nSizeOf = sz; 184 nAlign = align; 185 vData = NULL; 186 } 187 ~basic_aligned_storage()188 inline ~basic_aligned_storage() 189 { 190 flush(); 191 } 192 flush()193 void flush() 194 { 195 if (vData != NULL) 196 { 197 lsp_free(vData); 198 vData = NULL; 199 } 200 vItems = NULL; 201 nCapacity = 0; 202 nItems = 0; 203 } 204 remove(size_t idx)205 inline bool remove(size_t idx) 206 { 207 if (idx >= nItems) 208 return false; 209 if (idx != (--nItems)) 210 ::memmove(&vItems[idx * nSizeOf], &vItems[(idx+1)*nSizeOf], (nItems-idx) * nSizeOf); 211 return true; 212 } 213 remove_n(size_t idx,size_t n)214 inline bool remove_n(size_t idx, size_t n) 215 { 216 size_t last = idx + n; 217 if ((last + n) > nItems) 218 return false; 219 if ((last + n) != nItems) 220 ::memmove(&vItems[idx * nSizeOf], &vItems[last * nSizeOf], (nItems - last) * nSizeOf); 221 nItems -= n; 222 return true; 223 } 224 size()225 inline size_t size() const { return nItems; } 226 capacity()227 inline size_t capacity() const { return nCapacity; } 228 clear()229 inline void clear() { nItems = 0; } 230 231 }; 232 233 template <class T, size_t A=DEFAULT_ALIGN> 234 class castorage: public basic_aligned_storage 235 { 236 private: 237 castorage(const castorage<T, A> &src); // Disable copying 238 castorage<T, A> & operator = (const castorage<T, A> & src); // Disable copying 239 240 public: castorage()241 castorage() : basic_aligned_storage(sizeof(T), A) {}; ~castorage()242 ~castorage() {}; 243 244 public: append()245 inline T *append() { return reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); } add()246 inline T *add() { return reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); } 247 append(const T * v)248 inline T *append(const T *v) 249 { 250 T *dst = reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); 251 if (dst != NULL) 252 *dst = *v; 253 return dst; 254 } 255 append(const T * v,size_t n)256 inline T *append(const T *v, size_t n) 257 { 258 T *dst = reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); 259 if (dst != NULL) 260 ::memcpy(dst, v, n*sizeof(T)); 261 return dst; 262 } 263 append(T v)264 inline T *append(T v) 265 { 266 T *dst = reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); 267 if (dst != NULL) 268 *dst = v; 269 return dst; 270 } 271 add(const T * v)272 inline T *add(const T *v) 273 { 274 T *dst = reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); 275 if (dst != NULL) 276 *dst = *v; 277 return dst; 278 } 279 add(T v)280 inline T *add(T v) 281 { 282 T *dst = reinterpret_cast<T *>(basic_aligned_storage::alloc_item()); 283 if (dst != NULL) 284 *dst = v; 285 return dst; 286 } 287 get(size_t idx)288 inline T *get(size_t idx) { return reinterpret_cast<T *>(basic_aligned_storage::get_item(idx)); } 289 c_get(size_t idx)290 inline T *c_get(size_t idx) { return reinterpret_cast<T *>(basic_aligned_storage::c_get_item(idx)); } 291 292 inline T *operator[](size_t index) { return reinterpret_cast<T *>(basic_aligned_storage::get_item(index)); } 293 append_n(size_t n)294 inline T *append_n(size_t n) { return (n == 0) ? NULL : reinterpret_cast<T *>(basic_aligned_storage::alloc_items(n)); } 295 at(size_t index)296 inline T *at(size_t index) { return reinterpret_cast<T *>(basic_aligned_storage::at(index)); } 297 c_at(size_t index)298 inline T *c_at(size_t index) { return reinterpret_cast<T *>(basic_aligned_storage::c_at(index)); } 299 first()300 inline T *first() { return reinterpret_cast<T *>(basic_aligned_storage::first()); } 301 get_array()302 inline T *get_array() { return reinterpret_cast<T *>(basic_aligned_storage::first()); } 303 last()304 inline T *last() { return reinterpret_cast<T *>(basic_aligned_storage::last()); } 305 insert(size_t idx)306 inline T *insert(size_t idx) { return reinterpret_cast<T *>(basic_aligned_storage::insert_items(idx, 1)); } 307 insert(size_t idx,const T * v)308 inline T *insert(size_t idx, const T *v) 309 { 310 T *dst = reinterpret_cast<T *>(basic_aligned_storage::insert_items(idx, 1)); 311 if (dst != NULL) 312 *dst = *v; 313 return dst; 314 } 315 insert_n(size_t idx,size_t n)316 inline T *insert_n(size_t idx, size_t n) { return reinterpret_cast<T *>(basic_aligned_storage::insert_items(idx, n)); } 317 insert_n(size_t idx,const T * v,size_t n)318 inline T *insert_n(size_t idx, const T *v, size_t n) 319 { 320 T *dst = reinterpret_cast<T *>(basic_aligned_storage::insert_items(idx, n)); 321 if (dst != NULL) 322 ::memcpy(dst, v, n*sizeof(T)); 323 return dst; 324 } 325 remove(size_t idx)326 inline bool remove(size_t idx) { return basic_aligned_storage::remove(idx); } 327 remove(size_t idx,T * dst)328 inline bool remove(size_t idx, T *dst) 329 { 330 void *p = basic_aligned_storage::get_item(idx); 331 if (p == NULL) 332 return false; 333 *dst = *(reinterpret_cast<T *>(p)); 334 return basic_aligned_storage::remove(idx); 335 } 336 remove_n(size_t idx,size_t n)337 inline bool remove_n(size_t idx, size_t n) { return basic_aligned_storage::remove_n(idx, n); } 338 pop(T * dst)339 inline bool pop(T *dst) 340 { 341 T *src = reinterpret_cast<T *>(basic_aligned_storage::pop_last()); 342 if (src == NULL) 343 return false; 344 *dst = *src; 345 return true; 346 } 347 remove_last()348 inline bool remove_last() 349 { 350 void *ptr = basic_aligned_storage::pop_last(); 351 return ptr != NULL; 352 } 353 pop()354 inline bool pop() 355 { 356 void *ptr = basic_aligned_storage::pop_last(); 357 return ptr != NULL; 358 } 359 indexof(const T * ptr)360 inline ssize_t indexof(const T *ptr) 361 { 362 T *p = reinterpret_cast<T *>(vItems); 363 if (p == NULL) 364 return -1; 365 ssize_t idx = ptr - p; 366 return ((idx < 0) || (idx >= nItems)) ? -1 : idx; 367 } 368 swap(castorage<T,A> * src)369 inline void swap(castorage<T, A> *src) { do_swap_data(src); } 370 }; 371 } 372 373 #endif /* DATA_CASTORAGE_H_ */ 374