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#ifndef SkDataTable_DEFINED
98c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#define SkDataTable_DEFINED
108c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
118c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkChunkAlloc.h"
128c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkData.h"
138c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkString.h"
148c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkTDArray.h"
158c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
168c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com/**
178c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com *  Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
188c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com *  organized into a table of entries, each with a length, so the entries are
198c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com *  not required to all be the same size.
208c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com */
212f92966c6a2419023570d5951a4234cdaebcc3c9commit-bot@chromium.orgclass SK_API SkDataTable : public SkRefCnt {
228c5c7a905b708f7c0a991ca7c872af645544afefreed@google.compublic:
238c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    SK_DECLARE_INST_COUNT(SkDataTable)
248c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
258c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
268c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Returns true if the table is empty (i.e. has no entries).
278c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
288c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    bool isEmpty() const { return 0 == fCount; }
298c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
308c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
318c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Return the number of entries in the table. 0 for an empty table
328c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
338c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    int count() const { return fCount; }
348c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
358c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
368c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Return the size of the index'th entry in the table. The caller must
378c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  ensure that index is valid for this table.
388c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
39cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    size_t atSize(int index) const;
408c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
418c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
428c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Return a pointer to the data of the index'th entry in the table.
438c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  The caller must ensure that index is valid for this table.
448c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *
458c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param size If non-null, this returns the byte size of this entry. This
468c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *              will be the same value that atSize(index) would return.
478c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
48cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    const void* at(int index, size_t* size = NULL) const;
498c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
508c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    template <typename T>
51cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    const T* atT(int index, size_t* size = NULL) const {
52cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return reinterpret_cast<const T*>(this->at(index, size));
538c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
548c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
558c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
568c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Returns the index'th entry as a c-string, and assumes that the trailing
578c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  null byte had been copied into the table as well.
588c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
598c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    const char* atStr(int index) const {
608c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com        size_t size;
61cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        const char* str = this->atT<const char>(index, &size);
628c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com        SkASSERT(strlen(str) + 1 == size);
638c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com        return str;
648c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
658c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
66cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    typedef void (*FreeProc)(void* context);
67cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
683cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com    static SkDataTable* NewEmpty();
693cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com
708c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
718c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Return a new DataTable that contains a copy of the data stored in each
728c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  "array".
738c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *
748c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param ptrs array of points to each element to be copied into the table.
758c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param sizes array of byte-lengths for each entry in the corresponding
768c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *               ptrs[] array.
778c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param count the number of array elements in ptrs[] and sizes[] to copy.
788c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
79cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    static SkDataTable* NewCopyArrays(const void * const * ptrs,
80cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                                      const size_t sizes[], int count);
818c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
828c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
838c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Return a new table that contains a copy of the data in array.
848c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *
858c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param array contiguous array of data for all elements to be copied.
868c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param elemSize byte-length for a given element.
878c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  @param count the number of entries to be copied out of array. The number
888c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *               of bytes that will be copied is count * elemSize.
898c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
908c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    static SkDataTable* NewCopyArray(const void* array, size_t elemSize,
918c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com                                     int count);
9264b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com
93cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    static SkDataTable* NewArrayProc(const void* array, size_t elemSize,
94cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                                     int count, FreeProc proc, void* context);
95cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
968c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comprivate:
97cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    struct Dir {
98cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        const void* fPtr;
99cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        uintptr_t   fSize;
100cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    };
101cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
102cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    int         fCount;
103cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    size_t      fElemSize;
104cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    union {
105cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        const Dir*  fDir;
106cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        const char* fElems;
107cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    } fU;
108cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
109cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    FreeProc    fFreeProc;
110cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    void*       fFreeProcContext;
111cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
112cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDataTable();
113cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDataTable(const void* array, size_t elemSize, int count,
114cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                FreeProc, void* context);
115cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDataTable(const Dir*, int count, FreeProc, void* context);
1168c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    virtual ~SkDataTable();
1178c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
118cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    friend class SkDataTableBuilder;    // access to Dir
1198c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1202f92966c6a2419023570d5951a4234cdaebcc3c9commit-bot@chromium.org    typedef SkRefCnt INHERITED;
1218c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com};
1228c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1238c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com/**
1248c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com *  Helper class that allows for incrementally building up the data needed to
1258c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com *  create a SkDataTable.
1268c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com */
127cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgclass SK_API SkDataTableBuilder : SkNoncopyable {
1288c5c7a905b708f7c0a991ca7c872af645544afefreed@google.compublic:
1298c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    SkDataTableBuilder(size_t minChunkSize);
1308c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    ~SkDataTableBuilder();
1318c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
132cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    int  count() const { return fDir.count(); }
133cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    size_t minChunkSize() const { return fMinChunkSize; }
1348c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1358c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
1368c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Forget any previously appended entries, setting count() back to 0.
1378c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
138cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    void reset(size_t minChunkSize);
139cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    void reset() {
140cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        this->reset(fMinChunkSize);
141cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
1428c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1438c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
1448c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Copy size-bytes from data, and append it to the growing SkDataTable.
1458c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
1468c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    void append(const void* data, size_t size);
1478c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1488c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
1498c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Helper version of append() passes strlen() + 1 for the size,
1508c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  so the trailing-zero will be copied as well.
1518c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
1528c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    void appendStr(const char str[]) {
1538c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com        this->append(str, strlen(str) + 1);
1548c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
1558c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1568c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
1578c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Helper version of append() passes string.size() + 1 for the size,
1588c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  so the trailing-zero will be copied as well.
1598c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
1608c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    void appendString(const SkString& string) {
1618c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com        this->append(string.c_str(), string.size() + 1);
1628c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
1638c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1648c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    /**
1658c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     *  Return an SkDataTable from the accumulated entries that were added by
166cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org     *  calls to append(). This call also clears any accumluated entries from
167cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org     *  this builder, so its count() will be 0 after this call.
1688c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com     */
169cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDataTable* detachDataTable();
1708c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1718c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comprivate:
172cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkTDArray<SkDataTable::Dir> fDir;
173cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkChunkAlloc*               fHeap;
174cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    size_t                      fMinChunkSize;
1758c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com};
1768c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1778c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#endif
178