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