From add7ff74ca25ca2c9cc591abc484f8e6d38b2c39 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Mon, 11 Aug 2014 22:52:18 -0700 Subject: Optimize string literals in refcounted strings --- src/strings/rstring.cpp | 77 +++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) (limited to 'src/strings/rstring.cpp') diff --git a/src/strings/rstring.cpp b/src/strings/rstring.cpp index 3e5a46d..e74d1d5 100644 --- a/src/strings/rstring.cpp +++ b/src/strings/rstring.cpp @@ -36,45 +36,46 @@ namespace tmwa { namespace strings { - static_assert(sizeof(RString) == sizeof(const char *), "RString"); - - uint8_t RString::empty_string_rep[sizeof(Rep) + 1]; - RString::RString() - : owned(reinterpret_cast(&empty_string_rep)) + : u{.begin= ""}, maybe_end(u.begin) + { + } + RString::RString(LString l) + : u{.begin= &*l.begin()}, maybe_end(&*l.end()) { - owned->count++; } RString::RString(const RString& r) - : owned(r.owned) + : u(r.u), maybe_end(r.maybe_end) { - owned->count++; + if (!maybe_end) + u.owned->count++; } RString::RString(RString&& r) - : owned(reinterpret_cast(&empty_string_rep)) + : RString() { - std::swap(owned, r.owned); - r.owned->count++; + *this = std::move(r); } RString& RString::operator = (const RString& r) { // order important for self-assign - r.owned->count++; - // owned can be nullptr from ctors - // TODO do ctors *properly* (requires gcc 4.7 to stay sane) - if (owned && !owned->count--) - ::operator delete(owned); - owned = r.owned; + if (!r.maybe_end) + r.u.owned->count++; + if (!maybe_end && !u.owned->count--) + ::operator delete(u.owned); + u = r.u; + maybe_end = r.maybe_end; return *this; } RString& RString::operator = (RString&& r) { - std::swap(owned, r.owned); + std::swap(u, r.u); + std::swap(maybe_end, r.maybe_end); return *this; } + RString::RString(AString a) - : owned(nullptr) + : RString() { if (RString *r = const_cast(a.base())) { @@ -87,41 +88,36 @@ namespace strings } RString::~RString() { - if (owned && !owned->count--) - ::operator delete(owned); - owned = nullptr; + if (!maybe_end && !u.owned->count--) + ::operator delete(u.owned); } RString::RString(const MString& s) - : owned(nullptr) + : RString(s.begin(), s.end()) { - _assign(s.begin(), s.end()); } RString::RString(XPair p) - : owned(nullptr) + : RString(p.begin(), p.end()) { - _assign(p.begin(), p.end()); } RString::RString(const TString& t) - : owned(nullptr) + : RString(XString(t)) { - *this = XString(t); } RString::RString(const SString& s) - : owned(nullptr) + : RString(XString(s)) { - *this = XString(s); } RString::RString(ZString z) - : owned(nullptr) + : RString(XString(z)) { - *this = XString(z); } RString::RString(XString x) - : owned(nullptr) + : RString() { + // long term this stuff will change again const RString *f = x.base(); const char *xb = &*x.begin(); const char *xe = &*x.end(); @@ -130,21 +126,20 @@ namespace strings if (f && xb == fb && xe == fe) *this = *f; else - _assign(x.begin(), x.end()); - } - RString::RString(LString l) - : owned(nullptr) - { - *this = XString(l); + *this = RString(x.begin(), x.end()); } RString::iterator RString::begin() const { - return owned->body; + if (maybe_end) + return u.begin; + return u.owned->body; } RString::iterator RString::end() const { - return owned->body + owned->size; + if (maybe_end) + return maybe_end; + return u.owned->body + u.owned->size; } const RString *RString::base() const { -- cgit v1.2.3-60-g2f50