| /* | |
| * Copyright 2013 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef SkDataTable_DEFINED | |
| #define SkDataTable_DEFINED | |
| #include "SkChunkAlloc.h" | |
| #include "SkData.h" | |
| #include "SkString.h" | |
| #include "SkTDArray.h" | |
| /** | |
| * Like SkData, SkDataTable holds an immutable data buffer. The data buffer is | |
| * organized into a table of entries, each with a length, so the entries are | |
| * not required to all be the same size. | |
| */ | |
| class SK_API SkDataTable : public SkRefCnt { | |
| public: | |
| SK_DECLARE_INST_COUNT(SkDataTable) | |
| /** | |
| * Returns true if the table is empty (i.e. has no entries). | |
| */ | |
| bool isEmpty() const { return 0 == fCount; } | |
| /** | |
| * Return the number of entries in the table. 0 for an empty table | |
| */ | |
| int count() const { return fCount; } | |
| /** | |
| * Return the size of the index'th entry in the table. The caller must | |
| * ensure that index is valid for this table. | |
| */ | |
| size_t atSize(int index) const; | |
| /** | |
| * Return a pointer to the data of the index'th entry in the table. | |
| * The caller must ensure that index is valid for this table. | |
| * | |
| * @param size If non-null, this returns the byte size of this entry. This | |
| * will be the same value that atSize(index) would return. | |
| */ | |
| const void* at(int index, size_t* size = NULL) const; | |
| template <typename T> | |
| const T* atT(int index, size_t* size = NULL) const { | |
| return reinterpret_cast<const T*>(this->at(index, size)); | |
| } | |
| /** | |
| * Returns the index'th entry as a c-string, and assumes that the trailing | |
| * null byte had been copied into the table as well. | |
| */ | |
| const char* atStr(int index) const { | |
| size_t size; | |
| const char* str = this->atT<const char>(index, &size); | |
| SkASSERT(strlen(str) + 1 == size); | |
| return str; | |
| } | |
| typedef void (*FreeProc)(void* context); | |
| static SkDataTable* NewEmpty(); | |
| /** | |
| * Return a new DataTable that contains a copy of the data stored in each | |
| * "array". | |
| * | |
| * @param ptrs array of points to each element to be copied into the table. | |
| * @param sizes array of byte-lengths for each entry in the corresponding | |
| * ptrs[] array. | |
| * @param count the number of array elements in ptrs[] and sizes[] to copy. | |
| */ | |
| static SkDataTable* NewCopyArrays(const void * const * ptrs, | |
| const size_t sizes[], int count); | |
| /** | |
| * Return a new table that contains a copy of the data in array. | |
| * | |
| * @param array contiguous array of data for all elements to be copied. | |
| * @param elemSize byte-length for a given element. | |
| * @param count the number of entries to be copied out of array. The number | |
| * of bytes that will be copied is count * elemSize. | |
| */ | |
| static SkDataTable* NewCopyArray(const void* array, size_t elemSize, | |
| int count); | |
| static SkDataTable* NewArrayProc(const void* array, size_t elemSize, | |
| int count, FreeProc proc, void* context); | |
| private: | |
| struct Dir { | |
| const void* fPtr; | |
| uintptr_t fSize; | |
| }; | |
| int fCount; | |
| size_t fElemSize; | |
| union { | |
| const Dir* fDir; | |
| const char* fElems; | |
| } fU; | |
| FreeProc fFreeProc; | |
| void* fFreeProcContext; | |
| SkDataTable(); | |
| SkDataTable(const void* array, size_t elemSize, int count, | |
| FreeProc, void* context); | |
| SkDataTable(const Dir*, int count, FreeProc, void* context); | |
| virtual ~SkDataTable(); | |
| friend class SkDataTableBuilder; // access to Dir | |
| typedef SkRefCnt INHERITED; | |
| }; | |
| /** | |
| * Helper class that allows for incrementally building up the data needed to | |
| * create a SkDataTable. | |
| */ | |
| class SK_API SkDataTableBuilder : SkNoncopyable { | |
| public: | |
| SkDataTableBuilder(size_t minChunkSize); | |
| ~SkDataTableBuilder(); | |
| int count() const { return fDir.count(); } | |
| size_t minChunkSize() const { return fMinChunkSize; } | |
| /** | |
| * Forget any previously appended entries, setting count() back to 0. | |
| */ | |
| void reset(size_t minChunkSize); | |
| void reset() { | |
| this->reset(fMinChunkSize); | |
| } | |
| /** | |
| * Copy size-bytes from data, and append it to the growing SkDataTable. | |
| */ | |
| void append(const void* data, size_t size); | |
| /** | |
| * Helper version of append() passes strlen() + 1 for the size, | |
| * so the trailing-zero will be copied as well. | |
| */ | |
| void appendStr(const char str[]) { | |
| this->append(str, strlen(str) + 1); | |
| } | |
| /** | |
| * Helper version of append() passes string.size() + 1 for the size, | |
| * so the trailing-zero will be copied as well. | |
| */ | |
| void appendString(const SkString& string) { | |
| this->append(string.c_str(), string.size() + 1); | |
| } | |
| /** | |
| * Return an SkDataTable from the accumulated entries that were added by | |
| * calls to append(). This call also clears any accumluated entries from | |
| * this builder, so its count() will be 0 after this call. | |
| */ | |
| SkDataTable* detachDataTable(); | |
| private: | |
| SkTDArray<SkDataTable::Dir> fDir; | |
| SkChunkAlloc* fHeap; | |
| size_t fMinChunkSize; | |
| }; | |
| #endif |