aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkOrderedWriteBuffer.h2
-rw-r--r--include/core/SkWriter32.h19
-rw-r--r--src/core/SkOrderedWriteBuffer.cpp5
-rw-r--r--src/core/SkWriter32.cpp53
-rw-r--r--tests/Writer32Test.cpp18
5 files changed, 89 insertions, 8 deletions
diff --git a/include/core/SkOrderedWriteBuffer.h b/include/core/SkOrderedWriteBuffer.h
index 6183218af3..51daf5ca14 100644
--- a/include/core/SkOrderedWriteBuffer.h
+++ b/include/core/SkOrderedWriteBuffer.h
@@ -18,6 +18,8 @@
class SkOrderedWriteBuffer : public SkFlattenableWriteBuffer {
public:
SkOrderedWriteBuffer(size_t minSize);
+ SkOrderedWriteBuffer(size_t minSize, void* initialStorage,
+ size_t storageSize);
virtual ~SkOrderedWriteBuffer() {}
// deprecated naming convention that will be removed after callers are updated
diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h
index 1b475958fb..c140850b9c 100644
--- a/include/core/SkWriter32.h
+++ b/include/core/SkWriter32.h
@@ -23,14 +23,23 @@ class SkWStream;
class SkWriter32 : SkNoncopyable {
public:
+ /**
+ * The caller can specify an initial block of storage, which the caller manages.
+ * SkWriter32 will not attempt to free this in its destructor. It is up to the
+ * implementation to decide if, and how much, of the storage to utilize, and it
+ * is possible that it may be ignored entirely.
+ */
+ SkWriter32(size_t minSize, void* initialStorage, size_t storageSize);
+
SkWriter32(size_t minSize)
: fMinSize(minSize),
fSize(0),
fSingleBlock(NULL),
fSingleBlockSize(0),
fHead(NULL),
- fTail(NULL) {
- }
+ fTail(NULL),
+ fHeadIsExternalStorage(false) {}
+
~SkWriter32();
/**
@@ -45,7 +54,7 @@ public:
* dynamic allocation (and resets).
*/
void reset(void* block, size_t size);
-
+
bool writeBool(bool value) {
this->writeInt(value);
return value;
@@ -150,11 +159,13 @@ private:
char* fSingleBlock;
uint32_t fSingleBlockSize;
-
+
struct Block;
Block* fHead;
Block* fTail;
+ bool fHeadIsExternalStorage;
+
Block* newBlock(size_t bytes);
};
diff --git a/src/core/SkOrderedWriteBuffer.cpp b/src/core/SkOrderedWriteBuffer.cpp
index bfe2bfc0b4..08938d0e5b 100644
--- a/src/core/SkOrderedWriteBuffer.cpp
+++ b/src/core/SkOrderedWriteBuffer.cpp
@@ -14,6 +14,11 @@ SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize) :
fWriter(minSize) {
}
+SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize) :
+ INHERITED(),
+ fWriter(minSize, storage, storageSize) {
+}
+
void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
/*
* If we have a factoryset, then the first 32bits tell us...
diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp
index dfa18a0c65..2ed65d4155 100644
--- a/src/core/SkWriter32.cpp
+++ b/src/core/SkWriter32.cpp
@@ -9,8 +9,8 @@
struct SkWriter32::Block {
Block* fNext;
- size_t fSize;
- size_t fAllocated;
+ size_t fSize; // total space allocated (after this)
+ size_t fAllocated; // space used so far
size_t available() const { return fSize - fAllocated; }
char* base() { return (char*)(this + 1); }
@@ -31,6 +31,12 @@ struct SkWriter32::Block {
return (uint32_t*)ptr;
}
+ void rewind() {
+ fNext = NULL;
+ fAllocated = 0;
+ // keep fSize as is
+ }
+
static Block* Create(size_t size) {
SkASSERT(SkAlign4(size) == size);
Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
@@ -39,16 +45,50 @@ struct SkWriter32::Block {
block->fAllocated = 0;
return block;
}
+
+ static Block* CreateFromStorage(void* storage, size_t size) {
+ SkASSERT(SkIsAlign4((intptr_t)storage));
+ Block* block = (Block*)storage;
+ block->fNext = NULL;
+ block->fSize = size - sizeof(Block);
+ block->fAllocated = 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;
+
+ 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;
+ }
+}
+
SkWriter32::~SkWriter32() {
this->reset();
}
void SkWriter32::reset() {
- Block* block = fHead;
+ Block* block = fHead;
+
+ if (fHeadIsExternalStorage) {
+ SkASSERT(block);
+ // don't 'free' the first block, since it is owned by the caller
+ block = block->fNext;
+ }
while (block) {
Block* next = block->fNext;
sk_free(block);
@@ -56,8 +96,13 @@ void SkWriter32::reset() {
}
fSize = 0;
- fHead = fTail = NULL;
fSingleBlock = NULL;
+ if (fHeadIsExternalStorage) {
+ fHead->rewind();
+ fTail = fHead;
+ } else {
+ fHead = fTail = NULL;
+ }
}
void SkWriter32::reset(void* block, size_t size) {
diff --git a/tests/Writer32Test.cpp b/tests/Writer32Test.cpp
index a9a07aded8..35fb29f38e 100644
--- a/tests/Writer32Test.cpp
+++ b/tests/Writer32Test.cpp
@@ -76,6 +76,24 @@ static void Tests(skiatest::Reporter* reporter) {
writer.reset(storage, sizeof(storage));
test2(reporter, &writer);
}
+
+ // small storage
+ {
+ intptr_t storage[8];
+ SkWriter32 writer(100, storage, sizeof(storage));
+ test1(reporter, &writer);
+ writer.reset(); // should just rewind our storage
+ test2(reporter, &writer);
+ }
+
+ // large storage
+ {
+ intptr_t storage[1024];
+ SkWriter32 writer(100, storage, sizeof(storage));
+ test1(reporter, &writer);
+ writer.reset(); // should just rewind our storage
+ test2(reporter, &writer);
+ }
}
#include "TestClassDef.h"