only store trivial types in any_value (manage strrefs manually)

master
Daniel Kolesa 2021-04-11 03:54:06 +02:00
parent d358dd83e7
commit 3ed7b59d0b
4 changed files with 48 additions and 37 deletions

View File

@ -60,9 +60,7 @@ struct LIBCUBESCRIPT_EXPORT string_ref {
return std::string_view{*this}.length();
}
char const *data() const {
return std::string_view{*this}.data();
}
char const *data() const;
std::string_view view() const {
return std::string_view{*this};
@ -75,8 +73,7 @@ struct LIBCUBESCRIPT_EXPORT string_ref {
bool operator==(string_ref const &s) const;
private:
/* for internal use only */
string_ref(char const *p, internal_state *cs);
string_ref(char const *p);
char const *p_str;
};
@ -124,12 +121,7 @@ struct LIBCUBESCRIPT_EXPORT any_value {
ident &force_ident(state &cs);
private:
std::aligned_union_t<1,
integer_type,
float_type,
void *,
string_ref
> p_stor;
std::aligned_union_t<1, integer_type, float_type, void *> p_stor;
value_type p_type;
};

View File

@ -54,12 +54,12 @@ string_ref string_pool::steal(char *ptr) {
if (st) {
/* the buffer is superfluous now */
cstate->alloc(ss, ss->length + sizeof(string_ref_state) + 1, 0);
return string_ref{reinterpret_cast<char const *>(st + 1), cstate};
return string_ref{reinterpret_cast<char const *>(st + 1)};
}
}
ss->refcount = 0; /* string_ref will increment it */
counts.emplace(sr, ss);
return string_ref{ptr, cstate};
return string_ref{ptr};
}
void string_pool::unref(char const *ptr) {
@ -108,9 +108,19 @@ char *string_pool::alloc_buf(std::size_t len) const {
return strp;
}
/* strref implementation */
char const *str_managed_ref(char const *str) {
return get_ref_state(str)->state->strman->ref(str);
}
/* strref */
void str_managed_unref(char const *str) {
get_ref_state(str)->state->strman->unref(str);
}
std::string_view str_managed_view(char const *str) {
return get_ref_state(str)->state->strman->get(str);
}
/* strref implementation */
LIBCUBESCRIPT_EXPORT string_ref::string_ref(
internal_state *cs, std::string_view str
@ -129,24 +139,25 @@ LIBCUBESCRIPT_EXPORT string_ref::string_ref(string_ref const &ref):
}
/* this can be used by friends to do quick string_ref creation */
LIBCUBESCRIPT_EXPORT string_ref::string_ref(
char const *p, internal_state *cs
) {
p_str = cs->strman->ref(p);
LIBCUBESCRIPT_EXPORT string_ref::string_ref(char const *p) {
p_str = str_managed_ref(p);
}
LIBCUBESCRIPT_EXPORT string_ref::~string_ref() {
get_ref_state(p_str)->state->strman->unref(p_str);
str_managed_unref(p_str);
}
LIBCUBESCRIPT_EXPORT string_ref &string_ref::operator=(string_ref const &ref) {
p_str = ref.p_str;
get_ref_state(p_str)->state->strman->ref(p_str);
p_str = str_managed_ref(ref.p_str);
return *this;
}
LIBCUBESCRIPT_EXPORT char const *string_ref::data() const {
return p_str;
}
LIBCUBESCRIPT_EXPORT string_ref::operator std::string_view() const {
return get_ref_state(p_str)->state->strman->get(p_str);
return str_managed_view(p_str);
}
LIBCUBESCRIPT_EXPORT bool string_ref::operator==(string_ref const &s) const {

View File

@ -13,6 +13,10 @@ namespace cubescript {
struct string_ref_state;
char const *str_managed_ref(char const *str);
void str_managed_unref(char const *str);
std::string_view str_managed_view(char const *str);
/* string manager
*
* the purpose of this is to handle interning of strings; each string within

View File

@ -2,6 +2,7 @@
#include "cs_std.hh"
#include "cs_parser.hh"
#include "cs_state.hh"
#include "cs_strman.hh"
#include <cmath>
#include <iterator>
@ -66,7 +67,7 @@ template<typename T>
static inline void csv_cleanup(value_type tv, T *stor) {
switch (tv) {
case value_type::STRING:
csv_get<string_ref>(stor).~string_ref();
str_managed_unref(csv_get<char const *>(stor));
break;
case value_type::CODE: {
bcode_unref(csv_get<uint32_t *>(stor));
@ -105,9 +106,8 @@ any_value &any_value::operator=(any_value const &v) {
break;
case value_type::STRING:
p_type = value_type::STRING;
new (&csv_get<string_ref>(&p_stor)) string_ref{
csv_get<string_ref>(&v.p_stor)
};
p_stor = v.p_stor;
str_managed_ref(csv_get<char const *>(&p_stor));
break;
case value_type::CODE:
set_code(v.get_code());
@ -142,13 +142,13 @@ void any_value::set_float(float_type val) {
void any_value::set_string(std::string_view val, state &cs) {
csv_cleanup(p_type, &p_stor);
new (&csv_get<string_ref>(&p_stor)) string_ref{cs, val};
csv_get<char const *>(&p_stor) = state_p{cs}.ts().istate->strman->add(val);
p_type = value_type::STRING;
}
void any_value::set_string(string_ref const &val) {
csv_cleanup(p_type, &p_stor);
new (&csv_get<string_ref>(&p_stor)) string_ref{val};
csv_get<char const *>(&p_stor) = str_managed_ref(val.p_str);
p_type = value_type::STRING;
}
@ -197,7 +197,7 @@ float_type any_value::force_float() {
rf = float_type(csv_get<integer_type>(&p_stor));
break;
case value_type::STRING:
rf = parse_float(csv_get<string_ref>(&p_stor));
rf = parse_float(str_managed_view(csv_get<char const *>(&p_stor)));
break;
case value_type::FLOAT:
return csv_get<float_type>(&p_stor);
@ -215,7 +215,7 @@ integer_type any_value::force_integer() {
ri = integer_type(std::floor(csv_get<float_type>(&p_stor)));
break;
case value_type::STRING:
ri = parse_int(csv_get<string_ref>(&p_stor));
ri = parse_int(str_managed_view(csv_get<char const *>(&p_stor)));
break;
case value_type::INTEGER:
return csv_get<integer_type>(&p_stor);
@ -237,13 +237,13 @@ std::string_view any_value::force_string(state &cs) {
str = intstr(csv_get<integer_type>(&p_stor), rs);
break;
case value_type::STRING:
return csv_get<string_ref>(&p_stor);
return str_managed_view(csv_get<char const *>(&p_stor));
default:
str = rs.str();
break;
}
set_string(str, cs);
return csv_get<string_ref>(&p_stor);
return str_managed_view(csv_get<char const *>(&p_stor));
}
bcode_ref any_value::force_code(state &cs) {
@ -281,7 +281,7 @@ integer_type any_value::get_integer() const {
case value_type::INTEGER:
return csv_get<integer_type>(&p_stor);
case value_type::STRING:
return parse_int(csv_get<string_ref>(&p_stor));
return parse_int(str_managed_view(csv_get<char const *>(&p_stor)));
default:
break;
}
@ -295,7 +295,9 @@ float_type any_value::get_float() const {
case value_type::INTEGER:
return float_type(csv_get<integer_type>(&p_stor));
case value_type::STRING:
return parse_float(csv_get<string_ref>(&p_stor));
return parse_float(
str_managed_view(csv_get<char const *>(&p_stor))
);
default:
break;
}
@ -319,7 +321,7 @@ ident *any_value::get_ident() const {
string_ref any_value::get_string(state &cs) const {
switch (get_type()) {
case value_type::STRING:
return csv_get<string_ref>(&p_stor);
return string_ref{csv_get<char const *>(&p_stor)};
case value_type::INTEGER: {
charbuf rs{cs};
return string_ref{
@ -357,7 +359,9 @@ bool any_value::get_bool() const {
case value_type::INTEGER:
return csv_get<integer_type>(&p_stor) != 0;
case value_type::STRING: {
std::string_view s = csv_get<string_ref>(&p_stor);
std::string_view s = str_managed_view(
csv_get<char const *>(&p_stor)
);
if (s.empty()) {
return false;
}