aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-19 20:16:01 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-04-19 20:16:01 +0000
commit8c5c7a905b708f7c0a991ca7c872af645544afef (patch)
tree974279a91657b0a5d9b74e106bc6b723ab59e7e5 /src
parent0c888286f7db7e9cd861b2e425a17e109601d3fa (diff)
add SkDataTable, to efficiently store an immutable array. Includes a builder
helper class. Review URL: https://codereview.chromium.org/14188049 git-svn-id: http://skia.googlecode.com/svn/trunk@8779 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/core/SkDataTable.cpp135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/core/SkDataTable.cpp b/src/core/SkDataTable.cpp
new file mode 100644
index 0000000000..fa7ff7149a
--- /dev/null
+++ b/src/core/SkDataTable.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkData.h"
+#include "SkDataTable.h"
+#include "SkFlattenableBuffers.h"
+
+SK_DEFINE_INST_COUNT(SkDataTable)
+
+SkDataTable::SkDataTable(int count, SkData* data)
+ : fCount(count)
+ , fData(data) {}
+
+SkDataTable::~SkDataTable() {
+ fData->unref();
+}
+
+struct ElemHead {
+ const void* fPtr;
+ uintptr_t fSize;
+
+ static const ElemHead* Get(SkData* data) {
+ return (const ElemHead*)(data->data());
+ }
+};
+
+size_t SkDataTable::atSize(int index) const {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ return ElemHead::Get(fData)[index].fSize;
+}
+
+const void* SkDataTable::atData(int index, size_t* size) const {
+ SkASSERT((unsigned)index < (unsigned)fCount);
+ const ElemHead& head = ElemHead::Get(fData)[index];
+ if (size) {
+ *size = head.fSize;
+ }
+ return head.fPtr;
+}
+
+SkDataTable::SkDataTable(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ fCount = buffer.read32();
+ fData = buffer.readFlattenableT<SkData>();
+}
+
+void SkDataTable::flatten(SkFlattenableWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ buffer.write32(fCount);
+ buffer.writeFlattenable(fData);
+}
+
+SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs,
+ const size_t sizes[], int count) {
+ if (count < 0) {
+ count = 0;
+ }
+
+ size_t headerSize = count * sizeof(ElemHead);
+ size_t dataSize = 0;
+ for (int i = 0; i < count; ++i) {
+ dataSize += sizes[i];
+ }
+
+ size_t bufferSize = headerSize + dataSize;
+ void* buffer = sk_malloc_throw(bufferSize);
+
+ ElemHead* headerCurr = (ElemHead*)buffer;
+ char* dataCurr = (char*)buffer + headerSize;
+ for (int i = 0; i < count; ++i) {
+ headerCurr[i].fPtr = dataCurr;
+ headerCurr[i].fSize = sizes[i];
+ memcpy(dataCurr, ptrs[i], sizes[i]);
+ dataCurr += sizes[i];
+ }
+
+ return SkNEW_ARGS(SkDataTable, (count,
+ SkData::NewFromMalloc(buffer, bufferSize)));
+}
+
+SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize,
+ int count) {
+ if (count < 0) {
+ count = 0;
+ }
+
+ size_t headerSize = count * sizeof(ElemHead);
+ size_t dataSize = count * elemSize;
+
+ size_t bufferSize = headerSize + dataSize;
+ void* buffer = sk_malloc_throw(bufferSize);
+
+ ElemHead* headerCurr = (ElemHead*)buffer;
+ char* dataCurr = (char*)buffer + headerSize;
+ for (int i = 0; i < count; ++i) {
+ headerCurr[i].fPtr = dataCurr;
+ headerCurr[i].fSize = elemSize;
+ dataCurr += elemSize;
+ }
+ memcpy((char*)buffer + headerSize, array, dataSize);
+
+ return SkNEW_ARGS(SkDataTable, (count,
+ SkData::NewFromMalloc(buffer, bufferSize)));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize)
+ : fHeap(minChunkSize) {}
+
+SkDataTableBuilder::~SkDataTableBuilder() {}
+
+void SkDataTableBuilder::reset() {
+ fSizes.reset();
+ fPtrs.reset();
+ fHeap.reset();
+}
+
+void SkDataTableBuilder::append(const void* src, size_t size) {
+ void* dst = fHeap.alloc(size, SkChunkAlloc::kThrow_AllocFailType);
+ memcpy(dst, src, size);
+
+ *fSizes.append() = size;
+ *fPtrs.append() = dst;
+}
+
+SkDataTable* SkDataTableBuilder::createDataTable() {
+ SkASSERT(fSizes.count() == fPtrs.count());
+ return SkDataTable::NewCopyArrays(fPtrs.begin(), fSizes.begin(),
+ fSizes.count());
+}
+