summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-01-19 21:46:02 -0800
committerBen Longbons <b.r.longbons@gmail.com>2014-01-20 14:03:52 -0800
commit9c1799033d0c17fbefb52a9b2695922f5a715133 (patch)
treef2859d02f87081a9166e3253c4e7c4973b82fcea
parentb9ac1c6033a0b32ca9984f23223d9fc167415b10 (diff)
downloadtmwa-9c1799033d0c17fbefb52a9b2695922f5a715133.tar.gz
tmwa-9c1799033d0c17fbefb52a9b2695922f5a715133.tar.bz2
tmwa-9c1799033d0c17fbefb52a9b2695922f5a715133.tar.xz
tmwa-9c1799033d0c17fbefb52a9b2695922f5a715133.zip
Implement FString from scratch instead of hackishly
-rw-r--r--src/strings/fstring.cpp52
-rw-r--r--src/strings/fstring.hpp22
-rw-r--r--src/strings/fstring.py19
-rw-r--r--src/strings/fstring.tcc20
4 files changed, 94 insertions, 19 deletions
diff --git a/src/strings/fstring.cpp b/src/strings/fstring.cpp
index 32d19fe..97ef4b0 100644
--- a/src/strings/fstring.cpp
+++ b/src/strings/fstring.cpp
@@ -1,7 +1,7 @@
#include "fstring.hpp"
// strings/fstring.cpp - Functions for fstring.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)
//
@@ -27,35 +27,77 @@
namespace strings
{
+ uint8_t FString::empty_string_rep[sizeof(Rep) + 1];
+
FString::FString()
+ : owned(reinterpret_cast<Rep *>(&empty_string_rep))
+ {
+ owned->count++;
+ }
+
+ FString::FString(const FString& r)
+ : owned(r.owned)
+ {
+ owned->count++;
+ }
+ FString::FString(FString&& r)
+ : owned(reinterpret_cast<Rep *>(&empty_string_rep))
+ {
+ std::swap(owned, r.owned);
+ r.owned->count++;
+ }
+ FString& FString::operator = (const FString& r)
+ {
+ // order important for self-assign
+ r.owned->count++;
+ // owned can be NULL from ctors
+ // TODO do ctors *properly* (requires gcc 4.7 to stay sane)
+ if (owned && !owned->count--)
+ ::operator delete(owned);
+ owned = r.owned;
+ return *this;
+ }
+ FString& FString::operator = (FString&& r)
+ {
+ std::swap(owned, r.owned);
+ return *this;
+ }
+ FString::~FString()
{
- const char *sadness = "";
- _assign(sadness, sadness);
+ if (owned && !owned->count--)
+ ::operator delete(owned);
+ owned = nullptr;
}
FString::FString(const MString& s)
+ : owned(nullptr)
{
_assign(s.begin(), s.end());
}
FString::FString(XPair p)
+ : owned(nullptr)
{
_assign(p.begin(), p.end());
}
FString::FString(const TString& t)
+ : owned(nullptr)
{
*this = XString(t);
}
FString::FString(const SString& s)
+ : owned(nullptr)
{
*this = XString(s);
}
FString::FString(ZString z)
+ : owned(nullptr)
{
*this = XString(z);
}
FString::FString(XString x)
+ : owned(nullptr)
{
const FString *f = x.base();
const char *xb = &*x.begin();
@@ -70,11 +112,11 @@ namespace strings
FString::iterator FString::begin() const
{
- return &_hack2->begin()[0];
+ return owned->body;
}
FString::iterator FString::end() const
{
- return &_hack2->end()[-1];
+ return owned->body + owned->size;
}
const FString *FString::base() const
{
diff --git a/src/strings/fstring.hpp b/src/strings/fstring.hpp
index b025d74..48da326 100644
--- a/src/strings/fstring.hpp
+++ b/src/strings/fstring.hpp
@@ -2,7 +2,7 @@
#define TMWA_STRINGS_FSTRING_HPP
// strings/fstring.hpp - An owned, reference-counted immutable string.
//
-// 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)
//
@@ -22,24 +22,34 @@
# include <cstdarg>
# include <cstring>
-# include <memory>
-# include <vector>
-
# include "base.hpp"
namespace strings
{
/// An owning string that has reached its final contents.
/// The storage is NUL-terminated
- /// TODO reimplement without std::shared_ptr
class FString : public _crtp_string<FString, FString, ZPair>
{
- std::shared_ptr<std::vector<char>> _hack2;
+ struct Rep
+ {
+ size_t count;
+ size_t size;
+ char body[];
+ };
+ static
+ uint8_t empty_string_rep[sizeof(Rep) + 1];
+
+ Rep *owned;
template<class It>
void _assign(It b, It e);
public:
FString();
+ FString(const FString&);
+ FString(FString&&);
+ FString& operator = (const FString&);
+ FString& operator = (FString&&);
+ ~FString();
explicit FString(const MString& s);
diff --git a/src/strings/fstring.py b/src/strings/fstring.py
new file mode 100644
index 0000000..5418300
--- /dev/null
+++ b/src/strings/fstring.py
@@ -0,0 +1,19 @@
+class FString(object):
+ ''' print a FString
+ '''
+ __slots__ = ('_value')
+ name = 'strings::FString'
+ enabled = True
+
+ def __init__(self, value):
+ self._value = value
+
+ def children(self):
+ yield 'count', self._value['owned'].dereference()['count']
+
+ def to_string(self):
+ r = self._value['owned'].dereference()
+ b = r['body']
+ b = b.cast(b.type.target().pointer())
+ d = r['size']
+ return b.lazy_string(length=d)
diff --git a/src/strings/fstring.tcc b/src/strings/fstring.tcc
index 388aef1..9c5f37b 100644
--- a/src/strings/fstring.tcc
+++ b/src/strings/fstring.tcc
@@ -17,6 +17,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+#include "mstring.hpp"
+
namespace strings
{
template<class It>
@@ -24,22 +26,24 @@ namespace strings
{
if (b == e)
{
- // TODO use a special empty object
- // return;
+ *this = FString();
+ return;
}
if (!std::is_base_of<std::forward_iterator_tag, typename std::iterator_traits<It>::iterator_category>::value)
{
// can't use std::distance
- _hack2 = std::make_shared<std::vector<char>>();
+ MString m;
for (; b != e; ++b)
- _hack2->push_back(*b);
- _hack2->push_back('\0');
- _hack2->shrink_to_fit();
+ m += *b;
+ *this = FString(m); // will recurse
return;
}
size_t diff = std::distance(b, e);
- _hack2 = std::make_shared<std::vector<char>>(diff + 1, '\0');
- std::copy(b, e, _hack2->begin());
+ 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';
}
template<size_t n>