8 #ifndef INCL_evo_impl_container_h 9 #define INCL_evo_impl_container_h 17 #if defined(EVO_CPP11) 18 #include <initializer_list> 32 #define EVO_IMPL_CONTAINER_MEM_ALLOC1(TYPE) \ 33 (TYPE*)::malloc(sizeof(TYPE)); 34 #define EVO_IMPL_CONTAINER_MEM_ALLOC_BYTES(TYPE, BYTES) \ 35 (TYPE*)::malloc(BYTES); 36 #define EVO_IMPL_CONTAINER_MEM_FREE(PTR) { \ 37 assert( PTR != NULL ); \ 40 #define EVO_IMPL_CONTAINER_SWAP(PTR1, PTR2, TYPE) { \ 41 char temp[sizeof(TYPE)]; \ 42 memcpy(temp, PTR1, sizeof(TYPE)); \ 43 memcpy(PTR1, PTR2, sizeof(TYPE)); \ 44 memcpy(PTR2, temp, sizeof(TYPE)); \ 50 #if (defined(EVO_EXCEPTIONS_ENABLED) && !defined(EVO_EXCEPTIONS_NOGUARDS)) || defined(DOXYGEN) 52 #define EVO_EXCEPTION_GUARD_START try { 55 #define EVO_EXCEPTION_GUARD_END } catch (...) { abort(); } 57 #define EVO_EXCEPTION_GUARD_START 58 #define EVO_EXCEPTION_GUARD_END 66 static const bool SHARED =
true;
69 virtual ~Allocator() { }
75 virtual char* alloc(ulong bytes) = 0;
82 virtual char* realloc(
void* ptr, ulong bytes) = 0;
87 virtual void free(
void* ptr) = 0;
96 static const ulong INIT = 64;
97 static const ulong THRESHOLD = 134217728;
104 {
return (size < INIT ? INIT : size); }
113 static ulong
grow(ulong size) {
114 assert( size < ULONG_MAX );
115 ulong inc = (size >> 1) + 1;
118 if (ULONG_MAX - inc < size)
145 template<class T, class U=typename TypeId::Get<T>::Id>
147 #if defined(EVO_OLDCC) 160 assert( data != NULL );
163 for (ulong i=0; i<size; ++i)
164 new(&data[i]) Item();
176 static void init_safe(Item* data, ulong size,
const Item* src, ulong count) {
177 assert( data != NULL );
179 assert( src != NULL );
186 new(&data[i]) Item(src[i]);
188 new(&data[i]) Item();
198 static void init(Item* data, ulong size=1) {
199 assert( data != NULL );
202 for (ulong i=0; i<size; ++i)
203 new(&data[i]) Item();
212 static void init(Item* data,
const Item* src, ulong count) {
213 assert( data != NULL );
214 assert( src != NULL );
217 for (ulong i=0; i<count; ++i)
218 new(&data[i]) Item(src[i]);
228 static void init(Item* data, ulong size,
const Item* src, ulong count) {
229 assert( data != NULL );
231 assert( src != NULL );
238 new(&data[i]) Item(src[i]);
240 new(&data[i]) Item();
253 assert( data != NULL );
254 assert( oldSize >= 0 );
255 assert( newSize >= 0 );
257 for (ulong i = oldSize; i < newSize; ++i)
258 new(&data[i]) Item();
271 assert( data != NULL );
272 assert( oldSize >= 0 );
273 assert( newSize >= 0 );
275 for (ulong i=oldSize; i<newSize; ++i)
276 new(&data[i]) Item();
284 static void initcopy(Item* item,
const Item* src) {
285 assert( item != NULL );
286 assert( src != NULL );
288 new(*item) Item(*src);
297 static void copy(Item* dest,
const Item* src, ulong size) {
298 assert( dest != NULL );
299 assert( src != NULL );
302 for (ulong i=0; i<size; ++i)
311 static void uninit(Item* data, ulong size) {
312 assert( data != NULL );
327 assert( data != NULL );
330 for (; size > 0; ++data, --size)
333 EVO_IMPL_CONTAINER_ITEM_FREE(*data);
345 static void uninit_tail(Item* data, ulong oldSize, ulong newSize) {
346 assert( data != NULL );
347 assert( oldSize >= 0 );
348 assert( newSize >= 0 );
350 while (oldSize > newSize)
351 data[--oldSize].~T();
357 template<
class T>
struct DataInit<T, TypeId::ByteCopy> :
public DataType<T> {
358 #if defined(EVO_OLDCC) 363 static void init_safe(T* data, ulong size=1) {
364 assert( data != NULL );
367 for (ulong i=0; i<size; ++i)
371 static void init_safe(T* data, ulong size,
const T* src, ulong count) {
372 assert( data != NULL );
374 assert( src != NULL );
379 memcpy(data, src,
sizeof(T)*count);
381 for (ulong i=count; i<size; ++i)
385 static void init(T* data, ulong size=1) {
386 assert( data != NULL );
389 for (ulong i=0; i<size; ++i)
393 static void init(T* data,
const T* src, ulong count) {
394 assert( data != NULL );
395 assert( src != NULL );
397 assert( (ulong)(data < src ? (src-data) : (data-src)) >= count );
399 memcpy(data, src,
sizeof(T)*count);
401 static void init(T* data, ulong size,
const T* src, ulong count) {
402 assert( data != NULL );
404 assert( src != NULL );
409 memcpy(data, src,
sizeof(T)*count);
411 for (ulong i=count; i<size; ++i)
415 static void init_tail_safe(T* data, ulong oldSize, ulong newSize) {
416 assert( data != NULL );
417 assert( oldSize >= 0 );
418 assert( newSize >= 0 );
420 for (ulong i=oldSize; i<newSize; ++i)
424 static void init_tail_fast(T* data, ulong oldSize, ulong newSize) {
425 assert( data != NULL );
426 assert( oldSize >= 0 );
427 assert( newSize >= 0 );
429 for (ulong i=oldSize; i<newSize; ++i)
433 static void initcopy(T* item,
const T* src) {
434 assert( item != NULL );
435 assert( src != NULL );
440 static void copy(T* dest,
const T* src, ulong size) {
441 assert( dest != NULL );
442 assert( src != NULL );
445 memcpy(dest, src,
sizeof(T)*size);
447 static void uninit(T* data, ulong size) {
448 assert( data != NULL );
455 static void uninit_tail(T* data, ulong oldSize, ulong newSize) {
456 assert( data != NULL );
457 assert( oldSize >= 0 );
458 assert( newSize >= 0 );
460 while (oldSize > newSize)
461 data[--oldSize].~T();
466 #if defined(EVO_OLDCC) 471 static void init_safe(T* data, ulong size=1)
472 { memset(data, 0, size*
sizeof(T)); }
473 static void init_safe(T* data, ulong size,
const T* src, ulong count) {
474 assert( data != NULL );
476 assert( src != NULL );
481 memcpy(data, src,
sizeof(T)*count);
484 memset(data+count, 0,
sizeof(T)*size);
486 static void init(T*, ulong)
488 static void init(T* data,
const T* src, ulong count) {
489 assert( data != NULL );
490 assert( src != NULL );
493 memcpy(data, src,
sizeof(T)*count);
495 static void init(T* data, ulong size,
const T* src, ulong count) {
496 assert( data != NULL );
498 assert( src != NULL );
503 memcpy(data, src,
sizeof(T)*count);
505 static void init_tail_safe(T* data, ulong oldSize, ulong newSize) {
506 assert( data != NULL );
507 assert( oldSize >= 0 );
508 assert( newSize >= 0 );
509 if (newSize > oldSize)
510 memset(data+oldSize, 0, (newSize-oldSize)*
sizeof(T));
512 static void init_tail_fast(T*, ulong, ulong)
514 static void initcopy(T* item,
const T* src) {
515 assert( item != NULL );
516 assert( src != NULL );
517 memcpy(item, src,
sizeof(T));
519 static void copy(T* dest,
const T* src, ulong size) {
520 assert( dest != NULL );
521 assert( src != NULL );
524 memcpy(dest, src,
sizeof(T)*size);
526 static void uninit(T*, ulong)
528 static void uninit_tail(T*, ulong, ulong)
542 template<class T, class U=typename TypeId::Get<T>::Id>
544 #if defined(EVO_OLDCC) 560 {
static const T DEFAULT; val = DEFAULT; }
571 static void set_default_pod(T&)
578 #if defined(EVO_OLDCC) 584 #if EVO_UNIT_TEST_ITEMARG_REF 587 typedef Item PassType;
590 static void set_default(Item& val)
591 { memset(&val, 0,
sizeof(Item)); }
592 static void set_default_pod(Item& val)
593 { memset(&val, 0,
sizeof(Item)); }
606 template<class T, class U=typename TypeId::GetFill<T>::Id>
608 #if defined(EVO_OLDCC) 621 static void fill(T* dest, ulong size,
const T& value) {
623 for (T* end = dest + size; dest < end; ++dest)
639 static void fillends(T* dest, ulong size,
const T& value, ulong start, ulong end) {
640 assert(
sizeof(T) > 1 );
641 assert( dest != NULL );
642 assert( start < end );
645 dest[--start] = value;
646 for (; end < size; ++end)
653 template<
class T>
struct DataFill<T, TypeId::ByteCopy> :
public DataType<T> {
654 #if defined(EVO_OLDCC) 660 static void fill(T* dest, ulong size, PassType value) {
661 assert(
sizeof(T) > 1 );
662 for (T* end = dest + size; dest < end; ++dest)
663 memcpy(dest, &value,
sizeof(T));
665 static void fillends(T* dest, ulong size, PassType value, ulong start, ulong end) {
666 assert(
sizeof(T) > 1 );
667 assert( dest != NULL );
668 assert( start < end );
670 memcpy(dest + (--start), &value,
sizeof(T));
671 for (; end < size; ++end)
672 memcpy(dest + end, &value,
sizeof(T));
676 #if defined(EVO_OLDCC) 682 static void fill(T* dest, ulong size, PassType value) {
683 assert(
sizeof(T) == 1 );
685 memcpy(&cval, &value, 1);
686 memset(dest, (
int)cval, size);
688 static void fillends(T* dest, ulong size, PassType value, ulong start, ulong end) {
689 assert(
sizeof(T) == 1 );
690 assert( dest != NULL );
691 assert( start < end );
693 memcpy(&cval, &value, 1);
695 memset(dest, cval, start);
697 memset(dest+end, cval, size-end);
711 template<class T, bool B=IsPodType<T>::value>
721 static bool equal(
const T* data1,
const T* data2, ulong size) {
722 assert( data1 != NULL || size == 0 );
723 assert( data2 != NULL || size == 0 );
725 for (ulong i = 0; i < size; ++i)
726 if (!(data1[i] == data2[i]))
733 template<
class T>
struct DataEqual<T,true> {
734 static bool equal(
const T* data1,
const T* data2, ulong size) {
735 assert( data1 != NULL || size == 0 );
736 assert( data2 != NULL || size == 0 );
737 return (size == 0 || memcmp(data1, data2, size *
sizeof(T)) == 0);
752 template<class T, bool B1=IsPodType<T>::value,
bool B2=
sizeof(T) == 1>
754 #if defined(EVO_OLDCC) 769 static int compare(
const T* data1, ulong size1,
const T* data2, ulong size2) {
770 assert( data1 != NULL || size1 == 0 );
771 assert( data2 != NULL || size2 == 0 );
772 const ulong size = (size1 < size2 ? size1 : size2);
774 for (ulong i = 0; i < size; ++i) {
775 result = data1[i].compare(data2[i]);
781 else if (size2 < size1)
795 static int compare(
const T& item1,
const T& item2)
796 {
return item1.compare(item2); }
801 #if defined(EVO_OLDCC) 807 static int compare(
const T* data1, ulong size1,
const T* data2, ulong size2) {
808 assert( data1 != NULL || size1 == 0 );
809 assert( data2 != NULL || size2 == 0 );
811 if (data1 == data2) {
815 result = (size1 < size2 ? -1 : 1);
817 const T* end = data1 + (size1 < size2 ? size1 : size2);
818 for (result = 0; data1 < end; ++data1, ++data2) {
819 if (*data1 < *data2) {
822 }
else if (*data1 > *data2) {
827 if (result == 0 && (size1 != size2 || data1 != end))
828 result = (size1 < size2 ? -1 : 1);
833 static int compare(T item1, T item2)
834 {
return (item1 < item2 ? -1 : (item1 == item2 ? 0 : 1)); }
838 #if defined(EVO_OLDCC) 844 static int compare(
const T* data1, ulong size1,
const T* data2, ulong size2) {
845 assert( data1 != NULL || size1 == 0 );
846 assert( data2 != NULL || size2 == 0 );
848 if (data1 == data2) {
852 result = (size1 < size2 ? -1 : 1);
853 }
else if (size1 == size2) {
854 result = memcmp(data1, data2, size1);
855 }
else if (size1 < size2) {
856 result = memcmp(data1, data2, size1);
860 result = memcmp(data1, data2, size2);
867 static int compare(T item1, T item2)
868 {
return (item1 < item2 ? -1 : (item1 == item2 ? 0 : 1)); }
882 template<class T, class H=SpookyHash, bool B=IsPodType<T>::value>
884 #if defined(EVO_OLDCC) 899 static ulong
hash(
const T* data, ulong size, ulong seed=0) {
900 for (ulong i = 0; i < size; ++size)
901 seed = data[i].hash(seed);
912 static ulong
hash(
const T& data, ulong seed=0)
913 {
return data.hash(seed); }
918 #if defined(EVO_OLDCC) 924 static ulong hash(
const T* data, ulong size, ulong seed=0)
925 {
return H::hash(data, size*
sizeof(T), seed); }
926 static ulong hash(
const T& data, ulong seed=0)
927 {
return H::hash(&data,
sizeof(T), seed); }
938 #if defined(EVO_OLDCC) 950 virtual int operator()(PassItem a, PassItem b)
const = 0;
966 #if defined(EVO_OLDCC) 991 #if defined(EVO_OLDCC) 1013 #if defined(EVO_OLDCC) 1022 {
return a.comparei(b); }
1035 #if defined(EVO_OLDCC) 1044 {
return b.comparei(a); }
1062 #if defined(EVO_OLDCC) 1078 ulong
hash(PassItem key, ulong seed=0)
const 1106 template<
class T, u
int sz>
1113 template <
class T, u
int N> char ( &FixedArraySizeHelper(T(&array)[N]) )[N];
1120 #define EVO_FIXED_ARRAY_SIZE(ARRAY) (sizeof(evo::impl::FixedArraySizeHelper(ARRAY))) static void fillends(T *dest, ulong size, const T &value, ulong start, ulong end)
Fill each end of destination with copies of given item.
Definition: container.h:639
static void copy(Item *dest, const Item *src, ulong size)
Copy already initialized data (assignment operator).
Definition: container.h:297
Base type for comparison types.
Definition: container.h:937
#define EVO_EXCEPTION_GUARD_START
Start exception guard (try block).
Definition: container.h:52
Optimized data hash helpers.
Definition: container.h:883
static void init_tail_safe(Item *data, ulong oldSize, ulong newSize)
Initialize new tail data (default constructor).
Definition: container.h:252
static ulong grow(ulong size)
Grow data size.
Definition: container.h:113
Comparison object used with containers that order/sort items.
Definition: container.h:965
int operator()(PassItem a, PassItem b) const
Comparison method.
Definition: container.h:999
static void uninit_free_ptr(Item **data, ulong size)
Uninitialize and free array of pointers (destructor).
Definition: container.h:326
RemoveConst< T >::Type Item
Item type (const removed)
Definition: container.h:133
Comparison object used with containers that order/sort items (case-insensitive).
Definition: container.h:1012
DataCopy< T >::PassType PassItem
Best type for passing Item, either const Item& (by reference) or Item (by value) for POD types...
Definition: container.h:943
#define EVO_EXCEPTION_GUARD_END
End exception guard, catch and abort().
Definition: container.h:55
Evo implementation detail: Hashing support.
Comparison object used with containers that order/sort items (reverse).
Definition: container.h:990
Optimized container size and capacity calculation.
Definition: container.h:94
Optimized data copy helpers.
Definition: container.h:543
Optimized data initialization and uninitialization helpers.
Definition: container.h:146
static void init_tail_fast(Item *data, ulong oldSize, ulong newSize)
Initialize new tail data (default constructor).
Definition: container.h:270
const T Type
Translated type.
Definition: meta.h:325
static int compare(const T &item1, const T &item2)
Compare items.
Definition: container.h:795
static uint fixed_array_size(T(&)[sz])
Get size of fixed-length array.
Definition: container.h:1107
Data comparison helpers.
Definition: container.h:753
H HashType
Hash class type
Definition: container.h:889
Data equality helper.
Definition: container.h:712
int operator()(PassItem a, PassItem b) const
Comparison method.
Definition: container.h:1043
T Type
Translated type.
Definition: meta.h:331
static void init_safe(Item *data, ulong size, const Item *src, ulong count)
Initialize data using copy constructor and default constructor.
Definition: container.h:176
static void set_default_pod(T &val)
Set new POD value to default value (0).
Definition: container.h:569
static void initcopy(Item *item, const Item *src)
Initialize new item as copy of src (copy constructor).
Definition: container.h:284
Hash object used with containers that hash items.
Definition: container.h:1061
static void set_default(T &val)
Set value to default.
Definition: container.h:559
static ulong hash(const T *data, ulong size, ulong seed=0)
Compute hash value from data.
Definition: container.h:899
ulong hash(PassItem key, ulong seed=0) const
Hash function method.
Definition: container.h:1078
Evo C++ Library namespace.
Definition: alg.h:11
int operator()(PassItem a, PassItem b) const
Comparison method.
Definition: container.h:974
int operator()(PassItem a, PassItem b) const
Comparison method.
Definition: container.h:1021
static bool equal(const T *data1, const T *data2, ulong size)
Compare array data for equality.
Definition: container.h:721
Base data type for optimizated data helpers.
Definition: container.h:132
static void uninit(Item *data, ulong size)
Uninitialize data (destructor).
Definition: container.h:311
static int compare(const T *data1, ulong size1, const T *data2, ulong size2)
Compare data.
Definition: container.h:769
Optimized data fill helpers.
Definition: container.h:607
AddConst< T >::Type & PassType
Most efficient type for passing as parameter (const-reference or POD value).
Definition: container.h:551
static void init(Item *data, ulong size=1)
Initialize data using default constructor.
Definition: container.h:198
Compare< T > CompareBase
Base compare type.
Definition: container.h:1069
static void fill(T *dest, ulong size, const T &value)
Fill with copies of given item.
Definition: container.h:621
static void init(Item *data, const Item *src, ulong count)
Initialize data using copy constructor.
Definition: container.h:212
static void init_safe(Item *data, ulong size=1)
Initialize data using default constructor.
Definition: container.h:159
static ulong init(ulong size)
Get initial data size.
Definition: container.h:103
static void init(Item *data, ulong size, const Item *src, ulong count)
Initialize data using copy constructor and default constructor.
Definition: container.h:228
static void uninit_tail(Item *data, ulong oldSize, ulong newSize)
Uninitialize old tail data (destructor).
Definition: container.h:345
static ulong hash(const T &data, ulong seed=0)
Compute hash value from data.
Definition: container.h:912
Comparison object used with containers that order/sort items (case-insensitive, reverse).
Definition: container.h:1034