#include <xs/Array.h>
namespace xs {
Array Array::create (size_t size, SV** content, create_type_t type) {
Array ret = create();
ret.resize(size);
SV** dst = ret._svlist();
if (type == COPY) {
for (size_t i = 0; i < size; ++i) {
if (*content) {
SV* val = *dst++ = newSV(0);
sv_setsv_flags(val, *content++, SV_DO_COW_SVSETSV|SV_NOSTEAL);
} else {
++content;
++dst;
}
}
} else {
for (size_t i = 0; i < size; ++i) *dst++ = SvREFCNT_inc(*content++);
}
return ret;
}
Array::Array (const std::initializer_list<Scalar>& l, create_type_t type) {
SV** svs = (SV**)alloca(sizeof(SV*)*l.size());
const Scalar* from = l.begin();
for (size_t i = 0; i < l.size(); ++i) svs[i] = (*from++).get();
auto tmp = create(l.size(), svs, type);
*this = std::move(tmp);
}
void Array::store (size_t key, const Scalar& val) {
if (!sv) throw std::logic_error("store: empty object");
SvREFCNT_inc_simple_void(val.get());
if (key >= _cap()) av_extend((AV*)sv, key);
auto ptr = _svlist() + key;
auto old = *ptr;
*ptr = val.get();
if (_size() <= key) _size(key+1);
else SvREFCNT_dec(old);
}
void Array::push (const std::initializer_list<Scalar>& l) {
auto oldsize = size();
auto addsize = l.size();
resize(oldsize + addsize);
const Scalar* from = l.begin();
SV** dst = _svlist() + oldsize;
for (size_t i = 0; i < addsize; ++i) *dst++ = SvREFCNT_inc((from++)->get());
}
void Array::push (const List& l) {
auto oldsize = size();
auto addsize = l.size();
resize(oldsize + addsize);
SV** from = l._svlist();
SV** dst = _svlist() + oldsize;
for (size_t i = 0; i < addsize; ++i) *dst++ = SvREFCNT_inc(*from++);
}
void Array::push (const Scalar& v) {
auto oldsize = size();
resize(oldsize + 1);
_svlist()[oldsize] = SvREFCNT_inc(v.get());
}
void Array::unshift (const std::initializer_list<Scalar>& l) {
auto addsize = l.size();
av_unshift((AV*)sv, addsize);
const Scalar* from = l.begin();
SV** dst = _svlist();
for (size_t i = 0; i < addsize; ++i) *dst++ = SvREFCNT_inc((from++)->get());
}
void Array::unshift (const List& l) {
auto addsize = l.size();
av_unshift((AV*)sv, addsize);
SV** from = l._svlist();
SV** dst = _svlist();
for (size_t i = 0; i < addsize; ++i) *dst++ = SvREFCNT_inc(*from++);
}
void Array::unshift (const Scalar& v) {
av_unshift((AV*)sv, 1);
*(_svlist()) = SvREFCNT_inc(v.get());
}
U32 Array::push_on_stack (SV** sp, U32 max) const {
auto sz = size();
if (max && sz > max) sz = max;
EXTEND(sp, (I32)sz);
SV** list = _svlist();
for (decltype(sz) i = 0; i < sz; ++i) *++sp = sv_2mortal(SvREFCNT_inc(list[i]));
return sz;
}
}