Skip to content

Commit d5e6368

Browse files
johnstiles-googleSkia Commit-Bot
authored andcommitted
Add initializer_list support to SkTArray.
Also added unit tests for each of SkTArray's various constructors, and added `SkTArray::value_type` which allows calling code to refer to the array's value-type. These unit tests exposed some preexisting strict- aliasing issues in SkSTArray when compiled on GCC 6+ with optimizations enabled, which are being investigated separately at skia:10891. Change-Id: Ia0fb18830cfbbdcb1545fe7f7ac51d8e768a3f94 Bug: skia:10891 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330279 Commit-Queue: John Stiles <[email protected]> Reviewed-by: Brian Osman <[email protected]> Auto-Submit: John Stiles <[email protected]>
1 parent 750109b commit d5e6368

File tree

2 files changed

+90
-3
lines changed

2 files changed

+90
-3
lines changed

include/private/SkTArray.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "include/private/SkTo.h"
1818

1919
#include <string.h>
20+
#include <initializer_list>
2021
#include <memory>
2122
#include <new>
2223
#include <utility>
@@ -33,6 +34,8 @@
3334
*/
3435
template <typename T, bool MEM_MOVE = false> class SkTArray {
3536
public:
37+
using value_type = T;
38+
3639
/**
3740
* Creates an empty array with no initial storage
3841
*/
@@ -81,6 +84,13 @@ template <typename T, bool MEM_MOVE = false> class SkTArray {
8184
this->init(count);
8285
this->copy(array);
8386
}
87+
/**
88+
* Creates a SkTArray by copying contents of an initializer list.
89+
*/
90+
SkTArray(std::initializer_list<T> data) {
91+
this->init(data.size());
92+
this->copy(&*data.begin());
93+
}
8494

8595
SkTArray& operator=(const SkTArray& that) {
8696
if (this == &that) {
@@ -361,7 +371,7 @@ template <typename T, bool MEM_MOVE = false> class SkTArray {
361371
size_t size() const { return (size_t)fCount; }
362372
void resize(size_t count) { this->resize_back((int)count); }
363373

364-
/**
374+
/**
365375
* Get the i^th element.
366376
*/
367377
T& operator[] (int i) {
@@ -473,6 +483,17 @@ template <typename T, bool MEM_MOVE = false> class SkTArray {
473483
this->copy(array);
474484
}
475485

486+
/**
487+
* Copy the contents of an initializer list, using preallocated storage if
488+
* preAllocCount >= count. Otherwise storage will only be used when array
489+
* shrinks to fit.
490+
*/
491+
template <int N>
492+
SkTArray(std::initializer_list<T> data, SkAlignedSTStorage<N,T>* storage) {
493+
this->initWithPreallocatedStorage(data.size(), storage->get(), N);
494+
this->copy(&*data.begin());
495+
}
496+
476497
private:
477498
void init(int count = 0, int reserveCount = 0) {
478499
fCount = SkToU32(count);
@@ -606,7 +627,7 @@ template<typename T, bool MEM_MOVE> constexpr int SkTArray<T, MEM_MOVE>::kMinHea
606627
/**
607628
* Subclass of SkTArray that contains a preallocated memory block for the array.
608629
*/
609-
template <int N, typename T, bool MEM_MOVE= false>
630+
template <int N, typename T, bool MEM_MOVE = false>
610631
class SkSTArray : public SkTArray<T, MEM_MOVE> {
611632
private:
612633
using INHERITED = SkTArray<T, MEM_MOVE>;
@@ -639,6 +660,10 @@ class SkSTArray : public SkTArray<T, MEM_MOVE> {
639660
: INHERITED(array, count, &fStorage) {
640661
}
641662

663+
SkSTArray(std::initializer_list<T> data)
664+
: INHERITED(data, &fStorage) {
665+
}
666+
642667
SkSTArray& operator=(const SkSTArray& array) {
643668
INHERITED::operator=(array);
644669
return *this;

tests/TArrayTest.cpp

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,61 @@ static void TestTSet_basic(skiatest::Reporter* reporter) {
5757
REPORTER_ASSERT(reporter, a[1] == 3);
5858
REPORTER_ASSERT(reporter, a[2] == 2);
5959

60-
// {0, 3, 2 }
60+
// { 0, 3, 2 }
61+
}
62+
63+
template <typename T> static void test_construction(skiatest::Reporter* reporter) {
64+
// No arguments: Creates an empty array with no initial storage.
65+
T arrayNoArgs;
66+
REPORTER_ASSERT(reporter, arrayNoArgs.empty());
67+
68+
// Single integer: Creates an empty array that will preallocate space for reserveCount elements.
69+
T arrayReserve(15);
70+
REPORTER_ASSERT(reporter, arrayReserve.empty());
71+
REPORTER_ASSERT(reporter, arrayReserve.capacity() == 15);
72+
73+
// Another array, const&: Copies one array to another.
74+
T arrayInitial;
75+
arrayInitial.push_back(1);
76+
arrayInitial.push_back(2);
77+
arrayInitial.push_back(3);
78+
79+
T arrayCopy(arrayInitial);
80+
REPORTER_ASSERT(reporter, arrayInitial.size() == 3);
81+
REPORTER_ASSERT(reporter, arrayInitial[0] == 1);
82+
REPORTER_ASSERT(reporter, arrayInitial[1] == 2);
83+
REPORTER_ASSERT(reporter, arrayInitial[2] == 3);
84+
REPORTER_ASSERT(reporter, arrayCopy.size() == 3);
85+
REPORTER_ASSERT(reporter, arrayCopy[0] == 1);
86+
REPORTER_ASSERT(reporter, arrayCopy[1] == 2);
87+
REPORTER_ASSERT(reporter, arrayCopy[2] == 3);
88+
89+
// Another array, &&: Moves one array to another.
90+
T arrayMove(std::move(arrayInitial));
91+
REPORTER_ASSERT(reporter, arrayInitial.empty()); // NOLINT(bugprone-use-after-move)
92+
REPORTER_ASSERT(reporter, arrayMove.size() == 3);
93+
REPORTER_ASSERT(reporter, arrayMove[0] == 1);
94+
REPORTER_ASSERT(reporter, arrayMove[1] == 2);
95+
REPORTER_ASSERT(reporter, arrayMove[2] == 3);
96+
97+
// Pointer and count: Copies contents of a standard C array.
98+
typename T::value_type data[3] = { 7, 8, 9 };
99+
T arrayPtrCount(data, 3);
100+
REPORTER_ASSERT(reporter, arrayPtrCount.size() == 3);
101+
REPORTER_ASSERT(reporter, arrayPtrCount[0] == 7);
102+
REPORTER_ASSERT(reporter, arrayPtrCount[1] == 8);
103+
REPORTER_ASSERT(reporter, arrayPtrCount[2] == 9);
104+
105+
// Initializer list.
106+
T arrayInitializer{8, 6, 7, 5, 3, 0, 9};
107+
REPORTER_ASSERT(reporter, arrayInitializer.size() == 7);
108+
REPORTER_ASSERT(reporter, arrayInitializer[0] == 8);
109+
REPORTER_ASSERT(reporter, arrayInitializer[1] == 6);
110+
REPORTER_ASSERT(reporter, arrayInitializer[2] == 7);
111+
REPORTER_ASSERT(reporter, arrayInitializer[3] == 5);
112+
REPORTER_ASSERT(reporter, arrayInitializer[4] == 3);
113+
REPORTER_ASSERT(reporter, arrayInitializer[5] == 0);
114+
REPORTER_ASSERT(reporter, arrayInitializer[6] == 9);
61115
}
62116

63117
template <typename T> static void test_swap(skiatest::Reporter* reporter,
@@ -249,4 +303,12 @@ DEF_TEST(TArray, reporter) {
249303
test_reserve<SkSTArray<1, int>>(reporter);
250304
test_reserve<SkSTArray<2, int>>(reporter);
251305
test_reserve<SkSTArray<16, int>>(reporter);
306+
307+
test_construction<SkTArray<int>>(reporter);
308+
test_construction<SkTArray<double>>(reporter);
309+
#ifndef __GNUC__ // TODO(skbug.com/10891): SkSTArray generates bad code in GCC -fstrict-aliasing
310+
test_construction<SkSTArray<1, int>>(reporter);
311+
test_construction<SkSTArray<5, char>>(reporter);
312+
test_construction<SkSTArray<10, float>>(reporter);
313+
#endif
252314
}

0 commit comments

Comments
 (0)