#include "daScript/misc/platform.h"
#include "daScript/simulate/runtime_array.h"
namespace das
{
void array_clear ( Context & context, Array & arr ) {
if ( arr.isLocked() ) context.throw_error("can't clear locked array");
arr.size = 0;
}
void array_lock ( Context & context, Array & arr ) {
if ( arr.shared || arr.hopeless ) return;
arr.lock ++;
if ( arr.lock==0 ) context.throw_error("array lock overflow");
}
void array_unlock ( Context & context, Array & arr ) {
if ( arr.shared || arr.hopeless ) return;
if ( arr.lock==0 ) context.throw_error("array lock underflow");
arr.lock --;
}
void array_reserve(Context & context, Array & arr, uint32_t newCapacity, uint32_t stride) {
if ( arr.isLocked() ) context.throw_error("can't change capacity of a locked array");
if ( arr.capacity >= newCapacity ) return;
auto newData = (char *)context.heap->reallocate(arr.data, arr.capacity*stride, newCapacity*stride);
if ( !newData ) context.throw_error("out of linear allocator memory");
context.heap->mark_comment(newData, "array");
if ( newData != arr.data ) {
// memcpy(newData, arr.data, arr.capacity);
arr.data = newData;
}
arr.capacity = newCapacity;
}
void array_resize ( Context & context, Array & arr, uint32_t newSize, uint32_t stride, bool zero ) {
if ( arr.isLocked() ) context.throw_error("can't resize locked array");
if ( newSize > arr.capacity ) {
uint32_t newCapacity = 1 arr.size ) {
memset ( arr.data + arr.size*stride, 0, (newSize-arr.size)*stride );
}
arr.size = newSize;
}
// GoodArrayIterator
bool GoodArrayIterator::first ( Context & context, char * _value ) {
char ** value = (char **) _value;
array_lock(context, *array);
data = array->data;
*value = data;
array_end = data + array->size * stride;
return (bool) array->size;
}
bool GoodArrayIterator::next ( Context &, char * _value ) {
char ** value = (char **) _value;
data += stride;
*value = data;
return data != array_end;
}
void GoodArrayIterator::close ( Context & context, char * _value ) {
if ( _value ) {
char ** value = (char **) _value;
*value = nullptr;
}
array_unlock(context, *array);
context.heap->free((char *)this, sizeof(GoodArrayIterator));
}
vec4f SimNode_GoodArrayIterator::eval ( Context & context ) {
DAS_PROFILE_NODE
vec4f ll = source->eval(context);
Array * arr = cast::to(ll);
char * iter = context.heap->allocate(sizeof(GoodArrayIterator));
context.heap->mark_comment(iter,"array iterator");
context.heap->mark_location(iter,&debugInfo);
new (iter) GoodArrayIterator(arr, stride);
return cast::from(iter);
}
// FixedArrayIterator
bool FixedArrayIterator::first ( Context &, char * _value ) {
char ** value = (char **) _value;
*value = data;
fixed_array_end = data + size*stride;
return (bool) size;
}
bool FixedArrayIterator::next ( Context & , char * _value ) {
char ** value = (char **) _value;
data += stride;
*value = data;
return data != fixed_array_end;
}
void FixedArrayIterator::close ( Context & context, char * _value ) {
if ( _value ) {
char ** value = (char **) _value;
*value = nullptr;
}
context.heap->free((char *)this, sizeof(FixedArrayIterator));
}
vec4f SimNode_FixedArrayIterator::eval ( Context & context ) {
DAS_PROFILE_NODE
vec4f ll = source->eval(context);
char * data = cast::to(ll);
char * iter = context.heap->allocate(sizeof(FixedArrayIterator));
context.heap->mark_comment(iter,"fixed array iterator");
context.heap->mark_location(iter,&debugInfo);
new (iter) FixedArrayIterator(data, size, stride);
return cast::from(iter);
}
// delete
vec4f SimNode_DeleteArray::eval ( Context & context ) {
DAS_PROFILE_NODE
auto pArray = (Array *) subexpr->evalPtr(context);
pArray = pArray + total - 1;
for ( uint32_t i=0; i!=total; ++i, pArray-- ) {
if ( pArray->data ) {
if ( !pArray->isLocked() ) {
uint32_t oldSize = pArray->capacity*stride;
context.heap->free(pArray->data, oldSize);
} else {
context.throw_error("deleting locked array");
return v_zero();
}
}
memset ( pArray, 0, sizeof(Array) );
}
return v_zero();
}
}