• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkChunkAlloc.h"
12 #include "SkData.h"
13 #include "SkString.h"
14 #include "SkTDArray.h"
15 
16 /**
17  *  Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
18  *  organized into a table of entries, each with a length, so the entries are
19  *  not required to all be the same size.
20  */
21 class SK_API SkDataTable : public SkRefCnt {
22 public:
SK_DECLARE_INST_COUNT(SkDataTable)23     SK_DECLARE_INST_COUNT(SkDataTable)
24 
25     /**
26      *  Returns true if the table is empty (i.e. has no entries).
27      */
28     bool isEmpty() const { return 0 == fCount; }
29 
30     /**
31      *  Return the number of entries in the table. 0 for an empty table
32      */
count()33     int count() const { return fCount; }
34 
35     /**
36      *  Return the size of the index'th entry in the table. The caller must
37      *  ensure that index is valid for this table.
38      */
39     size_t atSize(int index) const;
40 
41     /**
42      *  Return a pointer to the data of the index'th entry in the table.
43      *  The caller must ensure that index is valid for this table.
44      *
45      *  @param size If non-null, this returns the byte size of this entry. This
46      *              will be the same value that atSize(index) would return.
47      */
48     const void* at(int index, size_t* size = NULL) const;
49 
50     template <typename T>
51     const T* atT(int index, size_t* size = NULL) const {
52         return reinterpret_cast<const T*>(this->at(index, size));
53     }
54 
55     /**
56      *  Returns the index'th entry as a c-string, and assumes that the trailing
57      *  null byte had been copied into the table as well.
58      */
atStr(int index)59     const char* atStr(int index) const {
60         size_t size;
61         const char* str = this->atT<const char>(index, &size);
62         SkASSERT(strlen(str) + 1 == size);
63         return str;
64     }
65 
66     typedef void (*FreeProc)(void* context);
67 
68     static SkDataTable* NewEmpty();
69 
70     /**
71      *  Return a new DataTable that contains a copy of the data stored in each
72      *  "array".
73      *
74      *  @param ptrs array of points to each element to be copied into the table.
75      *  @param sizes array of byte-lengths for each entry in the corresponding
76      *               ptrs[] array.
77      *  @param count the number of array elements in ptrs[] and sizes[] to copy.
78      */
79     static SkDataTable* NewCopyArrays(const void * const * ptrs,
80                                       const size_t sizes[], int count);
81 
82     /**
83      *  Return a new table that contains a copy of the data in array.
84      *
85      *  @param array contiguous array of data for all elements to be copied.
86      *  @param elemSize byte-length for a given element.
87      *  @param count the number of entries to be copied out of array. The number
88      *               of bytes that will be copied is count * elemSize.
89      */
90     static SkDataTable* NewCopyArray(const void* array, size_t elemSize,
91                                      int count);
92 
93     static SkDataTable* NewArrayProc(const void* array, size_t elemSize,
94                                      int count, FreeProc proc, void* context);
95 
96 private:
97     struct Dir {
98         const void* fPtr;
99         uintptr_t   fSize;
100     };
101 
102     int         fCount;
103     size_t      fElemSize;
104     union {
105         const Dir*  fDir;
106         const char* fElems;
107     } fU;
108 
109     FreeProc    fFreeProc;
110     void*       fFreeProcContext;
111 
112     SkDataTable();
113     SkDataTable(const void* array, size_t elemSize, int count,
114                 FreeProc, void* context);
115     SkDataTable(const Dir*, int count, FreeProc, void* context);
116     virtual ~SkDataTable();
117 
118     friend class SkDataTableBuilder;    // access to Dir
119 
120     typedef SkRefCnt INHERITED;
121 };
122 
123 /**
124  *  Helper class that allows for incrementally building up the data needed to
125  *  create a SkDataTable.
126  */
127 class SK_API SkDataTableBuilder : SkNoncopyable {
128 public:
129     SkDataTableBuilder(size_t minChunkSize);
130     ~SkDataTableBuilder();
131 
count()132     int  count() const { return fDir.count(); }
minChunkSize()133     size_t minChunkSize() const { return fMinChunkSize; }
134 
135     /**
136      *  Forget any previously appended entries, setting count() back to 0.
137      */
138     void reset(size_t minChunkSize);
reset()139     void reset() {
140         this->reset(fMinChunkSize);
141     }
142 
143     /**
144      *  Copy size-bytes from data, and append it to the growing SkDataTable.
145      */
146     void append(const void* data, size_t size);
147 
148     /**
149      *  Helper version of append() passes strlen() + 1 for the size,
150      *  so the trailing-zero will be copied as well.
151      */
appendStr(const char str[])152     void appendStr(const char str[]) {
153         this->append(str, strlen(str) + 1);
154     }
155 
156     /**
157      *  Helper version of append() passes string.size() + 1 for the size,
158      *  so the trailing-zero will be copied as well.
159      */
appendString(const SkString & string)160     void appendString(const SkString& string) {
161         this->append(string.c_str(), string.size() + 1);
162     }
163 
164     /**
165      *  Return an SkDataTable from the accumulated entries that were added by
166      *  calls to append(). This call also clears any accumluated entries from
167      *  this builder, so its count() will be 0 after this call.
168      */
169     SkDataTable* detachDataTable();
170 
171 private:
172     SkTDArray<SkDataTable::Dir> fDir;
173     SkChunkAlloc*               fHeap;
174     size_t                      fMinChunkSize;
175 };
176 
177 #endif
178