blob: a592cfb624f46c02c617330975469b97dfde9226 [file] [log] [blame]
#ifndef TH_GENERIC_FILE
#define TH_GENERIC_FILE "generic/THStorage.c"
#else
real* THStorage_(data)(const THStorage *self)
{
return self->data;
}
ptrdiff_t THStorage_(size)(const THStorage *self)
{
return self->size;
}
size_t THStorage_(elementSize)()
{
return sizeof(real);
}
THStorage* THStorage_(new)(void)
{
return THStorage_(newWithSize)(0);
}
THStorage* THStorage_(newWithSize)(ptrdiff_t size)
{
return THStorage_(newWithAllocator)(size, &THDefaultAllocator, NULL);
}
THStorage* THStorage_(newWithAllocator)(ptrdiff_t size,
THAllocator *allocator,
void *allocatorContext)
{
THStorage *storage = THAlloc(sizeof(THStorage));
storage->data = allocator->malloc(allocatorContext, sizeof(real)*size);
storage->size = size;
storage->refcount = 1;
storage->flag = TH_STORAGE_REFCOUNTED | TH_STORAGE_RESIZABLE | TH_STORAGE_FREEMEM;
storage->allocator = allocator;
storage->allocatorContext = allocatorContext;
return storage;
}
THStorage* THStorage_(newWithMapping)(const char *filename, ptrdiff_t size, int flags)
{
THMapAllocatorContext *ctx = THMapAllocatorContext_new(filename, flags);
THStorage *storage = THStorage_(newWithAllocator)(size,
&THMapAllocator,
ctx);
if(size <= 0)
storage->size = THMapAllocatorContext_size(ctx)/sizeof(real);
THStorage_(clearFlag)(storage, TH_STORAGE_RESIZABLE);
return storage;
}
THStorage* THStorage_(newWithSize1)(real data0)
{
THStorage *self = THStorage_(newWithSize)(1);
self->data[0] = data0;
return self;
}
THStorage* THStorage_(newWithSize2)(real data0, real data1)
{
THStorage *self = THStorage_(newWithSize)(2);
self->data[0] = data0;
self->data[1] = data1;
return self;
}
THStorage* THStorage_(newWithSize3)(real data0, real data1, real data2)
{
THStorage *self = THStorage_(newWithSize)(3);
self->data[0] = data0;
self->data[1] = data1;
self->data[2] = data2;
return self;
}
THStorage* THStorage_(newWithSize4)(real data0, real data1, real data2, real data3)
{
THStorage *self = THStorage_(newWithSize)(4);
self->data[0] = data0;
self->data[1] = data1;
self->data[2] = data2;
self->data[3] = data3;
return self;
}
void THStorage_(setFlag)(THStorage *storage, const char flag)
{
storage->flag |= flag;
}
void THStorage_(clearFlag)(THStorage *storage, const char flag)
{
storage->flag &= ~flag;
}
void THStorage_(retain)(THStorage *storage)
{
if(storage && (storage->flag & TH_STORAGE_REFCOUNTED))
THAtomicIncrementRef(&storage->refcount);
}
void THStorage_(free)(THStorage *storage)
{
if(!storage)
return;
if((storage->flag & TH_STORAGE_REFCOUNTED) && (THAtomicGet(&storage->refcount) > 0))
{
if(THAtomicDecrementRef(&storage->refcount))
{
if(storage->flag & TH_STORAGE_FREEMEM) {
storage->allocator->free(storage->allocatorContext, storage->data);
}
if(storage->flag & TH_STORAGE_VIEW) {
THStorage_(free)(storage->view);
}
THFree(storage);
}
}
}
THStorage* THStorage_(newWithData)(real *data, ptrdiff_t size)
{
return THStorage_(newWithDataAndAllocator)(data, size,
&THDefaultAllocator, NULL);
}
THStorage* THStorage_(newWithDataAndAllocator)(real* data, ptrdiff_t size,
THAllocator* allocator,
void* allocatorContext) {
THStorage *storage = THAlloc(sizeof(THStorage));
storage->data = data;
storage->size = size;
storage->refcount = 1;
storage->flag = TH_STORAGE_REFCOUNTED | TH_STORAGE_RESIZABLE | TH_STORAGE_FREEMEM;
storage->allocator = allocator;
storage->allocatorContext = allocatorContext;
return storage;
}
void THStorage_(resize)(THStorage *storage, ptrdiff_t size)
{
if(storage->flag & TH_STORAGE_RESIZABLE)
{
if(storage->allocator->realloc == NULL) {
/* case when the allocator does not have a realloc defined */
real *old_data = storage->data;
ptrdiff_t old_size = storage->size;
if (size == 0) {
storage->data = NULL;
} else {
storage->data = storage->allocator->malloc(
storage->allocatorContext,
sizeof(real)*size);
}
storage->size = size;
if (old_data != NULL) {
ptrdiff_t copy_size = old_size;
if (storage->size < copy_size) {
copy_size = storage->size;
}
if (copy_size > 0) {
memcpy(storage->data, old_data, sizeof(real)*copy_size);
}
storage->allocator->free(storage->allocatorContext, old_data);
}
} else {
storage->data = storage->allocator->realloc(
storage->allocatorContext,
storage->data,
sizeof(real)*size);
storage->size = size;
}
} else {
THError("Trying to resize storage that is not resizable");
}
}
void THStorage_(fill)(THStorage *storage, real value)
{
ptrdiff_t i;
for(i = 0; i < storage->size; i++)
storage->data[i] = value;
}
void THStorage_(set)(THStorage *self, ptrdiff_t idx, real value)
{
THArgCheck((idx >= 0) && (idx < self->size), 2, "out of bounds");
self->data[idx] = value;
}
real THStorage_(get)(const THStorage *self, ptrdiff_t idx)
{
THArgCheck((idx >= 0) && (idx < self->size), 2, "out of bounds");
return self->data[idx];
}
void THStorage_(swap)(THStorage *storage1, THStorage *storage2)
{
#define SWAP(val) { val = storage1->val; storage1->val = storage2->val; storage2->val = val; }
real *data;
ptrdiff_t size;
char flag;
THAllocator *allocator;
void *allocatorContext;
struct THStorage *view;
SWAP(data);
SWAP(size);
SWAP(flag);
// don't swap refcount!
SWAP(allocator);
SWAP(allocatorContext);
SWAP(view);
#undef SWAP
}
#endif