|
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: |
|
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 */ |
|
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 */ |
|
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 |
|
132 int count() const { return fDir.count(); } |
|
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); |
|
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 */ |
|
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 */ |
|
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 |