static void test_peeking_front_buffered_stream(skiatest::Reporter* r, const SkStream& original, size_t bufferSize) { std::unique_ptr<SkStream> dupe(original.duplicate()); REPORTER_ASSERT(r, dupe != nullptr); auto bufferedStream = SkFrontBufferedStream::Make(std::move(dupe), bufferSize); REPORTER_ASSERT(r, bufferedStream != nullptr); size_t peeked = 0; for (size_t i = 1; !bufferedStream->isAtEnd(); i++) { const size_t unpeekableBytes = compare_peek_to_read(r, bufferedStream.get(), i); if (unpeekableBytes > 0) { // This could not have returned a number greater than i. REPORTER_ASSERT(r, unpeekableBytes <= i); // We have reached the end of the buffer. Verify that it was at least // bufferSize. REPORTER_ASSERT(r, peeked + i - unpeekableBytes >= bufferSize); // No more peeking is supported. break; } peeked += i; } // Test that attempting to peek beyond the length of the buffer does not prevent rewinding. bufferedStream = SkFrontBufferedStream::Make(original.duplicate(), bufferSize); REPORTER_ASSERT(r, bufferedStream != nullptr); const size_t bytesToPeek = bufferSize + 1; SkAutoMalloc peekStorage(bytesToPeek); SkAutoMalloc readStorage(bytesToPeek); for (size_t start = 0; start <= bufferSize; start++) { // Skip to the starting point REPORTER_ASSERT(r, bufferedStream->skip(start) == start); const size_t bytesPeeked = bufferedStream->peek(peekStorage.get(), bytesToPeek); if (0 == bytesPeeked) { // Peeking should only fail completely if we have read/skipped beyond the buffer. REPORTER_ASSERT(r, start >= bufferSize); break; } // Only read the amount that was successfully peeked. const size_t bytesRead = bufferedStream->read(readStorage.get(), bytesPeeked); REPORTER_ASSERT(r, bytesRead == bytesPeeked); REPORTER_ASSERT(r, !memcmp(peekStorage.get(), readStorage.get(), bytesPeeked)); // This should be safe to rewind. REPORTER_ASSERT(r, bufferedStream->rewind()); } }
static void test_peeking_front_buffered_stream(skiatest::Reporter* r, const SkStream& original, size_t bufferSize) { SkStream* dupe = original.duplicate(); REPORTER_ASSERT(r, dupe != NULL); SkAutoTDelete<SkStream> bufferedStream(SkFrontBufferedStream::Create(dupe, bufferSize)); REPORTER_ASSERT(r, bufferedStream != NULL); test_peeking_stream(r, bufferedStream, bufferSize); }
SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const { SkStream* stream = this->getLocalStream(); if (stream) { // should have been provided by CreateFromStream() *ttcIndex = 0; SkAutoTUnref<SkStream> dupStream(stream->duplicate()); if (dupStream) { return dupStream.detach(); } // TODO: update interface use, remove the following code in this block. size_t length = stream->getLength(); const void* memory = stream->getMemoryBase(); if (NULL != memory) { return new SkMemoryStream(memory, length, true); } SkAutoTMalloc<uint8_t> allocMemory(length); stream->rewind(); if (length == stream->read(allocMemory.get(), length)) { SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream()); copyStream->setMemoryOwned(allocMemory.detach(), length); return copyStream.detach(); } stream->rewind(); stream->ref(); } else { SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); if (NULL == fci.get()) { return NULL; } stream = fci->openStream(this->getIdentity()); *ttcIndex = this->getIdentity().fTTCIndex; } return stream; }