acme
Foundational cross-platform layer of the ca2 framework
Loading...
Searching...
No Matches
aaa__array_base_impl.h
1
2
3
4template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
5base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::base_array()
6{
7
8 m_nGrowBy = 0;
9 m_pData = nullptr;
10 m_nSize = 0;
11 m_nMaxSize = 0;
12
13}
14
15
16
17
18template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
19base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::~base_array ()
20{
21
22 if (m_pData != nullptr)
23 {
24
25 destroy();
26
27 }
28
29}
30
31
32template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
33::collection::count base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::resize(::collection::count nNewSize, ARG_TYPE t, ::collection::count nGrowBy)
34{
35
36 return allocate(nNewSize, nGrowBy, &t);
37
38}
39
40
41template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
42::collection::count base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::allocate_in_bytes(::collection::count nNewSize,::collection::count nGrowBy)
43{
44
45 if(nGrowBy < 0)
46 {
47
48 return allocate(nNewSize / sizeof(TYPE),-1);
49
50 }
51 else
52 {
53
54 return allocate(nNewSize / sizeof(TYPE),nGrowBy / sizeof(TYPE));
55
56 }
57
58}
59
60
61template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
62::collection::index base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::erase_at(::collection::index nIndex,::collection::count nCount)
63{
64
65 //ASSERT_OK(this);
66
67 ::collection::index nUpperBound = nIndex + nCount;
68
69 if (nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount))
70 {
71
72 throw ::exception(error_bad_argument);
73
74 }
75
76 ::collection::count nMoveCount = m_nSize - (nUpperBound);
77
78 ALLOCATOR::destruct_count(m_pData + nIndex, nCount REFERENCING_DEBUGGING_COMMA_THIS);
79
80 if(nMoveCount)
81 {
82 ::safe_memory_transfer(m_pData + nIndex,(size_t)nMoveCount * sizeof(TYPE),m_pData + nUpperBound,(size_t)nMoveCount * sizeof(TYPE));
83 }
84
85 m_nSize -= nCount;
86
87 return nIndex;
88
89}
90
91
92template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
93::collection::index base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::erase_item(TYPE * p)
94{
95
96 return erase_at(p - m_pData);
97
98}
99
100
101
102template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
103void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::free_extra()
104{
105
106 if(m_nSize != m_nMaxSize)
107 {
108 // shrink to desired i32_size
109#ifdef SIZE_T_MAX
110 ASSERT(m_nSize <= SIZE_T_MAX / sizeof(TYPE)); // no overflow
111#endif
112 TYPE* pNewData = nullptr;
113 if(m_nSize != 0)
114 {
115 TYPE * pNewData;
116#if defined(__MCRTDBG) || MEMDLEAK
117#ifdef __MCRTDBG
118 if (::get_task() != nullptr)
119 {
120 if (::get_task()->m_strFile.has_character())
121 {
122 pNewData = ALLOCATOR::alloc(m_nSize, ::get_task()->m_strFile, ::get_task()->m_iLine);
123 }
124 else
125 {
126 pNewData = ALLOCATOR::alloc(m_nSize, __FILE__, __LINE__);
127 }
128 }
129 else
130 {
131 pNewData = ALLOCATOR::alloc(m_nSize, __FILE__, __LINE__);
132 }
133#else
134
135 if (::get_task_object_debug().has_character())
136 {
137
138 pNewData = ALLOCATOR::alloc(m_nSize, ::get_task_object_debug(), 0);
139
140 }
141 else
142 {
143
144 pNewData = ALLOCATOR::alloc(m_nSize, __FILE__, __LINE__);
145
146 }
147
148#endif
149
150#else
151
152 pNewData = ALLOCATOR::alloc(m_nSize);
153
154#endif // copy aaa_primitive_new data from old
155
156 // copy aaa_primitive_new data from old
157 ::safe_memory_copy(pNewData, (size_t)m_nSize * sizeof(TYPE),m_pData, (size_t)m_nSize * sizeof(TYPE));
158
159 }
160
161 // get rid of old stuff (note: no destructors called)
162 ALLOCATOR::_free(m_pData);
163
164 m_pData = pNewData;
165
166 m_nMaxSize = m_nSize;
167
168 }
169
170}
171
172
173
174template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
175void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::destroy()
176{
177
178 if(m_pData != nullptr)
179 {
180
181 ALLOCATOR::destruct_count(m_pData, m_nSize REFERENCING_DEBUGGING_COMMA_THIS);
182
183 ALLOCATOR::_free(m_pData);
184
185 m_pData = nullptr;
186 m_nSize = 0;
187 m_nMaxSize = 0;
188
189 }
190
191}
192
193
194template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
195::collection::index base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::insert_at(::collection::index nIndex,const TYPE & newElement,::collection::count nCount /*=1*/)
196{
197
198 ::collection::index nIndexParam = make_room_at(nIndex, nCount);
199
200 while(nCount--)
201 {
202
203 ALLOCATOR::copy(m_pData + nIndex, &newElement);
204
205 nIndex++;
206
207 }
208
209 return nIndexParam;
210
211}
212
213template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
214::collection::index base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::make_room_at(::collection::index nIndex, ::collection::count nCount /*=1*/)
215{
216
217 ASSERT(nIndex >= 0); // will expand to meet need
218
219 if(nCount <= 0)
220 return -1;
221
222 if(nIndex < 0)
223 throw ::exception(error_bad_argument);
224
225 if(nIndex >= m_nSize)
226 {
227
228 // adding after the end of the array
229 set_size(nIndex + nCount,-1); // grow so nIndex is valid
230
231 }
232 else
233 {
234
235 // inserting in the middle of the array
236 ::collection::count nOldSize = (::collection::count) m_nSize;
237
238 set_size((::collection::count) m_nSize + nCount,-1); // grow it to aaa_primitive_new i32_size
239 // destroy intial data before copying over it
240 // shift old data up to fill gap
241 ::safe_memory_transfer(m_pData + nIndex + nCount,(size_t) ((nOldSize - nIndex) * sizeof(TYPE)),m_pData + nIndex,(size_t)((nOldSize - nIndex) * sizeof(TYPE)));
242
243 ::zero(m_pData + nIndex, nCount* sizeof(TYPE));
244
245 ALLOCATOR::construct_count(m_pData + nIndex,nCount);
246
247 }
248
249 // insert aaa_primitive_new value in the gap
250 ASSERT(nIndex + nCount <= m_nSize);
251
252 return nIndex;
253
254}
255
256
257
258template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
259::collection::count base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::append(const base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & src)
260{
261
262 ::collection::count nOldSize = m_nSize;
263
264 ::collection::count nSrcSize = src.m_nSize; // to enable to append to itself
265
266 allocate(nOldSize + nSrcSize);
267
268 ALLOCATOR::copy_count(m_pData + nOldSize, src.m_pData, nSrcSize);
269
270 return nOldSize;
271
272}
273
274
275template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
276void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::copy(const base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & src)
277{
278
279 if(this == &src)
280 {
281
282 return;
283
284 }
285
286 ::collection::count nSrcSize = src.m_nSize;
287
288 allocate(nSrcSize);
289
290 ALLOCATOR::copy_count(m_pData,src.m_pData, nSrcSize);
291
292}
293
294
295
296// take in accptr that _001RemoveIndexes machine
297// the ::collection::index raw_array by sorting it and returning
298// only the indexes that could be erased
299// without indexes duplicates
300template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
301void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::_001RemoveIndexes(index_array & ia)
302{
303
304 // sort
305 ::sort::quick_sort(ia,true);
306
307 ::collection::index i = ia.get_upper_bound();
308
309 // filter out of upper bound indexes
310 while(i >= 0 && ia[i] >= get_size())
311 {
312
313 ia.erase_at(i);
314
315 i--;
316
317 }
318
319 // filter out of lower bound indexes
320 while(ia.get_size() > 0 && ia[0] < 0)
321 {
322
323 ia.erase_at(0);
324
325 }
326
327 i = ia.get_upper_bound();
328
329 // filter out duplicates
330 while(i > 0 && ia[i] >= get_size())
331 {
332
333 if(ia[i] == ia[i - 1])
334 ia.erase_at(i);
335
336 i--;
337
338 }
339
340 erase_indexes(ia);
341
342}
343
344
345template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
346void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::erase_indexes(const index_array & ia)
347{
348
349
350 // erase indexes
351 for(::collection::index i = ia.get_upper_bound(); i >= 0; i--)
352 {
353
354 erase_at(ia[i]);
355
356 }
357
358}
359
360
361template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
362void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::erase_descending_indexes(const index_array & ia)
363{
364
365 for(::collection::index i = 0; i < ia.get_count(); i++)
366 {
367
368 erase_at(ia[i]);
369
370 }
371
372}
373
374
375
376template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
377::collection::index base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::insert_at(::collection::index nIndex,base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > * pNewArray)
378{
379
380 ASSERT(pNewArray != nullptr);
381 ASSERT(nIndex >= 0); // will expand to meet need
382
383 ::collection::count nCount = pNewArray->get_size();
384
385 if (nCount <= 0)
386 return -1;
387
388 if (nIndex < 0)
389 throw ::exception(error_bad_argument);
390
391 if (nIndex >= m_nSize)
392 {
393
394 // adding after the end of the array
395 set_size(nIndex + nCount, -1); // grow so nIndex is valid
396
397 }
398 else
399 {
400
401 // inserting in the middle of the array
402 ::collection::count nOldSize = (::collection::count) m_nSize;
403
404 set_size((::collection::count) (m_nSize + nCount), -1); // grow it to aaa_primitive_new i32_size
405 // destroy intial data before copying over it
406 // shift old data up to fill gap
407 ::safe_memory_transfer(m_pData + nIndex + nCount, (size_t) ((nOldSize - nIndex) * sizeof(TYPE)), m_pData + nIndex, (size_t) ((nOldSize - nIndex) * sizeof(TYPE)));
408
409 ::zero(m_pData + nIndex, nCount* sizeof(TYPE));
410
411 ALLOCATOR::construct_count(m_pData + nIndex, nCount);
412
413 }
414
415 // insert aaa_primitive_new value in the gap
416 ASSERT(nIndex + nCount <= m_nSize);
417
418 ::collection::index nIndexParam = nIndex;
419
420 ::collection::index i = 0;
421
422 while (nCount--)
423 {
424
425 ALLOCATOR::copy(m_pData + nIndex, pNewArray->m_pData + i);
426
427 nIndex++;
428
429 }
430
431 return nIndexParam;
432
433
434}
435
436
437template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
438TYPE base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::pick_at(::collection::index nIndex)
439{
440
441 ::collection::count nCount = 1;
442
443 ::collection::index nUpperBound = nIndex + nCount;
444
445 if (nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount))
446 {
447
448 throw ::exception(error_bad_argument);
449
450 }
451
452 ::collection::count nMoveCount = m_nSize - (nUpperBound);
453
454 auto t = m_pData[nIndex];
455
456 ALLOCATOR::destruct_count(m_pData + nIndex, nCount REFERENCING_DEBUGGING_COMMA_THIS);
457
458 if (nMoveCount)
459 {
460
461 ::safe_memory_transfer(m_pData + nIndex, (size_t)nMoveCount * sizeof(TYPE), m_pData + nUpperBound, (size_t)nMoveCount * sizeof(TYPE));
462
463 }
464
465 m_nSize -= nCount;
466
467 return ::transfer(t);
468
469}
470
471
472template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
473base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::pick_at(::collection::index nIndex, ::collection::count nCount)
474{
475
476 //ASSERT_OK(this);
477
478 ::collection::index nUpperBound = nIndex + nCount;
479
480 if (nIndex < 0 || nCount < 0 || (nUpperBound > m_nSize) || (nUpperBound < nIndex) || (nUpperBound < nCount))
481 {
482
483 throw ::exception(error_bad_argument);
484
485 }
486
487 ::collection::count nMoveCount = m_nSize - (nUpperBound);
488
489 base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > a(m_pData + nIndex, (size_t)nMoveCount);
490
491 ALLOCATOR::destruct_count(m_pData + nIndex, nCount REFERENCING_DEBUGGING_COMMA_THIS);
492
493 if (nMoveCount)
494 {
495
496 ::safe_memory_transfer(m_pData + nIndex, (size_t)nMoveCount * sizeof(TYPE), m_pData + nUpperBound, (size_t)nMoveCount * sizeof(TYPE));
497
498 }
499
500 m_nSize -= nCount;
501
502 return a;
503
504}
505
506
507template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
508::collection::count base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::set_raw_size(::collection::count nNewSize,::collection::count nGrowBy)
509{
510
511 ::collection::count countOld = get_count();
512
513 ASSERT(nNewSize >= 0);
514
515 if(nNewSize < 0)
516 throw ::exception(error_bad_argument);
517
518 if(nGrowBy >= 0)
519 m_nGrowBy = nGrowBy; // set aaa_primitive_new i32_size
520
521 if(nNewSize == 0)
522 {
523
524 // shrink to nothing
525 if(m_pData != nullptr)
526 {
527
528 ALLOCATOR::_free(m_pData);
529
530 m_pData = nullptr;
531
532 }
533
534 m_nSize = m_nMaxSize = 0;
535 }
536 else if (m_pData == nullptr)
537 {
538 // create buffer big enough to hold number of requested elements or
539 // m_nGrowBy elements, whichever is larger.
540#ifdef SIZE_T_MAX
541 if (nNewSize > SIZE_T_MAX / sizeof(TYPE))
542 throw ::exception(error_no_memory);
543 ASSERT(nNewSize <= SIZE_T_MAX / sizeof(TYPE)); // no overflow
544#endif
545 ::collection::count nAllocSize = (::collection::count) maximum(nNewSize, m_nGrowBy);
546#if defined(__MCRTDBG) || MEMDLEAK
547 if (::get_task() != nullptr)
548 {
549#if defined(MEMDLEAK)
550
551 if (::get_task()->m_strFile.has_character())
552 {
553
554 m_pData = ALLOCATOR::alloc(nAllocSize, ::get_task()->m_strFile, 0);
555
556 }
557 else
558 {
559
560 m_pData = ALLOCATOR::alloc(nAllocSize, __FILE__, __LINE__);
561
562 }
563
564#else
565
566 if (::get_task_object_debug().has_character())
567 {
568
569 m_pData = ALLOCATOR::alloc(nAllocSize, ::get_task_object_debug(), ::get_task()->m_iLine);
570
571 }
572 else
573 {
574
575 m_pData = ALLOCATOR::alloc(nAllocSize, __FILE__, __LINE__);
576
577 }
578
579#endif
580
581 }
582 else
583 {
584
585 m_pData = ALLOCATOR::alloc(nAllocSize, __FILE__, __LINE__);
586
587 }
588
589#else
590
591 m_pData = ALLOCATOR::alloc(nAllocSize);
592
593#endif
594
595 m_nSize = nNewSize;
596 m_nMaxSize = nAllocSize;
597 }
598 else if(nNewSize <= m_nMaxSize)
599 {
600 m_nSize = nNewSize;
601 }
602 else
603 {
604 // otherwise, grow aaa_base_array
605 nGrowBy = (::collection::count) m_nGrowBy;
606 if(nGrowBy == 0)
607 {
608 // heuristically determine growth when nGrowBy == 0
609 // (this avoids heap fragmentation in many situations)
610 nGrowBy = (::collection::count) m_nSize;
611 nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy);
612 }
613 ::collection::count nNewMax;
614 if(nNewSize < m_nMaxSize + nGrowBy)
615 nNewMax = (::collection::count) (m_nMaxSize + nGrowBy); // granularity
616 else
617 nNewMax = nNewSize; // no slush
618
619 ASSERT(nNewMax >= m_nMaxSize); // no wrap around
620
621 if(nNewMax < m_nMaxSize)
622 throw ::exception(error_bad_argument);
623
624#ifdef SIZE_T_MAX
625 ASSERT(nNewMax <= SIZE_T_MAX / sizeof(TYPE)); // no overflow
626#endif
627 TYPE * pNewData;
628#if defined(__MCRTDBG) || MEMDLEAK
629#ifdef __MCRTDBG
630
631 if (::get_task() != nullptr)
632 {
633
634 if (::get_task()->m_strFile.has_character())
635 {
636
637 pNewData = ALLOCATOR::alloc(nNewMax, ::get_task()->m_strFile, ::get_task()->m_iLine);
638
639 }
640 else
641 {
642
643 pNewData = ALLOCATOR::alloc(nNewMax, __FILE__, __LINE__);
644
645 }
646
647 }
648 else
649 {
650
651 pNewData = ALLOCATOR::alloc(nNewMax, __FILE__, __LINE__);
652
653 }
654
655#else
656
657 if (::get_task_object_debug().has_character())
658 {
659
660 pNewData = ALLOCATOR::alloc(nNewMax, ::get_task_object_debug(), ::get_task()->m_iLine);
661
662 }
663 else
664 {
665
666 pNewData = ALLOCATOR::alloc(nNewMax, __FILE__, __LINE__);
667
668 }
669
670#endif
671
672#else
673
674 pNewData = ALLOCATOR::alloc(nNewMax);
675
676#endif // copy aaa_primitive_new data from old
677
678 ::safe_memory_copy(pNewData,(size_t)nNewMax * sizeof(TYPE),m_pData,(size_t)m_nSize * sizeof(TYPE));
679
681 // get rid of old stuff (note: no destructors called)
682 ALLOCATOR::_free(m_pData);
683
684 m_pData = pNewData;
685
686 m_nSize = nNewSize;
687
688 m_nMaxSize = nNewMax;
689
690 }
691
692 return countOld;
693
694}
695
696
697template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
698::collection::count base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::allocate(::collection::count nNewSize,::collection::count nGrowBy, const TYPE * ptype)
699{
700
701 ::collection::count countOld = get_count();
702
703 ASSERT(nNewSize >= 0);
704
705 if(nNewSize < 0)
706 {
707
708 throw ::exception(error_bad_argument);
709
710 }
711
712 if(nGrowBy >= 0)
713 {
714
715 m_nGrowBy = nGrowBy; // set aaa_primitive_new i32_size
716
717 }
718
719
720 if(nNewSize == m_nSize)
721 {
722
723 return m_nSize;
724
725 }
726
727 if(nNewSize == 0)
728 {
729
730 // shrink to nothing
731 if(m_pData != nullptr)
732 {
733
734 ALLOCATOR::destruct_count(m_pData, m_nSize REFERENCING_DEBUGGING_COMMA_THIS);
735
736 ALLOCATOR::_free(m_pData);
737
738 m_pData = nullptr;
739
740 }
741
742 m_nSize = m_nMaxSize = 0;
743
744 }
745 else if(m_pData == nullptr)
746 {
747
748 // create buffer big enough to hold number of requested elements or
749 // m_nGrowBy elements, whichever is larger.
750#ifdef SIZE_T_MAX
751 if(::comparison::gt(nNewSize, SIZE_T_MAX / sizeof(TYPE)))
752 throw ::exception(error_no_memory);
753 ASSERT(::comparison::lt(nNewSize, SIZE_T_MAX / sizeof(TYPE))); // no overflow
754#endif
755
756 auto nAllocSize = maximum(nNewSize, m_nGrowBy);
757
758#if MEMDLEAK || defined(__MCRTDBG)
759
760 if(::get_task() != nullptr)
761 {
762
763#if defined(__MCRTDBG)
764
765 if(::get_task()->m_strFile.has_character())
766 {
767
768 m_pData = ALLOCATOR::alloc(nAllocSize, ::get_task()->m_strFile, ::get_task()->m_iLine);
769
770 }
771 else
772 {
773
774 m_pData = ALLOCATOR::alloc(nAllocSize, __FILE__, __LINE__);
775
776 }
777
778#else
779
780 if (::get_task_object_debug().has_character())
781 {
782
783 m_pData = ALLOCATOR::alloc(nAllocSize, "thread://" + ::get_task_object_name() + ", " + ::get_task_object_debug() + ", " + string(__FILE__), __LINE__;
784
785 }
786 else
787 {
788
789 m_pData = ALLOCATOR::alloc(nAllocSize, "thread://" + ::get_task_object_name() + ", " + string(__FILE__), __LINE__;
790
791 }
792
793#endif
794
795 }
796 else
797 {
798
799 m_pData = ALLOCATOR::alloc(nAllocSize, __FILE__, __LINE__);
800
801 }
802
803#else
804
805 m_pData = ALLOCATOR::alloc(nAllocSize);
806
807#endif
808
809 if (::is_null(ptype))
810 {
811
812 ALLOCATOR::construct_count(m_pData, nNewSize);
813
814 }
815 else
816 {
817
818 ALLOCATOR::copy_construct_count(m_pData, nNewSize, *ptype);
819
820 }
821
822 m_nSize = nNewSize;
823
824 m_nMaxSize = nAllocSize;
825
826 }
827 else if(nNewSize <= m_nMaxSize)
828 {
829
830 if(nNewSize > m_nSize)
831 {
832
833 if (::is_null(ptype))
834 {
835
836 ALLOCATOR::construct_count(m_pData + m_nSize, nNewSize - m_nSize);
837
838 }
839 else
840 {
841
842 ALLOCATOR::copy_construct_count(m_pData + m_nSize, nNewSize - m_nSize, *ptype);
843
844 }
845
846 }
847 else if(m_nSize > nNewSize)
848 {
849
850 ALLOCATOR::destruct_count(m_pData + nNewSize,m_nSize - nNewSize REFERENCING_DEBUGGING_COMMA_THIS);
851
852 }
853
854 m_nSize = nNewSize;
855
856 }
857 else
858 {
859
860 // otherwise, grow aaa_base_array
861 nGrowBy = m_nGrowBy;
862
863 if(nGrowBy == 0)
864 {
865
866 // heuristically determine growth when nGrowBy == 0
867 // (this avoids heap fragmentation in many situations)
868 nGrowBy = m_nSize;
869 nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy);
870
871 }
872
873 ::collection::count nNewMax;
874
875 if(nNewSize < m_nMaxSize+ nGrowBy)
876 {
877
878 nNewMax = m_nMaxSize+ nGrowBy; // granularity
879
880 }
881 else
882 {
883
884 nNewMax = nNewSize; // no slush
885
886 }
887
888 ASSERT(nNewMax >= m_nMaxSize); // no wrap around
889
890 if(nNewMax < m_nMaxSize)
891 {
892
893 throw ::exception(error_bad_argument);
894
895 }
896
897#ifdef SIZE_T_MAX
898
899 ASSERT(::comparison::lt(nNewMax, SIZE_T_MAX / sizeof(TYPE))); // no overflow
900
901#endif
902
903#if MEMDLEAK || defined(__MCRTDBG)
904
905 TYPE* pNewData = nullptr;
906
907 if(::get_task() != nullptr)
908 {
909
910#if defined(__MCRTDBG)
911
912 if(::get_task()->m_strFile.has_character())
913 {
914
915 pNewData = ALLOCATOR::alloc(nNewMax, ::get_task()->m_strFile,::get_task()->m_iLine);
916
917 }
918 else
919 {
920
921 pNewData = ALLOCATOR::alloc(nNewMax, __FILE__, __LINE__);
922
923 }
924
925#else
926
927 if (::get_task_object_debug().has_character())
928 {
929
930 pNewData = ALLOCATOR::alloc(nNewMax, "thread://" + ::get_task_object_name() + ", " + ::get_task_object_debug() + ", " + string(__FILE__), __LINE__;
931
932 }
933 else
934 {
935
936 pNewData = ALLOCATOR::alloc(nNewMax, "thread://" + ::get_task_object_name() + ", " + string(__FILE__), __LINE__;
937
938 }
939
940#endif
941
942 }
943 else
944 {
945
946 pNewData = ALLOCATOR::alloc(nNewMax, __FILE__, __LINE__);
947
948 }
949
950
951#else
952
953 TYPE* pNewData = ALLOCATOR::alloc(nNewMax);
954
955#endif
956
957 // copy aaa_primitive_new data from old
958 ::safe_memory_copy(pNewData,(size_t)nNewMax * sizeof(TYPE),m_pData,(size_t)m_nSize * sizeof(TYPE));
959
960 // construct remaining elements
961 ASSERT(nNewSize > m_nSize);
962
963 if (nNewSize > m_nSize)
964 {
965
966 if (::is_null(ptype))
967 {
968
969 ALLOCATOR::construct_count(pNewData + m_nSize, nNewSize - m_nSize);
970
971 }
972 else
973 {
974
975 ALLOCATOR::copy_construct_count(pNewData + m_nSize, nNewSize - m_nSize, *ptype);
976
977 }
978
979 }
980
981 // get rid of old stuff (note: no destructors called)
982 ALLOCATOR::_free(m_pData);
983
984 m_pData = pNewData;
985
986 m_nSize = nNewSize;
987
988 m_nMaxSize = nNewMax;
989
990 }
991
992 return countOld;
993
994}
995
996
997
998template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
999void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::on_after_read()
1000{
1001
1002
1003}
1004
1005
1006
1007
1008
1009template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
1010inline void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::set_at_grow(::collection::index nIndex, ARG_TYPE newElement, ::collection::count nGrowBy)
1011{
1012
1013 ASSERT(nIndex >= 0);
1014
1015 if (nIndex >= this->m_nSize)
1016 {
1017
1018 this->set_size(nIndex + 1, nGrowBy);
1019
1020 }
1021
1022 m_pData[nIndex] = newElement;
1023
1024}
1025
1026
1027template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
1028inline TYPE & base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::element_at_grow(::collection::index nIndex, ::collection::count nGrowBy)
1029{
1030
1031 ASSERT(nIndex >= 0);
1032
1033 if (nIndex >= this->m_nSize)
1034 {
1035
1036 this->set_size(nIndex + 1, nGrowBy);
1037
1038 }
1039
1040 return m_pData[nIndex];
1041
1042}
1043
1044
1045template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
1046inline void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::set_each(ARG_TYPE element, ::collection::index first, ::collection::count in_count_out_last)
1047{
1048
1049 prepare_first_in_count_last_out(first, in_count_out_last);
1050
1051 for(::collection::index i = first; i <= in_count_out_last; i++)
1052 {
1053
1054 m_pData[i] = element;
1055
1056 }
1057
1058}
1059
1060template < typename TYPE, typename ARG_TYPE, typename ALLOCATOR, ::enum_type t_etypeContainer >
1061 template < typename ITERATOR >
1062 inline void base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::erase(const ITERATOR & begin, const ITERATOR & last) { ::erase(*this, begin, last); }
::collection::count allocate(::collection::count nNewSize, bool bShrink, bool bRaw, P &p)
if bRaw is true does not call default constructors on ___new elements
Definition base_array.h:972
::collection::index erase_at(::collection::index nIndex, ::collection::count nCount=1)
Definition aaa__array_base_impl.h:62