use AlignedUnion and fix leaks

master
Daniel Kolesa 2016-09-06 20:06:49 +02:00
parent 7aebfe1b2e
commit f4e9cbf27f
5 changed files with 96 additions and 74 deletions

122
cs_val.cc
View File

@ -4,13 +4,19 @@
namespace cscript { namespace cscript {
template<typename T, typename U>
inline T &csv_get(U &stor) {
/* ugly, but internal and unlikely to cause bugs */
return const_cast<T &>(reinterpret_cast<T const &>(stor));
}
void CsValue::cleanup() { void CsValue::cleanup() {
switch (get_type()) { switch (get_type()) {
case CsValueType::string: case CsValueType::string:
delete[] p_s; delete[] csv_get<char *>(p_stor);
break; break;
case CsValueType::code: { case CsValueType::code: {
ostd::Uint32 *bcode = reinterpret_cast<ostd::Uint32 *>(p_code); ostd::Uint32 *bcode = csv_get<ostd::Uint32 *>(p_stor);
if (bcode[-1] == CODE_START) { if (bcode[-1] == CODE_START) {
delete[] bcode; delete[] bcode;
} }
@ -27,12 +33,12 @@ CsValueType CsValue::get_type() const {
void CsValue::set_int(CsInt val) { void CsValue::set_int(CsInt val) {
p_type = CsValueType::integer; p_type = CsValueType::integer;
p_i = val; csv_get<CsInt>(p_stor) = val;
} }
void CsValue::set_float(CsFloat val) { void CsValue::set_float(CsFloat val) {
p_type = CsValueType::number; p_type = CsValueType::number;
p_f = val; csv_get<CsFloat>(p_stor) = val;
} }
void CsValue::set_str(CsString val) { void CsValue::set_str(CsString val) {
@ -50,35 +56,35 @@ void CsValue::set_str(CsString val) {
void CsValue::set_null() { void CsValue::set_null() {
p_type = CsValueType::null; p_type = CsValueType::null;
p_code = nullptr; csv_get<CsBytecode *>(p_stor) = nullptr;
} }
void CsValue::set_code(CsBytecode *val) { void CsValue::set_code(CsBytecode *val) {
p_type = CsValueType::code; p_type = CsValueType::code;
p_code = val; csv_get<CsBytecode *>(p_stor) = val;
} }
void CsValue::set_cstr(ostd::ConstCharRange val) { void CsValue::set_cstr(ostd::ConstCharRange val) {
p_type = CsValueType::cstring; p_type = CsValueType::cstring;
p_len = val.size(); p_len = val.size();
p_cstr = val.data(); csv_get<char const *>(p_stor) = val.data();
} }
void CsValue::set_mstr(ostd::CharRange val) { void CsValue::set_mstr(ostd::CharRange val) {
p_type = CsValueType::string; p_type = CsValueType::string;
p_len = val.size(); p_len = val.size();
p_s = val.data(); csv_get<char *>(p_stor) = val.data();
} }
void CsValue::set_ident(CsIdent *val) { void CsValue::set_ident(CsIdent *val) {
p_type = CsValueType::ident; p_type = CsValueType::ident;
p_id = val; csv_get<CsIdent *>(p_stor) = val;
} }
void CsValue::set_macro(ostd::ConstCharRange val) { void CsValue::set_macro(ostd::ConstCharRange val) {
p_type = CsValueType::macro; p_type = CsValueType::macro;
p_len = val.size(); p_len = val.size();
p_cstr = val.data(); csv_get<char const *>(p_stor) = val.data();
} }
void CsValue::set(CsValue &tv) { void CsValue::set(CsValue &tv) {
@ -99,15 +105,17 @@ CsFloat CsValue::force_float() {
CsFloat rf = 0.0f; CsFloat rf = 0.0f;
switch (get_type()) { switch (get_type()) {
case CsValueType::integer: case CsValueType::integer:
rf = p_i; rf = csv_get<CsInt>(p_stor);
break; break;
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
rf = cs_parse_float(ostd::ConstCharRange(p_s, p_len)); rf = cs_parse_float(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
break; break;
case CsValueType::number: case CsValueType::number:
return p_f; return csv_get<CsFloat>(p_stor);
default: default:
break; break;
} }
@ -120,15 +128,17 @@ CsInt CsValue::force_int() {
CsInt ri = 0; CsInt ri = 0;
switch (get_type()) { switch (get_type()) {
case CsValueType::number: case CsValueType::number:
ri = p_f; ri = csv_get<CsFloat>(p_stor);
break; break;
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
ri = cs_parse_int(ostd::ConstCharRange(p_s, p_len)); ri = cs_parse_int(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
break; break;
case CsValueType::integer: case CsValueType::integer:
return p_i; return csv_get<CsInt>(p_stor);
default: default:
break; break;
} }
@ -141,35 +151,37 @@ ostd::ConstCharRange CsValue::force_str() {
CsString rs; CsString rs;
switch (get_type()) { switch (get_type()) {
case CsValueType::number: case CsValueType::number:
rs = ostd::move(floatstr(p_f)); rs = ostd::move(floatstr(csv_get<CsFloat>(p_stor)));
break; break;
case CsValueType::integer: case CsValueType::integer:
rs = ostd::move(intstr(p_i)); rs = ostd::move(intstr(csv_get<CsInt>(p_stor)));
break; break;
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
rs = ostd::ConstCharRange(p_s, p_len); rs = ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len);
break; break;
case CsValueType::string: case CsValueType::string:
return ostd::ConstCharRange(p_s, p_len); return ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len);
default: default:
break; break;
} }
cleanup(); cleanup();
set_str(ostd::move(rs)); set_str(ostd::move(rs));
return ostd::ConstCharRange(p_s, p_len); return ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len);
} }
CsInt CsValue::get_int() const { CsInt CsValue::get_int() const {
switch (get_type()) { switch (get_type()) {
case CsValueType::number: case CsValueType::number:
return CsInt(p_f); return CsInt(csv_get<CsFloat>(p_stor));
case CsValueType::integer: case CsValueType::integer:
return p_i; return csv_get<CsInt>(p_stor);
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
return cs_parse_int(ostd::ConstCharRange(p_s, p_len)); return cs_parse_int(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
default: default:
break; break;
} }
@ -179,13 +191,15 @@ CsInt CsValue::get_int() const {
CsFloat CsValue::get_float() const { CsFloat CsValue::get_float() const {
switch (get_type()) { switch (get_type()) {
case CsValueType::number: case CsValueType::number:
return p_f; return csv_get<CsFloat>(p_stor);
case CsValueType::integer: case CsValueType::integer:
return CsFloat(p_i); return CsFloat(csv_get<CsInt>(p_stor));
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
return cs_parse_float(ostd::ConstCharRange(p_s, p_len)); return cs_parse_float(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
default: default:
break; break;
} }
@ -196,14 +210,14 @@ CsBytecode *CsValue::get_code() const {
if (get_type() != CsValueType::code) { if (get_type() != CsValueType::code) {
return nullptr; return nullptr;
} }
return p_code; return csv_get<CsBytecode *>(p_stor);
} }
CsIdent *CsValue::get_ident() const { CsIdent *CsValue::get_ident() const {
if (get_type() != CsValueType::ident) { if (get_type() != CsValueType::ident) {
return nullptr; return nullptr;
} }
return p_id; return csv_get<CsIdent *>(p_stor);
} }
CsString CsValue::get_str() const { CsString CsValue::get_str() const {
@ -211,11 +225,11 @@ CsString CsValue::get_str() const {
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
return ostd::ConstCharRange(p_s, p_len); return ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len);
case CsValueType::integer: case CsValueType::integer:
return intstr(p_i); return intstr(csv_get<CsInt>(p_stor));
case CsValueType::number: case CsValueType::number:
return floatstr(p_f); return floatstr(csv_get<CsFloat>(p_stor));
default: default:
break; break;
} }
@ -227,7 +241,7 @@ ostd::ConstCharRange CsValue::get_strr() const {
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
return ostd::ConstCharRange(p_s, p_len); return ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len);
default: default:
break; break;
} }
@ -239,13 +253,15 @@ void CsValue::get_val(CsValue &r) const {
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
r.set_str(ostd::ConstCharRange(p_s, p_len)); r.set_str(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
break; break;
case CsValueType::integer: case CsValueType::integer:
r.set_int(p_i); r.set_int(csv_get<CsInt>(p_stor));
break; break;
case CsValueType::number: case CsValueType::number:
r.set_float(p_f); r.set_float(csv_get<CsFloat>(p_stor));
break; break;
default: default:
r.set_null(); r.set_null();
@ -266,7 +282,7 @@ bool CsValue::code_is_empty() const {
if (get_type() != CsValueType::code) { if (get_type() != CsValueType::code) {
return true; return true;
} }
return cscript::cs_code_is_empty(p_code); return cscript::cs_code_is_empty(csv_get<CsBytecode *>(p_stor));
} }
static inline bool cs_get_bool(ostd::ConstCharRange s) { static inline bool cs_get_bool(ostd::ConstCharRange s) {
@ -289,16 +305,42 @@ static inline bool cs_get_bool(ostd::ConstCharRange s) {
bool CsValue::get_bool() const { bool CsValue::get_bool() const {
switch (get_type()) { switch (get_type()) {
case CsValueType::number: case CsValueType::number:
return p_f != 0; return csv_get<CsFloat>(p_stor) != 0;
case CsValueType::integer: case CsValueType::integer:
return p_i != 0; return csv_get<CsInt>(p_stor) != 0;
case CsValueType::string: case CsValueType::string:
case CsValueType::macro: case CsValueType::macro:
case CsValueType::cstring: case CsValueType::cstring:
return cs_get_bool(ostd::ConstCharRange(p_s, p_len)); return cs_get_bool(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
default: default:
return false; return false;
} }
} }
void CsValue::copy_arg(CsValue &r) const {
r.cleanup();
switch (get_type()) {
case CsValueType::integer:
case CsValueType::number:
case CsValueType::ident:
r = *this;
break;
case CsValueType::string:
case CsValueType::cstring:
case CsValueType::macro:
r.set_str(
ostd::ConstCharRange(csv_get<char const *>(p_stor), p_len)
);
break;
case CsValueType::code:
r.set_code(cs_copy_code(get_code()));
break;
default:
r.set_null();
break;
}
}
} /* namespace cscript */ } /* namespace cscript */

View File

@ -260,32 +260,13 @@ static ostd::Uint32 *skipcode(
} }
} }
void CsValue::copy_arg(CsValue &r) const { CsBytecode *cs_copy_code(CsBytecode *c) {
r.cleanup(); ostd::Uint32 *bcode = reinterpret_cast<ostd::Uint32 *>(c);
switch (get_type()) { ostd::Uint32 *end = skipcode(bcode);
case CsValueType::integer: ostd::Uint32 *dst = new ostd::Uint32[end - bcode + 1];
case CsValueType::number: *dst++ = CODE_START;
case CsValueType::ident: memcpy(dst, bcode, (end - bcode) * sizeof(ostd::Uint32));
r = *this; return reinterpret_cast<CsBytecode *>(dst);
break;
case CsValueType::string:
case CsValueType::cstring:
case CsValueType::macro:
r.set_str(ostd::ConstCharRange(p_s, p_len));
break;
case CsValueType::code: {
ostd::Uint32 *bcode = reinterpret_cast<ostd::Uint32 *>(r.get_code());
ostd::Uint32 *end = skipcode(bcode);
ostd::Uint32 *dst = new ostd::Uint32[end - bcode + 1];
*dst++ = CODE_START;
memcpy(dst, bcode, (end - bcode) * sizeof(ostd::Uint32));
r.set_code(reinterpret_cast<CsBytecode *>(dst));
break;
}
default:
r.set_null();
break;
}
} }
static inline void callcommand( static inline void callcommand(

View File

@ -348,6 +348,8 @@ static void cs_do_args(CsState &cs, F body) {
} }
} }
CsBytecode *cs_copy_code(CsBytecode *c);
} /* namespace cscript */ } /* namespace cscript */
#endif /* LIBCUBESCRIPT_CS_VM_HH */ #endif /* LIBCUBESCRIPT_CS_VM_HH */

View File

@ -100,14 +100,7 @@ struct OSTD_EXPORT CsValue {
void copy_arg(CsValue &r) const; void copy_arg(CsValue &r) const;
private: private:
union { ostd::AlignedUnion<1, CsInt, CsFloat, void *> p_stor;
CsInt p_i;
CsFloat p_f;
CsBytecode *p_code;
CsIdent *p_id;
char *p_s;
char const *p_cstr;
};
ostd::Size p_len; ostd::Size p_len;
CsValueType p_type; CsValueType p_type;
}; };
@ -139,6 +132,9 @@ struct OSTD_EXPORT CsIdent {
CsIdent(CsIdent const &) = delete; CsIdent(CsIdent const &) = delete;
CsIdent(CsIdent &&) = delete; CsIdent(CsIdent &&) = delete;
/* trigger destructors for all inherited members properly */
virtual ~CsIdent() {};
CsIdent &operator=(CsIdent const &) = delete; CsIdent &operator=(CsIdent const &) = delete;
CsIdent &operator=(CsIdent &&) = delete; CsIdent &operator=(CsIdent &&) = delete;

View File

@ -194,6 +194,7 @@ static void do_call(CsState &cs, ostd::ConstCharRange line) {
if (ret.get_type() != CsValueType::null) { if (ret.get_type() != CsValueType::null) {
ostd::writeln(ret.get_str()); ostd::writeln(ret.get_str());
} }
ret.cleanup();
} }
static void do_tty(CsState &cs) { static void do_tty(CsState &cs) {