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#ifndef SkDataTable_DEFINED
97839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#define SkDataTable_DEFINED
107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkChunkAlloc.h"
127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkData.h"
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkString.h"
147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkTDArray.h"
157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/**
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  organized into a table of entries, each with a length, so the entries are
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  not required to all be the same size.
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerclass SK_API SkDataTable : public SkRefCnt {
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerpublic:
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SK_DECLARE_INST_COUNT(SkDataTable)
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Returns true if the table is empty (i.e. has no entries).
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    bool isEmpty() const { return 0 == fCount; }
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Return the number of entries in the table. 0 for an empty table
327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int count() const { return fCount; }
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Return the size of the index'th entry in the table. The caller must
377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  ensure that index is valid for this table.
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t atSize(int index) const;
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Return a pointer to the data of the index'th entry in the table.
437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  The caller must ensure that index is valid for this table.
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param size If non-null, this returns the byte size of this entry. This
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *              will be the same value that atSize(index) would return.
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const void* at(int index, size_t* size = NULL) const;
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    template <typename T>
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const T* atT(int index, size_t* size = NULL) const {
527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return reinterpret_cast<const T*>(this->at(index, size));
537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Returns the index'th entry as a c-string, and assumes that the trailing
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  null byte had been copied into the table as well.
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const char* atStr(int index) const {
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        size_t size;
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const char* str = this->atT<const char>(index, &size);
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkASSERT(strlen(str) + 1 == size);
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return str;
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    typedef void (*FreeProc)(void* context);
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static SkDataTable* NewEmpty();
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Return a new DataTable that contains a copy of the data stored in each
727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  "array".
737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *
747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param ptrs array of points to each element to be copied into the table.
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param sizes array of byte-lengths for each entry in the corresponding
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *               ptrs[] array.
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param count the number of array elements in ptrs[] and sizes[] to copy.
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static SkDataTable* NewCopyArrays(const void * const * ptrs,
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                      const size_t sizes[], int count);
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Return a new table that contains a copy of the data in array.
847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *
857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param array contiguous array of data for all elements to be copied.
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param elemSize byte-length for a given element.
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  @param count the number of entries to be copied out of array. The number
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *               of bytes that will be copied is count * elemSize.
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static SkDataTable* NewCopyArray(const void* array, size_t elemSize,
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                     int count);
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    static SkDataTable* NewArrayProc(const void* array, size_t elemSize,
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                                     int count, FreeProc proc, void* context);
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerprivate:
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    struct Dir {
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const void* fPtr;
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        uintptr_t   fSize;
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    };
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int         fCount;
1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t      fElemSize;
1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    union {
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const Dir*  fDir;
1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        const char* fElems;
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } fU;
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    FreeProc    fFreeProc;
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void*       fFreeProcContext;
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTable();
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTable(const void* array, size_t elemSize, int count,
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger                FreeProc, void* context);
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTable(const Dir*, int count, FreeProc, void* context);
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    virtual ~SkDataTable();
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    friend class SkDataTableBuilder;    // access to Dir
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    typedef SkRefCnt INHERITED;
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger};
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/**
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  Helper class that allows for incrementally building up the data needed to
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  create a SkDataTable.
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerclass SK_API SkDataTableBuilder : SkNoncopyable {
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerpublic:
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTableBuilder(size_t minChunkSize);
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    ~SkDataTableBuilder();
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    int  count() const { return fDir.count(); }
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t minChunkSize() const { return fMinChunkSize; }
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Forget any previously appended entries, setting count() back to 0.
1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void reset(size_t minChunkSize);
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void reset() {
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        this->reset(fMinChunkSize);
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Copy size-bytes from data, and append it to the growing SkDataTable.
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void append(const void* data, size_t size);
1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Helper version of append() passes strlen() + 1 for the size,
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  so the trailing-zero will be copied as well.
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void appendStr(const char str[]) {
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        this->append(str, strlen(str) + 1);
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
1577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Helper version of append() passes string.size() + 1 for the size,
1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  so the trailing-zero will be copied as well.
1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    void appendString(const SkString& string) {
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        this->append(string.c_str(), string.size() + 1);
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    /**
1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  Return an SkDataTable from the accumulated entries that were added by
1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  calls to append(). This call also clears any accumluated entries from
1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     *  this builder, so its count() will be 0 after this call.
1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger     */
1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDataTable* detachDataTable();
1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerprivate:
1727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkTDArray<SkDataTable::Dir> fDir;
1737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkChunkAlloc*               fHeap;
1747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t                      fMinChunkSize;
1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger};
1767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
178