Index: src/core/SkStream.cpp |
=================================================================== |
--- src/core/SkStream.cpp (revision 10125) |
+++ src/core/SkStream.cpp (working copy) |
@@ -661,6 +661,125 @@ |
} |
} |
+class SkBlockMemoryRefCnt : public SkRefCnt { |
+public: |
+ SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { } |
+ |
+ virtual ~SkBlockMemoryRefCnt() { |
+ SkDynamicMemoryWStream::Block* block = fHead; |
+ while (block != NULL) { |
+ SkDynamicMemoryWStream::Block* next = block->fNext; |
+ sk_free(block); |
+ block = next; |
+ } |
+ } |
+ |
+ SkDynamicMemoryWStream::Block* const fHead; |
+}; |
+ |
+class SkBlockMemoryStream : public SkStreamAsset { |
+public: |
+ SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size) |
+ : fBlockMemory(new SkBlockMemoryRefCnt(head)), fCurrent(head), fSize(size) |
+ , fOffset(0), fCurrentOffset(0) { } |
+ |
+ SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size) |
+ : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead), fSize(size) |
+ , fOffset(0), fCurrentOffset(0) { } |
+ |
+ virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE { |
+ size_t count = rawCount; |
+ if (fOffset + count > fSize) { |
+ count = fSize - fOffset; |
+ } |
+ size_t bytesLeftToRead = count; |
+ while (fCurrent != NULL) { |
+ size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset; |
+ size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent |
+ ? bytesLeftToRead : bytesLeftInCurrent; |
+ if (buffer) { |
+ memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent); |
+ } |
+ if (bytesLeftToRead <= bytesFromCurrent) { |
+ fCurrentOffset += bytesFromCurrent; |
+ fOffset += count; |
+ return count; |
+ } |
+ bytesLeftToRead -= bytesFromCurrent; |
+ buffer = (void*) ((char* ) buffer + bytesFromCurrent); |
+ fCurrent = fCurrent->fNext; |
+ fCurrentOffset = 0; |
+ } |
+ SkASSERT(false); |
+ return 0; |
+ } |
+ |
+ virtual bool isAtEnd() const SK_OVERRIDE { |
+ return fOffset == fSize; |
+ } |
+ |
+ virtual bool rewind() SK_OVERRIDE { |
+ fCurrent = fBlockMemory->fHead; |
+ fCurrentOffset = 0; |
+ fOffset = 0; |
+ return true; |
+ } |
+ virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE { |
+ return new SkBlockMemoryStream(fBlockMemory.get(), fSize); |
+ } |
+ |
+ virtual size_t getPosition() const SK_OVERRIDE { |
+ return fOffset; |
+ } |
+ virtual bool seek(size_t position) SK_OVERRIDE { |
+ if (position >= fOffset) { |
+ size_t skipAmount = position - fOffset; |
+ return this->skip(skipAmount) == skipAmount; |
+ } |
+ return this->rewind() && this->skip(position) == position; |
+ } |
+ virtual bool move(long offset) SK_OVERRIDE { |
+ return seek(fOffset + offset); |
+ } |
+ virtual SkBlockMemoryStream* fork() const SK_OVERRIDE { |
+ SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate()); |
+ that->fOffset = this->fOffset; |
+ that->fCurrent = this->fCurrent; |
+ that->fCurrentOffset = this->fCurrentOffset; |
+ return that.detach(); |
+ } |
+ |
+ virtual size_t getLength() const SK_OVERRIDE { |
+ return fSize; |
+ } |
+ |
+ virtual const void* getMemoryBase() SK_OVERRIDE { |
+ if (fBlockMemory->fHead->fNext == NULL) { |
+ return fBlockMemory->fHead->start(); |
+ } |
+ return false; |
+ } |
+ |
+private: |
+ SkAutoTUnref<SkBlockMemoryRefCnt> fBlockMemory; |
+ SkDynamicMemoryWStream::Block const * fCurrent; |
+ size_t const fSize; |
+ size_t fOffset; |
+ size_t fCurrentOffset; |
+}; |
+ |
+SkStreamAsset* SkDynamicMemoryWStream::detatchAsStream() { |
+ if (fCopy) { |
+ SkMemoryStream* stream = new SkMemoryStream(fCopy); |
+ this->reset(); |
+ return stream; |
+ } |
+ SkBlockMemoryStream* stream = new SkBlockMemoryStream(fHead, fBytesWritten); |
+ fHead = 0; |
+ this->reset(); |
+ return stream; |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
void SkDebugWStream::newline() |