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 {
46 allocate(0,
length,
false);
60 :
length(sizeof...(args), *this)
64 allocate(0,
length,
false);
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>
86 allocate(0,
length,
false);
90 _stackValues[i] = l[i];
113 allocate(0,
length,
false);
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 {
210 size_t oldLength =
length;
212 allocate(oldLength,
length,
false);
216 _stackValues[i] = l[i];
228 size_t oldLength =
length;
230 allocate(oldLength,
length,
false);
234 _stackValues[i] = l[i];
257 if (FIXED &&
length < FIXED) _stackValues[
length] = item;
275 size_t lastIndex =
length - 1;
276 if (FIXED && lastIndex < FIXED) tmp = _stackValues[lastIndex];
277 else tmp =
_values[lastIndex - FIXED];
293 return Platform::errorOrDefault(RuntimeError::OutOfRange,
"cannot shift out of empty list", 0);
297 tmp = _stackValues[0];
298 Platform::memmove(_stackValues, _stackValues + 1, (FIXED - 1) *
sizeof(T));
300 _stackValues[FIXED - 1] =
_values[0];
345 for (
size_t i = 0; i < item.
length; i++) {
348 tmp[tmp.
length - 1] = item[i];
370 if (end == 0) end =
length;
371 allocate(
length, end,
true);
373 for (
size_t i = start; i < end; i++) {
391 template<
typename... Ts>
void unshift(Ts ... args) {
407 if (start < 0) start +=
length;
408 if (start < 0) start = 0;
409 size_t iStart = (size_t)start;
415 if (iStart + deleteCount >
length) deleteCount =
length - iStart;
417 const size_t addLength =
sizeof...(args);
418 const long diff = (long)(addLength - deleteCount);
421 deletedItems.allocate(0, deleteCount,
false);
422 for (
size_t i = 0; i < deleteCount; i++) {
424 T val = (*this)[iStart + i];
425 deletedItems.
push(val);
432 long newLength = (long)(
length) + diff;
433 if (newLength <= 0) {
438 allocate(
length,
static_cast<size_t>(newLength),
true);
441 RNBO_ASSERT(start - diff >= 0)
442 for (
long i = (
long)start - diff; i < (long)
length; i++) {
443 RNBO_ASSERT(i + diff >= 0)
445 (*this)[(size_t)(i + diff)] = (*this)[(size_t)i];
451 }
else if (diff > 0) {
452 for (
long i = (
long)(
length - 1); i >= (long)start; i--) {
453 RNBO_ASSERT(i + diff >= 0)
455 (*this)[(size_t)(i + diff)] = (*this)[(size_t)i];
464 T addValues[(
sizeof...(args)) + 1] = {
static_cast<T
>(args)...};
465 RNBO_ASSERT(start >= 0)
466 for (
size_t i = 0; i < addLength; i++) {
468 (*this)[i + (size_t)start] = addValues[i];
471 _values[i + (size_t)start] = addValues[i];
475 length =
static_cast<size_t>(newLength);
490 int ilen =
static_cast<int>(this->
length);
494 start = ilen + start;
506 if (start >= ilen || ilen == 0) {
514 tmp.allocate(0,
static_cast<size_t>(end - start),
false);
515 for (
int i = start; i < end; i++) {
518 tmp[tmp.
length - 1] = (*this)[i];
538 fromIndex = int(
length) + fromIndex;
539 if (fromIndex < 0) fromIndex = 0;
542 for (
size_t i =
size_t(fromIndex); i <
length; i++) {
544 if ((*
this)[i] == value)
return true;
547 if (
_values[i] == value)
return true;
563 int indexOf(T value,
int fromIndex = 0)
const {
565 fromIndex = int(
length) + fromIndex;
566 if (fromIndex < 0) fromIndex = 0;
569 for (
size_t i =
size_t(fromIndex); i <
length; i++) {
571 if ((*
this)[i] == value)
return (
int)i;
574 if (
_values[i] == value)
return (
int)i;
587 size_t len2 =
length >> 1;
589 for (
size_t i = 0; i < len2; ++i) {
592 size_t target =
length - i - 1;
593 (*this)[i] = (*this)[target];
594 (*this)[target] = tmp;
599 size_t target =
length - i - 1;
614 allocate(
length, size,
true);
629 operator size_t()
const {
634 size_t oldLength = _length;
636 if (_length < 0) _length = 0;
637 _owner->checkLength(oldLength);
642 size_t oldLength = _length;
644 _owner->checkLength(oldLength);
649 size_t oldLength = _length;
650 _length = _length + 1;
651 _owner->checkLength(oldLength);
655 size_t oldLength = _length;
656 _length = _length - 1;
657 if (_length < 0) _length = 0;
658 _owner->checkLength(oldLength);
661 void operator++(
int) {
662 size_t oldLength = _length;
663 _length = _length + 1;
664 _owner->checkLength(oldLength);
667 void operator--(
int) {
668 size_t oldLength = _length;
669 _length = _length - 1;
670 if (_length < 0) _length = 0;
671 _owner->checkLength(oldLength);
692 void checkLength(
size_t oldLength) {
693 allocate(oldLength,
length,
true);
696 void allocate(
size_t oldLength,
size_t newLength,
bool keepValues)
701 auto sizeToAllocate = newLength - FIXED;
702 auto lengthToAllocate = listChunkSize + (size_t(sizeToAllocate/listChunkSize)) * listChunkSize;
703 _values = (T*) Platform::calloc(lengthToAllocate,
sizeof(T));
706 if (keepValues && old_values) {
707 Platform::memcpy(
_values, old_values, (oldLength - FIXED) *
sizeof(T));
711 Platform::free(old_values);
720 T _stackValues[FIXED + 1];
734 using list = listbase<number>;
735 using indexlist = listbase<Index>;
736 using intlist = listbase<int>;
739 static list listWithSize(
size_t n) { list l; l.
length = n;
return l; }
741 static list intlistWithSize(
size_t n) { intlist l; l.
length = n;
return l; }
743 static list indexlistWithSize(
size_t n) { indexlist l; l.
length = n;
return l; }
766 operator number()
const {
return _val.
length > 0 ? _val[0] : 0; }
767 operator list()
const {
return _val; }
769 number operator[](
size_t i)
const {
777 const list& operator->()
const {
788 using UniqueListPtr = std::unique_ptr<listbase<number>>;
793 #endif // #ifndef _RNBO_LIST_H_