diff options
-rw-r--r-- | include/core/SkStream.h | 3 | ||||
-rw-r--r-- | src/core/SkStream.cpp | 22 | ||||
-rw-r--r-- | tests/StreamTest.cpp | 20 |
3 files changed, 42 insertions, 3 deletions
diff --git a/include/core/SkStream.h b/include/core/SkStream.h index 10929a8343..8df59afaf3 100644 --- a/include/core/SkStream.h +++ b/include/core/SkStream.h @@ -376,6 +376,9 @@ public: void copyTo(void* dst) const; void writeToStream(SkWStream* dst) const; + /** Equivalent to copyTo() followed by reset(), but may save memory use. */ + void copyToAndReset(void* dst); + /** Return the contents as SkData, and then reset the stream. */ sk_sp<SkData> detachAsData(); diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp index 1435dab235..133df83078 100644 --- a/src/core/SkStream.cpp +++ b/src/core/SkStream.cpp @@ -570,15 +570,31 @@ void SkDynamicMemoryWStream::padToAlign4() { } } + +void SkDynamicMemoryWStream::copyToAndReset(void* ptr) { + // By looping through the source and freeing as we copy, we + // can reduce real memory use with large streams. + char* dst = reinterpret_cast<char*>(ptr); + Block* block = fHead; + while (block != nullptr) { + size_t len = block->written(); + memcpy(dst, block->start(), len); + dst += len; + Block* next = block->fNext; + sk_free(block); + block = next; + } + fHead = fTail = nullptr; + fBytesWrittenBeforeTail = 0; +} + sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() { const size_t size = this->bytesWritten(); if (0 == size) { return SkData::MakeEmpty(); } - sk_sp<SkData> data = SkData::MakeUninitialized(size); - this->copyTo(data->writable_data()); - this->reset(); // this is the "detach" part + this->copyToAndReset(data->writable_data()); return data; } diff --git a/tests/StreamTest.cpp b/tests/StreamTest.cpp index 2e476a1858..8b5b2ae05a 100644 --- a/tests/StreamTest.cpp +++ b/tests/StreamTest.cpp @@ -410,6 +410,26 @@ static void stream_copy_test(skiatest::Reporter* reporter, } } +DEF_TEST(DynamicMemoryWStream_detachAsData, r) { + const char az[] = "abcdefghijklmnopqrstuvwxyz"; + const unsigned N = 40000; + SkDynamicMemoryWStream dmws; + for (unsigned i = 0; i < N; ++i) { + dmws.writeText(az); + } + REPORTER_ASSERT(r, dmws.bytesWritten() == N * strlen(az)); + auto data = dmws.detachAsData(); + REPORTER_ASSERT(r, data->size() == N * strlen(az)); + const uint8_t* ptr = data->bytes(); + for (unsigned i = 0; i < N; ++i) { + if (0 != memcmp(ptr, az, strlen(az))) { + ERRORF(r, "detachAsData() memcmp failed"); + return; + } + ptr += strlen(az); + } +} + DEF_TEST(StreamCopy, reporter) { SkRandom random(123456); static const int N = 10000; |