| #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 |