LMMS
Loading...
Searching...
No Matches
ReferenceCountedArray.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 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_REFERENCECOUNTEDARRAY_H_INCLUDED
27#define WATER_REFERENCECOUNTEDARRAY_H_INCLUDED
28
30
31namespace water {
32
33//==============================================================================
54template <class ObjectClass>
56{
57public:
59
60 //==============================================================================
68
71 {
72 numUsed = other.size();
73 data.setAllocatedSize (numUsed);
74 memcpy (data.elements, other.getRawDataPointer(), (size_t) numUsed * sizeof (ObjectClass*));
75
76 for (int i = numUsed; --i >= 0;)
77 if (ObjectClass* o = data.elements[i])
78 o->incReferenceCount();
79 }
80
82 template <class OtherObjectClass>
84 {
85 numUsed = other.size();
86 data.setAllocatedSize (numUsed);
87 memcpy (data.elements, other.getRawDataPointer(), numUsed * sizeof (ObjectClass*));
88
89 for (int i = numUsed; --i >= 0;)
90 if (ObjectClass* o = data.elements[i])
91 o->incReferenceCount();
92 }
93
98 {
99 ReferenceCountedArray otherCopy (other);
100 swapWith (otherCopy);
101 return *this;
102 }
103
107 template <class OtherObjectClass>
109 {
110 ReferenceCountedArray<ObjectClass> otherCopy (other);
111 swapWith (otherCopy);
112 return *this;
113 }
114
122
123 //==============================================================================
127 void clear()
128 {
130 data.setAllocatedSize (0);
131 }
132
138 {
140 }
141
143 inline int size() const noexcept
144 {
145 return numUsed;
146 }
147
149 inline bool isEmpty() const noexcept
150 {
151 return size() == 0;
152 }
153
162 inline ObjectClassPtr operator[] (const int index) const noexcept
163 {
164 return getObjectPointer (index);
165 }
166
173 inline ObjectClassPtr getUnchecked (const int index) const noexcept
174 {
175 return getObjectPointerUnchecked (index);
176 }
177
186 inline ObjectClass* getObjectPointer (const int index) const noexcept
187 {
188 if (isPositiveAndBelow (index, numUsed))
189 {
190 wassert (data.elements != nullptr);
191 return data.elements [index];
192 }
193
194 return ObjectClassPtr();
195 }
196
200 inline ObjectClass* getObjectPointerUnchecked (const int index) const noexcept
201 {
202 wassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
203 return data.elements [index];
204 }
205
212 {
213 if (numUsed > 0)
214 {
215 wassert (data.elements != nullptr);
216 return data.elements [0];
217 }
218
219 return ObjectClassPtr();
220 }
221
228 {
229 if (numUsed > 0)
230 {
231 wassert (data.elements != nullptr);
232 return data.elements [numUsed - 1];
233 }
234
235 return ObjectClassPtr();
236 }
237
242 inline ObjectClass** getRawDataPointer() const noexcept
243 {
244 return data.elements;
245 }
246
247 //==============================================================================
251 inline ObjectClass** begin() const noexcept
252 {
253 return data.elements;
254 }
255
259 inline ObjectClass** end() const noexcept
260 {
261 return data.elements + numUsed;
262 }
263
264 //==============================================================================
270 int indexOf (const ObjectClass* const objectToLookFor) const noexcept
271 {
272 ObjectClass** e = data.elements.getData();
273 ObjectClass** const endPointer = e + numUsed;
274
275 while (e != endPointer)
276 {
277 if (objectToLookFor == *e)
278 return static_cast<int> (e - data.elements.getData());
279
280 ++e;
281 }
282
283 return -1;
284 }
285
291 bool contains (const ObjectClass* const objectToLookFor) const noexcept
292 {
293 ObjectClass** e = data.elements.getData();
294 ObjectClass** const endPointer = e + numUsed;
295
296 while (e != endPointer)
297 {
298 if (objectToLookFor == *e)
299 return true;
300
301 ++e;
302 }
303
304 return false;
305 }
306
314 ObjectClass* add (ObjectClass* const newObject) noexcept
315 {
316 data.ensureAllocatedSize (numUsed + 1);
317 wassert (data.elements != nullptr);
318 data.elements [numUsed++] = newObject;
319
320 if (newObject != nullptr)
321 newObject->incReferenceCount();
322
323 return newObject;
324 }
325
339 ObjectClass* insert (int indexToInsertAt,
340 ObjectClass* const newObject) noexcept
341 {
342 if (indexToInsertAt < 0)
343 return add (newObject);
344
345 if (indexToInsertAt > numUsed)
346 indexToInsertAt = numUsed;
347
348 data.ensureAllocatedSize (numUsed + 1);
349 wassert (data.elements != nullptr);
350
351 ObjectClass** const e = data.elements + indexToInsertAt;
352 const int numToMove = numUsed - indexToInsertAt;
353
354 if (numToMove > 0)
355 memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
356
357 *e = newObject;
358
359 if (newObject != nullptr)
360 newObject->incReferenceCount();
361
362 ++numUsed;
363
364 return newObject;
365 }
366
375 bool addIfNotAlreadyThere (ObjectClass* const newObject) noexcept
376 {
377 if (contains (newObject))
378 return false;
379
380 add (newObject);
381 return true;
382 }
383
396 void set (const int indexToChange,
397 ObjectClass* const newObject)
398 {
399 if (indexToChange >= 0)
400 {
401 if (newObject != nullptr)
402 newObject->incReferenceCount();
403
404 if (indexToChange < numUsed)
405 {
406 if (ObjectClass* o = data.elements [indexToChange])
407 releaseObject (o);
408
409 data.elements [indexToChange] = newObject;
410 }
411 else
412 {
413 data.ensureAllocatedSize (numUsed + 1);
414 wassert (data.elements != nullptr);
415 data.elements [numUsed++] = newObject;
416 }
417 }
418 }
419
429 void addArray (const ReferenceCountedArray<ObjectClass>& arrayToAddFrom,
430 int startIndex = 0,
431 int numElementsToAdd = -1) noexcept
432 {
433 if (startIndex < 0)
434 {
436 startIndex = 0;
437 }
438
439 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
440 numElementsToAdd = arrayToAddFrom.size() - startIndex;
441
442 if (numElementsToAdd > 0)
443 {
444 data.ensureAllocatedSize (numUsed + numElementsToAdd);
445
446 while (--numElementsToAdd >= 0)
447 add (arrayToAddFrom.getUnchecked (startIndex++));
448 }
449 }
450
463 template <class ElementComparator>
464 int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
465 {
466 const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
467 insert (index, newObject);
468 return index;
469 }
470
476 template <class ElementComparator>
477 void addOrReplaceSorted (ElementComparator& comparator,
478 ObjectClass* newObject) noexcept
479 {
480 const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
481
482 if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0)
483 set (index - 1, newObject); // replace an existing object that matches
484 else
485 insert (index, newObject); // no match, so insert the new one
486 }
487
500 template <class ElementComparator>
501 int indexOfSorted (ElementComparator& comparator,
502 const ObjectClass* const objectToLookFor) const noexcept
503 {
504 ignoreUnused (comparator);
505 int s = 0, e = numUsed;
506
507 while (s < e)
508 {
509 if (comparator.compareElements (objectToLookFor, data.elements [s]) == 0)
510 return s;
511
512 const int halfway = (s + e) / 2;
513 if (halfway == s)
514 break;
515
516 if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0)
517 s = halfway;
518 else
519 e = halfway;
520 }
521
522 return -1;
523 }
524
525 //==============================================================================
539 void remove (const int indexToRemove)
540 {
541 if (isPositiveAndBelow (indexToRemove, numUsed))
542 {
543 ObjectClass** const e = data.elements + indexToRemove;
544
545 if (ObjectClass* o = *e)
546 releaseObject (o);
547
548 --numUsed;
549 const int numberToShift = numUsed - indexToRemove;
550
551 if (numberToShift > 0)
552 std::memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numberToShift);
553
554 if ((numUsed << 1) < static_cast<int>(data.numAllocated))
556 }
557 }
558
568 ObjectClassPtr removeAndReturn (const int indexToRemove)
569 {
570 ObjectClassPtr removedItem;
571
572 if (isPositiveAndBelow (indexToRemove, numUsed))
573 {
574 ObjectClass** const e = data.elements + indexToRemove;
575
576 if (ObjectClass* o = *e)
577 {
578 removedItem = o;
579 releaseObject (o);
580 }
581
582 --numUsed;
583 const int numberToShift = numUsed - indexToRemove;
584
585 if (numberToShift > 0)
586 memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numberToShift);
587
588 if ((numUsed << 1) < data.numAllocated)
590 }
591
592 return removedItem;
593 }
594
603 void removeObject (ObjectClass* const objectToRemove)
604 {
605 remove (indexOf (objectToRemove));
606 }
607
623 void removeRange (const int startIndex,
624 const int numberToRemove)
625 {
626 const int start = jlimit (0, numUsed, startIndex);
627 const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
628
629 if (endIndex > start)
630 {
631 int i;
632 for (i = start; i < endIndex; ++i)
633 {
634 if (ObjectClass* o = data.elements[i])
635 {
636 releaseObject (o);
637 data.elements[i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer)
638 }
639 }
640
641 const int rangeSize = endIndex - start;
642 ObjectClass** e = data.elements + start;
643 i = numUsed - endIndex;
644 numUsed -= rangeSize;
645
646 while (--i >= 0)
647 {
648 *e = e [rangeSize];
649 ++e;
650 }
651
652 if ((numUsed << 1) < data.numAllocated)
654 }
655 }
656
665 void removeLast (int howManyToRemove = 1)
666 {
667 if (howManyToRemove > numUsed)
668 howManyToRemove = numUsed;
669
670 while (--howManyToRemove >= 0)
671 remove (numUsed - 1);
672 }
673
679 void swap (const int index1,
680 const int index2) noexcept
681 {
682 if (isPositiveAndBelow (index1, numUsed)
683 && isPositiveAndBelow (index2, numUsed))
684 {
685 std::swap (data.elements [index1],
686 data.elements [index2]);
687 }
688 }
689
703 void move (const int currentIndex,
704 int newIndex) noexcept
705 {
706 if (currentIndex != newIndex)
707 {
708 if (isPositiveAndBelow (currentIndex, numUsed))
709 {
710 if (! isPositiveAndBelow (newIndex, numUsed))
711 newIndex = numUsed - 1;
712
713 ObjectClass* const value = data.elements [currentIndex];
714
715 if (newIndex > currentIndex)
716 {
717 memmove (data.elements + currentIndex,
718 data.elements + currentIndex + 1,
719 sizeof (ObjectClass*) * (size_t) (newIndex - currentIndex));
720 }
721 else
722 {
723 memmove (data.elements + newIndex + 1,
724 data.elements + newIndex,
725 sizeof (ObjectClass*) * (size_t) (currentIndex - newIndex));
726 }
727
728 data.elements [newIndex] = value;
729 }
730 }
731 }
732
733 //==============================================================================
739 template <class OtherArrayType>
740 void swapWith (OtherArrayType& otherArray) noexcept
741 {
742 data.swapWith (otherArray.data);
743 std::swap (numUsed, otherArray.numUsed);
744 }
745
746 //==============================================================================
751 bool operator== (const ReferenceCountedArray& other) const noexcept
752 {
753 if (numUsed != other.numUsed)
754 return false;
755
756 for (int i = numUsed; --i >= 0;)
757 if (data.elements [i] != other.data.elements [i])
758 return false;
759
760 return true;
761 }
762
767 bool operator!= (const ReferenceCountedArray<ObjectClass>& other) const noexcept
768 {
769 return ! operator== (other);
770 }
771
772 //==============================================================================
799 template <class ElementComparator>
800 void sort (ElementComparator& comparator,
801 const bool retainOrderOfEquivalentItems = false) const noexcept
802 {
803 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
804 // avoids getting warning messages about the parameter being unused
805
806 sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
807 }
808
809 //==============================================================================
817 {
818 data.shrinkToNoMoreThan (numUsed);
819 }
820
827 void ensureStorageAllocated (const int minNumElements)
828 {
829 data.ensureAllocatedSize (minNumElements);
830 }
831
832private:
833 //==============================================================================
834 ArrayAllocationBase <ObjectClass*> data;
836
838 {
839 while (numUsed > 0)
840 if (ObjectClass* o = data.elements [--numUsed])
841 releaseObject (o);
842
843 wassert (numUsed == 0);
844 }
845
846 static void releaseObject (ObjectClass* o)
847 {
848 if (o->decReferenceCountWithoutDeleting())
849 delete o;
850 }
851};
852
853}
854
855#endif // WATER_REFERENCECOUNTEDARRAY_H_INCLUDED
#define noexcept
Definition DistrhoDefines.h:72
ObjectClass ** begin() const noexcept
Definition ReferenceCountedArray.h:251
void minimiseStorageOverheads() noexcept
Definition ReferenceCountedArray.h:816
ObjectClass ** end() const noexcept
Definition ReferenceCountedArray.h:259
ObjectClassPtr getLast() const noexcept
Definition ReferenceCountedArray.h:227
bool operator==(const ReferenceCountedArray &other) const noexcept
Definition ReferenceCountedArray.h:751
void addArray(const ReferenceCountedArray< ObjectClass > &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1) noexcept
Definition ReferenceCountedArray.h:429
void remove(const int indexToRemove)
Definition ReferenceCountedArray.h:539
ObjectClass * add(ObjectClass *const newObject) noexcept
Definition ReferenceCountedArray.h:314
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition ReferenceCountedArray.h:464
bool isEmpty() const noexcept
Definition ReferenceCountedArray.h:149
void releaseAllObjects()
Definition ReferenceCountedArray.h:837
ReferenceCountedObjectPtr< ObjectClass > ObjectClassPtr
Definition ReferenceCountedArray.h:58
ObjectClass * getObjectPointerUnchecked(const int index) const noexcept
Definition ReferenceCountedArray.h:200
void swapWith(OtherArrayType &otherArray) noexcept
Definition ReferenceCountedArray.h:740
void set(const int indexToChange, ObjectClass *const newObject)
Definition ReferenceCountedArray.h:396
void sort(ElementComparator &comparator, const bool retainOrderOfEquivalentItems=false) const noexcept
Definition ReferenceCountedArray.h:800
void ensureStorageAllocated(const int minNumElements)
Definition ReferenceCountedArray.h:827
int indexOf(const ObjectClass *const objectToLookFor) const noexcept
Definition ReferenceCountedArray.h:270
void clearQuick()
Definition ReferenceCountedArray.h:137
bool addIfNotAlreadyThere(ObjectClass *const newObject) noexcept
Definition ReferenceCountedArray.h:375
ArrayAllocationBase< ObjectClass * > data
Definition ReferenceCountedArray.h:834
ReferenceCountedArray(const ReferenceCountedArray< OtherObjectClass > &other) noexcept
Definition ReferenceCountedArray.h:83
ReferenceCountedArray() noexcept
Definition ReferenceCountedArray.h:64
void addOrReplaceSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition ReferenceCountedArray.h:477
bool operator!=(const ReferenceCountedArray< ObjectClass > &other) const noexcept
Definition ReferenceCountedArray.h:767
ObjectClass * getObjectPointer(const int index) const noexcept
Definition ReferenceCountedArray.h:186
ObjectClass ** getRawDataPointer() const noexcept
Definition ReferenceCountedArray.h:242
void removeLast(int howManyToRemove=1)
Definition ReferenceCountedArray.h:665
bool contains(const ObjectClass *const objectToLookFor) const noexcept
Definition ReferenceCountedArray.h:291
ObjectClassPtr operator[](const int index) const noexcept
Definition ReferenceCountedArray.h:162
ObjectClassPtr getUnchecked(const int index) const noexcept
Definition ReferenceCountedArray.h:173
~ReferenceCountedArray()
Definition ReferenceCountedArray.h:118
ObjectClassPtr removeAndReturn(const int indexToRemove)
Definition ReferenceCountedArray.h:568
ObjectClassPtr getFirst() const noexcept
Definition ReferenceCountedArray.h:211
void swap(const int index1, const int index2) noexcept
Definition ReferenceCountedArray.h:679
int indexOfSorted(ElementComparator &comparator, const ObjectClass *const objectToLookFor) const noexcept
Definition ReferenceCountedArray.h:501
void removeObject(ObjectClass *const objectToRemove)
Definition ReferenceCountedArray.h:603
void removeRange(const int startIndex, const int numberToRemove)
Definition ReferenceCountedArray.h:623
void move(const int currentIndex, int newIndex) noexcept
Definition ReferenceCountedArray.h:703
static void releaseObject(ObjectClass *o)
Definition ReferenceCountedArray.h:846
int numUsed
Definition ReferenceCountedArray.h:835
int size() const noexcept
Definition ReferenceCountedArray.h:143
void clear()
Definition ReferenceCountedArray.h:127
ObjectClass * insert(int indexToInsertAt, ObjectClass *const newObject) noexcept
Definition ReferenceCountedArray.h:339
ReferenceCountedArray & operator=(const ReferenceCountedArray &other) noexcept
Definition ReferenceCountedArray.h:97
ReferenceCountedArray(const ReferenceCountedArray &other) noexcept
Definition ReferenceCountedArray.h:70
Definition ReferenceCountedObject.h:227
* e
Definition inflate.c:1404
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
static PuglViewHint int value
Definition pugl.h:1708
virtual ASIOError start()=0
#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 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
memcpy(hh, h, RAND_HEAD_LEN)
#define const
Definition zconf.h:137