18c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com/* 28c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * Copyright 2013 Google Inc. 38c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * 48c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * Use of this source code is governed by a BSD-style license that can be 58c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * found in the LICENSE file. 68c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com */ 78c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 88c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkData.h" 98c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkDataTable.h" 108c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 11cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgstatic void malloc_freeproc(void* context) { 12cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org sk_free(context); 13cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 148c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 15cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org// Makes empty table 16cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable() { 17cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fCount = 0; 18cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fElemSize = 0; // 0 signals that we use fDir instead of fElems 19cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fU.fDir = NULL; 20cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc = NULL; 21cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProcContext = NULL; 228c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 238c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 24cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable(const void* array, size_t elemSize, int count, 25cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org FreeProc proc, void* context) { 26cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkASSERT(count > 0); 27c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com 28cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fCount = count; 29cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fElemSize = elemSize; // non-zero signals we use fElems instead of fDir 30cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fU.fElems = (const char*)array; 31cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc = proc; 32cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProcContext = context; 33cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 348c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 35cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) { 36cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkASSERT(count > 0); 37c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com 38cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fCount = count; 39cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fElemSize = 0; // 0 signals that we use fDir instead of fElems 40cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fU.fDir = dir; 41cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc = proc; 42cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProcContext = ctx; 43cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 44cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 45cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::~SkDataTable() { 46cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fFreeProc) { 47cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc(fFreeProcContext); 488c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 49cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 508c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 518c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comsize_t SkDataTable::atSize(int index) const { 528c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 53cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 54cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fElemSize) { 55cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fElemSize; 56cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } else { 57cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fU.fDir[index].fSize; 58cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 598c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 608c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 61cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgconst void* SkDataTable::at(int index, size_t* size) const { 628c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 63cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 64cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fElemSize) { 65cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (size) { 66cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org *size = fElemSize; 67cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 68cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fU.fElems + index * fElemSize; 69cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } else { 70cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (size) { 71cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org *size = fU.fDir[index].fSize; 72cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 73cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fU.fDir[index].fPtr; 748c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 758c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 768c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 773cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com/////////////////////////////////////////////////////////////////////////////// 783cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com 793cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.comSkDataTable* SkDataTable::NewEmpty() { 803cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com static SkDataTable* gEmpty; 813cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com if (NULL == gEmpty) { 82cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org gEmpty = SkNEW(SkDataTable); 833cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com } 843cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com gEmpty->ref(); 853cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com return gEmpty; 863cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com} 873cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com 888c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs, 898c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com const size_t sizes[], int count) { 90cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (count <= 0) { 91cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkDataTable::NewEmpty(); 928c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 938c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 948c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com size_t dataSize = 0; 958c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com for (int i = 0; i < count; ++i) { 968c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com dataSize += sizes[i]; 978c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 988c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 99cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org size_t bufferSize = count * sizeof(Dir) + dataSize; 1008c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com void* buffer = sk_malloc_throw(bufferSize); 1018c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 102cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org Dir* dir = (Dir*)buffer; 103cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org char* elem = (char*)(dir + count); 1048c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com for (int i = 0; i < count; ++i) { 105cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org dir[i].fPtr = elem; 106cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org dir[i].fSize = sizes[i]; 107cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org memcpy(elem, ptrs[i], sizes[i]); 108cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org elem += sizes[i]; 1098c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 110c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com 111cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer)); 1128c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 1138c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 1148c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize, 1158c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com int count) { 116cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (count <= 0) { 117cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkDataTable::NewEmpty(); 1188c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 11964b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com 120cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org size_t bufferSize = elemSize * count; 1218c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com void* buffer = sk_malloc_throw(bufferSize); 122cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org memcpy(buffer, array, bufferSize); 12364b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com 124cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkNEW_ARGS(SkDataTable, 125cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org (buffer, elemSize, count, malloc_freeproc, buffer)); 126cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 12764b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com 128cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize, 129cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org int count, FreeProc proc, void* ctx) { 130cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (count <= 0) { 131cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkDataTable::NewEmpty(); 132cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 133cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx)); 1348c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 1358c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 1368c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com/////////////////////////////////////////////////////////////////////////////// 1378c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 138cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgstatic void chunkalloc_freeproc(void* context) { 139cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkDELETE((SkChunkAlloc*)context); 140cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 141cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 1428c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize) 143cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org : fHeap(NULL) 144cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org , fMinChunkSize(minChunkSize) {} 1458c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 146cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTableBuilder::~SkDataTableBuilder() { this->reset(); } 1478c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 148cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgvoid SkDataTableBuilder::reset(size_t minChunkSize) { 149cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fMinChunkSize = minChunkSize; 150cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fDir.reset(); 151cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fHeap) { 152cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkDELETE(fHeap); 153cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fHeap = NULL; 154cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 1558c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 1568c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 1578c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comvoid SkDataTableBuilder::append(const void* src, size_t size) { 158cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (NULL == fHeap) { 159cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize)); 160cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 161cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 162cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType); 1638c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com memcpy(dst, src, size); 1648c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 165cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkDataTable::Dir* dir = fDir.append(); 166cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org dir->fPtr = dst; 167cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org dir->fSize = size; 1688c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 1698c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 170cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable* SkDataTableBuilder::detachDataTable() { 171cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org const int count = fDir.count(); 172cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (0 == count) { 173cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return SkDataTable::NewEmpty(); 174cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 175cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 176cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org // Copy the dir into the heap; 177cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir), 178cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkChunkAlloc::kThrow_AllocFailType); 179cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir)); 180cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 181cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkDataTable* table = SkNEW_ARGS(SkDataTable, 182cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org ((SkDataTable::Dir*)dir, count, 183cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org chunkalloc_freeproc, fHeap)); 184cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org // we have to detach our fHeap, since we are giving that to the table 185cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fHeap = NULL; 186cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fDir.reset(); 187cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return table; 1888c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 189