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/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;