blob: d15e65b4739cc0708af3e018189717d0345056aa [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkDataTable.h"
#include "include/core/SkRefCnt.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkOnce.h"
#include <cstring>
static void malloc_freeproc(void* context) {
sk_free(context);
}
// Makes empty table
SkDataTable::SkDataTable() {
fCount = 0;
fElemSize = 0; // 0 signals that we use fDir instead of fElems
fU.fDir = nullptr;
fFreeProc = nullptr;
fFreeProcContext = nullptr;
}
SkDataTable::SkDataTable(const void* array, size_t elemSize, int count,
FreeProc proc, void* context) {
SkASSERT(count > 0);
fCount = count;
fElemSize = elemSize; // non-zero signals we use fElems instead of fDir
fU.fElems = (const char*)array;
fFreeProc = proc;
fFreeProcContext = context;
}
SkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) {
SkASSERT(count > 0);
fCount = count;
fElemSize = 0; // 0 signals that we use fDir instead of fElems
fU.fDir = dir;
fFreeProc = proc;
fFreeProcContext = ctx;
}
SkDataTable::~SkDataTable() {
if (fFreeProc) {
fFreeProc(fFreeProcContext);
}
}
size_t SkDataTable::atSize(int index) const {
SkASSERT((unsigned)index < (unsigned)fCount);
if (fElemSize) {
return fElemSize;
} else {
return fU.fDir[index].fSize;
}
}
const void* SkDataTable::at(int index, size_t* size) const {
SkASSERT((unsigned)index < (unsigned)fCount);
if (fElemSize) {
if (size) {
*size = fElemSize;
}
return fU.fElems + index * fElemSize;
} else {
if (size) {
*size = fU.fDir[index].fSize;
}
return fU.fDir[index].fPtr;
}
}
///////////////////////////////////////////////////////////////////////////////
sk_sp<SkDataTable> SkDataTable::MakeEmpty() {
static SkDataTable* singleton;
static SkOnce once;
once([]{ singleton = new SkDataTable(); });
return sk_ref_sp(singleton);
}
sk_sp<SkDataTable> SkDataTable::MakeCopyArrays(const void * const * ptrs,
const size_t sizes[], int count) {
if (count <= 0) {
return SkDataTable::MakeEmpty();
}
size_t dataSize = 0;
for (int i = 0; i < count; ++i) {
dataSize += sizes[i];
}
size_t bufferSize = count * sizeof(Dir) + dataSize;
void* buffer = sk_malloc_throw(bufferSize);
Dir* dir = (Dir*)buffer;
char* elem = (char*)(dir + count);
for (int i = 0; i < count; ++i) {
dir[i].fPtr = elem;
dir[i].fSize = sizes[i];
memcpy(elem, ptrs[i], sizes[i]);
elem += sizes[i];
}
return sk_sp<SkDataTable>(new SkDataTable(dir, count, malloc_freeproc, buffer));
}
sk_sp<SkDataTable> SkDataTable::MakeCopyArray(const void* array, size_t elemSize, int count) {
if (count <= 0) {
return SkDataTable::MakeEmpty();
}
size_t bufferSize = elemSize * count;
void* buffer = sk_malloc_throw(bufferSize);
memcpy(buffer, array, bufferSize);
return sk_sp<SkDataTable>(new SkDataTable(buffer, elemSize, count, malloc_freeproc, buffer));
}
sk_sp<SkDataTable> SkDataTable::MakeArrayProc(const void* array, size_t elemSize, int count,
FreeProc proc, void* ctx) {
if (count <= 0) {
return SkDataTable::MakeEmpty();
}
return sk_sp<SkDataTable>(new SkDataTable(array, elemSize, count, proc, ctx));
}