LMMS
Loading...
Searching...
No Matches
Array.h
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017-2019 Filipe Coelho <falktx@falktx.com>
7
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
10
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
22
23 ==============================================================================
24*/
25
26#ifndef WATER_ARRAY_H_INCLUDED
27#define WATER_ARRAY_H_INCLUDED
28
31
32namespace water {
33
34//==============================================================================
55template <typename ElementType, size_t minimumAllocatedSize = 0>
56class Array
57{
58private:
59 typedef PARAMETER_TYPE (ElementType) ParameterType;
60
61public:
62 //==============================================================================
65 : data(),
66 numUsed(0)
67 {
68 }
69
74 : data(),
75 numUsed(0)
76 {
77 CARLA_SAFE_ASSERT_RETURN(data.setAllocatedSize (other.numUsed),);
78 numUsed = other.numUsed;
79
80 for (int i = 0; i < numUsed; ++i)
81 new (data.elements + i) ElementType (other.data.elements[i]);
82 }
83
88 template <typename TypeToCreateFrom>
89 explicit Array (const TypeToCreateFrom* values) noexcept : numUsed (0)
90 {
91 while (*values != TypeToCreateFrom())
92 {
93 CARLA_SAFE_ASSERT_BREAK(add (*values++));
94 }
95 }
96
102 template <typename TypeToCreateFrom>
103 Array (const TypeToCreateFrom* values, int numValues) noexcept : numUsed (numValues)
104 {
105 CARLA_SAFE_ASSERT_RETURN(data.setAllocatedSize (numValues),);
106
107 for (int i = 0; i < numValues; ++i)
108 new (data.elements + i) ElementType (values[i]);
109 }
110
113 {
115 }
116
120 Array& operator= (const Array& other) noexcept
121 {
122 if (this != &other)
123 {
124 Array<ElementType> otherCopy (other);
125 swapWith (otherCopy);
126 }
127
128 return *this;
129 }
130
131 //==============================================================================
137 template <class OtherArrayType>
138 bool operator== (const OtherArrayType& other) const
139 {
140 if (numUsed != other.numUsed)
141 return false;
142
143 for (int i = numUsed; --i >= 0;)
144 if (! (data.elements [i] == other.data.elements [i]))
145 return false;
146
147 return true;
148 }
149
155 template <class OtherArrayType>
156 bool operator!= (const OtherArrayType& other) const
157 {
158 return ! operator== (other);
159 }
160
161 //==============================================================================
170 {
172 data.setAllocatedSize (0);
173 numUsed = 0;
174 }
175
180 {
182 numUsed = 0;
183 }
184
185 //==============================================================================
187 inline int size() const noexcept
188 {
189 return numUsed;
190 }
191
193 inline bool isEmpty() const noexcept
194 {
195 return size() == 0;
196 }
197
208 ElementType operator[] (const int index) const
209 {
210 if (isPositiveAndBelow (index, numUsed))
211 {
212 wassert (data.elements != nullptr);
213 return data.elements [index];
214 }
215
216 return ElementType();
217 }
218
228 inline ElementType getUnchecked (const int index) const
229 {
230 wassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
231 return data.elements [index];
232 }
233
243 inline ElementType& getReference (const int index) const noexcept
244 {
245 wassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
246 return data.elements [index];
247 }
248
253 inline ElementType getFirst() const
254 {
255 if (numUsed > 0)
256 {
257 wassert (data.elements != nullptr);
258 return data.elements[0];
259 }
260
261 return ElementType();
262 }
263
268 inline ElementType getLast() const
269 {
270 if (numUsed > 0)
271 {
272 wassert (data.elements != nullptr);
273 return data.elements[numUsed - 1];
274 }
275
276 return ElementType();
277 }
278
283 inline ElementType* getRawDataPointer() noexcept
284 {
285 return data.elements;
286 }
287
288 //==============================================================================
292 inline ElementType* begin() const noexcept
293 {
294 return data.elements;
295 }
296
300 inline ElementType* end() const noexcept
301 {
302 #ifdef DEBUG
303 if (data.elements == nullptr || numUsed <= 0) // (to keep static analysers happy)
304 return data.elements;
305 #endif
306
307 return data.elements + numUsed;
308 }
309
310 //==============================================================================
319 int indexOf (ParameterType elementToLookFor) const
320 {
321 const ElementType* e = data.elements.getData();
322 const ElementType* const end_ = e + numUsed;
323
324 for (; e != end_; ++e)
325 if (elementToLookFor == *e)
326 return static_cast<int> (e - data.elements.getData());
327
328 return -1;
329 }
330
336 bool contains (ParameterType elementToLookFor) const
337 {
338 const ElementType* e = data.elements.getData();
339 const ElementType* const end_ = e + numUsed;
340
341 for (; e != end_; ++e)
342 if (elementToLookFor == *e)
343 return true;
344
345 return false;
346 }
347
348 //==============================================================================
354 bool add (const ElementType& newElement) noexcept
355 {
356 if (! data.ensureAllocatedSize (static_cast<size_t>(numUsed + 1)))
357 return false;
358
359 new (data.elements + numUsed++) ElementType (newElement);
360 return true;
361 }
362
375 bool insert (int indexToInsertAt, ParameterType newElement) noexcept
376 {
377 if (! data.ensureAllocatedSize (numUsed + 1))
378 return false;
379
380 if (isPositiveAndBelow (indexToInsertAt, numUsed))
381 {
382 ElementType* const insertPos = data.elements + indexToInsertAt;
383 const int numberToMove = numUsed - indexToInsertAt;
384
385 if (numberToMove > 0)
386 data.moveMemory (insertPos + 1, insertPos, numberToMove);
387
388 new (insertPos) ElementType (newElement);
389 ++numUsed;
390 }
391 else
392 {
393 new (data.elements + numUsed++) ElementType (newElement);
394 }
395
396 return true;
397 }
398
411 bool insertMultiple (int indexToInsertAt, ParameterType newElement,
412 int numberOfTimesToInsertIt)
413 {
414 if (numberOfTimesToInsertIt > 0)
415 {
416 if (! data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt))
417 return false;
418
419 ElementType* insertPos;
420
421 if (isPositiveAndBelow (indexToInsertAt, numUsed))
422 {
423 insertPos = data.elements + indexToInsertAt;
424 const int numberToMove = numUsed - indexToInsertAt;
425 data.moveMemory (insertPos + numberOfTimesToInsertIt, insertPos, numberToMove);
426 }
427 else
428 {
429 insertPos = data.elements + numUsed;
430 }
431
432 numUsed += numberOfTimesToInsertIt;
433
434 while (--numberOfTimesToInsertIt >= 0)
435 {
436 new (insertPos) ElementType (newElement);
437 ++insertPos; // NB: this increment is done separately from the
438 // new statement to avoid a compiler bug in VS2014
439 }
440 }
441
442 return true;
443 }
444
445#if 0
458 bool insertArray (int indexToInsertAt,
459 const ElementType* newElements,
460 int numberOfElements)
461 {
462 if (numberOfElements > 0)
463 {
464 if (! data.ensureAllocatedSize (numUsed + numberOfElements))
465 return false;
466
467 ElementType* insertPos = data.elements;
468
469 if (isPositiveAndBelow (indexToInsertAt, numUsed))
470 {
471 insertPos += indexToInsertAt;
472 const int numberToMove = numUsed - indexToInsertAt;
473 std::memmove (insertPos + numberOfElements, insertPos, (size_t) numberToMove * sizeof (ElementType));
474 }
475 else
476 {
477 insertPos += numUsed;
478 }
479
480 numUsed += numberOfElements;
481
482 while (--numberOfElements >= 0)
483 new (insertPos++) ElementType (*newElements++);
484 }
485
486 return true;
487 }
488#endif
489
500 {
501 if (contains (newElement))
502 return false;
503
504 return add (newElement);
505 }
506
516 void set (const int indexToChange, ParameterType newValue)
517 {
518 wassert (indexToChange >= 0);
519
520 if (isPositiveAndBelow (indexToChange, numUsed))
521 {
522 wassert (data.elements != nullptr);
523 data.elements [indexToChange] = newValue;
524 }
525 else if (indexToChange >= 0)
526 {
527 data.ensureAllocatedSize (numUsed + 1);
528 new (data.elements + numUsed++) ElementType (newValue);
529 }
530 }
531
541 void setUnchecked (const int indexToChange, ParameterType newValue)
542 {
543 wassert (isPositiveAndBelow (indexToChange, numUsed));
544 data.elements [indexToChange] = newValue;
545 }
546
554 template <typename Type>
555 void addArray (const Type* elementsToAdd, int numElementsToAdd)
556 {
557 if (numElementsToAdd > 0)
558 {
559 data.ensureAllocatedSize (numUsed + numElementsToAdd);
560
561 while (--numElementsToAdd >= 0)
562 {
563 new (data.elements + numUsed) ElementType (*elementsToAdd++);
564 ++numUsed;
565 }
566 }
567 }
568
575 template <typename Type>
576 void addNullTerminatedArray (const Type* const* elementsToAdd)
577 {
578 int num = 0;
579 for (const Type* const* e = elementsToAdd; *e != nullptr; ++e)
580 ++num;
581
582 addArray (elementsToAdd, num);
583 }
584
590 template <class OtherArrayType>
591 void swapWith (OtherArrayType& otherArray) noexcept
592 {
593 data.swapWith (otherArray.data);
594 std::swap (numUsed, otherArray.numUsed);
595 }
596
606 template <class OtherArrayType>
607 void addArray (const OtherArrayType& arrayToAddFrom,
608 int startIndex = 0,
609 int numElementsToAdd = -1)
610 {
611 if (startIndex < 0)
612 {
614 startIndex = 0;
615 }
616
617 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
618 numElementsToAdd = arrayToAddFrom.size() - startIndex;
619
620 while (--numElementsToAdd >= 0)
621 add (arrayToAddFrom.getUnchecked (startIndex++));
622 }
623
631 void resize (const int targetNumItems)
632 {
633 wassert (targetNumItems >= 0);
634
635 const int numToAdd = targetNumItems - numUsed;
636 if (numToAdd > 0)
637 insertMultiple (numUsed, ElementType(), numToAdd);
638 else if (numToAdd < 0)
639 removeRange (targetNumItems, -numToAdd);
640 }
641
654 template <class ElementComparator>
655 int addSorted (ElementComparator& comparator, ParameterType newElement)
656 {
657 const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newElement, 0, numUsed);
658 insert (index, newElement);
659 return index;
660 }
661
672 {
673 DefaultElementComparator <ElementType> comparator;
674 addSorted (comparator, newElement);
675 }
676
689 template <typename ElementComparator, typename TargetValueType>
690 int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const
691 {
692 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
693 // avoids getting warning messages about the parameter being unused
694
695 for (int s = 0, e = numUsed;;)
696 {
697 if (s >= e)
698 return -1;
699
700 if (comparator.compareElements (elementToLookFor, data.elements [s]) == 0)
701 return s;
702
703 const int halfway = (s + e) / 2;
704 if (halfway == s)
705 return -1;
706
707 if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0)
708 s = halfway;
709 else
710 e = halfway;
711 }
712 }
713
714 //==============================================================================
724 void remove (int indexToRemove)
725 {
726 if (isPositiveAndBelow (indexToRemove, numUsed))
727 {
728 wassert (data.elements != nullptr);
729 removeInternal (indexToRemove);
730 }
731 }
732
743 ElementType removeAndReturn (const int indexToRemove)
744 {
745 if (isPositiveAndBelow (indexToRemove, numUsed))
746 {
747 wassert (data.elements != nullptr);
748 ElementType removed (data.elements[indexToRemove]);
749 removeInternal (indexToRemove);
750 return removed;
751 }
752
753 return ElementType();
754 }
755
766 void remove (const ElementType* elementToRemove)
767 {
768 wassert (elementToRemove != nullptr);
769 wassert (data.elements != nullptr);
770 const int indexToRemove = int (elementToRemove - data.elements);
771
772 if (! isPositiveAndBelow (indexToRemove, numUsed))
773 {
775 return;
776 }
777
778 removeInternal (indexToRemove);
779 }
780
790 {
791 ElementType* const e = data.elements;
792
793 for (int i = 0; i < numUsed; ++i)
794 {
795 if (valueToRemove == e[i])
796 {
798 break;
799 }
800 }
801 }
802
813 {
814 int numRemoved = 0;
815
816 for (int i = numUsed; --i >= 0;)
817 {
818 if (valueToRemove == data.elements[i])
819 {
821 ++numRemoved;
822 }
823 }
824
825 return numRemoved;
826 }
827
839 template <typename PredicateType>
840 int removeIf (PredicateType predicate)
841 {
842 int numRemoved = 0;
843
844 for (int i = numUsed; --i >= 0;)
845 {
846 if (predicate (data.elements[i]) == true)
847 {
849 ++numRemoved;
850 }
851 }
852
853 return numRemoved;
854 }
855
868 void removeRange (int startIndex, int numberToRemove)
869 {
870 const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
871 startIndex = jlimit (0, numUsed, startIndex);
872 numberToRemove = endIndex - startIndex;
873
874 if (numberToRemove > 0)
875 {
876#if 1
877 ElementType* const e = data.elements + startIndex;
878
879 const int numToShift = numUsed - endIndex;
880 if (numToShift > 0)
881 data.moveMemory (e, e + numberToRemove, numToShift);
882
883 for (int i = 0; i < numberToRemove; ++i)
884 e[numToShift + i].~ElementType();
885#else
886 ElementType* dst = data.elements + startIndex;
887 ElementType* src = dst + numberToRemove;
888
889 const int numToShift = numUsed - endIndex;
890 for (int i = 0; i < numToShift; ++i)
891 data.moveElement (dst++, std::move (*(src++)));
892
893 for (int i = 0; i < numberToRemove; ++i)
894 (dst++)->~ElementType();
895#endif
896
897 numUsed -= numberToRemove;
899 }
900 }
901
907 void removeLast (int howManyToRemove = 1)
908 {
909 if (howManyToRemove > numUsed)
910 howManyToRemove = numUsed;
911
912 for (int i = 1; i <= howManyToRemove; ++i)
913 data.elements [numUsed - i].~ElementType();
914
915 numUsed -= howManyToRemove;
917 }
918
924 template <class OtherArrayType>
925 void removeValuesIn (const OtherArrayType& otherArray)
926 {
927 if (this == &otherArray)
928 {
929 clear();
930 }
931 else
932 {
933 if (otherArray.size() > 0)
934 {
935 for (int i = numUsed; --i >= 0;)
936 if (otherArray.contains (data.elements [i]))
938 }
939 }
940 }
941
949 template <class OtherArrayType>
950 void removeValuesNotIn (const OtherArrayType& otherArray)
951 {
952 if (this != &otherArray)
953 {
954 if (otherArray.size() <= 0)
955 {
956 clear();
957 }
958 else
959 {
960 for (int i = numUsed; --i >= 0;)
961 if (! otherArray.contains (data.elements [i]))
963 }
964 }
965 }
966
975 void swap (const int index1,
976 const int index2)
977 {
978 if (isPositiveAndBelow (index1, numUsed)
979 && isPositiveAndBelow (index2, numUsed))
980 {
981 std::swap (data.elements [index1],
982 data.elements [index2]);
983 }
984 }
985
986 //==============================================================================
994 {
995 return data.shrinkToNoMoreThan (numUsed);
996 }
997
1004 bool ensureStorageAllocated (const int minNumElements) noexcept
1005 {
1006 return data.ensureAllocatedSize (minNumElements);
1007 }
1008
1009 //==============================================================================
1014 void sort()
1015 {
1017 sort (comparator);
1018 }
1019
1046 template <class ElementComparator>
1047 void sort (ElementComparator& comparator,
1048 const bool retainOrderOfEquivalentItems = false)
1049 {
1050 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
1051 // avoids getting warning messages about the parameter being unused
1052 sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
1053 }
1054
1055private:
1056 //==============================================================================
1057 ArrayAllocationBase <ElementType> data;
1059
1060 void removeInternal (const int indexToRemove)
1061 {
1062 --numUsed;
1063 ElementType* const e = data.elements + indexToRemove;
1064 e->~ElementType();
1065 const int numberToShift = numUsed - indexToRemove;
1066
1067 if (numberToShift > 0)
1068 data.moveMemory (e, e + 1, static_cast<size_t>(numberToShift));
1069
1071 }
1072
1074 {
1075 for (int i = 0; i < numUsed; ++i)
1076 data.elements[i].~ElementType();
1077 }
1078
1080 {
1082
1083 const size_t snumUsed = static_cast<size_t>(numUsed);
1084
1085 if (data.numAllocated > jmax (minimumAllocatedSize, snumUsed * 2U))
1086 data.shrinkToNoMoreThan (jmax (snumUsed, jmax (minimumAllocatedSize, 64U / sizeof (ElementType))));
1087 }
1088};
1089
1090}
1091
1092#endif // WATER_ARRAY_H_INCLUDED
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
#define CARLA_SAFE_ASSERT_BREAK(cond)
Definition CarlaDefines.h:188
#define noexcept
Definition DistrhoDefines.h:72
Array() noexcept
Definition Array.h:64
Array & operator=(const Array &other) noexcept
Definition Array.h:120
void removeInternal(const int indexToRemove)
Definition Array.h:1060
~Array() noexcept
Definition Array.h:112
ElementType & getReference(const int index) const noexcept
Definition Array.h:243
int indexOf(ParameterType elementToLookFor) const
Definition Array.h:319
void deleteAllElements() noexcept
Definition Array.h:1073
void clearQuick() noexcept
Definition Array.h:179
typedef PARAMETER_TYPE(ElementType) ParameterType
Array(const TypeToCreateFrom *values, int numValues) noexcept
Definition Array.h:103
bool operator!=(const OtherArrayType &other) const
Definition Array.h:156
void resize(const int targetNumItems)
Definition Array.h:631
Array(const Array< ElementType > &other) noexcept
Definition Array.h:73
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition Array.h:555
int removeAllInstancesOf(ParameterType valueToRemove)
Definition Array.h:812
void removeFirstMatchingValue(ParameterType valueToRemove)
Definition Array.h:789
void removeLast(int howManyToRemove=1)
Definition Array.h:907
int indexOfSorted(ElementComparator &comparator, TargetValueType elementToLookFor) const
Definition Array.h:690
bool add(const ElementType &newElement) noexcept
Definition Array.h:354
void remove(const ElementType *elementToRemove)
Definition Array.h:766
ElementType * begin() const noexcept
Definition Array.h:292
void swapWith(OtherArrayType &otherArray) noexcept
Definition Array.h:591
bool ensureStorageAllocated(const int minNumElements) noexcept
Definition Array.h:1004
int size() const noexcept
Definition Array.h:187
void sort()
Definition Array.h:1014
void swap(const int index1, const int index2)
Definition Array.h:975
ElementType * end() const noexcept
Definition Array.h:300
bool minimiseStorageOverheads() noexcept
Definition Array.h:993
void setUnchecked(const int indexToChange, ParameterType newValue)
Definition Array.h:541
bool insertMultiple(int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt)
Definition Array.h:411
bool addIfNotAlreadyThere(ParameterType newElement)
Definition Array.h:499
void minimiseStorageAfterRemoval()
Definition Array.h:1079
bool operator==(const OtherArrayType &other) const
Definition Array.h:138
ElementType getUnchecked(const int index) const
Definition Array.h:228
int addSorted(ElementComparator &comparator, ParameterType newElement)
Definition Array.h:655
void remove(int indexToRemove)
Definition Array.h:724
void addUsingDefaultSort(ParameterType newElement)
Definition Array.h:671
bool insert(int indexToInsertAt, ParameterType newElement) noexcept
Definition Array.h:375
ArrayAllocationBase< ElementType > data
Definition Array.h:1057
ElementType operator[](const int index) const
Definition Array.h:208
void addNullTerminatedArray(const Type *const *elementsToAdd)
Definition Array.h:576
int numUsed
Definition Array.h:1058
void removeRange(int startIndex, int numberToRemove)
Definition Array.h:868
ElementType getLast() const
Definition Array.h:268
void removeValuesIn(const OtherArrayType &otherArray)
Definition Array.h:925
ElementType getFirst() const
Definition Array.h:253
void clear() noexcept
Definition Array.h:169
Array(const TypeToCreateFrom *values) noexcept
Definition Array.h:89
bool contains(ParameterType elementToLookFor) const
Definition Array.h:336
void removeValuesNotIn(const OtherArrayType &otherArray)
Definition Array.h:950
ElementType * getRawDataPointer() noexcept
Definition Array.h:283
void set(const int indexToChange, ParameterType newValue)
Definition Array.h:516
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Definition Array.h:607
void sort(ElementComparator &comparator, const bool retainOrderOfEquivalentItems=false)
Definition Array.h:1047
bool isEmpty() const noexcept
Definition Array.h:193
ElementType removeAndReturn(const int indexToRemove)
Definition Array.h:743
Array() noexcept
Definition Array.h:64
int removeIf(PredicateType predicate)
Definition Array.h:840
Definition ElementComparator.h:179
* e
Definition inflate.c:1404
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
ParameterType
Definition CarlaBackend.h:763
JSAMPIMAGE data
Definition jpeglib.h:945
#define wassertfalse
#define wassert(expression)
Definition AudioSampleBuffer.h:33
static int findInsertIndexInSortedArray(ElementComparator &comparator, ElementType *const array, const ElementType newElement, int firstElement, int lastElement)
Definition ElementComparator.h:119
bool isPositiveAndBelow(Type valueToTest, Type upperLimit) noexcept
Definition MathsFunctions.h:187
void ignoreUnused(const Type1 &) noexcept
Definition MathsFunctions.h:237
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
Type jlimit(const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) noexcept
Definition MathsFunctions.h:169
static void sortArray(ElementComparator &comparator, ElementType *const array, int firstElement, int lastElement, const bool retainOrderOfEquivalentItems)
Definition ElementComparator.h:79
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137