diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-19 20:16:01 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-04-19 20:16:01 +0000 |
commit | 8c5c7a905b708f7c0a991ca7c872af645544afef (patch) | |
tree | 974279a91657b0a5d9b74e106bc6b723ab59e7e5 /src/core | |
parent | 0c888286f7db7e9cd861b2e425a17e109601d3fa (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/core')
-rw-r--r-- | src/core/SkDataTable.cpp | 135 |
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()); +} + |