#include <xs/Hash.h>
namespace xs {
Hash::Hash (const std::initializer_list<std::pair<panda::string_view, Scalar>>& l) {
sv = (SV*)newHV();
reserve(l.size());
auto end = l.end();
for (auto ptr = l.begin(); ptr != end; ++ptr) store(ptr->first, ptr->second);
}
void Hash::store (const panda::string_view& key, const Scalar& v, U32 hash) {
if (!sv) throw std::logic_error("store: empty object");
SV* val = v;
if (val) SvREFCNT_inc_simple_void_NN(val);
else val = newSV(0);
SV** ret = hv_store((HV*)sv, key.data(), key.length(), val, hash);
if (!ret) SvREFCNT_dec_NN(val);
}
U32 Hash::push_on_stack (SV** sp) const {
HV* hv = (HV*)sv;
auto sz = HvUSEDKEYS(hv) * 2;
if (!sz) return 0;
EXTEND(sp, (I32)sz);
STRLEN hvmax = HvMAX(hv);
HE** hvarr = HvARRAY(hv);
for (STRLEN bucket_num = 0; bucket_num <= hvmax; ++bucket_num)
for (const HE* he = hvarr[bucket_num]; he; he = HeNEXT(he)) {
*++sp = sv_2mortal(newSVpvn(HeKEY(he), HeKLEN(he)));
*++sp = sv_2mortal(SvREFCNT_inc_NN(HeVAL(he)));
}
return sz;
}
}