replace detach/getStream apis on dynamicwstream with SkData

http://codereview.appspot.com/4657046/



git-svn-id: http://skia.googlecode.com/svn/trunk@1714 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 0408781..0827ae6 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -1,5 +1,6 @@
 #include "gm.h"
 #include "SkColorPriv.h"
+#include "SkData.h"
 #include "SkGraphics.h"
 #include "SkImageDecoder.h"
 #include "SkImageEncoder.h"
@@ -180,7 +181,8 @@
 
 static bool write_pdf(const SkString& path, const SkDynamicMemoryWStream& pdf) {
     SkFILEWStream stream(path.c_str());
-    return stream.write(pdf.getStream(), pdf.getOffset());
+    SkAutoDataUnref data(pdf.copyToData());
+    return stream.writeData(data.get());
 }
 
 enum Backend {
diff --git a/include/core/SkData.h b/include/core/SkData.h
index 8bb3a29..07e7f4b 100644
--- a/include/core/SkData.h
+++ b/include/core/SkData.h
@@ -72,6 +72,12 @@
                                ReleaseProc proc, void* context);
 
     /**
+     *  Create a new dataref, reference the data ptr as is, and calling
+     *  sk_free to delete it.
+     */
+    static SkData* NewFromMalloc(const void* data, size_t length);
+
+    /**
      *  Create a new dataref using a subset of the data in the specified
      *  src dataref.
      */
@@ -94,4 +100,45 @@
     ~SkData();
 };
 
+/**
+ *  Specialized version of SkAutoTUnref<SkData> for automatically unref-ing a
+ *  SkData. If the SkData is null, data(), bytes() and size() will return 0.
+ */
+class SkAutoDataUnref : SkNoncopyable {
+public:
+    SkAutoDataUnref(SkData* data) : fRef(data) {
+        if (data) {
+            fData = data->data();
+            fSize = data->size();
+        } else {
+            fData = NULL;
+            fSize = 0;
+        }
+    }
+    ~SkAutoDataUnref() {
+        SkSafeUnref(fRef);
+    }
+
+    const void* data() const { return fData; }
+    const uint8_t* bytes() const {
+        return reinterpret_cast<const uint8_t*> (fData);
+    }
+    size_t size() const { return fSize; }
+    SkData* get() const { return fRef; }
+
+    void release() {
+        if (fRef) {
+            fRef->unref();
+            fRef = NULL;
+            fData = NULL;
+            fSize = 0;
+        }
+    }
+
+private:
+    SkData*     fRef;
+    const void* fData;
+    size_t      fSize;
+};
+
 #endif
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
index 915afdd..9b26787 100644
--- a/include/core/SkStream.h
+++ b/include/core/SkStream.h
@@ -102,6 +102,8 @@
     bool    writePackedUInt(size_t);
     
     bool writeStream(SkStream* input, size_t length);
+
+    bool writeData(const SkData*);
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////
@@ -184,6 +186,20 @@
         will be freed with sk_free.
     */
     void setMemoryOwned(const void* data, size_t length);
+
+    /**
+     *  Return the stream's data in a SkData. The caller must call unref() when
+     *  it is finished using the data.
+     */
+    SkData* copyToData() const;
+
+    /**
+     *  Use the specified data as the memory for this stream. The stream will
+     *  call ref() on the data (assuming it is not null). The function returns
+     *  the data parameter as a convenience.
+     */
+    SkData* setData(SkData*);
+
     void skipToAlign4();
     virtual bool rewind();
     virtual size_t read(void* buffer, size_t size);
@@ -193,9 +209,8 @@
     size_t peek() const { return fOffset; }
     
 private:
-    const void* fSrc;
-    size_t fSize, fOffset;
-    SkBool8 fWeOwnTheData;
+    SkData* fData;
+    size_t  fOffset;
 };
 
 /** \class SkBufferStream
@@ -275,27 +290,21 @@
 public:
     SkDynamicMemoryWStream();
     virtual ~SkDynamicMemoryWStream();
+
     virtual bool write(const void* buffer, size_t size);
     // random access write
     // modifies stream and returns true if offset + size is less than or equal to getOffset()
     bool write(const void* buffer, size_t offset, size_t size);
     bool read(void* buffer, size_t offset, size_t size);
     size_t getOffset() const { return fBytesWritten; }
+    size_t bytesWritten() const { return fBytesWritten; }
 
     // copy what has been written to the stream into dst
-    void    copyTo(void* dst) const;
-    /*  return a cache of the flattened data returned by copyTo().
-        This copy is only valid until the next call to write().
-        The memory is managed by the stream class.
-    */
-    const char* getStream() const;
-
-    // same as getStream, but additionally detach the flattened datat
-    // DEPRECATED : use copyToData() instead
-    const char* detach() const;
+    void copyTo(void* dst) const;
 
     /**
-     *  Return a copy of the data written so far
+     *  Return a copy of the data written so far. This call is responsible for
+     *  calling unref() when they are finished with the data.
      */
     SkData* copyToData() const;
 
@@ -307,7 +316,9 @@
     Block*  fHead;
     Block*  fTail;
     size_t  fBytesWritten;
-    mutable char*   fCopyToCache;
+    mutable SkData* fCopy;  // is invalidated if we write after it is created
+
+    void invalidateCopy();
 };
 
 
diff --git a/include/svg/SkSVGParser.h b/include/svg/SkSVGParser.h
index 83b120d..dd116bd 100644
--- a/include/svg/SkSVGParser.h
+++ b/include/svg/SkSVGParser.h
@@ -42,7 +42,7 @@
         fXMLWriter.addAttributeLen(attrName, attrValue, len); }
     void _endElement() { fXMLWriter.endElement(); }
     int findAttribute(SkSVGBase* , const char* attrValue, size_t len, bool isPaint);
-    const char* getFinal();
+//    const char* getFinal();
     SkTDict<SkSVGElement*>& getIDs() { return fIDs; }
     SkString& getPaintLast(SkSVGPaint::Field field);
     void _startElement(const char name[]) { fXMLWriter.startElement(name); }
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 74a0708..1464fe7 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -1,5 +1,6 @@
 #include "SampleApp.h"
 
+#include "SkData.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
 #include "SkGpuCanvas.h"
@@ -827,7 +828,8 @@
                 fPicture->serialize(&ostream);
                 fPicture->unref();
 
-                SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
+                SkAutoDataUnref data(ostream.copyToData());
+                SkMemoryStream istream(data.data(), data.size());
                 SkPicture pict(&istream);
                 orig->drawPicture(pict);
             } else {
diff --git a/src/animator/SkScriptTokenizer.cpp b/src/animator/SkScriptTokenizer.cpp
index edcc2af..17f1e87 100644
--- a/src/animator/SkScriptTokenizer.cpp
+++ b/src/animator/SkScriptTokenizer.cpp
@@ -1,4 +1,5 @@
 #include "SkScript2.h"
+#include "SkData.h"
 #include "SkFloatingPoint.h"
 #include "SkMath.h"
 #include "SkParse.h"
@@ -736,11 +737,12 @@
     }
     if (fStream.getOffset() > 0) {
         addToken(kEnd);
+        SkAutoDataUnref data(fStream.copyToData());
 #ifdef SK_DEBUG
-        decompile((const unsigned char*)fStream.getStream(), fStream.getOffset());
+        decompile(data.bytes(), data.size());
 #endif
         SkScriptRuntime runtime(fCallBackArray);
-        runtime.executeTokens((unsigned char*) fStream.getStream());
+        runtime.executeTokens((unsigned char*) data.bytes());
         SkScriptValue2 value1;
         runtime.getResult(&value1.fOperand);
         value1.fType = fReturnType;
@@ -1142,11 +1144,12 @@
     addToken(typeOp);
     if (constantOperands) {
         addToken(kEnd);
+        SkAutoDataUnref data(fStream.copyToData());
 #ifdef SK_DEBUG        
-        decompile((const unsigned char*) stream.getStream(), stream.getOffset());
+        decompile(data.bytes(), data.size());
 #endif
         SkScriptRuntime runtime(fCallBackArray);
-        runtime.executeTokens((unsigned char*) stream.getStream());
+        runtime.executeTokens((unsigned char*)data.bytes());
         runtime.getResult(&value1.fOperand);
         if (attributes->fResultIsBoolean == kResultIsBoolean)
             value1.fType = SkOperand2::kS32;
diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp
index d7ab3c5..791e858 100644
--- a/src/core/SkData.cpp
+++ b/src/core/SkData.cpp
@@ -57,22 +57,26 @@
 }
 
 // assumes fPtr was allocated via sk_malloc
-static void sk_malloc_releaseproc(const void* ptr, size_t, void*) {
+static void sk_free_releaseproc(const void* ptr, size_t, void*) {
     sk_free((void*)ptr);
 }
 
+SkData* SkData::NewFromMalloc(const void* data, size_t length) {
+    return new SkData(data, length, sk_free_releaseproc, NULL);
+}
+
 SkData* SkData::NewWithCopy(const void* data, size_t length) {
     if (0 == length) {
         return SkData::NewEmpty();
     }
 
-    void* copy = sk_malloc_throw(length); // balanced in sk_malloc_releaseproc
+    void* copy = sk_malloc_throw(length); // balanced in sk_free_releaseproc
     memcpy(copy, data, length);
-    return new SkData(copy, length, sk_malloc_releaseproc, NULL);
+    return new SkData(copy, length, sk_free_releaseproc, NULL);
 }
 
 SkData* SkData::NewWithProc(const void* data, size_t length,
-                                  ReleaseProc proc, void* context) {
+                            ReleaseProc proc, void* context) {
     return new SkData(data, length, proc, context);
 }
 
diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp
index eb06452..16ff98a 100644
--- a/src/core/SkStream.cpp
+++ b/src/core/SkStream.cpp
@@ -191,7 +191,14 @@
     return true;
 }
 
-////////////////////////////////////////////////////////////////////////////
+bool SkWStream::writeData(const SkData* data) {
+    if (data) {
+        this->write(data->data(), data->size());
+    }
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
 {
@@ -246,112 +253,105 @@
     return 0;
 }
 
-////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 
-SkMemoryStream::SkMemoryStream()
-{
-    fWeOwnTheData = false;
-    this->setMemory(NULL, 0);
+SkMemoryStream::SkMemoryStream() {
+    fData = SkData::NewEmpty();
+    fOffset = 0;
 }
 
 SkMemoryStream::SkMemoryStream(size_t size) {
-    fWeOwnTheData = true;
+    fData = SkData::NewFromMalloc(sk_malloc_throw(size), size);
     fOffset = 0;
-    fSize = size;
-    fSrc = sk_malloc_throw(size);
 }
 
-SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData)
-{
-    fWeOwnTheData = false;
-    this->setMemory(src, size, copyData);
-}
-
-SkMemoryStream::~SkMemoryStream()
-{
-    if (fWeOwnTheData)
-        sk_free((void*)fSrc);
-}
-
-void SkMemoryStream::setMemoryOwned(const void* src, size_t size)
-{
-    if (fWeOwnTheData)
-        sk_free((void*)fSrc);
-
-    fSize = size;
-    fOffset = 0;
-    fWeOwnTheData = true;
-
-    fSrc = src;
-}
-
-void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
-{
-    if (fWeOwnTheData)
-        sk_free((void*)fSrc);
-
-    fSize = size;
-    fOffset = 0;
-    fWeOwnTheData = copyData;
-
-    if (copyData)
-    {
-        void* copy = sk_malloc_throw(size);
-        memcpy(copy, src, size);
-        src = copy;
+SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) {
+    if (copyData) {
+        fData = SkData::NewWithCopy(src, size);
+    } else {
+        fData = SkData::NewWithProc(src, size, NULL, NULL);
     }
-    fSrc = src;
+    fOffset = 0;
 }
 
-void SkMemoryStream::skipToAlign4()
-{
+SkMemoryStream::~SkMemoryStream() {
+    fData->unref();
+}
+
+void SkMemoryStream::setMemoryOwned(const void* src, size_t size) {
+    fData->unref();
+    fData = SkData::NewFromMalloc(src, size);
+    fOffset = 0;
+}
+
+void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) {
+    fData->unref();
+    if (copyData) {
+        fData = SkData::NewWithCopy(src, size);
+    } else {
+        fData = SkData::NewWithProc(src, size, NULL, NULL);
+    }
+    fOffset = 0;
+}
+
+SkData* SkMemoryStream::copyToData() const {
+    fData->ref();
+    return fData;
+}
+
+SkData* SkMemoryStream::setData(SkData* data) {
+    SkRefCnt_SafeAssign(fData, data);
+    return data;
+}
+
+void SkMemoryStream::skipToAlign4() {
     // cast to remove unary-minus warning
     fOffset += -(int)fOffset & 0x03;
 }
 
-bool SkMemoryStream::rewind()
-{
+bool SkMemoryStream::rewind() {
     fOffset = 0;
     return true;
 }
 
-size_t SkMemoryStream::read(void* buffer, size_t size)
-{
+size_t SkMemoryStream::read(void* buffer, size_t size) {
+    size_t dataSize = fData->size();
+
     if (buffer == NULL && size == 0)    // special signature, they want the total size
-        return fSize;
+        return dataSize;
 
     // if buffer is NULL, seek ahead by size
 
-    if (size == 0)
+    if (size == 0) {
         return 0;
-    if (size > fSize - fOffset)
-        size = fSize - fOffset;
+    }
+    if (size > dataSize - fOffset) {
+        size = dataSize - fOffset;
+    }
     if (buffer) {
-        memcpy(buffer, (const char*)fSrc + fOffset, size);
+        memcpy(buffer, fData->bytes() + fOffset, size);
     }
     fOffset += size;
     return size;
 }
 
-const void* SkMemoryStream::getMemoryBase()
-{
-    return fSrc;
+const void* SkMemoryStream::getMemoryBase() {
+    return fData->data();
 }
 
-const void* SkMemoryStream::getAtPos()
-{
-    return (const char*)fSrc + fOffset;
+const void* SkMemoryStream::getAtPos() {
+    return fData->bytes() + fOffset;
 }
 
-size_t SkMemoryStream::seek(size_t offset)
-{
-    if (offset > fSize)
-        offset = fSize;
+size_t SkMemoryStream::seek(size_t offset) {
+    if (offset > fData->size()) {
+        offset = fData->size();
+    }
     fOffset = offset;
     return offset;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
 
 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
     : fProxy(proxy)
@@ -586,7 +586,8 @@
     }
 };
 
-SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
+SkDynamicMemoryWStream::SkDynamicMemoryWStream()
+    : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopy(NULL)
 {
 }
 
@@ -595,16 +596,10 @@
     reset();
 }
 
-const char* SkDynamicMemoryWStream::detach() const
-{
-    const char* result = getStream();
-    fCopyToCache = NULL;
-    return result;
-}
-
 void SkDynamicMemoryWStream::reset()
 {
-    sk_free(fCopyToCache);
+    this->invalidateCopy();
+    
     Block*  block = fHead;
     
     while (block != NULL) {
@@ -614,17 +609,13 @@
     }
     fHead = fTail = NULL;
     fBytesWritten = 0;
-    fCopyToCache = NULL;
 }
 
 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
 {
     if (count > 0) {
+        this->invalidateCopy();
 
-        if (fCopyToCache) {
-            sk_free(fCopyToCache);
-            fCopyToCache = NULL;
-        }
         fBytesWritten += count;
         
         size_t  size;
@@ -654,8 +645,12 @@
 
 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
 {
-    if (offset + count > fBytesWritten)
+    if (offset + count > fBytesWritten) {
         return false; // test does not partially modify
+    }
+
+    this->invalidateCopy();
+    
     Block* block = fHead;
     while (block != NULL) {
         size_t size = block->written();
@@ -696,25 +691,20 @@
 
 void SkDynamicMemoryWStream::copyTo(void* dst) const
 {
-    Block* block = fHead;
-    
-    while (block != NULL) {
-        size_t size = block->written();
-        memcpy(dst, block->start(), size);
-        dst = (void*)((char*)dst + size);
-        block = block->fNext;
+    if (fCopy) {
+        memcpy(dst, fCopy->data(), fBytesWritten);
+    } else {
+        Block* block = fHead;
+        
+        while (block != NULL) {
+            size_t size = block->written();
+            memcpy(dst, block->start(), size);
+            dst = (void*)((char*)dst + size);
+            block = block->fNext;
+        }
     }
 }
 
-const char* SkDynamicMemoryWStream::getStream() const
-{
-    if (fCopyToCache == NULL) {
-        fCopyToCache = (char*)sk_malloc_throw(fBytesWritten);
-        this->copyTo(fCopyToCache);
-    }
-    return fCopyToCache;
-}
-
 void SkDynamicMemoryWStream::padToAlign4()
 {
     // cast to remove unary-minus warning
@@ -725,17 +715,24 @@
     write(&zero, padBytes);
 }
 
-static void sk_free_release_proc(const void* ptr, size_t length, void*) {
-    sk_free((void*)ptr);
-}
-
 SkData* SkDynamicMemoryWStream::copyToData() const {
-    // should rewrite when we remove detach()
-    return SkData::NewWithProc(this->detach(), fBytesWritten,
-                               sk_free_release_proc, NULL);
+    if (NULL == fCopy) {
+        void* buffer = sk_malloc_throw(fBytesWritten);
+        this->copyTo(buffer);
+        fCopy = SkData::NewFromMalloc(buffer, fBytesWritten);
+    }
+    fCopy->ref();
+    return fCopy;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////////////////////
+void SkDynamicMemoryWStream::invalidateCopy() {
+    if (fCopy) {
+        fCopy->unref();
+        fCopy = NULL;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 void SkDebugWStream::newline()
 {
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 67bc64a..8ead3c8 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -18,6 +18,7 @@
 
 #include "SkColor.h"
 #include "SkClipStack.h"
+#include "SkData.h"
 #include "SkDraw.h"
 #include "SkGlyphCache.h"
 #include "SkPaint.h"
@@ -1080,6 +1081,9 @@
     return mediaBox;
 }
 
+/**
+ *  Can this return SkData instead of SkStream?
+ */
 SkStream* SkPDFDevice::content() const {
     SkDynamicMemoryWStream data;
     if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
@@ -1104,12 +1108,14 @@
                            translation);
         gsState.updateMatrix(entry->fState.fMatrix);
         gsState.updateDrawingState(entry->fState);
-        data.write(entry->fContent.getStream(), entry->fContent.getOffset());
+        
+        SkAutoDataUnref copy(entry->fContent.copyToData());
+        data.write(copy.data(), copy.size());
     }
     gsState.drainStack();
 
     SkMemoryStream* result = new SkMemoryStream;
-    result->setMemoryOwned(data.detach(), data.getOffset());
+    result->setData(data.copyToData())->unref();
     return result;
 }
 
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index f570a1f..d0d31e3 100755
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -16,6 +16,7 @@
 
 #include <ctype.h>
 
+#include "SkData.h"
 #include "SkFontHost.h"
 #include "SkGlyphCache.h"
 #include "SkPaint.h"
@@ -140,6 +141,7 @@
     // Make as few copies as possible given these constraints.
     SkDynamicMemoryWStream dynamicStream;
     SkRefPtr<SkMemoryStream> staticStream;
+    SkData* data = NULL;
     const uint8_t* src;
     size_t srcLen;
     if ((srcLen = srcStream->getLength()) > 0) {
@@ -168,11 +170,15 @@
             dynamicStream.write(buf, amount);
         amount = 0;
         dynamicStream.write(&amount, 1);  // NULL terminator.
-        // getStream makes another copy, but we couldn't do any better.
-        src = (const uint8_t*)dynamicStream.getStream();
-        srcLen = dynamicStream.getOffset() - 1;
+        data = dynamicStream.copyToData();
+        src = data->bytes();
+        srcLen = data->size() - 1;
     }
 
+    // this handles releasing the data we may have gotten from dynamicStream.
+    // if data is null, it is a no-op
+    SkAutoDataUnref aud(data);
+
     if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
         SkMemoryStream* result =
             new SkMemoryStream(*headerLen + *dataLen + *trailerLen);
@@ -616,7 +622,7 @@
     append_cmap_footer(&cmap);
     SkRefPtr<SkMemoryStream> cmapStream = new SkMemoryStream();
     cmapStream->unref();  // SkRefPtr and new took a reference.
-    cmapStream->setMemoryOwned(cmap.detach(), cmap.getOffset());
+    cmapStream->setData(cmap.copyToData())->unref();
     SkRefPtr<SkPDFStream> pdfCmap = new SkPDFStream(cmapStream.get());
     fResources.push(pdfCmap.get());  // Pass reference from new.
     insert("ToUnicode", new SkPDFObjRef(pdfCmap.get()))->unref();
@@ -792,7 +798,7 @@
         }
         SkRefPtr<SkMemoryStream> glyphStream = new SkMemoryStream();
         glyphStream->unref();  // SkRefPtr and new both took a ref.
-        glyphStream->setMemoryOwned(content.detach(), content.getOffset());
+        glyphStream->setData(content.copyToData())->unref();
 
         SkRefPtr<SkPDFStream> glyphDescription =
             new SkPDFStream(glyphStream.get());
diff --git a/src/pdf/SkPDFStream.cpp b/src/pdf/SkPDFStream.cpp
index b1bd5ff..11afa32 100644
--- a/src/pdf/SkPDFStream.cpp
+++ b/src/pdf/SkPDFStream.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "SkData.h"
 #include "SkFlate.h"
 #include "SkPDFCatalog.h"
 #include "SkPDFStream.h"
@@ -45,10 +46,12 @@
 
     this->INHERITED::emitObject(stream, catalog, false);
     stream->writeText(" stream\n");
-    if (fPlainData.get())
+    if (fPlainData.get()) {
         stream->write(fPlainData->getMemoryBase(), fLength);
-    else
-        stream->write(fCompressedData.getStream(), fLength);
+    } else {
+        SkAutoDataUnref data(fCompressedData.copyToData());
+        stream->write(data.data(), fLength);
+    }
     stream->writeText("\nendstream");
 }
 
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 18c3e60..1ff7d45 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -16,6 +16,7 @@
 
 
 #include "SkCanvas.h"
+#include "SkData.h"
 #include "SkDevice.h"
 #include "SkPaint.h"
 #include "SkGPipe.h"
@@ -68,7 +69,8 @@
     size_t size = stream.getOffset();
     if (writer) {
         writer->write32(size);
-        writer->write(stream.getStream(), size);
+        SkAutoDataUnref data(stream.copyToData());
+        writer->write(data.data(), size);
     }
     return 4 + size;
 }
diff --git a/src/svg/SkSVGParser.cpp b/src/svg/SkSVGParser.cpp
index f4ad198..fec3493 100644
--- a/src/svg/SkSVGParser.cpp
+++ b/src/svg/SkSVGParser.cpp
@@ -90,6 +90,7 @@
     return -1;
 }
 
+#if 0
 const char* SkSVGParser::getFinal() {
     _startElement("screenplay");
     // generate defs
@@ -114,6 +115,7 @@
     fStream.write("", 1);
     return fStream.getStream();
 }
+#endif
 
 SkString& SkSVGParser::getPaintLast(SkSVGPaint::Field field) {
     SkSVGPaint* state = fHead;
diff --git a/tests/FlateTest.cpp b/tests/FlateTest.cpp
index fe2bb4a..8b85fdf 100644
--- a/tests/FlateTest.cpp
+++ b/tests/FlateTest.cpp
@@ -18,6 +18,7 @@
 #include <string.h>
 
 #include "Test.h"
+#include "SkData.h"
 #include "SkFlate.h"
 #include "SkStream.h"
 
@@ -67,7 +68,9 @@
     else
       REPORTER_ASSERT(reporter, compressed.getOffset() > 1024);
 
-    testStream->setMemory(compressed.getStream(), compressed.getOffset(), true);
+    SkAutoDataUnref data1(compressed.copyToData());
+
+    testStream->setData(data1.get())->unref();
     SkDynamicMemoryWStream uncompressed;
     status = SkFlate::Inflate(testStream, &uncompressed);
     REPORTER_ASSERT(reporter, status);
@@ -76,15 +79,14 @@
     inputSize = testStream->getLength();
     if (inputSize == 0)
         inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey);
-    REPORTER_ASSERT(reporter, compressed.getOffset() == inputSize);
+    REPORTER_ASSERT(reporter, data1.size() == inputSize);
     REPORTER_ASSERT(reporter, memcmp(testStream->getMemoryBase(),
-                                     compressed.getStream(),
-                                     compressed.getOffset()) == 0);
+                                     data1.data(), data1.size()) == 0);
 
     // Check that the uncompressed data matches the source data.
+    SkAutoDataUnref data2(uncompressed.copyToData());
     REPORTER_ASSERT(reporter, testData.getLength() == uncompressed.getOffset());
-    REPORTER_ASSERT(reporter, memcmp(testData.getMemoryBase(),
-                                     uncompressed.getStream(),
+    REPORTER_ASSERT(reporter, memcmp(testData.getMemoryBase(), data2.data(),
                                      testData.getLength()) == 0);
 }
 
diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp
index 9a58fa6..a5feba8 100644
--- a/tests/PDFPrimitivesTest.cpp
+++ b/tests/PDFPrimitivesTest.cpp
@@ -17,12 +17,22 @@
 #include <string>
 
 #include "Test.h"
+#include "SkData.h"
 #include "SkPDFCatalog.h"
 #include "SkPDFStream.h"
 #include "SkPDFTypes.h"
 #include "SkScalar.h"
 #include "SkStream.h"
 
+static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset,
+                          const void* buffer, size_t len) {
+    SkAutoDataUnref data(stream.copyToData());
+    if (offset + len > data.size()) {
+        return false;
+    }
+    return memcmp(data.bytes() + offset, buffer, len) == 0;
+}
+
 static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj,
                               const std::string& representation,
                               bool indirect) {
@@ -32,8 +42,8 @@
     SkDynamicMemoryWStream buffer;
     obj->emitObject(&buffer, NULL, false);
     REPORTER_ASSERT(reporter, directSize == buffer.getOffset());
-    REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), representation.c_str(),
-                                     directSize) == 0);
+    REPORTER_ASSERT(reporter, stream_equals(buffer, 0, representation.c_str(),
+                                            directSize));
 
     if (indirect) {
         // Indirect output.
@@ -52,14 +62,12 @@
         buffer.reset();
         obj->emitObject(&buffer, &catalog, true);
         REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset());
-        REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), header,
-                                         headerLen) == 0);
-        REPORTER_ASSERT(reporter,
-                        memcmp(buffer.getStream() + headerLen,
-                               representation.c_str(), directSize) == 0);
-        REPORTER_ASSERT(reporter,
-                        memcmp(buffer.getStream() + headerLen + directSize,
-                               footer, footerLen) == 0);
+        REPORTER_ASSERT(reporter, stream_equals(buffer, 0, header, headerLen));
+        REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen,
+                                                representation.c_str(),
+                                                directSize));
+        REPORTER_ASSERT(reporter, stream_equals(buffer, headerLen + directSize,
+                                                footer, footerLen));
     }
 }
 
@@ -87,8 +95,8 @@
     catalog.emitObjectNumber(&buffer, int3.get());
     catalog.emitObjectNumber(&buffer, int1Again.get());
     char expectedResult[] = "1 02 03 01 0";
-    REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), expectedResult,
-                                     strlen(expectedResult)) == 0);
+    REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
+                                            strlen(expectedResult)));
 }
 
 static void TestObjectRef(skiatest::Reporter* reporter) {
@@ -109,8 +117,8 @@
     SkDynamicMemoryWStream buffer;
     int2ref->emitObject(&buffer, &catalog, false);
     REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult));
-    REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), expectedResult,
-                                     buffer.getOffset()) == 0);
+    REPORTER_ASSERT(reporter, stream_equals(buffer, 0, expectedResult,
+                                            buffer.getOffset()));
 }
 
 static void TestPDFPrimitives(skiatest::Reporter* reporter) {
diff --git a/tests/StreamTest.cpp b/tests/StreamTest.cpp
index dffec76..bfec89d 100644
--- a/tests/StreamTest.cpp
+++ b/tests/StreamTest.cpp
@@ -82,7 +82,6 @@
     for (i = 0; i < 100; i++) {
         REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
     }
-    REPORTER_ASSERT(reporter, memcmp(dst, ds.getStream(), 100*26) == 0);
 
     {
         SkData* data = ds.copyToData();