diff options
-rw-r--r-- | include/private/SkTemplates.h | 25 | ||||
-rw-r--r-- | tests/TemplatesTest.cpp | 56 |
2 files changed, 75 insertions, 6 deletions
diff --git a/include/private/SkTemplates.h b/include/private/SkTemplates.h index 7e2c19f09d..01a8ec0c3b 100644 --- a/include/private/SkTemplates.h +++ b/include/private/SkTemplates.h @@ -192,6 +192,7 @@ public: (--iter)->~T(); } + SkASSERT(count >= 0); if (fCount != count) { if (fCount > kCount) { // 'fArray' was allocated last time so free it now @@ -267,7 +268,7 @@ public: /** Allocates space for 'count' Ts. */ explicit SkAutoTMalloc(size_t count) { - fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW); + fPtr = count ? (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW) : nullptr; } ~SkAutoTMalloc() { @@ -276,7 +277,11 @@ public: /** Resize the memory area pointed to by the current ptr preserving contents. */ void realloc(size_t count) { - fPtr = reinterpret_cast<T*>(sk_realloc_throw(fPtr, count * sizeof(T))); + if (count) { + fPtr = reinterpret_cast<T*>(sk_realloc_throw(fPtr, count * sizeof(T))); + } else { + this->reset(0); + } } /** Resize the memory area pointed to by the current ptr without preserving contents. */ @@ -326,8 +331,10 @@ public: SkAutoSTMalloc(size_t count) { if (count > kCount) { fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); - } else { + } else if (count) { fPtr = fTStorage; + } else { + fPtr = nullptr; } } @@ -344,8 +351,10 @@ public: } if (count > kCount) { fPtr = (T*)sk_malloc_throw(count * sizeof(T)); - } else { + } else if (count) { fPtr = fTStorage; + } else { + fPtr = nullptr; } return fPtr; } @@ -377,8 +386,12 @@ public: } else { fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); } - } else if (fPtr != fTStorage) { - fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); + } else if (count) { + if (fPtr != fTStorage) { + fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); + } + } else { + this->reset(0); } } diff --git a/tests/TemplatesTest.cpp b/tests/TemplatesTest.cpp index 31859f3f0c..fc3bc320af 100644 --- a/tests/TemplatesTest.cpp +++ b/tests/TemplatesTest.cpp @@ -70,3 +70,59 @@ static void test_automalloc_realloc(skiatest::Reporter* reporter) { DEF_TEST(Templates, reporter) { test_automalloc_realloc(reporter); } + +constexpr int static kStackPreallocCount = 10; + +// Ensures the containers in SkTemplates.h all have a consistent api. +template<typename TContainer, typename TCount> +static void test_container_apis(skiatest::Reporter* reporter) { + REPORTER_ASSERT(reporter, !TContainer((TCount)0).get()); + REPORTER_ASSERT(reporter, TContainer((TCount)1).get()); + REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount).get()); + REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount + 1).get()); + + TContainer container; + // The default constructor may or may not init to empty, depending on the type of container. + + container.reset((TCount)1); + REPORTER_ASSERT(reporter, container.get()); + + container.reset((TCount)kStackPreallocCount); + REPORTER_ASSERT(reporter, container.get()); + + container.reset((TCount)kStackPreallocCount + 1); + REPORTER_ASSERT(reporter, container.get()); + + container.reset((TCount)0); + REPORTER_ASSERT(reporter, !container.get()); +} + +DEF_TEST(TemplateContainerAPIs, reporter) { + test_container_apis<SkAutoTArray<int>, int>(reporter); + test_container_apis<SkAutoSTArray<kStackPreallocCount, int>, int>(reporter); + test_container_apis<SkAutoTMalloc<int>, size_t>(reporter); + test_container_apis<SkAutoSTMalloc<kStackPreallocCount, int>, size_t>(reporter); +} + +// Ensures that realloc(0) results in a null pointer. +template<typename TAutoMalloc> static void test_realloc_to_zero(skiatest::Reporter* reporter) { + TAutoMalloc autoMalloc(kStackPreallocCount); + REPORTER_ASSERT(reporter, autoMalloc.get()); + + autoMalloc.realloc(0); + REPORTER_ASSERT(reporter, !autoMalloc.get()); + + autoMalloc.realloc(kStackPreallocCount + 1); + REPORTER_ASSERT(reporter, autoMalloc.get()); + + autoMalloc.realloc(0); + REPORTER_ASSERT(reporter, !autoMalloc.get()); + + autoMalloc.realloc(kStackPreallocCount); + REPORTER_ASSERT(reporter, autoMalloc.get()); +} + +DEF_TEST(AutoReallocToZero, reporter) { + test_realloc_to_zero<SkAutoTMalloc<int> >(reporter); + test_realloc_to_zero<SkAutoSTMalloc<kStackPreallocCount, int> >(reporter); +} |