summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-08-11 22:52:18 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-08-25 17:58:12 -0700
commitadd7ff74ca25ca2c9cc591abc484f8e6d38b2c39 (patch)
treec62ef1510966effdf81bec6710125b75783ff512 /src
parent54df2e07fc4cc0bd8557e4152be15353ecf53d0d (diff)
downloadtmwa-add7ff74ca25ca2c9cc591abc484f8e6d38b2c39.tar.gz
tmwa-add7ff74ca25ca2c9cc591abc484f8e6d38b2c39.tar.bz2
tmwa-add7ff74ca25ca2c9cc591abc484f8e6d38b2c39.tar.xz
tmwa-add7ff74ca25ca2c9cc591abc484f8e6d38b2c39.zip
Optimize string literals in refcounted strings
Diffstat (limited to 'src')
-rw-r--r--src/strings/astring.cpp54
-rw-r--r--src/strings/astring.hpp2
-rw-r--r--src/strings/rstring.cpp77
-rw-r--r--src/strings/rstring.hpp13
-rw-r--r--src/strings/rstring.tcc25
-rw-r--r--src/strings/strings2_test.cpp6
6 files changed, 67 insertions, 110 deletions
diff --git a/src/strings/astring.cpp b/src/strings/astring.cpp
index f1f12c3..e2521df 100644
--- a/src/strings/astring.cpp
+++ b/src/strings/astring.cpp
@@ -47,7 +47,6 @@ namespace strings
std::copy(src + 0, src + 255, dst);
}
- // TODO dedup all this code once I drop gcc 4.6 support
AString::AString()
: data{}, special()
{
@@ -100,78 +99,43 @@ namespace strings
}
AString::AString(const MString& s)
- : data{}, special()
+ : AString(s.begin(), s.end())
{
- if (s.size() > 255 || s.size() == 0)
- {
- new(r_ptr()) RString(s);
- special = 255;
- }
- else
- {
- *std::copy(s.begin(), s.end(), data) = '\0';
- special = 255 - s.size();
- }
}
AString::AString(XPair p)
- : data{}, special()
+ : AString(p.begin(), p.end())
{
- new(r_ptr()) RString();
- special = 255;
- *this = XString(p);
}
AString::AString(const TString& t)
- : data{}, special()
+ : AString(XString(t))
{
- new(r_ptr()) RString();
- special = 255;
- *this = XString(t);
}
AString::AString(const SString& s)
- : data{}, special()
+ : AString(XString(s))
{
- new(r_ptr()) RString();
- special = 255;
- *this = XString(s);
}
AString::AString(ZString z)
- : data{}, special()
+ : AString(XString(z))
{
- new(r_ptr()) RString();
- special = 255;
- *this = XString(z);
}
AString::AString(XString x)
- : data{}, special()
+ : AString()
{
if (const RString *r = x.base())
{
if (&*r->begin() == &*x.begin() && &*r->end() == &*x.end())
{
- new(r_ptr()) RString(*r);
- special = 255;
+ *this = *r;
return;
}
}
- if (x.size() > 255 || x.size() == 0)
- {
- new(r_ptr()) RString(x);
- special = 255;
- }
- else
- {
- *std::copy(x.begin(), x.end(), data) = '\0';
- special = 255 - x.size();
- }
+ *this = AString(x.begin(), x.end());
}
AString::AString(LString l)
- : data{}, special()
+ : AString(RString(l))
{
- new(r_ptr()) RString();
- special = 255;
- *this = XString(l);
}
AString::iterator AString::begin() const
diff --git a/src/strings/astring.hpp b/src/strings/astring.hpp
index 83399f0..ccf2be6 100644
--- a/src/strings/astring.hpp
+++ b/src/strings/astring.hpp
@@ -35,7 +35,7 @@ namespace strings
#ifdef __clang__
__attribute__((unused))
#endif
- RString *align[0];
+ RString align[0];
char data[255];
unsigned char special;
RString *r_ptr() { return reinterpret_cast<RString *>(data); }
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<Rep *>(&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<Rep *>(&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<RString *>(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
{
diff --git a/src/strings/rstring.hpp b/src/strings/rstring.hpp
index fd3ee65..ad44beb 100644
--- a/src/strings/rstring.hpp
+++ b/src/strings/rstring.hpp
@@ -39,15 +39,17 @@ namespace strings
size_t size;
char body[];
};
- static
- uint8_t empty_string_rep[sizeof(Rep) + 1];
- Rep *owned;
+ union
+ {
+ Rep *owned;
+ const char *begin;
+ } u;
+ const char *maybe_end;
- template<class It>
- void _assign(It b, It e);
public:
RString();
+ RString(LString s);
RString(const RString&);
RString(RString&&);
RString& operator = (const RString&);
@@ -68,7 +70,6 @@ namespace strings
RString(XString);
template<uint8_t n>
RString(const VString<n>& v);
- RString(LString s);
iterator begin() const;
iterator end() const;
diff --git a/src/strings/rstring.tcc b/src/strings/rstring.tcc
index c247b8f..8a85b1d 100644
--- a/src/strings/rstring.tcc
+++ b/src/strings/rstring.tcc
@@ -1,6 +1,6 @@
// strings/rstring.tcc - Inline functions for rstring.hpp
//
-// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com>
+// Copyright © 2013-2014 Ben Longbons <b.r.longbons@gmail.com>
//
// This file is part of The Mana World (Athena server)
//
@@ -25,12 +25,11 @@ namespace tmwa
namespace strings
{
template<class It>
- void RString::_assign(It b, It e)
+ RString::RString(It b, It e)
+ : RString()
{
- owned = nullptr;
if (b == e)
{
- *this = RString();
return;
}
if (!std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value)
@@ -43,23 +42,19 @@ namespace strings
return;
}
size_t diff = std::distance(b, e);
- owned = static_cast<Rep *>(::operator new(sizeof(Rep) + diff + 1));
- owned->count = 0;
- owned->size = diff;
- std::copy(b, e, owned->body);
- owned->body[diff] = '\0';
- }
+ u.owned = static_cast<Rep *>(::operator new(sizeof(Rep) + diff + 1));
+ maybe_end = nullptr;
- template<class It>
- RString::RString(It b, It e)
- {
- _assign(b, e);
+ u.owned->count = 0;
+ u.owned->size = diff;
+ std::copy(b, e, u.owned->body);
+ u.owned->body[diff] = '\0';
}
template<uint8_t n>
RString::RString(const VString<n>& v)
+ : RString(v.begin(), v.end())
{
- _assign(v.begin(), v.end());
}
} // namespace strings
} // namespace tmwa
diff --git a/src/strings/strings2_test.cpp b/src/strings/strings2_test.cpp
index 18c7db4..8ac8482 100644
--- a/src/strings/strings2_test.cpp
+++ b/src/strings/strings2_test.cpp
@@ -170,9 +170,11 @@ TEST(StringTests, rempty)
TEST(StringTests, rshort)
{
LString short_text = "0123456789"_s;
- RString r = short_text;
+ EXPECT_EQ(&*short_text.begin(), &*RString(short_text).begin());
+ EXPECT_EQ(&*short_text.begin(), &*AString(short_text).begin());
+ RString r = VString<255>(short_text);
EXPECT_EQ(r.size(), 10);
- AString a = short_text;
+ AString a = VString<255>(short_text);
EXPECT_EQ(r, a);
AString r2 = r, r3;
RString a2 = a, a3;