JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_ArrayBase.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#if JUCE_UNIT_TESTS
27
29{
31 {
32 public:
33 TriviallyCopyableType() = default;
34
35 TriviallyCopyableType (int v)
36 : value (v)
37 {}
38
39 TriviallyCopyableType (float v)
40 : value ((int) v)
41 {}
42
43 bool operator== (const TriviallyCopyableType& other) const
44 {
45 return getValue() == other.getValue();
46 }
47
48 int getValue() const { return value; }
49
50 private:
51 int value { -1111 };
52 };
53
55 {
56 public:
57 NonTriviallyCopyableType() = default;
58
59 NonTriviallyCopyableType (int v)
60 : value (v)
61 {}
62
63 NonTriviallyCopyableType (float v)
64 : value ((int) v)
65 {}
66
67 NonTriviallyCopyableType (const NonTriviallyCopyableType& other)
68 : value (other.value)
69 {}
70
71 NonTriviallyCopyableType& operator= (const NonTriviallyCopyableType& other)
72 {
73 value = other.value;
74 return *this;
75 }
76
77 bool operator== (const NonTriviallyCopyableType& other) const
78 {
79 return getValue() == other.getValue();
80 }
81
82 int getValue() const { return *ptr; }
83
84 private:
85 int value { -1111 };
86 int* ptr = &value;
87 };
88}
89
90static bool operator== (const ArrayBaseTestsHelpers::TriviallyCopyableType& tct,
91 const ArrayBaseTestsHelpers::NonTriviallyCopyableType& ntct)
92{
93 return tct.getValue() == ntct.getValue();
94}
95
96static bool operator== (const ArrayBaseTestsHelpers::NonTriviallyCopyableType& ntct,
97 const ArrayBaseTestsHelpers::TriviallyCopyableType& tct)
98{
99 return tct == ntct;
100}
101
102class ArrayBaseTests final : public UnitTest
103{
104 using CopyableType = ArrayBaseTestsHelpers::TriviallyCopyableType;
105 using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;
106
107 #if ! (defined (__GNUC__) && __GNUC__ < 5 && ! defined (__clang__))
108 static_assert (std::is_trivially_copyable_v<CopyableType>,
109 "Test TriviallyCopyableType is not trivially copyable");
110 static_assert (! std::is_trivially_copyable_v<NoncopyableType>,
111 "Test NonTriviallyCopyableType is trivially copyable");
112 #endif
113
114public:
116 : UnitTest ("ArrayBase", UnitTestCategories::containers)
117 {}
118
119 void runTest() override
120 {
121 beginTest ("grow capacity");
122 {
126
128
129 int originalCapacity = 4;
130 referenceContainer.reserve ((size_t) originalCapacity);
131 expectEquals ((int) referenceContainer.capacity(), originalCapacity);
132 copyableContainer.setAllocatedSize (originalCapacity);
133 expectEquals (copyableContainer.capacity(), originalCapacity);
134 noncopyableContainer.setAllocatedSize (originalCapacity);
135 expectEquals (noncopyableContainer.capacity(), originalCapacity);
136
138
140
142
143 expect ((int) referenceContainer.capacity() != originalCapacity);
144 expect (copyableContainer.capacity() != originalCapacity);
145 expect (noncopyableContainer.capacity() != originalCapacity);
146 }
147
148 beginTest ("shrink capacity");
149 {
153
154 int numElements = 45;
156
157 copyableContainer.shrinkToNoMoreThan (numElements);
158 noncopyableContainer.setAllocatedSize (numElements + 1);
159
161
162 referenceContainer.clear();
163 copyableContainer.removeElements (0, numElements);
164 noncopyableContainer.removeElements (0, numElements);
165
167
168 copyableContainer.setAllocatedSize (0);
169 noncopyableContainer.setAllocatedSize (0);
170
172
174
176 }
177
178 beginTest ("equality");
179 {
181 ArrayBase<int, DummyCriticalSection> testContainer1, testContainer2;
182
183 for (auto i : referenceContainer)
184 {
185 testContainer1.add (i);
186 testContainer2.add (i);
187 }
188
190 expect (testContainer2 == testContainer1);
191
192 testContainer1.ensureAllocatedSize (257);
193 referenceContainer.shrink_to_fit();
194
196 expect (testContainer2 == testContainer1);
197
198 testContainer1.removeElements (0, 1);
199
201 expect (testContainer2 != testContainer1);
202 }
203
204 beginTest ("accessors");
205 {
209
211
212 int testValue = -123;
216
218
219 expect (copyableContainer .getFirst().getValue() == testValue);
220 expect (noncopyableContainer.getFirst().getValue() == testValue);
221
222 auto last = referenceContainer.back().getValue();
223
224 expectEquals (copyableContainer .getLast().getValue(), last);
225 expectEquals (noncopyableContainer.getLast().getValue(), last);
226
229
230 auto defualtValue = CopyableType().getValue();
231 expectEquals (defualtValue, NoncopyableType().getValue());
232
233 expectEquals (copyableEmpty .getFirst().getValue(), defualtValue);
234 expectEquals (noncopyableEmpty.getFirst().getValue(), defualtValue);
235 expectEquals (copyableEmpty .getLast() .getValue(), defualtValue);
236 expectEquals (noncopyableEmpty.getLast() .getValue(), defualtValue);
237
239 expect (floatPointers.getValueWithDefault (-3) == nullptr);
240 }
241
242 beginTest ("add moved");
243 {
247
248 for (int i = 0; i < 5; ++i)
249 {
250 CopyableType ref (-i);
251 CopyableType ct (-i);
252 NoncopyableType nct (-i);
253 referenceContainer.push_back (std::move (ref));
254 copyableContainer.add (std::move (ct));
255 noncopyableContainer.add (std::move (nct));
256 }
257
259 }
260
261 beginTest ("add multiple");
262 {
266
267 for (int i = 4; i < 7; ++i)
269
272
274 }
275
276 beginTest ("add array from a pointer");
277 {
280
283
284 copyableContainer.addArray (copyableData.data(), (int) copyableData.size());
285 noncopyableContainer.addArray (noncopyableData.data(), (int) noncopyableData.size());
286
288 }
289
290 beginTest ("add array from a pointer of a different type");
291 {
295
296 std::vector<float> floatData = { 1.4f, 2.5f, 3.6f };
297
298 for (auto f : floatData)
299 referenceContainer.push_back ({ f });
300
301 copyableContainer.addArray (floatData.data(), (int) floatData.size());
302 noncopyableContainer.addArray (floatData.data(), (int) floatData.size());
303
305 }
306
307 beginTest ("add array from initializer_list");
308 {
312
313 std::initializer_list<CopyableType> ilct { { 3 }, { 4 }, { 5 } };
314 std::initializer_list<NoncopyableType> ilnct { { 3 }, { 4 }, { 5 } };
315
316 for (auto v : ilct)
317 referenceContainer.push_back ({ v });
318
319 copyableContainer.addArray (ilct);
320 noncopyableContainer.addArray (ilnct);
321
323 }
324
325 beginTest ("add array from containers");
326 {
330
332
337
338 for (auto& v : referenceContainerCopy)
339 noncopyableReferenceContainerCopy.push_back ({ v.getValue() });
340
341 for (size_t i = 0; i < referenceContainerCopy.size(); ++i)
342 {
343 auto value = referenceContainerCopy[i].getValue();
344 copyableContainerCopy.add ({ value });
345 noncopyableContainerCopy.add ({ value });
346 }
347
348 // From self-types
351
352 for (auto v : referenceContainerCopy)
353 referenceContainer.push_back (v);
354
356
357 // From std containers
360
361 for (auto v : referenceContainerCopy)
362 referenceContainer.push_back (v);
363
365
366 // From std containers with offset
367 int offset = 5;
368 copyableContainer.addArray (referenceContainerCopy, offset);
370
371 for (size_t i = 5; i < referenceContainerCopy.size(); ++i)
373
375 }
376
377 beginTest ("insert");
378 {
382
384
385 referenceContainer.insert (referenceContainer.begin(), -4);
386 copyableContainer.insert (0, -4, 1);
387 noncopyableContainer.insert (0, -4, 1);
388
390
391 for (int i = 0; i < 3; ++i)
392 referenceContainer.insert (referenceContainer.begin() + 1, -3);
393
394 copyableContainer.insert (1, -3, 3);
395 noncopyableContainer.insert (1, -3, 3);
396
398
399 for (int i = 0; i < 50; ++i)
400 referenceContainer.insert (referenceContainer.end() - 1, -9);
401
402 copyableContainer.insert (copyableContainer.size() - 2, -9, 50);
403 noncopyableContainer.insert (noncopyableContainer.size() - 2, -9, 50);
404 }
405
406 beginTest ("insert array");
407 {
410
411 std::vector<CopyableType> copyableData = { 3, 4, 5, 6, 7, 8 };
412 std::vector<NoncopyableType> noncopyableData = { 3, 4, 5, 6, 7, 8 };
413
415
416 copyableContainer.insertArray (0, copyableData.data(), (int) copyableData.size());
417 noncopyableContainer.insertArray (0, noncopyableData.data(), (int) noncopyableData.size());
418
420
421 int insertPos = copyableContainer.size() - 1;
422
423 for (auto it = copyableData.end(); it != copyableData.begin(); --it)
424 referenceContainer.insert (referenceContainer.begin() + insertPos, CopyableType (*(it - 1)));
425
426 copyableContainer.insertArray (insertPos, copyableData.data(), (int) copyableData.size());
427 noncopyableContainer.insertArray (insertPos, noncopyableData.data(), (int) noncopyableData.size());
428
430 }
431
432 beginTest ("remove");
433 {
437
439
440 for (int i = 0; i < 4; ++i)
441 {
442 referenceContainer.erase (referenceContainer.begin() + i);
443 copyableContainer.removeElements (i, 1);
444 noncopyableContainer.removeElements (i, 1);
445 }
446
448
450 int blockSize = 3;
451
452 for (int i = 0; i < 4; ++i)
453 {
454 for (int j = 0; j < blockSize; ++j)
455 referenceContainer.erase (referenceContainer.begin() + i);
456
457 copyableContainer.removeElements (i, blockSize);
458 noncopyableContainer.removeElements (i, blockSize);
459 }
460
462
463 auto numToRemove = copyableContainer.size() - 2;
464
465 for (int i = 0; i < numToRemove; ++i)
466 referenceContainer.erase (referenceContainer.begin() + 1);
467
468 copyableContainer.removeElements (1, numToRemove);
469 noncopyableContainer.removeElements (1, numToRemove);
470
472 }
473
474 beginTest ("move");
475 {
479
481
484 testValues.emplace_back (0, 5);
485 testValues.emplace_back (4, 1);
486 testValues.emplace_back (5, 0);
487
488 for (auto p : testValues)
489 {
490 if (p.second > p.first)
491 std::rotate (referenceContainer.begin() + p.first,
492 referenceContainer.begin() + p.first + 1,
493 referenceContainer.begin() + p.second + 1);
494 else
495 std::rotate (referenceContainer.begin() + p.second,
496 referenceContainer.begin() + p.first,
497 referenceContainer.begin() + p.first + 1);
498
499 copyableContainer.move (p.first, p.second);
500 noncopyableContainer.move (p.first, p.second);
501
503 }
504 }
505
506 beginTest ("After converting move construction, ownership is transferred");
507 {
508 Derived obj;
510 derived.setAllocatedSize (5);
511 derived.add (&obj);
512
514
515 expectEquals (base.capacity(), 5);
516 expectEquals (base.size(), 1);
517 expect (base.getFirst() == &obj);
518 expectEquals (derived.capacity(), 0);
519 expectEquals (derived.size(), 0);
520 expect (derived.data() == nullptr);
521 }
522
523 beginTest ("After converting move assignment, ownership is transferred");
524 {
525 Derived obj;
527 derived.setAllocatedSize (5);
528 derived.add (&obj);
530
531 base = std::move (derived);
532
533 expectEquals (base.capacity(), 5);
534 expectEquals (base.size(), 1);
535 expect (base.getFirst() == &obj);
536 expectEquals (derived.capacity(), 0);
537 expectEquals (derived.size(), 0);
538 expect (derived.data() == nullptr);
539 }
540 }
541
542private:
543 struct Base
544 {
545 virtual ~Base() = default;
546 };
547
548 struct Derived final : public Base
549 {
550 };
551
555 int numValues)
556 {
557 for (int i = 0; i < numValues; ++i)
558 {
559 referenceContainer.push_back ({ i });
560 copyableContainer.add ({ i });
561 NoncopyableContainer.add ({ i });
562 }
563 }
564
565 template <typename A, typename B>
568 {
569 expectEquals ((int) a.size(), (int) b.size());
570
571 for (int i = 0; i < (int) a.size(); ++i)
572 expect (a[i] == b[i]);
573 }
574
575 template <typename A, typename B>
578 {
579 expectEquals ((int) a.size(), (int) b.size());
580
581 for (int i = 0; i < (int) a.size(); ++i)
582 expect (a[i] == b[(size_t) i]);
583 }
584
585 template <typename A, typename B, typename C>
589 {
590 checkEqual (a, b);
591 checkEqual (a, c);
592 checkEqual (b, c);
593 }
594};
595
597
598#endif
599
600} // namespace juce
T emplace_back(T... args)
typedef int
JUCE Namespace.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
T push_back(T... args)
T ref(T... args)
T rotate(T... args)
T size(T... args)