17839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/*
27839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Copyright 2013 Google Inc.
37839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *
47839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
57839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * found in the LICENSE file.
67839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
77839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
87839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkData.h"
97839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkDataTable.h"
107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkFlattenableBuffers.h"
117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSK_DEFINE_INST_COUNT(SkDataTable)
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void malloc_freeproc(void* context) {
157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    sk_free(context);
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Makes empty table
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable::SkDataTable() {
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fCount = 0;
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fElemSize = 0;   // 0 signals that we use fDir instead of fElems
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fU.fDir = NULL;
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProc = NULL;
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProcContext = NULL;
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable::SkDataTable(const void* array, size_t elemSize, int count,
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                         FreeProc proc, void* context) {
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(count > 0);
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fCount = count;
327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fElemSize = elemSize;   // non-zero signals we use fElems instead of fDir
337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fU.fElems = (const char*)array;
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProc = proc;
357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProcContext = context;
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) {
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT(count > 0);
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fCount = count;
427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fElemSize = 0;  // 0 signals that we use fDir instead of fElems
437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fU.fDir = dir;
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProc = proc;
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProcContext = ctx;
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable::~SkDataTable() {
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fFreeProc) {
507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fFreeProc(fFreeProcContext);
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergersize_t SkDataTable::atSize(int index) const {
557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT((unsigned)index < (unsigned)fCount);
567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fElemSize) {
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return fElemSize;
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return fU.fDir[index].fSize;
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerconst void* SkDataTable::at(int index, size_t* size) const {
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkASSERT((unsigned)index < (unsigned)fCount);
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fElemSize) {
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (size) {
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            *size = fElemSize;
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return fU.fElems + index * fElemSize;
727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (size) {
747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            *size = fU.fDir[index].fSize;
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return fU.fDir[index].fPtr;
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable::SkDataTable(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fElemSize = 0;
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fU.fElems = NULL;
837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProc = NULL;
847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFreeProcContext = NULL;
857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fCount = buffer.read32();
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fCount) {
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fElemSize = buffer.read32();
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (fElemSize) {
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            size_t size = buffer.getArrayCount();
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            // size is the size of our elems data
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            SkASSERT(fCount * fElemSize == size);
937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            void* addr = sk_malloc_throw(size);
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            if (buffer.readByteArray(addr) != size) {
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                sk_throw();
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            fU.fElems = (const char*)addr;
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            fFreeProcContext = addr;
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        } else {
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            size_t dataSize = buffer.read32();
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            size_t allocSize = fCount * sizeof(Dir) + dataSize;
1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            void* addr = sk_malloc_throw(allocSize);
1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            Dir* dir = (Dir*)addr;
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            char* elem = (char*)(dir + fCount);
1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            for (int i = 0; i < fCount; ++i) {
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                dir[i].fPtr = elem;
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                dir[i].fSize = buffer.readByteArray(elem);
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                elem += dir[i].fSize;
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            fU.fDir = dir;
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            fFreeProcContext = addr;
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fFreeProc = malloc_freeproc;
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkDataTable::flatten(SkFlattenableWriteBuffer& buffer) const {
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    this->INHERITED::flatten(buffer);
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    buffer.write32(fCount);
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fCount) {
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        buffer.write32(fElemSize);
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (fElemSize) {
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            buffer.writeByteArray(fU.fElems, fCount * fElemSize);
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        } else {
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            size_t dataSize = 0;
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            for (int i = 0; i < fCount; ++i) {
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                dataSize += fU.fDir[i].fSize;
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            buffer.write32(dataSize);
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            for (int i = 0; i < fCount; ++i) {
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                buffer.writeByteArray(fU.fDir[i].fPtr, fU.fDir[i].fSize);
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            }
1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable* SkDataTable::NewEmpty() {
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static SkDataTable* gEmpty;
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (NULL == gEmpty) {
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        gEmpty = SkNEW(SkDataTable);
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    gEmpty->ref();
1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return gEmpty;
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs,
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                        const size_t sizes[], int count) {
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (count <= 0) {
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkDataTable::NewEmpty();
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t dataSize = 0;
1577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (int i = 0; i < count; ++i) {
1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        dataSize += sizes[i];
1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t bufferSize = count * sizeof(Dir) + dataSize;
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void* buffer = sk_malloc_throw(bufferSize);
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    Dir* dir = (Dir*)buffer;
1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    char* elem = (char*)(dir + count);
1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    for (int i = 0; i < count; ++i) {
1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        dir[i].fPtr = elem;
1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        dir[i].fSize = sizes[i];
1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        memcpy(elem, ptrs[i], sizes[i]);
1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        elem += sizes[i];
1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer));
1747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize,
1777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                       int count) {
1787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (count <= 0) {
1797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkDataTable::NewEmpty();
1807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t bufferSize = elemSize * count;
1837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void* buffer = sk_malloc_throw(bufferSize);
1847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    memcpy(buffer, array, bufferSize);
1857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return SkNEW_ARGS(SkDataTable,
1877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                      (buffer, elemSize, count, malloc_freeproc, buffer));
1887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize,
1917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                       int count, FreeProc proc, void* ctx) {
1927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (count <= 0) {
1937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkDataTable::NewEmpty();
1947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx));
1967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic void chunkalloc_freeproc(void* context) {
2017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDELETE((SkChunkAlloc*)context);
2027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
2037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize)
2057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    : fHeap(NULL)
2067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    , fMinChunkSize(minChunkSize) {}
2077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTableBuilder::~SkDataTableBuilder() { this->reset(); }
2097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkDataTableBuilder::reset(size_t minChunkSize) {
2117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fMinChunkSize = minChunkSize;
2127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDir.reset();
2137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fHeap) {
2147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDELETE(fHeap);
2157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fHeap = NULL;
2167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
2177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
2187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkDataTableBuilder::append(const void* src, size_t size) {
2207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (NULL == fHeap) {
2217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize));
2227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
2237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType);
2257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    memcpy(dst, src, size);
2267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTable::Dir* dir = fDir.append();
2287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    dir->fPtr = dst;
2297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    dir->fSize = size;
2307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDataTable* SkDataTableBuilder::detachDataTable() {
2337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const int count = fDir.count();
2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (0 == count) {
2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return SkDataTable::NewEmpty();
2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
2377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // Copy the dir into the heap;
2397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir),
2407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                             SkChunkAlloc::kThrow_AllocFailType);
2417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir));
2427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTable* table = SkNEW_ARGS(SkDataTable,
2447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                    ((SkDataTable::Dir*)dir, count,
2457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                     chunkalloc_freeproc, fHeap));
2467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    // we have to detach our fHeap, since we are giving that to the table
2477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fHeap = NULL;
2487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDir.reset();
2497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return table;
2507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
251