diff --git a/src/cs_util.cc b/src/cs_util.cc index c002e7f..69c1d71 100644 --- a/src/cs_util.cc +++ b/src/cs_util.cc @@ -193,11 +193,10 @@ inline cs_strref_state *get_ref_state(char const *ptr) { } char const *cs_strman::add(ostd::string_range str) { - /* if it already exists, nothing will happen */ - auto p = counts.try_emplace(str, nullptr); + auto it = counts.find(str); /* already present: just increment ref */ - if (!p.second) { - auto *st = p.first->second; + if (it != counts.end()) { + auto *st = it->second; /* having a null pointer is the same as non-existence */ if (st) { ++st->refcount; @@ -207,19 +206,20 @@ char const *cs_strman::add(ostd::string_range str) { /* not present: allocate brand new data */ auto ss = str.size(); auto mem = cstate->alloc(nullptr, 0, ss + sizeof(cs_strref_state) + 1); - /*if (!mem) { - cstate->panic(); - }*/ - /* write length and refcount, store it */ + if (!mem) { + throw cs_internal_error{"allocation failed"}; + } + /* write length and refcount */ auto *sst = static_cast(mem); sst->length = ss; sst->refcount = 1; - p.first->second = sst; /* write string data */ auto *strp = reinterpret_cast(sst + 1); memcpy(strp, str.data(), ss); /* terminated for best compatibility */ strp[ss] = '\0'; + /* store it */ + counts.emplace(ostd::string_range{strp, strp + ss}, sst); return strp; } @@ -239,14 +239,12 @@ void cs_strman::unref(char const *ptr) { auto it = counts.find(sr); if (it == counts.end()) { /* internal error: this should *never* happen */ - //cstate->panic(); + throw cs_internal_error{"no refcount"}; } + /* we're freeing the key */ + counts.erase(it); /* dealloc */ cstate->alloc(ss, ss->length + sizeof(cs_strref_state) + 1, 0); - /* set to null, which is okay - * we keep the value around, in case the string ever reappears - */ - it->second = nullptr; } } diff --git a/src/cs_val.cc b/src/cs_val.cc index bc6dd71..eb2cae1 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -20,7 +20,9 @@ template static inline void csv_cleanup(cs_value_type tv, T &stor) { switch (tv) { case cs_value_type::String: - delete[] csv_get(stor); + case cs_value_type::Macro: + case cs_value_type::Cstring: + reinterpret_cast(&stor)->~cs_strref(); break; case cs_value_type::Code: { uint32_t *bcode = csv_get(stor); @@ -68,7 +70,11 @@ cs_value &cs_value::operator=(cs_value const &v) { case cs_value_type::String: case cs_value_type::Cstring: case cs_value_type::Macro: - set_str(cs_string{csv_get(v.p_stor), v.p_len}); + p_type = cs_value_type::String; + p_len = v.p_len; + new (&p_stor) cs_strref{ + *reinterpret_cast(&v.p_stor) + }; break; case cs_value_type::Code: set_code(cs_copy_code(v.get_code())); @@ -106,11 +112,11 @@ void cs_value::set_float(cs_float val) { void cs_value::set_str(cs_string val) { csv_cleanup(p_type, p_stor); + new (&p_stor) cs_strref{ + *state(), ostd::string_range{&val[0], &val[val.size()] + }}; p_type = cs_value_type::String; p_len = val.size(); - char *buf = new char[p_len + 1]; - memcpy(buf, val.data(), p_len + 1); - csv_get(p_stor) = buf; } void cs_value::set_null() { @@ -126,9 +132,9 @@ void cs_value::set_code(cs_bcode *val) { void cs_value::set_cstr(ostd::string_range val) { csv_cleanup(p_type, p_stor); + new (&p_stor) cs_strref{*state(), val}; p_type = cs_value_type::Cstring; p_len = val.size(); - csv_get(p_stor) = val.data(); } void cs_value::set_ident(cs_ident *val) { @@ -139,9 +145,9 @@ void cs_value::set_ident(cs_ident *val) { void cs_value::set_macro(ostd::string_range val) { csv_cleanup(p_type, p_stor); + new (&p_stor) cs_strref{*state(), val}; p_type = cs_value_type::Macro; p_len = val.size(); - csv_get(p_stor) = val.data(); } void cs_value::force_null() { @@ -316,9 +322,7 @@ void cs_value::get_val(cs_value &r) const { case cs_value_type::String: case cs_value_type::Macro: case cs_value_type::Cstring: - r.set_str( - cs_string{csv_get(p_stor), p_len} - ); + r = *this; break; case cs_value_type::Int: r.set_int(csv_get(p_stor));