unify how we handle externally-provided storage in SkWriter32, with the goal
of simplifying the logic in reserve() so it can be inlined/accelerated.
Review URL: https://codereview.appspot.com/6962048

git-svn-id: http://skia.googlecode.com/svn/trunk@6923 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp
index 4bb83b3..b66a7fe 100644
--- a/src/core/SkWriter32.cpp
+++ b/src/core/SkWriter32.cpp
@@ -1,80 +1,20 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "SkWriter32.h"
 
-struct SkWriter32::Block {
-    Block*  fNext;
-    size_t  fSizeOfBlock;      // total space allocated (after this)
-    size_t  fAllocatedSoFar;    // space used so far
-
-    size_t  available() const { return fSizeOfBlock - fAllocatedSoFar; }
-    char*   base() { return (char*)(this + 1); }
-    const char* base() const { return (const char*)(this + 1); }
-
-    uint32_t* alloc(size_t size) {
-        SkASSERT(SkAlign4(size) == size);
-        SkASSERT(this->available() >= size);
-        void* ptr = this->base() + fAllocatedSoFar;
-        fAllocatedSoFar += size;
-        SkASSERT(fAllocatedSoFar <= fSizeOfBlock);
-        return (uint32_t*)ptr;
-    }
-
-    uint32_t* peek32(size_t offset) {
-        SkASSERT(offset <= fAllocatedSoFar + 4);
-        void* ptr = this->base() + offset;
-        return (uint32_t*)ptr;
-    }
-
-    void rewind() {
-        fNext = NULL;
-        fAllocatedSoFar = 0;
-        // keep fSizeOfBlock as is
-    }
-
-    static Block* Create(size_t size) {
-        SkASSERT(SkAlign4(size) == size);
-        Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
-        block->fNext = NULL;
-        block->fSizeOfBlock = size;
-        block->fAllocatedSoFar = 0;
-        return block;
-    }
-
-    static Block* CreateFromStorage(void* storage, size_t size) {
-        SkASSERT(SkIsAlign4((intptr_t)storage));
-        Block* block = (Block*)storage;
-        block->fNext = NULL;
-        block->fSizeOfBlock = size - sizeof(Block);
-        block->fAllocatedSoFar = 0;
-        return block;
-    }
-
-};
-
-#define MIN_BLOCKSIZE   (sizeof(SkWriter32::Block) + sizeof(intptr_t))
-
-///////////////////////////////////////////////////////////////////////////////
-
 SkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) {
     fMinSize = minSize;
     fSize = 0;
-    fSingleBlock = NULL;
-    fSingleBlockSize = 0;
     fWrittenBeforeLastBlock = 0;
+    fHead = fTail = NULL;
 
-    storageSize &= ~3;  // trunc down to multiple of 4
-    if (storageSize >= MIN_BLOCKSIZE) {
-        fHead = fTail = Block::CreateFromStorage(storage, storageSize);
-        fHeadIsExternalStorage = true;
-    } else {
-        fHead = fTail = NULL;
-        fHeadIsExternalStorage = false;
+    if (storageSize) {
+        this->reset(storage, storageSize);
     }
 }
 
@@ -85,7 +25,7 @@
 void SkWriter32::reset() {
     Block* block = fHead;
 
-    if (fHeadIsExternalStorage) {
+    if (this->isHeadExternallyAllocated()) {
         SkASSERT(block);
         // don't 'free' the first block, since it is owned by the caller
         block = block->fNext;
@@ -98,40 +38,29 @@
 
     fSize = 0;
     fWrittenBeforeLastBlock = 0;
-    fSingleBlock = NULL;
-    if (fHeadIsExternalStorage) {
-        SkASSERT(fHead);
-        fHead->rewind();
-        fTail = fHead;
-    } else {
-        fHead = fTail = NULL;
+    fHead = fTail = NULL;
+}
+
+void SkWriter32::reset(void* storage, size_t storageSize) {
+    this->reset();
+    
+    storageSize &= ~3;  // trunc down to multiple of 4
+    if (storageSize > 0 && SkIsAlign4((intptr_t)storage)) {
+        fHead = fTail = fExternalBlock.initFromStorage(storage, storageSize);
     }
 }
 
-void SkWriter32::reset(void* block, size_t size) {
-    this->reset();
-    SkASSERT(0 == ((fSingleBlock - (char*)0) & 3));   // need 4-byte alignment
-    fSingleBlock = (char*)block;
-    fSingleBlockSize = (size & ~3);
-}
-
-uint32_t* SkWriter32::reserve(size_t size) {
+SkWriter32::Block* SkWriter32::doReserve(size_t size) {
     SkASSERT(SkAlign4(size) == size);
 
-    if (fSingleBlock) {
-        uint32_t* ptr = (uint32_t*)(fSingleBlock + fSize);
-        fSize += size;
-        SkASSERT(fSize <= fSingleBlockSize);
-        return ptr;
-    }
-
     Block* block = fTail;
+    SkASSERT(NULL == block || block->available() < size);
 
     if (NULL == block) {
         SkASSERT(NULL == fHead);
         fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
         SkASSERT(0 == fWrittenBeforeLastBlock);
-    } else if (block->available() < size) {
+    } else {
         SkASSERT(fSize > 0);
         fWrittenBeforeLastBlock = fSize;
 
@@ -139,10 +68,7 @@
         block->fNext = fTail;
         block = fTail;
     }
-
-    fSize += size;
-
-    return block->alloc(size);
+    return block;
 }
 
 uint32_t* SkWriter32::peek32(size_t offset) {
@@ -151,10 +77,6 @@
     SkASSERT(SkAlign4(offset) == offset);
     SkASSERT(offset <= fSize);
 
-    if (fSingleBlock) {
-        return (uint32_t*)(fSingleBlock + offset);
-    }
-
     // try the fast case, where offset is within fTail
     if (offset >= fWrittenBeforeLastBlock) {
         return fTail->peek32(offset - fWrittenBeforeLastBlock);
@@ -176,7 +98,7 @@
         return;
     }
     if (0 == offset) {
-        this->reset(NULL, 0);
+        this->reset();
         return;
     }
 
@@ -186,10 +108,6 @@
     SkASSERT(offset <= fSize);
     fSize = offset;
 
-    if (fSingleBlock) {
-        return;
-    }
-
     // Try the fast case, where offset is within fTail
     if (offset >= fWrittenBeforeLastBlock) {
         fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock;
@@ -227,11 +145,6 @@
 }
 
 void SkWriter32::flatten(void* dst) const {
-    if (fSingleBlock) {
-        memcpy(dst, fSingleBlock, fSize);
-        return;
-    }
-
     const Block* block = fHead;
     SkDEBUGCODE(size_t total = 0;)
 
@@ -270,17 +183,6 @@
 #include "SkStream.h"
 
 size_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
-    if (fSingleBlock) {
-        SkASSERT(fSingleBlockSize >= fSize);
-        size_t remaining = fSingleBlockSize - fSize;
-        if (length > remaining) {
-            length = remaining;
-        }
-        stream->read(fSingleBlock + fSize, length);
-        fSize += length;
-        return length;
-    }
-
     char scratch[1024];
     const size_t MAX = sizeof(scratch);
     size_t remaining = length;
@@ -301,10 +203,6 @@
 }
 
 bool SkWriter32::writeToStream(SkWStream* stream) {
-    if (fSingleBlock) {
-        return stream->write(fSingleBlock, fSize);
-    }
-
     const Block* block = fHead;
     while (block) {
         if (!stream->write(block->base(), block->fAllocatedSoFar)) {
@@ -318,12 +216,6 @@
 #ifdef SK_DEBUG
 void SkWriter32::validate() const {
     SkASSERT(SkIsAlign4(fSize));
-    SkASSERT(SkIsAlign4(fSingleBlockSize));
-
-    if (fSingleBlock) {
-        SkASSERT(fSize <= fSingleBlockSize);
-        return;
-    }
 
     size_t accum = 0;
     const Block* block = fHead;