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