2013-04-19 20:16:01 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-10-15 20:39:57 +00:00
|
|
|
class SK_API SkDataTable : public SkRefCnt {
|
2013-04-19 20:16:01 +00:00
|
|
|
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.
|
|
|
|
*/
|
2013-04-21 01:37:46 +00:00
|
|
|
size_t atSize(int index) const;
|
2013-04-19 20:16:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-04-21 01:37:46 +00:00
|
|
|
const void* at(int index, size_t* size = NULL) const;
|
2013-04-19 20:16:01 +00:00
|
|
|
|
|
|
|
template <typename T>
|
2013-04-21 01:37:46 +00:00
|
|
|
const T* atT(int index, size_t* size = NULL) const {
|
|
|
|
return reinterpret_cast<const T*>(this->at(index, size));
|
2013-04-19 20:16:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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;
|
2013-04-21 01:37:46 +00:00
|
|
|
const char* str = this->atT<const char>(index, &size);
|
2013-04-19 20:16:01 +00:00
|
|
|
SkASSERT(strlen(str) + 1 == size);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2013-04-21 01:37:46 +00:00
|
|
|
typedef void (*FreeProc)(void* context);
|
|
|
|
|
2013-04-19 20:22:39 +00:00
|
|
|
static SkDataTable* NewEmpty();
|
|
|
|
|
2013-04-19 20:16:01 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-04-21 01:37:46 +00:00
|
|
|
static SkDataTable* NewCopyArrays(const void * const * ptrs,
|
|
|
|
const size_t sizes[], int count);
|
2013-04-19 20:16:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
2013-04-20 07:01:07 +00:00
|
|
|
|
2013-04-21 01:37:46 +00:00
|
|
|
static SkDataTable* NewArrayProc(const void* array, size_t elemSize,
|
|
|
|
int count, FreeProc proc, void* context);
|
|
|
|
|
2013-04-19 20:16:01 +00:00
|
|
|
private:
|
2013-04-21 01:37:46 +00:00
|
|
|
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);
|
2013-04-19 20:16:01 +00:00
|
|
|
virtual ~SkDataTable();
|
|
|
|
|
2013-04-21 01:37:46 +00:00
|
|
|
friend class SkDataTableBuilder; // access to Dir
|
2013-04-19 20:16:01 +00:00
|
|
|
|
2013-10-15 20:39:57 +00:00
|
|
|
typedef SkRefCnt INHERITED;
|
2013-04-19 20:16:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper class that allows for incrementally building up the data needed to
|
|
|
|
* create a SkDataTable.
|
|
|
|
*/
|
2013-04-21 01:37:46 +00:00
|
|
|
class SK_API SkDataTableBuilder : SkNoncopyable {
|
2013-04-19 20:16:01 +00:00
|
|
|
public:
|
|
|
|
SkDataTableBuilder(size_t minChunkSize);
|
|
|
|
~SkDataTableBuilder();
|
|
|
|
|
2013-04-21 01:37:46 +00:00
|
|
|
int count() const { return fDir.count(); }
|
|
|
|
size_t minChunkSize() const { return fMinChunkSize; }
|
2013-04-19 20:16:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Forget any previously appended entries, setting count() back to 0.
|
|
|
|
*/
|
2013-04-21 01:37:46 +00:00
|
|
|
void reset(size_t minChunkSize);
|
|
|
|
void reset() {
|
|
|
|
this->reset(fMinChunkSize);
|
|
|
|
}
|
2013-04-19 20:16:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
2013-04-21 01:37:46 +00:00
|
|
|
* calls to append(). This call also clears any accumluated entries from
|
|
|
|
* this builder, so its count() will be 0 after this call.
|
2013-04-19 20:16:01 +00:00
|
|
|
*/
|
2013-04-21 01:37:46 +00:00
|
|
|
SkDataTable* detachDataTable();
|
2013-04-19 20:16:01 +00:00
|
|
|
|
|
|
|
private:
|
2013-04-21 01:37:46 +00:00
|
|
|
SkTDArray<SkDataTable::Dir> fDir;
|
|
|
|
SkChunkAlloc* fHeap;
|
|
|
|
size_t fMinChunkSize;
|
2013-04-19 20:16:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|