intern all strings in cs_value
parent
c004db42c6
commit
8def7ce85c
|
@ -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<cs_strref_state *>(mem);
|
||||
sst->length = ss;
|
||||
sst->refcount = 1;
|
||||
p.first->second = sst;
|
||||
/* write string data */
|
||||
auto *strp = reinterpret_cast<char *>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@ template<typename T>
|
|||
static inline void csv_cleanup(cs_value_type tv, T &stor) {
|
||||
switch (tv) {
|
||||
case cs_value_type::String:
|
||||
delete[] csv_get<char *>(stor);
|
||||
case cs_value_type::Macro:
|
||||
case cs_value_type::Cstring:
|
||||
reinterpret_cast<cs_strref *>(&stor)->~cs_strref();
|
||||
break;
|
||||
case cs_value_type::Code: {
|
||||
uint32_t *bcode = csv_get<uint32_t *>(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<char const *>(v.p_stor), v.p_len});
|
||||
p_type = cs_value_type::String;
|
||||
p_len = v.p_len;
|
||||
new (&p_stor) cs_strref{
|
||||
*reinterpret_cast<cs_strref const *>(&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<char *>(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<char const *>(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<char const *>(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<char const *>(p_stor), p_len}
|
||||
);
|
||||
r = *this;
|
||||
break;
|
||||
case cs_value_type::Int:
|
||||
r.set_int(csv_get<cs_int>(p_stor));
|
||||
|
|
Loading…
Reference in New Issue