3DCoat Core API
The 3DCoat API documentation.
Loading...
Searching...
No Matches
cList.h
1#pragma once
2
3//--------------------------------------------------------------------------------------------------------------|
4// Speed comparison between "cList<>::Ctor / cList<>" (sec) |
5//--------------------------------------------------------------------------------------------------------------|
6// "100" times allocate "500000" elements and free them |
7// | cStr | int | float | cVec3 |
8// Debug 32 | 11.76 / 2.06 (x 5.7) | 0.18 / 0.18 (x 1.0) | 0.18 / 0.18 (x 1.0) | 2.44 / 0.70 (x 3.5) |
9// Release 32 | 2.06 / 0.01 (x 298.3) | 0.00 / 0.00 (x 1.1) | 0.00 / 0.00 (x 1.0) | 0.00 / 0.00 (x 1.0) |
10// Debug 64 | 5.59 / 2.57 (x 2.2) | 0.19 / 0.19 (x 1.0) | 0.19 / 0.19 (x 1.0) | 0.94 / 0.69 (x 1.4) |
11// Release 64 | 2.62 / 0.01 (x 311.0) | 0.00 / 0.00 (x 1.1) | 0.00 / 0.00 (x 1.0) | 0.00 / 0.00 (x 1.0) |
12//--------------------------------------------------------------------------------------------------------------|
13// "500000" times allocate "100" elements and free them |
14// | cStr | int | float | cVec3 |
15// Debug 32 | 19.64 / 6.93 (x 2.8) | 1.70 / 1.12 (x 1.5) | 1.70 / 1.09 (x 1.6) | 4.98 / 2.10 (x 2.4) |
16// Release 32 | 3.41 / 2.10 (x 1.6) | 1.13 / 0.74 (x 1.5) | 1.84 / 1.45 (x 1.3) | 3.36 / 2.93 (x 1.1) |
17// Debug 64 | 7.58 / 3.23 (x 2.3) | 2.23 / 1.70 (x 1.3) | 2.37 / 1.74 (x 1.4) | 5.11 / 4.23 (x 1.2) |
18// Release 64 | 5.07 / 4.18 (x 1.2) | 0.86 / 0.59 (x 1.5) | 0.86 / 0.59 (x 1.5) | 3.60 / 3.33 (x 1.1) |
19//--------------------------------------------------------------------------------------------------------------|
20
21//*****************************************************************************
22// cList_DefCompare
23//*****************************************************************************
24template<class TYPE>
25inline int cList_DefCompare(const TYPE *l, const TYPE *r) {
26 if(*l > *r) {
27 return 1;
28 } else if(*l < *r) {
29 return -1;
30 } else {
31 return 0;
32 }
33}
34
35//*****************************************************************************
36// cList_DefEquals
37//*****************************************************************************
38template<class TYPE>
39inline bool cList_DefEquals(const TYPE *l, const TYPE *r) {
40 return *l == *r;
41}
42
43// @todo fine Rewrite by explicit specialization on the VS2013.
44inline bool cList_DefEqualsFloat(const float *l, const float *r) {
45 return cMath::Equals( *l, *r );
46}
47
48// cList_Debug
49struct APICALL cList_Debug {
50 static int ContainersCount;
51 static int CtorContainersCount;
52};
53
54//*****************************************************************************
55// cList_Container
56//*****************************************************************************
57template<class TYPE>
58class cList_Container { // most common container
59public:
60 int Count, Capacity;
61 TYPE List[1024];
62 static cList_Container * New(const int Capacity) {
63 //cList_Debug::ContainersCount++;
64 const size_t ST = sizeof(TYPE); // TYPE == std::function: macOS 48, Windows 64, Linux 32
65 const size_t Size = 8 + Capacity * ST; // 8 bytes for fields "Count" and "Capacity"
66 //byte* Ptr = new byte[Size]; // Aligned by: macOS 16, Windows 16, Linux 16
67 byte* Ptr = (byte*)malloc(Size); // Aligned by: macOS 16, Windows 16, Linux 16
68 cList_Container *C = (cList_Container *)Ptr; // This conversion applies alignment.
69 const bool Triv = std::is_trivially_default_constructible<TYPE>();
70 if (!Triv){
71 for (int i = 0; i < Capacity; i++) {
72 // Note that "std::alignment_of<std::function<void()>>::value" is macOS 16, Windows 8, Linux 8.
73 // When "TYPE == std::function" under macOS the gap between "Capacity" and element "List[0]" is 8 bytes.
74 // That is why we should not use a byte pointer (or we should respect the gap) to call the default constructors here.
75 new (&C->List[i])TYPE();
76 }
77 }
78 return C;
79 }
80 static void Free(cList_Container *Ptr) {
81 //cList_Debug::ContainersCount--;
82 //delete[]((byte*)Ptr);
83 free(Ptr);
84 }
85 void Copy(cList_Container* to, int Count) const {
86 if (std::is_trivially_copy_constructible<TYPE>()){
87 memcpy(((byte*)to) + 8, List, Count*sizeof(TYPE));
88 }
89 else{
90 for (int i = 0; i < Count; i++){
91 to->List[i] = List[i];
92 }
93 }
94 }
95 void DestroyElements(){
96 if (std::is_compound<TYPE>()){
97 for (int i = 0; i < Capacity; i++){
98 List[i].~TYPE();
99 }
100 }
101 }
102}; // cList_Container
103
104//*****************************************************************************
105// cList_TrivialContainer
106//*****************************************************************************
107template<class TYPE>
108class cList_TrivialContainer { // Doesn't call constructors/destructors in the lists like "cList<cStr>"
109public:
110 int Count, Capacity;
111 TYPE List[1024];
112 static cList_TrivialContainer * New(const int Capacity) {
113 //cList_Debug::ContainersCount++;
114 size_t Size = 8 + Capacity * sizeof(TYPE);
115 byte *Ptr = (byte*)malloc(Size);
116 return (cList_TrivialContainer *)Ptr;
117 }
118 static void Free(cList_TrivialContainer *Ptr) {
119 //cList_Debug::ContainersCount--;
120 //delete[]((byte*)Ptr);
121 free(Ptr);
122 }
123 void Copy(cList_TrivialContainer* to, int Count) const {
124 memcpy(((byte*)to) + 8, List, Count*sizeof(TYPE));
125 }
126 void DestroyElements(){
127 }
128}; // cList_Container
129
135template <class TYPE, class CONTAINER = cList_Container<TYPE> >
136class cList {
137public:
138 // you can use it for agile grab the types in the code
139 // # By analogy with the STL-containers.
140 typedef TYPE value_type;
141 typedef CONTAINER container_type;
142
143 typedef cList<TYPE, cList_Container<TYPE> > Ctor; // C++ doesn't support template typedefs. Use for type "cList<cStr>::Ctor".
144
145 typedef int Compare(const TYPE *, const TYPE *);
146
147 struct CompareFunctor {
148 virtual ~CompareFunctor() {}
149 virtual bool operator()( const TYPE& a, const TYPE& b ) const = 0;
150 };
151
152 typedef bool Equals(const TYPE *, const TYPE *);
153
154 typedef TYPE* iterator;
155 iterator begin() {
156 return m_Container ? m_Container->List : nullptr;
157 }
158 iterator end() {
159 return m_Container ? m_Container->List + m_Container->Count : nullptr;
160 }
161
162 iterator begin() const {
163 return m_Container ? m_Container->List : nullptr;
164 }
165 iterator end() const {
166 return m_Container ? m_Container->List + m_Container->Count : nullptr;
167 }
168 //-------------------------------------------------------------------------
169 // .ctor
170 //-------------------------------------------------------------------------
171 cList();
172 cList(const cList<TYPE, CONTAINER> &Src);
173 cList(const TYPE *Src, const int Count); // cList<int> U(I, 100);
174 explicit cList(const int Count); // cList<int> T(20);
175 cList(const int Count, const TYPE &Fill); // cList<int> Z(20, 0);
176
177 // .dtor
178 ~cList();
179
180 size_t Size() const; // Total size of used for elements memory (bytes)
181 size_t SizeCapacity() const; // Total size of allocated memory (bytes)
182
183 // Assignment operators
184 void Copy(const cList<TYPE, CONTAINER> &Src);
185 void Copy(const TYPE *Src, const int Count);
186 // @copy DynArray::MoveArrayTo()
187 void Move( cList<TYPE, CONTAINER>& Dest );
188 // @copy DynArray::Move()
189 bool Move( int from, int to );
190 // @copy DynArray::CopyTo()
191 void CopyTo(cList<TYPE, CONTAINER>& Dest);
192 void Set(cList<TYPE, CONTAINER> *Src);
193 void operator = (const cList<TYPE, CONTAINER> &Src);
194 void Swap(cList<TYPE, CONTAINER> *With);
195 template <class Reader>
196 void FromBS(Reader& BS, int count);
197 template <class Writer>
198 void ToBS(Writer& BS);
199
200 // Access operators
201 const TYPE & operator [] (const int Index) const;
202 TYPE & operator [] (const int Index);
203 const TYPE & GetAt(const int Index) const;
204 TYPE & GetAt(const int Index);
205 const TYPE & GetFirst() const;
206 TYPE & GetFirst();
207 const TYPE & GetLast() const;
208 TYPE & GetLast();
209 void SetAt(const int Index, const TYPE &Value);
210 const TYPE * ToPtr() const; // Returns a const pointer to the list
211 TYPE * ToPtr(); // Returns a mutable pointer to the list
212 void GetRange(const int Index, const int Count, cList<TYPE, CONTAINER> *To) const;
214 TYPE uGet(const int Index, const TYPE& defvalue);
216 void uSet(const int Index, const TYPE& value, const TYPE& defvalue);
217
218 // @copy DynArray::operator+( int )
219 // @todo Remove it?
220 TYPE* operator + ( int Index ) {
221 cAssert( Index >= 0 && Index < Count() && !IsEmpty() );
222 return m_Container->List + Index;
223 }
224
225 void Free(); // Removes all items from the list and frees all the space
226 void FreeUnused(); // Resizes the list to exactly the number of elements it contains
227 void FreeContents(); // Calls the destructor of all elements in the list
228
229 // Fast version of Resize().
230 // @copy "SetCapacityMod" == DynArray::CleanupAllocation()
231 // @see pool.cpp
232 template< int mod = 8 >
233 void SetCapacityMod();
234
235 int Count() const; // Gets the number of elements actually contained in the "cList"
236
237 // @todo fine Remove after change DynArray<> to cList<>.
238 int GetAmount() const { return Count(); }
239
240 void SetCount(const int Count); // Sets the number of elements actually contained in the "cList"
241 // Sets the number of elements actually contained in the "cList" and
242 // initializes every element with specified value "Fill"
243 void SetCount(int Count, const TYPE &Value);
244
245 // Gets or sets the number of elements that the "cList" can contain
246 int Capacity() const;
247 void SetCapacity(const int Capacity);
248
249 bool IsEmpty() const;
250 void Clear();
251 void Fill(const TYPE &Value);
252
253 // Adds "Count" elements to the end of the list. Returns the index of the last added element.
254 int Add(const TYPE &Value, const int Count = 1);
255
256 // @todo fine Copied from class DynArray<>. Remove or rename it.
257 void AddValues( const TYPE* Values, int N ) {
258 AddRange( Values, N );
259 }
260
261 template <class array>
262 void AddRange(const array &Src); // Adds the elements of another "cList" object to the end of current
263 void AddRange(const TYPE *Src, const int Count); // Adds "Count" elements of another list to the end of current
264
265 // Inserts element to the list at the specified position with specified number of times
266 void Insert(const int Index, const TYPE &Value, const int Count = 1);
267
268 // Inserts the elements of another "cList" object into current at the specified position
269 void InsertRange(const int Index, const cList<TYPE, CONTAINER> &Src);
270
271 // Insert the elements of another list of specified length at the specified position
272 void InsertRange(const int Index, const TYPE *Src, const int Count);
273
274 TYPE& ExpandTo( int Index, const TYPE& );
275
276 // @copy DynArray::Putp()
277 // @return true when inserted.
278 bool InsertFirstOrRemove( const TYPE& );
279
280 // Removes the first occurence of a specific object from the "cList" object.
281 // Returns "true" if value was found; otherwise, false.
282 bool Remove(const TYPE &Value, Equals *E = (Equals *)&cList_DefEquals);
283
284 // cList<int> L;
285 // ...
286 // while(L.Remove(10, ZeroResidue)) {
287 // }
288
289 // Removes a range of elements from the "cList" object with
290 // specified number of elements to remove
291 void RemoveAt(const int Index, const int Count = 1);
292
293 void RemoveLast();
294
295 // Searches for the specified object and returns the zero - based index of the first occurrence
296 // within the entire "cList" object using the specified equals function
297 int IndexOf(const TYPE &Value, Equals *E = (Equals *)&cList_DefEquals) const;
298
299 // cList<cStr> L;
300 // ...
301 // int i = L.IndexOf("Tilda", cStr::EqualsNoCase);
302
303 // Using the specified equals function searches for the specified object and returns the zero - based
304 // index of the first occurrence within the range of elements in the "cList" object that
305 // extends from the specified index to the last element
306 int IndexOf(const TYPE &Value, const int StartIndex, Equals *E = (Equals *)&cList_DefEquals) const;
307
308 // Searches for the specified "Value" and returns the zero - based index of the first occurrence
309 // within the range of elements in the "cList" object that starts at the specified index and
310 // contains the specified number of elements
311 int IndexOf(const TYPE &Value, const int StartIndex, const int Count, Equals *E = (Equals *)&cList_DefEquals) const;
312
313 // Searches for the specified "Value" and returns the zero - based index of the last occurrence
314 // within the entire "cList" object
315 int LastIndexOf(const TYPE &Value, Equals *E = (Equals *)&cList_DefEquals) const;
316
317 // Searches for the specified "Value" and returns the zero - based index of the last occurrence
318 // within the range of elements in the "cList" object that extends from the first element
319 // to the specified index
320 int LastIndexOf(const TYPE &Value, const int StartIndex, Equals *E = (Equals *)&cList_DefEquals) const;
321
322 // Searches for the specified "Value" and returns the zero - based index of the last occurrence
323 // within the range of elements in the "cList" object the contains the specified number of elements
324 // and ends at the specified index
325 int LastIndexOf(const TYPE &Value, const int StartIndex, const int Count, Equals *E = (Equals *)&cList_DefEquals) const;
326
327 // Searches the entire sorted "cList" object for an element using the specified compare function and returns
328 // the zero - based index, if "Value" is found; otherwise, -1
329 int BinarySearch(const TYPE &Value, Compare *C = (Compare *)&cList_DefCompare) const;
330
331 // cList<cStr> L;
332 // ...
333 // int i = L.BinarySearch("Over", cStr::CompareNoCase);
334
335 // Searches the range of elements in the sorted "cList" object for an element using the specified
336 // compare function and returns the zero - based index, if "Value" is found; otherwise, -1
337 int BinarySearch(const int Index, const int Count, const TYPE &Value, Compare *C = (Compare *)&cList_DefCompare) const;
338
339 // Determines whether an element is in the "cList" object using the specified equals function
340 bool Contains(const TYPE &Value, Equals *E = (Equals *)&cList_DefEquals) const;
341
342 // @todo fine Copied from class DynArray<>. Change to cList::Contains().
343 int find( const TYPE& Value ) const {
344 for ( int i = 0; i < Count(); i++ ) {
345 if ( !memcmp( &Value, &m_Container->List[ i ], sizeof( TYPE ) ) ) {
346 return i;
347 }
348 }
349 return -1;
350 }
351
352 // @todo fine Copied from the class DynArray<>. Remove or rename it.
353 TYPE pop_front() {
354 const TYPE e = GetFirst();
355 RemoveAt( 0, 1 );
356 return e;
357 }
358
359 // @todo fine Copied from the class DynArray<>. Remove or rename it.
360 TYPE pop_back() {
361 const TYPE e = GetLast();
362 RemoveLast();
363 return e;
364 }
365
366 // Determines using "IndexOf" function whether an element is in the "cList" object, and only if
367 // it is not in the list, adds it. Returns the index of founded or added element.
368 int AddUnique(const TYPE &Value, Equals *E = (Equals *)&cList_DefEquals);
369
370 // @return true when added
371 bool AddOnce( const TYPE&, Equals *E = ( Equals * )&cList_DefEquals );
372
373 // cList<cStr> L;
374 // ...
375 // bool s = L.Contains("Over", cStr::EqualsNoCase);
376
377 void Reverse(); // Reverses the order of the elements in the entire "cList" object
378 void Reverse(const int Index, const int Count); // Reverses the order of the elements in the specified range
379
380 // Sorts the elements in the entire "cList" object using the specified compare function
381 void Sort(Compare *C = (Compare *)&cList_DefCompare);
382 void Sort(const CompareFunctor&);
383
384 // Sorts the elements in a range of elements in "cList" object using the specified compare function
385 void Sort(const int Index, const int Count, Compare *C = (Compare *)&cList_DefCompare);
386 void Sort(int Index, int Count, const CompareFunctor& );
387 void EnsureCapacity(int size);
388
389 void operator += (const TYPE &);
390 void operator -= (const TYPE &);
391 void operator *= (const TYPE &);
392 void operator /= (const TYPE &);
393
394 bool operator == (const cList<TYPE, CONTAINER> &) const;
395 bool operator != (const cList<TYPE, CONTAINER> &) const;
396
397 // cList<cVec3> L;
398 // ...
399 // L += cVec3(10, 20, 0);
400 // L *= cVec3(20.0f);
401 //
402
403
405
407 bool some(::std::function<bool(const TYPE&)>) const;
408 bool some(::std::function<bool(TYPE&)>);
409
411 bool every(::std::function<bool(const TYPE&)>) const;
412 bool every(::std::function<bool(TYPE&)>);
413
415 int find(::std::function<bool(const TYPE&)>) const;
416 int find(::std::function<bool(TYPE&)>);
417
419 void forEach(::std::function<void(const TYPE&)>) const;
420 void forEach(::std::function<void(TYPE&)>);
421
423 void filter(cList<TYPE, CONTAINER>& result, ::std::function<bool(const TYPE&)>) const;
424 void filter(cList<TYPE, CONTAINER>& result, ::std::function<bool(TYPE&)>);
425
427 template<class RES>
428 void reduce(RES& res, ::std::function<void(RES&, const TYPE&)> fn) const;
429 template<class RES>
430 void reduce(RES& res, ::std::function<void(RES&, TYPE&)> fn);
431
432
433
434protected:
435 friend class cXml;
436 void Null();
437 CONTAINER *m_Container;
438
439 CONTAINER * EnsureCapacity(const int Capacity, const bool SkipDelete);
440 CONTAINER * Resize(const int Capacity, const bool SkipDelete);
441};
442
443//the difference from cList is that destuctors are not called during deallocation of the list
444//this array is most efficient of all in terms of memory consumption and speed of allocation
445template <class TYPE>
446class cArray : public cList<TYPE, cList_TrivialContainer<TYPE> >{
447
448};
449
450// cList<TYPE, CONTAINER>::Null
451template<class TYPE, class CONTAINER>
452inline void cList<TYPE, CONTAINER>::Null() {
453 m_Container = nullptr;
454}
455
456
457// cList<TYPE, CONTAINER>.ctor : ()
458template<class TYPE, class CONTAINER>
460 Null();
461}
462
463// cList<TYPE, CONTAINER>.ctor : (const cList<TYPE, CONTAINER> &)
464template<class TYPE, class CONTAINER>
466 Null();
467 Copy(Src);
468}
469
470// cList<TYPE, CONTAINER>.ctor : (const TYPE *, const int)
471template<class TYPE, class CONTAINER>
472inline cList<TYPE, CONTAINER>::cList(const TYPE *Src, const int Count) {
473 Null();
474 Copy(Src, Count);
475}
476
477// cList<TYPE, CONTAINER>.ctor : (const int)
478template<class TYPE, class CONTAINER>
479inline cList<TYPE, CONTAINER>::cList(const int Count) {
480 Null();
481 SetCount(Count);
482}
483
484// cList<TYPE, CONTAINER>.ctor : (const int, const TYPE &)
485template<class TYPE, class CONTAINER>
486inline cList<TYPE, CONTAINER>::cList(const int Count, const TYPE &Fill) {
487 Null();
488 SetCount(Count, Fill);
489}
490
491// cList<TYPE, CONTAINER>.dtor
492template<class TYPE, class CONTAINER>
494 Free();
495}
496
497// cList<TYPE, CONTAINER>::Size
498template<class TYPE, class CONTAINER>
499inline size_t cList<TYPE, CONTAINER>::Size() const {
500 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
501 return CurCount * sizeof(TYPE);
502}
503
504// cList<TYPE, CONTAINER>::SizeCapacity
505template<class TYPE, class CONTAINER>
506inline size_t cList<TYPE, CONTAINER>::SizeCapacity() const {
507 int CurCapacity = (nullptr == m_Container) ? 0 : m_Container->Capacity;
508 return CurCapacity * sizeof(TYPE);
509}
510
511// cList<TYPE, CONTAINER>::Copy : (const cList<TYPE, CONTAINER> &)
512template<class TYPE, class CONTAINER>
514 int i;
515 int SrcCount = (nullptr == Src.m_Container) ? 0 : Src.m_Container->Count;
516 EnsureCapacity(SrcCount, false);
517 if(m_Container != nullptr) {
518 m_Container->Count = SrcCount;
519 for(i = 0; i < m_Container->Count; i++) {
520 m_Container->List[i] = Src.m_Container->List[i];
521 }
522 }
523}
524
525// cList<TYPE, CONTAINER>::Copy : (const TYPE *, const int)
526template<class TYPE, class CONTAINER>
527inline void cList<TYPE, CONTAINER>::Copy(const TYPE *Src, const int Count) {
528 int i;
529
530 CONTAINER *OldContainer = EnsureCapacity(Count, true);
531 if(m_Container != nullptr) {
532 m_Container->Count = Count;
533 for(i = 0; i < m_Container->Count; i++) {
534 m_Container->List[i] = Src[i];
535 }
536 }
537 if(OldContainer != nullptr) {
538 if (!std::is_trivially_copy_constructible<TYPE>()){
539 OldContainer->DestroyElements();
540 }
541 CONTAINER::Free(OldContainer);
542 }
543}
544
545// cList<TYPE, CONTAINER>::Move : (cList<TYPE, CONTAINER> &)
546template<class TYPE, class CONTAINER>
548 Dest.Clear();
549 Dest.m_Container = m_Container;
550 m_Container = nullptr;
551}
552
553// cList<TYPE, CONTAINER>::Move : (int, int)
554template<class TYPE, class CONTAINER>
555inline bool cList<TYPE, CONTAINER>::Move( int from, int to ){
556 const int n = Count();
557 if ( from >= n ) from = n - 1; else if ( from < 0 ) from = 0;
558 if ( to >= n ) to = n - 1; else if ( to < 0 ) to = 0;
559 if ( from == to ) return false;
560 const TYPE t = m_Container->List[ from ];
561 if ( from < to ) {
562 memcpy(
563 m_Container->List + from,
564 m_Container->List + from + 1,
565 (to - from) * sizeof( TYPE ) );
566 } else {
567 memmove(
568 m_Container->List + to + 1,
569 m_Container->List + to,
570 (from - to) * sizeof( TYPE ) );
571 }
572 m_Container->List[ to ] = t;
573 return true;
574}
575
576template <class TYPE, class CONTAINER>
578 Dest = *this;
579}
580
581// cList<TYPE, CONTAINER>::Set : (cList<TYPE, CONTAINER> *)
582template<class TYPE, class CONTAINER>
584 cAssert((nullptr == m_Container) || (m_Container != Src->m_Container));
585 Free();
586
587 m_Container = Src->m_Container;
588 Src->m_Container = nullptr;
589}
590
591// cList<TYPE, CONTAINER>::operator =
592template<class TYPE, class CONTAINER>
594 Copy(Src);
595}
596
597// cList<TYPE, CONTAINER>::Swap : (cList<TYPE, CONTAINER> *)
598template<class TYPE, class CONTAINER>
600 cMath::Swap(m_Container, With->m_Container);
601}
602
603template <class TYPE, class CONTAINER>
604template <class Reader>
605void cList<TYPE, CONTAINER>::FromBS(Reader& BS, int count) {
606 Clear();
607 SetCount(count);
608 if(Count()){
609 BS.Read(ToPtr(), Count() * sizeof(TYPE));
610 }
611}
612
613template <class TYPE, class CONTAINER>
614template <class Writer>
615void cList<TYPE, CONTAINER>::ToBS(Writer& BS) {
616 BS.Write(ToPtr(), Count() * sizeof(TYPE));
617}
618
619// cList<TYPE, CONTAINER>::operator [] const
620template<class TYPE, class CONTAINER>
621inline const TYPE & cList<TYPE, CONTAINER>::operator [] (const int Index) const {
622 cAssert(Index >= 0);
623 cAssert(m_Container != nullptr);
624 cAssert(Index < m_Container->Count);
625 return m_Container->List[Index];
626}
627
628// cList<TYPE, CONTAINER>::operator []
629template<class TYPE, class CONTAINER>
630inline TYPE & cList<TYPE, CONTAINER>::operator [] (const int Index) {
631 cAssert(Index >= 0);
632 cAssert(m_Container != nullptr);
633 cAssert(Index < m_Container->Count);
634 return m_Container->List[Index];
635}
636
637// cList<TYPE, CONTAINER>::GetAt const
638template<class TYPE, class CONTAINER>
639inline const TYPE & cList<TYPE, CONTAINER>::GetAt(const int Index) const {
640 cAssert(Index >= 0);
641 cAssert(m_Container != nullptr);
642 cAssert(Index < m_Container->Count);
643 return m_Container->List[Index];
644}
645
646// cList<TYPE, CONTAINER>::GetAt
647template<class TYPE, class CONTAINER>
648inline TYPE & cList<TYPE, CONTAINER>::GetAt(const int Index) {
649 cAssert(Index >= 0);
650 cAssert(m_Container != nullptr);
651 cAssert(Index < m_Container->Count);
652 return m_Container->List[Index];
653}
654
655// cList<TYPE, CONTAINER>::GetFirst const
656template<class TYPE, class CONTAINER>
657inline const TYPE & cList<TYPE, CONTAINER>::GetFirst() const {
658 cAssert(m_Container != nullptr);
659 cAssert(m_Container->Count >= 1);
660 return m_Container->List[0];
661}
662
663// cList<TYPE, CONTAINER>::GetFirst
664template<class TYPE, class CONTAINER>
665inline TYPE & cList<TYPE, CONTAINER>::GetFirst() {
666 cAssert(m_Container != nullptr);
667 cAssert(m_Container->Count >= 1);
668 return m_Container->List[0];
669}
670
671// cList<TYPE, CONTAINER>::GetLast const
672template<class TYPE, class CONTAINER>
673inline const TYPE & cList<TYPE, CONTAINER>::GetLast() const {
674 cAssert(m_Container != nullptr);
675 cAssert(m_Container->Count >= 1);
676 return m_Container->List[m_Container->Count - 1];
677}
678
679// cList<TYPE, CONTAINER>::GetLast
680template<class TYPE, class CONTAINER>
681inline TYPE & cList<TYPE, CONTAINER>::GetLast() {
682 cAssert(m_Container != nullptr);
683 cAssert(m_Container->Count >= 1);
684 return m_Container->List[m_Container->Count - 1];
685}
686
687// cList<TYPE, CONTAINER>::SetAt
688template<class TYPE, class CONTAINER>
689inline void cList<TYPE, CONTAINER>::SetAt(const int Index, const TYPE &Value) {
690 cAssert(Index >= 0);
691 cAssert(m_Container != nullptr);
692 cAssert(Index < m_Container->Count);
693 m_Container->List[Index] = Value;
694}
695
696// cList<TYPE, CONTAINER>::ToPtr() const
697template<class TYPE, class CONTAINER>
698inline const TYPE * cList<TYPE, CONTAINER>::ToPtr() const {
699 return (nullptr == m_Container) ? nullptr : m_Container->List;
700}
701
702// cList<TYPE, CONTAINER>::ToPtr
703template<class TYPE, class CONTAINER>
704inline TYPE * cList<TYPE, CONTAINER>::ToPtr() {
705 return (nullptr == m_Container) ? nullptr : m_Container->List;
706}
707
708//------------------------------------------------------------------------------------------
709// cList<TYPE, CONTAINER>::GetRange
710//------------------------------------------------------------------------------------------
711template<class TYPE, class CONTAINER>
712inline void cList<TYPE, CONTAINER>::GetRange(const int Index, const int Count, cList<TYPE, CONTAINER> *To) const {
713 cAssert(Index >= 0);
714 cAssert(Count >= 0);
715 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
716 cAssert(Index + Count <= CurCount);
717
718 int i;
719
720 To->Clear();
721
722 for(i = Index; i < Index + Count; i++) {
723 To->Add(m_Container->List[i]);
724 }
725} // cList<TYPE, CONTAINER>::GetRange
726
727// cList<TYPE, CONTAINER>::Free
728template<class TYPE, class CONTAINER>
729inline void cList<TYPE, CONTAINER>::Free() {
730 if(m_Container != nullptr) {
731 m_Container->DestroyElements();
732 CONTAINER::Free(m_Container);
733 m_Container = nullptr;
734 }
735}
736
737template<class TYPE, class CONTAINER>
738TYPE cList<TYPE, CONTAINER>::uGet(const int Index, const TYPE& defvalue){
739 if (Index >= 0 && Index < Count())return (*this)[Index];
740 return defvalue;
741}
742
743template<class TYPE, class CONTAINER>
744void cList<TYPE, CONTAINER>::uSet(const int Index, const TYPE& value, const TYPE& defvalue){
745 if (Index >= 0){
746 int n = Count();
747 if (Index >= n)Add(defvalue, Index - n + 1);
748 (*this)[Index] = value;
749 }
750}
751
752// cList<TYPE, CONTAINER>::FreeContents
753template<class TYPE, class CONTAINER>
755 if(m_Container != nullptr) {
756 int i;
757 for(i = 0; i < m_Container->Count; i++) {
758 delete m_Container->List[i];
759 m_Container->List[i] = nullptr;
760 }
761 }
762}
763
764// cList<TYPE, CONTAINER>::FreeUnused
765template<class TYPE, class CONTAINER>
767 if(m_Container != nullptr) {
768 Resize(m_Container->Count, false);
769 }
770}
771
772// cList<TYPE, CONTAINER>::Clear
773template<class TYPE, class CONTAINER>
774inline void cList<TYPE, CONTAINER>::Clear() {
775 if(m_Container != nullptr) {
776 m_Container->Count = 0;
777 }
778}
779
780// cList<TYPE, CONTAINER>::SetCapacityMod
781template<class TYPE, class CONTAINER>
782template< int mod >
784 static_assert( mod % 8 == 0,
785 "`mod` must be an integral of multiple of 8" );
786 const int ncap = Count() * mod / 8;
787 SetCapacity( ncap );
788}
789
790// cList<TYPE, CONTAINER>::Count
791template<class TYPE, class CONTAINER>
792inline int cList<TYPE, CONTAINER>::Count() const {
793 return (nullptr == m_Container) ? 0 : m_Container->Count;
794}
795
796// cList<TYPE, CONTAINER>::IsEmpty
797template<class TYPE, class CONTAINER>
798inline bool cList<TYPE, CONTAINER>::IsEmpty() const {
799 return (nullptr == m_Container) || (m_Container->Count < 1);
800}
801
802// cList<TYPE, CONTAINER>::Capacity
803template<class TYPE, class CONTAINER>
804inline int cList<TYPE, CONTAINER>::Capacity() const {
805 return (nullptr == m_Container) ? 0 : m_Container->Capacity;
806}
807
808// cList<TYPE, CONTAINER>::SetCapacity
809template<class TYPE, class CONTAINER>
810inline void cList<TYPE, CONTAINER>::SetCapacity(const int Capacity) {
811 Resize(Capacity, false);
812}
813
814//-----------------------------------------------------------------------------
815// cList<TYPE, CONTAINER>::Add
816//-----------------------------------------------------------------------------
817template<class TYPE, class CONTAINER>
818inline int cList<TYPE, CONTAINER>::Add(const TYPE &Value, const int Count) {
819 cAssert(Count >= 0);
820 int i;
821 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
822 CONTAINER *OldContainer = EnsureCapacity(CurCount + Count, true);
823 for(i = 0; i < Count; i++) {
824 m_Container->List[m_Container->Count] = Value;
825 m_Container->Count++;
826 }
827 if(OldContainer != nullptr) {
828 if (!std::is_trivially_copy_constructible<TYPE>()){
829 OldContainer->DestroyElements();
830 }
831 CONTAINER::Free(OldContainer);
832 }
833 return ((nullptr == m_Container) ? 0 : m_Container->Count) - 1;
834} // cList<TYPE, CONTAINER>::Add
835
836template <class TYPE, class CONTAINER>
837template <class array>
838void cList<TYPE, CONTAINER>::AddRange(const array& Src) {
839 int i;
840 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
841 int SrcCount = Src.Count();
842 EnsureCapacity(CurCount + SrcCount, false);
843 for (i = 0; i < SrcCount; i++) {
844 m_Container->List[m_Container->Count] = Src[i];
845 m_Container->Count++;
846 }
847}
848
849//-----------------------------------------------------------------------------
850// cList<TYPE, CONTAINER>::AddRange : (const TYPE *, const int)
851//-----------------------------------------------------------------------------
852template<class TYPE, class CONTAINER>
853inline void cList<TYPE, CONTAINER>::AddRange(const TYPE *Src, const int Count) {
854 cAssert(Count >= 0);
855 int i;
856 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
857 CONTAINER *OldContainer = EnsureCapacity(CurCount + Count, true);
858 for(i = 0; i < Count; i++) {
859 m_Container->List[m_Container->Count] = Src[i];
860 m_Container->Count++;
861 }
862 if(OldContainer != nullptr) {
863 if (!std::is_trivially_copy_constructible<TYPE>()){
864 OldContainer->DestroyElements();
865 }
866 CONTAINER::Free(OldContainer);
867 }
868} // cList<TYPE, CONTAINER>::AddRange
869
870//-------------------------------------------------------------------------------------------------------------
871// cList<TYPE, CONTAINER>::IndexOf
872//-------------------------------------------------------------------------------------------------------------
873template<class TYPE, class CONTAINER>
874inline int cList<TYPE, CONTAINER>::IndexOf(const TYPE &Value, const int StartIndex, const int Count, Equals *E) const {
875 cAssert(StartIndex >= 0);
876 cAssert(Count >= 0);
877 cAssert(StartIndex + Count <= ((nullptr == m_Container) ? 0 : m_Container->Count));
878
879 int i;
880
881 for(i = StartIndex; i < StartIndex + Count; i++) {
882 if(E(&m_Container->List[i], &Value)) {
883 return i;
884 }
885 }
886
887 return -1;
888}
889
890template<class TYPE, class CONTAINER>
891inline int cList<TYPE, CONTAINER>::IndexOf(const TYPE &Value, const int StartIndex, Equals *E) const {
892 return IndexOf(Value, StartIndex, Count() - StartIndex, E);
893}
894
895template<class TYPE, class CONTAINER>
896inline int cList<TYPE, CONTAINER>::IndexOf(const TYPE &Value, Equals *E) const {
897 return IndexOf(Value, 0, Count(), E);
898}
899// cList<TYPE, CONTAINER>::IndexOf
900
901//--------------------------------------------------------------------------------------------------------------
902// cList<TYPE, CONTAINER>::LastIndexOf
903//--------------------------------------------------------------------------------------------------------------
904template<class TYPE, class CONTAINER>
905inline int cList<TYPE, CONTAINER>::LastIndexOf(const TYPE &Value, Equals *E) const {
906 return LastIndexOf(Value, Count() - 1, Count(), E);
907}
908
909template<class TYPE, class CONTAINER>
910inline int cList<TYPE, CONTAINER>::LastIndexOf(const TYPE &Value, const int StartIndex, Equals *E) const {
911 return LastIndexOf(Value, StartIndex, StartIndex + 1, E);
912}
913
914template<class TYPE, class CONTAINER>
915inline int cList<TYPE, CONTAINER>::LastIndexOf(const TYPE &Value, const int StartIndex, const int Count, Equals *E) const {
916 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
917 if(0 == CurCount) {
918 cAssert(StartIndex >= -1);
919 cAssert(StartIndex <= 0);
920 cAssert(Count >= 0);
921 return -1;
922 }
923
924 cAssert(StartIndex >= 0);
925 cAssert(StartIndex < CurCount);
926 cAssert(Count >= 0);
927 cAssert(Count <= StartIndex + 1);
928
929 int i, i0;
930
931 i0 = StartIndex - Count + 1;
932 for(i = StartIndex; i >= i0; i--) {
933 if(E(&m_Container->List[i], &Value)) {
934 return i;
935 }
936 }
937
938 return -1;
939} // cList<TYPE, CONTAINER>::LastIndexOf
940
941//------------------------------------------------------------------------------------------------------------
942// cList<TYPE, CONTAINER>::BinarySearch
943//------------------------------------------------------------------------------------------------------------
944template<class TYPE, class CONTAINER>
945inline int cList<TYPE, CONTAINER>::BinarySearch(const int Index, const int Count, const TYPE &Value, Compare *C) const {
946 cAssert(Index >= 0);
947 cAssert(Count >= 0);
948 cAssert(Index + Count <= ((nullptr == m_Container) ? 0 : m_Container->Count));
949
950 int l, r, m;
951
952 if(Count > 0) {
953 l = 0;
954 r = Index + Count - 1;
955 while(l < r) {
956 m = (l + r) / 2;
957 if(C(&Value, &GetAt(m)) <= 0) {
958 r = m;
959 } else {
960 l = m + 1;
961 }
962 }
963 if(C(&Value, &GetAt(l)) == 0) {
964 return l;
965 }
966 }
967
968 return -1;
969}
970
971template<class TYPE, class CONTAINER>
972inline int cList<TYPE, CONTAINER>::BinarySearch(const TYPE &Value, Compare *C) const {
973 return BinarySearch(0, Count(), Value, C);
974}
975// cList<TYPE, CONTAINER>::BinarySearch
976
977// cList<TYPE, CONTAINER>::Contains
978template<class TYPE, class CONTAINER>
979inline bool cList<TYPE, CONTAINER>::Contains(const TYPE &Value, Equals *E) const {
980 int i;
981 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
982 for(i = 0; i < CurCount; i++) {
983 if(E(&m_Container->List[i], &Value)) {
984 return true;
985 }
986 }
987 return false;
988}
989
990// cList<TYPE, CONTAINER>::AddUnique
991template<class TYPE, class CONTAINER>
992inline int cList<TYPE, CONTAINER>::AddUnique(const TYPE &Value, Equals *E) {
993 int i = IndexOf(Value, E);
994 if(-1 == i) {
995 i = Add(Value);
996 }
997 return i;
998}
999
1000// cList<TYPE, CONTAINER>::AddOnce
1001template<class TYPE, class CONTAINER>
1002inline bool cList<TYPE, CONTAINER>::AddOnce( const TYPE& Value, Equals* E ){
1003 const int i = IndexOf( Value, E );
1004 if ( i == -1 ) {
1005 Add( Value );
1006 return true;
1007 }
1008 return false;
1009}
1010
1011//-----------------------------------------------------------------------------
1012// cList<TYPE, CONTAINER>::RemoveAt
1013//-----------------------------------------------------------------------------
1014template<class TYPE, class CONTAINER>
1015inline void cList<TYPE, CONTAINER>::RemoveAt(const int Index, const int Count) {
1016 cAssert(Index >= 0);
1017 cAssert(Count >= 0);
1018 cAssert(Index + Count <= ((nullptr == m_Container) ? 0 : m_Container->Count));
1019 int i;
1020 if(m_Container != nullptr) {
1021 int lcount = Count;
1022 if (Index + lcount > m_Container->Count){
1023 lcount = m_Container->Count - Index;
1024 }
1025 m_Container->Count -= lcount;
1026 for(i = Index; i < m_Container->Count; i++) {
1027 m_Container->List[i] = m_Container->List[i + lcount];
1028 }
1029 }
1030} // cList<TYPE, CONTAINER>::RemoveAt
1031
1032// cList<TYPE, CONTAINER>::RemoveLast
1033template<class TYPE, class CONTAINER>
1035 cAssert(m_Container != nullptr);
1036 cAssert(m_Container->Count >= 1);
1037 m_Container->Count--;
1038}
1039
1040//-----------------------------------------------------------------------------
1041// cList<TYPE, CONTAINER>::Remove
1042//-----------------------------------------------------------------------------
1043template<class TYPE, class CONTAINER>
1044inline bool cList<TYPE, CONTAINER>::Remove(const TYPE &Value, Equals *E) {
1045 int Index = IndexOf(Value, E);
1046 if(Index >= 0) {
1047 RemoveAt(Index);
1048 return true;
1049 }
1050 return false;
1051} // cList<TYPE, CONTAINER>::Remove
1052
1053//-----------------------------------------------------------------------------------
1054// cList<TYPE, CONTAINER>::Insert
1055//-----------------------------------------------------------------------------------
1056template<class TYPE, class CONTAINER>
1057inline void cList<TYPE, CONTAINER>::Insert(const int Index, const TYPE &Value, const int Count) {
1058 cAssert(Index >= 0);
1059 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1060 cAssert(Index <= CurCount);
1061 cAssert(Count >= 0);
1062
1063 int i;
1064
1065 CONTAINER *OldContainer = EnsureCapacity(CurCount + Count, true);
1066 for(i = CurCount - 1 + Count; i >= Index + Count; i--) {
1067 m_Container->List[i] = m_Container->List[i - Count];
1068 }
1069 if(m_Container != nullptr) {
1070 m_Container->Count += Count;
1071 cAssert(Index + Count <= m_Container->Count);
1072 }
1073 for(i = 0; i < Count; i++) {
1074 m_Container->List[Index + i] = Value;
1075 }
1076 if(OldContainer != nullptr) {
1077 if (!std::is_trivially_copy_constructible<TYPE>()){
1078 OldContainer->DestroyElements();
1079 }
1080 CONTAINER::Free(OldContainer);
1081 }
1082} // cList<TYPE, CONTAINER>::Insert
1083
1084//---------------------------------------------------------------------------------------
1085// cList<TYPE, CONTAINER>::InsertRange : void (const int, const cList<TYPE, CONTAINER> &)
1086//---------------------------------------------------------------------------------------
1087template<class TYPE, class CONTAINER>
1088inline void cList<TYPE, CONTAINER>::InsertRange(const int Index, const cList<TYPE, CONTAINER> &Src) {
1089 cAssert(Index >= 0);
1090 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1091 cAssert(Index <= CurCount);
1092 int SrcCount = (nullptr == Src.m_Container) ? 0 : Src.m_Container->Count;
1093
1094 int i;
1095
1096 EnsureCapacity(CurCount + SrcCount, false);
1097 for(i = CurCount - 1 + SrcCount; i >= Index + SrcCount; i--) {
1098 m_Container->List[i] = m_Container->List[i - SrcCount];
1099 }
1100 if(m_Container != nullptr) {
1101 m_Container->Count += SrcCount;
1102 cAssert(Index + SrcCount <= m_Container->Count);
1103 }
1104 for(i = 0; i < SrcCount; i++) {
1105 m_Container->List[Index + i] = Src.m_Container->List[i];
1106 }
1107} // cList<TYPE, CONTAINER>::InsertRange
1108
1109//--------------------------------------------------------------------------------
1110// cList<TYPE, CONTAINER>::InsertRange : void (const int, const TYPE *, const int)
1111//--------------------------------------------------------------------------------
1112template<class TYPE, class CONTAINER>
1113inline void cList<TYPE, CONTAINER>::InsertRange(const int Index, const TYPE *Src, const int Count) {
1114 cAssert(Index >= 0);
1115 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1116 cAssert(Index <= CurCount);
1117 cAssert(Count >= 0);
1118
1119 int i;
1120
1121 CONTAINER *OldContainer = EnsureCapacity(CurCount + Count, true);
1122 for(i = CurCount - 1 + Count; i >= Index + Count; i--) {
1123 m_Container->List[i] = m_Container->List[i - Count];
1124 }
1125 if(m_Container != nullptr) {
1126 m_Container->Count += Count;
1127 cAssert(Index + Count <= m_Container->Count);
1128 }
1129 for(i = 0; i < Count; i++) {
1130 m_Container->List[Index + i] = Src[i];
1131 }
1132 if(OldContainer != nullptr) {
1133 if (!std::is_trivially_copy_constructible<TYPE>()){
1134 OldContainer->DestroyElements();
1135 }
1136 CONTAINER::Free(OldContainer);
1137 }
1138} // cList<TYPE, CONTAINER>::InsertRange
1139
1140
1141//--------------------------------------------------------------------------------
1142// cList<TYPE, CONTAINER>::ExpandTo
1143//--------------------------------------------------------------------------------
1144template<class TYPE, class CONTAINER>
1145inline TYPE& cList<TYPE, CONTAINER>::ExpandTo( int Index, const TYPE& Value ) {
1146 if ( Index >= Count() ) {
1147 Add( Value, Index - Count() + 1 );
1148 }
1149 return (*this)[ Index ];
1150}
1151
1152//-----------------------------------------------------------------------------
1153// cList<TYPE, CONTAINER>::Putp
1154//-----------------------------------------------------------------------------
1155template<class TYPE, class CONTAINER>
1156inline bool cList<TYPE, CONTAINER>::InsertFirstOrRemove( const TYPE& Value ) {
1157 const int i = find( Value );
1158 (i == -1) ? Insert( 0, Value ) : RemoveAt( i, 1 );
1159 return (i == -1);
1160}
1161
1162//-----------------------------------------------------------------------------
1163// cList<TYPE, CONTAINER>::Reverse
1164//-----------------------------------------------------------------------------
1165template<class TYPE, class CONTAINER>
1166inline void cList<TYPE, CONTAINER>::Reverse(const int Index, const int Count) {
1167 cAssert(Index >= 0);
1168 cAssert(Count >= 0);
1169 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1170 cAssert(Index + Count <= CurCount);
1171
1172 int i, h;
1173
1174 if(Count > 1) {
1175 h = Count / 2;
1176 for(i = 0; i < h; i++) {
1177 cMath::Swap(m_Container->List[Index + i], m_Container->List[Index + Count - 1 - i]);
1178 }
1179 }
1180}
1181
1182template<class TYPE, class CONTAINER>
1183inline void cList<TYPE, CONTAINER>::Reverse() {
1184 if(m_Container != nullptr) {
1185 Reverse(0, m_Container->Count);
1186 }
1187}
1188// cList<TYPE, CONTAINER>::Reverse
1189
1190//-----------------------------------------------------------------------------
1191// cList<TYPE, CONTAINER>::Resize
1192//-----------------------------------------------------------------------------
1193template<class TYPE, class CONTAINER>
1194inline CONTAINER * cList<TYPE, CONTAINER>::Resize(const int Capacity, const bool SkipDelete) {
1195 cAssert(Capacity >= 0);
1196
1197 if(Capacity <= 0) {
1198 Free();
1199 return nullptr;
1200 }
1201
1202 int OldCapacity = (nullptr == m_Container) ? 0 : m_Container->Capacity;
1203 if(Capacity == OldCapacity) {
1204 return nullptr;
1205 }
1206
1207 CONTAINER *OldContainer = m_Container;
1208 m_Container = CONTAINER::New(Capacity);
1209 m_Container->Count = (nullptr == OldContainer) ? 0 : OldContainer->Count;
1210 m_Container->Capacity = Capacity;
1211
1212 if(Capacity < m_Container->Count) {
1213 m_Container->Count = Capacity;
1214 }
1215
1216 if(OldContainer != nullptr) {
1217 OldContainer->Copy(m_Container, m_Container->Count);
1218 if(SkipDelete) {
1219 return OldContainer;
1220 } else {
1221 if (!std::is_trivially_copy_constructible<TYPE>()){
1222 OldContainer->DestroyElements();
1223 }
1224 CONTAINER::Free(OldContainer);
1225 }
1226 }
1227 return nullptr;
1228} // cList<TYPE, CONTAINER>::Resize
1229
1230//------------------------------------------------------------------------------------
1231// cList<TYPE, CONTAINER>::EnsureCapacity
1232//------------------------------------------------------------------------------------
1233template<class TYPE, class CONTAINER>
1234inline CONTAINER * cList<TYPE, CONTAINER>::EnsureCapacity(const int Capacity, const bool SkipDelete) {
1235 int OldCapacity = (nullptr == m_Container) ? 0 : m_Container->Capacity;
1236 if(Capacity > OldCapacity) {
1237 int S = Capacity + OldCapacity / 2;
1238 if (S < 8)S = 8;
1239 return Resize(S, SkipDelete);
1240 }
1241 return nullptr;
1242} // cList<TYPE, CONTAINER>::EnsureCapacity
1243
1244template<class TYPE, class CONTAINER>
1245inline void cList<TYPE, CONTAINER>::EnsureCapacity(int size){
1246 EnsureCapacity(size, false);
1247
1248}
1249// cList<TYPE, CONTAINER>::SetCount : void (const int)
1250template<class TYPE, class CONTAINER>
1251inline void cList<TYPE, CONTAINER>::SetCount(const int Count) {
1252 cAssert(Count >= 0);
1253 EnsureCapacity(Count, false);
1254 if(m_Container != nullptr) {
1255 m_Container->Count = Count;
1256 }
1257}
1258
1259// cList<TYPE, CONTAINER>::Fill
1260template<class TYPE, class CONTAINER>
1261inline void cList<TYPE, CONTAINER>::Fill(const TYPE &Value) {
1262 int i;
1263 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1264 for(i = 0; i < CurCount; i++) {
1265 m_Container->List[i] = Value;
1266 }
1267}
1268
1269// cList<TYPE, CONTAINER>::SetCount : void (const int, const TYPE &)
1270template<class TYPE, class CONTAINER>
1271inline void cList<TYPE, CONTAINER>::SetCount(const int _Count, const TYPE &Value) {
1272 int n0 = Count();
1273 SetCount(_Count);
1274 for (int i = n0; i < _Count; i++)SetAt(i, Value);
1275}
1276
1277//-----------------------------------------------------------------------------
1278// cList<TYPE, CONTAINER>::Sort : (..., Compare *)
1279//-----------------------------------------------------------------------------
1280template<class TYPE, class CONTAINER>
1281inline void cList<TYPE, CONTAINER>::Sort(const int Index, const int Count, Compare *C) {
1282 cAssert(Index >= 0);
1283 cAssert(Count >= 0);
1284 cAssert(Index + Count <= ((nullptr == m_Container) ? 0 : m_Container->Count));
1285
1286 int i = 0, j = 0, M = 0;
1287 bool f = false;
1288 TYPE K;
1289
1290 M = Count / 2;
1291 while(M >= 1) {
1292 for(i = M; i < Count; i++) {
1293 K = GetAt(i + Index);
1294 j = i - M;
1295 f = false;
1296 while(j >= 0 && !f) {
1297 if(C(&K, &GetAt(j + Index)) < 0) {
1298 SetAt(j + M + Index, GetAt(j + Index));
1299 j -= M;
1300 } else {
1301 f = true;
1302 }
1303 }
1304 SetAt(j + M + Index, K);
1305 }
1306 M /= 2;
1307 }
1308} // cList<TYPE, CONTAINER>::Sort : (..., Compare *)
1309
1310//-----------------------------------------------------------------------------
1311// cList<TYPE, CONTAINER>::Sort : (..., const CompareFunctor &)
1312//-----------------------------------------------------------------------------
1313template<class TYPE, class CONTAINER>
1314inline void cList<TYPE, CONTAINER>::Sort(const int Index, const int Count, const CompareFunctor &C) {
1315 cAssert(Index >= 0);
1316 cAssert(Count >= 0);
1317 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1318 cAssert(Index + Count <= CurCount);
1319
1320 int i = 0, j = 0, M = 0;
1321 bool f = false;
1322 TYPE K;
1323
1324 M = Count / 2;
1325 while(M >= 1) {
1326 for(i = M; i < Count; i++) {
1327 K = GetAt(i + Index);
1328 j = i - M;
1329 f = false;
1330 while(j >= 0 && !f) {
1331 if(C(K, GetAt(j + Index))) {
1332 f = true;
1333 } else {
1334 SetAt(j + M + Index, GetAt(j + Index));
1335 j -= M;
1336 }
1337 }
1338 SetAt(j + M + Index, K);
1339 }
1340 M /= 2;
1341 }
1342} // cList<TYPE, CONTAINER>::Sort : (..., const CompareFunctor &)
1343
1344// cList<TYPE, CONTAINER>::Sort
1345template<class TYPE, class CONTAINER>
1346void cList<TYPE, CONTAINER>::Sort(Compare *C) {
1347 Sort(0, Count(), C);
1348}
1349// cList<TYPE, CONTAINER>::Sort
1350template<class TYPE, class CONTAINER>
1351void cList<TYPE, CONTAINER>::Sort(const CompareFunctor &C) {
1352 Sort(0, Count(), C);
1353}
1354
1355// cList<TYPE, CONTAINER>::operator +=
1356template<class TYPE, class CONTAINER>
1357inline void cList<TYPE, CONTAINER>::operator += (const TYPE &u) {
1358 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1359 for(int i = 0; i < CurCount; i++) {
1360 m_Container->List[i] += u;
1361 }
1362}
1363
1364// cList<TYPE, CONTAINER>::operator -=
1365template<class TYPE, class CONTAINER>
1366inline void cList<TYPE, CONTAINER>::operator -= (const TYPE &u) {
1367 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1368 for(int i = 0; i < CurCount; i++) {
1369 m_Container->List[i] -= u;
1370 }
1371}
1372
1373// cList<TYPE, CONTAINER>::operator *=
1374template<class TYPE, class CONTAINER>
1375inline void cList<TYPE, CONTAINER>::operator *= (const TYPE &u) {
1376 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1377 for(int i = 0; i < CurCount; i++) {
1378 m_Container->List[i] *= u;
1379 }
1380}
1381
1382// cList<TYPE, CONTAINER>::operator /=
1383template<class TYPE, class CONTAINER>
1384inline void cList<TYPE, CONTAINER>::operator /= (const TYPE &u) {
1385 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1386 for(int i = 0; i < CurCount; i++) {
1387 m_Container->List[i] /= u;
1388 }
1389}
1390
1391// cList<TYPE, CONTAINER>::operator ==
1392template<class TYPE, class CONTAINER>
1393inline bool cList<TYPE, CONTAINER>::operator == (const cList<TYPE, CONTAINER> &Other) const {
1394 int CurCount = (nullptr == m_Container) ? 0 : m_Container->Count;
1395 int OtherCount = (nullptr == Other.m_Container) ? 0 : Other.m_Container->Count;
1396 if(CurCount != OtherCount) {
1397 return false;
1398 }
1399 for(int i = 0; i < CurCount; i++) {
1400 if(m_Container->List[i] != Other.m_Container->List[i]) {
1401 return false;
1402 }
1403 }
1404 return true;
1405}
1406
1407// cList<TYPE, CONTAINER>::operator !=
1408template<class TYPE, class CONTAINER>
1409inline bool cList<TYPE, CONTAINER>::operator != (const cList<TYPE, CONTAINER> &Other) const {
1410 return !(*this == Other);
1411}
1412
1413template<class TYPE, class CONTAINER>
1414::std::ostream & operator << (::std::ostream &out, const cList<TYPE, CONTAINER> &l) {
1415 for(int i = 0; i < l.Count(); ++i) {
1416 const bool needSeparator = ((i + 1) != l.Count());
1417 out << l[i] << (needSeparator ? " " : "");
1418 }
1419 return out;
1420}
1421
1422template<class TYPE, class CONTAINER>
1423inline bool cList<TYPE, CONTAINER>::some(::std::function<bool(const TYPE&)> fn) const {
1424 for (int i = 0; i < Count(); i++) if (fn((*this)[i])) return true;
1425 return false;
1426}
1427
1428template<class TYPE, class CONTAINER>
1429inline bool cList<TYPE, CONTAINER>::some(::std::function<bool(TYPE&)> fn) {
1430 for (int i = 0; i < Count(); i++) if (fn((*this)[i])) return true;
1431 return false;
1432}
1433
1434template<class TYPE, class CONTAINER>
1435inline int cList<TYPE, CONTAINER>::find(::std::function<bool(const TYPE&)> fn) const {
1436 for (int i = 0; i < Count(); i++) if (fn((*this)[i])) return i;
1437 return -1;
1438}
1439
1440template<class TYPE, class CONTAINER>
1441inline int cList<TYPE, CONTAINER>::find(::std::function<bool(TYPE&)> fn) {
1442 for (int i = 0; i < Count(); i++) if (fn((*this)[i])) return i;
1443 return -1;
1444}
1445
1446template<class TYPE, class CONTAINER>
1447inline bool cList<TYPE, CONTAINER>::every(::std::function<bool(const TYPE&)> fn) const {
1448 for (int i = 0; i < Count(); i++) if (!fn((*this)[i])) return false;
1449 return true;
1450}
1451
1452template<class TYPE, class CONTAINER>
1453inline void cList<TYPE, CONTAINER>::forEach(::std::function<void(TYPE&)> fn) {
1454 for (int i = 0; i < Count(); i++) fn((*this)[i]);
1455}
1456
1457template<class TYPE, class CONTAINER>
1458inline void cList<TYPE, CONTAINER>::forEach(::std::function<void(const TYPE&)> fn) const {
1459 for (int i = 0; i < Count(); i++) fn((*this)[i]);
1460}
1461
1462template<class TYPE, class CONTAINER>
1463inline void cList<TYPE, CONTAINER>::filter(cList<TYPE, CONTAINER>& result, ::std::function<bool(const TYPE&)> fn) const {
1464 result.Clear();
1465 for (int i = 0; i < Count(); i++) if (fn((*this)[i])) result.Add((*this)[i]);
1466}
1467
1468template<class TYPE, class CONTAINER>
1469template<class RES>
1470inline void cList<TYPE, CONTAINER>::reduce(RES& res, ::std::function<void(RES&, const TYPE&)> fn) const {
1471 for (int i = 0; i < Count(); i++) fn(res, (*this)[i]);
1472}
1473
1474template<class TYPE, class CONTAINER>
1475template<class RES>
1476inline void cList<TYPE, CONTAINER>::reduce(RES& res, ::std::function<void(RES&, TYPE&)> fn) {
1477 for (int i = 0; i < Count(); i++) fn(res, (*this)[i]);
1478}
The array template, refer it as coat::list <...> if you are using the Core API.
Definition cList.h:136
void filter(cList< TYPE, CONTAINER > &result, ::std::function< bool(const TYPE &)>) const
filter returns new array with elements that passed the check
Definition cList.h:1463
void reduce(RES &res, ::std::function< void(RES &, const TYPE &)> fn) const
reduce - sort of summ of all elements
Definition cList.h:1470
void forEach(::std::function< void(const TYPE &)>) const
execute callback for each element
Definition cList.h:1458
TYPE uGet(const int Index, const TYPE &defvalue)
Unlimited get - get value at index Index, if beyoud range - return defvalue.
Definition cList.h:738
bool every(::std::function< bool(const TYPE &)>) const
every returns true if all callbacks returned true
Definition cList.h:1447
int find(::std::function< bool(const TYPE &)>) const
find returns index of the element if some of callbacks returns true or returns -1
Definition cList.h:1435
bool some(::std::function< bool(const TYPE &)>) const
js - like functions
Definition cList.h:1423
void uSet(const int Index, const TYPE &value, const TYPE &defvalue)
Unlimited set - set value at index Index, if beyoud range - add correcsponding count of defvalue-s.
Definition cList.h:744