1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkDataTable_DEFINED
9#define SkDataTable_DEFINED
10
11#include "../private/SkTDArray.h"
12#include "SkData.h"
13#include "SkString.h"
14
15/**
16 *  Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
17 *  organized into a table of entries, each with a length, so the entries are
18 *  not required to all be the same size.
19 */
20class SK_API SkDataTable : public SkRefCnt {
21public:
22    /**
23     *  Returns true if the table is empty (i.e. has no entries).
24     */
25    bool isEmpty() const { return 0 == fCount; }
26
27    /**
28     *  Return the number of entries in the table. 0 for an empty table
29     */
30    int count() const { return fCount; }
31
32    /**
33     *  Return the size of the index'th entry in the table. The caller must
34     *  ensure that index is valid for this table.
35     */
36    size_t atSize(int index) const;
37
38    /**
39     *  Return a pointer to the data of the index'th entry in the table.
40     *  The caller must ensure that index is valid for this table.
41     *
42     *  @param size If non-null, this returns the byte size of this entry. This
43     *              will be the same value that atSize(index) would return.
44     */
45    const void* at(int index, size_t* size = nullptr) const;
46
47    template <typename T>
48    const T* atT(int index, size_t* size = nullptr) const {
49        return reinterpret_cast<const T*>(this->at(index, size));
50    }
51
52    /**
53     *  Returns the index'th entry as a c-string, and assumes that the trailing
54     *  null byte had been copied into the table as well.
55     */
56    const char* atStr(int index) const {
57        size_t size;
58        const char* str = this->atT<const char>(index, &size);
59        SkASSERT(strlen(str) + 1 == size);
60        return str;
61    }
62
63    typedef void (*FreeProc)(void* context);
64
65    static sk_sp<SkDataTable> MakeEmpty();
66
67    /**
68     *  Return a new DataTable that contains a copy of the data stored in each
69     *  "array".
70     *
71     *  @param ptrs array of points to each element to be copied into the table.
72     *  @param sizes array of byte-lengths for each entry in the corresponding
73     *               ptrs[] array.
74     *  @param count the number of array elements in ptrs[] and sizes[] to copy.
75     */
76    static sk_sp<SkDataTable> MakeCopyArrays(const void * const * ptrs,
77                                             const size_t sizes[], int count);
78
79    /**
80     *  Return a new table that contains a copy of the data in array.
81     *
82     *  @param array contiguous array of data for all elements to be copied.
83     *  @param elemSize byte-length for a given element.
84     *  @param count the number of entries to be copied out of array. The number
85     *               of bytes that will be copied is count * elemSize.
86     */
87    static sk_sp<SkDataTable> MakeCopyArray(const void* array, size_t elemSize, int count);
88
89    static sk_sp<SkDataTable> MakeArrayProc(const void* array, size_t elemSize, int count,
90                                            FreeProc proc, void* context);
91
92private:
93    struct Dir {
94        const void* fPtr;
95        uintptr_t   fSize;
96    };
97
98    int         fCount;
99    size_t      fElemSize;
100    union {
101        const Dir*  fDir;
102        const char* fElems;
103    } fU;
104
105    FreeProc    fFreeProc;
106    void*       fFreeProcContext;
107
108    SkDataTable();
109    SkDataTable(const void* array, size_t elemSize, int count,
110                FreeProc, void* context);
111    SkDataTable(const Dir*, int count, FreeProc, void* context);
112    virtual ~SkDataTable();
113
114    friend class SkDataTableBuilder;    // access to Dir
115
116    typedef SkRefCnt INHERITED;
117};
118
119#endif
120