5 #include "RNBO_Platform.h"
8 #include "RNBO_UniquePtr.h"
13 #ifndef RNBO_FIXEDLISTSIZE
14 #define RNBO_FIXEDLISTSIZE 0
19 template<
class T,
size_t N>
class array;
21 static const size_t listChunkSize = 8;
35 template<
typename T,
size_t FIXED = RNBO_FIXEDLISTSIZE>
class listbase {
60 :
length(sizeof...(args), *this)
65 T listValues[
sizeof...(args)] = {
static_cast<T
>(args)...};
68 for (; i <
length && i < FIXED; i++) {
69 _stackValues[i] = listValues[i];
78 template<
typename TA,
size_t NA>
90 _stackValues[i] = l[i];
117 _stackValues[i] = l[i];
163 Platform::errorOrDefault(RuntimeError::OutOfRange,
"list index out of range",
false );
164 _dummy =
static_cast<T
>(0);
168 if (i < FIXED)
return _stackValues[i];
169 else return _values[i - FIXED];
186 return Platform::errorOrDefault(RuntimeError::OutOfRange,
"list index out of range", (T)0);
189 if (i < FIXED)
return _stackValues[i];
190 else return _values[i - FIXED];
200 const listbase* operator->()
const {
215 _stackValues[i] = l[i];
232 _stackValues[i] = l[i];
254 allocate(
length + 1,
true);
255 if (FIXED &&
length < FIXED) _stackValues[
length] = item;
273 size_t lastIndex =
length - 1;
274 if (FIXED && lastIndex < FIXED) tmp = _stackValues[lastIndex];
275 else tmp =
_values[lastIndex - FIXED];
291 return Platform::errorOrDefault(RuntimeError::OutOfRange,
"cannot shift out of empty list", 0);
295 tmp = _stackValues[0];
296 Platform::memmove(_stackValues, _stackValues + 1, (FIXED - 1) *
sizeof(T));
298 _stackValues[FIXED - 1] =
_values[0];
343 for (
size_t i = 0; i < item.
length; i++) {
346 tmp[tmp.
length - 1] = item[i];
368 if (end == 0) end =
length;
371 for (
size_t i = start; i < end; i++) {
389 template<
typename... Ts>
void unshift(Ts ... args) {
405 if (start < 0) start +=
length;
406 if (start < 0) start = 0;
407 size_t iStart = (size_t)start;
413 if (iStart + deleteCount >
length) deleteCount =
length - iStart;
415 const size_t addLength =
sizeof...(args);
416 const long diff = (long)(addLength - deleteCount);
419 deletedItems.allocate(deleteCount,
false);
420 for (
size_t i = 0; i < deleteCount; i++) {
422 T val = (*this)[iStart + i];
423 deletedItems.
push(val);
430 long newLength = (long)(
length) + diff;
431 if (newLength <= 0) {
436 allocate(
static_cast<size_t>(newLength),
true);
439 RNBO_ASSERT(start - diff >= 0)
440 for (
long i = (
long)start - diff; i < (long)
length; i++) {
441 RNBO_ASSERT(i + diff >= 0)
443 (*this)[(size_t)(i + diff)] = (*this)[(size_t)i];
449 }
else if (diff > 0) {
450 for (
long i = (
long)(
length - 1); i >= (long)start; i--) {
451 RNBO_ASSERT(i + diff >= 0)
453 (*this)[(size_t)(i + diff)] = (*this)[(size_t)i];
462 T addValues[(
sizeof...(args)) + 1] = {
static_cast<T
>(args)...};
463 RNBO_ASSERT(start >= 0)
464 for (
size_t i = 0; i < addLength; i++) {
466 (*this)[i + (size_t)start] = addValues[i];
469 _values[i + (size_t)start] = addValues[i];
473 length =
static_cast<size_t>(newLength);
488 int ilen =
static_cast<int>(this->
length);
492 start = ilen + start;
504 if (start >= ilen || ilen == 0) {
512 tmp.allocate(
static_cast<size_t>(end - start),
false);
513 for (
int i = start; i < end; i++) {
516 tmp[tmp.
length - 1] = (*this)[i];
536 fromIndex = int(
length) + fromIndex;
537 if (fromIndex < 0) fromIndex = 0;
540 for (
size_t i =
size_t(fromIndex); i <
length; i++) {
542 if ((*
this)[i] == value)
return true;
545 if (
_values[i] == value)
return true;
561 int indexOf(T value,
int fromIndex = 0)
const {
563 fromIndex = int(
length) + fromIndex;
564 if (fromIndex < 0) fromIndex = 0;
567 for (
size_t i =
size_t(fromIndex); i <
length; i++) {
569 if ((*
this)[i] == value)
return (
int)i;
572 if (
_values[i] == value)
return (
int)i;
585 size_t len2 =
length >> 1;
587 for (
size_t i = 0; i < len2; ++i) {
590 size_t target =
length - i - 1;
591 (*this)[i] = (*this)[target];
592 (*this)[target] = tmp;
597 size_t target =
length - i - 1;
612 allocate(size,
true);
627 operator size_t()
const {
633 if (_length < 0) _length = 0;
634 _owner->checkLength();
640 _owner->checkLength();
645 _length = _length + 1;
646 _owner->checkLength();
650 _length = _length - 1;
651 if (_length < 0) _length = 0;
652 _owner->checkLength();
655 void operator++(
int) {
656 _length = _length + 1;
657 _owner->checkLength();
660 void operator--(
int) {
661 _length = _length - 1;
662 if (_length < 0) _length = 0;
663 _owner->checkLength();
688 void allocate(
size_t size,
bool keepValues)
693 auto sizeToAllocate = size - FIXED;
694 auto lengthToAllocate = listChunkSize + (size_t(sizeToAllocate/listChunkSize)) * listChunkSize;
695 _values = (T*) Platform::calloc(lengthToAllocate,
sizeof(T));
698 if (keepValues && old_values) {
699 Platform::memcpy(
_values, old_values, (
length - FIXED) *
sizeof(T));
703 Platform::free(old_values);
712 T _stackValues[FIXED + 1];
726 using list = listbase<number>;
727 using indexlist = listbase<Index>;
728 using intlist = listbase<int>;
731 static list listWithSize(
size_t n) { list l; l.
length = n;
return l; }
733 static list intlistWithSize(
size_t n) { intlist l; l.
length = n;
return l; }
735 static list indexlistWithSize(
size_t n) { indexlist l; l.
length = n;
return l; }
758 operator number()
const {
return _val.
length > 0 ? _val[0] : 0; }
759 operator list()
const {
return _val; }
761 number operator[](
size_t i)
const {
769 const list& operator->()
const {
780 using UniqueListPtr = std::unique_ptr<listbase<number>>;
785 #endif // #ifndef _RNBO_LIST_H_