From 730e5dde39333cb2f63c72a7d7152bee5c4dbb05 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Sat, 8 Feb 2014 15:09:25 -0800 Subject: Implement AString --- src/strings/all.hpp | 3 +- src/strings/astring.cpp | 229 ++++++++++++++++++++++++++++++++++++++++++ src/strings/astring.hpp | 98 ++++++++++++++++++ src/strings/astring.py | 24 +++++ src/strings/astring.tcc | 76 ++++++++++++++ src/strings/base.hpp | 2 +- src/strings/base.tcc | 2 +- src/strings/base_test.cpp | 4 +- src/strings/fstring.cpp | 173 ------------------------------- src/strings/fstring.hpp | 104 ------------------- src/strings/fstring.py | 19 ---- src/strings/fstring.tcc | 67 ------------ src/strings/fwd.hpp | 6 +- src/strings/rstring.cpp | 164 ++++++++++++++++++++++++++++++ src/strings/rstring.hpp | 93 +++++++++++++++++ src/strings/rstring.py | 19 ++++ src/strings/rstring.tcc | 67 ++++++++++++ src/strings/sstring.cpp | 45 +++++++-- src/strings/sstring.hpp | 16 +-- src/strings/strings2_test.cpp | 106 +++++++++++++++++-- src/strings/strings_test.cpp | 29 ++++-- src/strings/tstring.cpp | 31 ++++-- src/strings/tstring.hpp | 11 +- src/strings/vstring.hpp | 5 +- src/strings/vstring.tcc | 12 ++- src/strings/xstring.cpp | 11 +- src/strings/xstring.hpp | 13 +-- src/strings/zstring.cpp | 11 +- src/strings/zstring.hpp | 15 +-- src/strings/zstring.tcc | 2 +- 30 files changed, 1008 insertions(+), 449 deletions(-) create mode 100644 src/strings/astring.cpp create mode 100644 src/strings/astring.hpp create mode 100644 src/strings/astring.py create mode 100644 src/strings/astring.tcc delete mode 100644 src/strings/fstring.cpp delete mode 100644 src/strings/fstring.hpp delete mode 100644 src/strings/fstring.py delete mode 100644 src/strings/fstring.tcc create mode 100644 src/strings/rstring.cpp create mode 100644 src/strings/rstring.hpp create mode 100644 src/strings/rstring.py create mode 100644 src/strings/rstring.tcc (limited to 'src/strings') diff --git a/src/strings/all.hpp b/src/strings/all.hpp index 7fd543f..46d5366 100644 --- a/src/strings/all.hpp +++ b/src/strings/all.hpp @@ -21,7 +21,8 @@ # include "base.hpp" # include "mstring.hpp" -# include "fstring.hpp" +# include "rstring.hpp" +# include "astring.hpp" # include "tstring.hpp" # include "sstring.hpp" # include "zstring.hpp" diff --git a/src/strings/astring.cpp b/src/strings/astring.cpp new file mode 100644 index 0000000..f7cfa2e --- /dev/null +++ b/src/strings/astring.cpp @@ -0,0 +1,229 @@ +#include "astring.hpp" +// strings/astring.cpp - Functions for astring.hpp +// +// Copyright © 2013-2014 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "mstring.hpp" +#include "tstring.hpp" +#include "sstring.hpp" +#include "zstring.hpp" +#include "xstring.hpp" +#include "vstring.hpp" + +namespace strings +{ + static_assert(sizeof(AString) == 256, "AString"); + + static + void acpy(char (&dst)[255], const char (&src)[255]) + { + std::copy(src + 0, src + 255, dst); + } + + // TODO dedup all this code once I drop gcc 4.6 support + AString::AString() + : data{}, special() + { + new(r_ptr()) RString(); + special = 255; + } + + AString::AString(const AString& a) + : data(), special(a.special) + { + acpy(data, a.data); + if (special == 255) + new(r_ptr()) RString(*a.r_ptr()); + } + AString::AString(AString&& a) + : data(), special(a.special) + { + acpy(data, a.data); + if (special == 255) + new(r_ptr()) RString(std::move(*a.r_ptr())); + } + AString& AString::operator = (const AString& a) + { + if (this == &a) + return *this; + if (special == 255) + r_ptr()->~RString(); + acpy(data, a.data); + special = a.special; + if (special == 255) + new(r_ptr()) RString(*a.r_ptr()); + return *this; + } + AString& AString::operator = (AString&& a) + { + std::swap(data, a.data); + std::swap(special, a.special); + return *this; + } + AString::AString(RString r) + : data{}, special() + { + new(r_ptr()) RString(std::move(r)); + special = 255; + } + AString::~AString() + { + if (special == 255) + r_ptr()->~RString(); + } + + AString::AString(const MString& s) + : data{}, special() + { + 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() + { + new(r_ptr()) RString(); + special = 255; + *this = XString(p); + } + + AString::AString(const TString& t) + : data{}, special() + { + new(r_ptr()) RString(); + special = 255; + *this = XString(t); + } + AString::AString(const SString& s) + : data{}, special() + { + new(r_ptr()) RString(); + special = 255; + *this = XString(s); + } + AString::AString(ZString z) + : data{}, special() + { + new(r_ptr()) RString(); + special = 255; + *this = XString(z); + } + AString::AString(XString x) + : data{}, special() + { + if (const RString *r = x.base()) + { + if (&*r->begin() == &*x.begin() && &*r->end() == &*x.end()) + { + new(r_ptr()) RString(*r); + special = 255; + 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(); + } + } + + AString::iterator AString::begin() const + { + if (special == 255) + return &*r_ptr()->begin(); + else + return data + 0; + } + AString::iterator AString::end() const + { + if (special == 255) + return &*r_ptr()->end(); + else + return data + (255 - special); + } + const RString *AString::base() const + { + if (special == 255) + return r_ptr(); + else + return nullptr; + } + const char *AString::c_str() const + { + return &*begin(); + } + + const char *decay_for_printf(const AString& as) + { + return as.c_str(); + } + + int do_vprint(AString& out, const char *fmt, va_list ap) + { + // TODO try with a fixed-size buffer first, then write + // directory into the allocated output? + int len; + { + va_list ap2; + va_copy(ap2, ap); + len = vsnprintf(nullptr, 0, fmt, ap2); + va_end(ap2); + } + char buffer[len + 1]; + vsnprintf(buffer, len + 1, fmt, ap); + + out = AString(buffer, buffer + len); + return len; + } + + AStringConverter::AStringConverter(AString& s) + : out(s), mid(nullptr) + {} + + AStringConverter::~AStringConverter() + { + if (mid) + { + out = ZString(really_construct_from_a_pointer, mid, nullptr); + free(mid); + } + } + + char **AStringConverter::operator &() + { + return ∣ + } + + AStringConverter convert_for_scanf(AString& s) + { + return AStringConverter(s); + } +} // namespace strings diff --git a/src/strings/astring.hpp b/src/strings/astring.hpp new file mode 100644 index 0000000..e682ef0 --- /dev/null +++ b/src/strings/astring.hpp @@ -0,0 +1,98 @@ +#ifndef TMWA_STRINGS_ASTRING_HPP +#define TMWA_STRINGS_ASTRING_HPP +// strings/astring.hpp - An owned, reference-counted immutable string. +// +// Copyright © 2013-2014 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +# include +# include + +# include "base.hpp" +# include "rstring.hpp" + +namespace strings +{ + /// An owning string that has reached its final contents. + /// The storage is NUL-terminated + class AString : public _crtp_string + { + RString *align[0]; + char data[255]; + unsigned char special; + RString *r_ptr() { return reinterpret_cast(data); } + const RString *r_ptr() const { return reinterpret_cast(data); } + public: + AString(); + AString(const AString&); + AString(AString&&); + AString& operator = (const AString&); + AString& operator = (AString&&); + AString(RString); + ~AString(); + + explicit AString(const MString& s); + + template + AString(char (&s)[n]) = delete; + + template + AString(const char (&s)[n]); + + template + AString(It b, It e); + + AString(XPair p); + //AString(const AString&) + AString(const TString&); + AString(const SString&); + AString(ZString); + AString(XString); + template + AString(const VString& v); + + iterator begin() const; + iterator end() const; + const RString *base() const; + const char *c_str() const; + }; + + // cxxstdio helpers + // I think the conversion will happen automatically. TODO test this. + // Nope, it doesn't, since there's a template + // Actually, it might now. + const char *decay_for_printf(const AString& fs); + + __attribute__((format(printf, 2, 0))) + int do_vprint(AString& out, const char *fmt, va_list ap); + + class AStringConverter + { + AString& out; + char *mid; + public: + AStringConverter(AString& s); + ~AStringConverter(); + char **operator &(); + }; + + AStringConverter convert_for_scanf(AString& s); +} // namespace strings + +# include "astring.tcc" + +#endif // TMWA_STRINGS_ASTRING_HPP diff --git a/src/strings/astring.py b/src/strings/astring.py new file mode 100644 index 0000000..ec1dafe --- /dev/null +++ b/src/strings/astring.py @@ -0,0 +1,24 @@ +class AString(object): + ''' print an AString + ''' + __slots__ = ('_value') + name = 'strings::AString' + enabled = True + + def __init__(self, value): + self._value = value + + def to_string(self): + return None + + def children(self): + b = self._value['data'] + s = self._value['special'] + if s == 255: + b = b.cast(gdb.lookup_type('strings::RString').pointer()) + yield 'allocated', b.dereference() + else: + b = b.cast(b.type.target().pointer()) + n = 255 + d = n - s + yield 'contained', b.lazy_string(length=d) diff --git a/src/strings/astring.tcc b/src/strings/astring.tcc new file mode 100644 index 0000000..ed07bd9 --- /dev/null +++ b/src/strings/astring.tcc @@ -0,0 +1,76 @@ +// strings/astring.tcc - Inline functions for astring.hpp +// +// Copyright © 2013 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "mstring.hpp" + +namespace strings +{ + template + AString::AString(const char (&s)[n]) + : data{}, special() + { + XPair x = s; + 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(); + } + } + + template + AString::AString(It b, It e) + : data{}, special() + { + if (!std::is_base_of::iterator_category>::value) + { + // can't use std::distance + MString m; + for (; b != e; ++b) + m += *b; + *this = AString(m); // will recurse + return; + } + auto d = std::distance(b, e); + if (d > 255 || d == 0) + { + new(r_ptr()) RString(b, e); + special = 255; + } + else + { + *std::copy(b, e, data) = '\0'; + special = 255 - d; + } + } + + template + AString::AString(const VString& v) + : data{}, special() + { + *std::copy(v.begin(), v.end(), data) = '\0'; + special = 255 - v.size(); + if (!v) + new(r_ptr()) RString(); + } +} // namespace strings diff --git a/src/strings/base.hpp b/src/strings/base.hpp index 7461872..c081f70 100644 --- a/src/strings/base.hpp +++ b/src/strings/base.hpp @@ -88,7 +88,7 @@ namespace strings const T& _ref() const; iterator begin() const; iterator end() const; - const FString *base() const; + const RString *base() const; public: size_t size() const; reverse_iterator rbegin() const; diff --git a/src/strings/base.tcc b/src/strings/base.tcc index 491b4ca..a5a57d0 100644 --- a/src/strings/base.tcc +++ b/src/strings/base.tcc @@ -104,7 +104,7 @@ namespace strings return _ref().end(); } template - const FString *_crtp_string::base() const + const RString *_crtp_string::base() const { return _ref().base(); } diff --git a/src/strings/base_test.cpp b/src/strings/base_test.cpp index cb41fa9..3f9900e 100644 --- a/src/strings/base_test.cpp +++ b/src/strings/base_test.cpp @@ -4,7 +4,7 @@ #include "vstring.hpp" #include "xstring.hpp" -#include "fstring.hpp" +#include "rstring.hpp" using namespace strings; @@ -18,7 +18,7 @@ static_assert(!string_comparison_allowed<_test, VString<1>>::value, "tv"); static_assert(!string_comparison_allowed<_test, _test2>::value, "t2"); static_assert(string_comparison_allowed, XString>::value, "vx"); static_assert(string_comparison_allowed::value, "xx"); -static_assert(string_comparison_allowed::value, "xf"); +static_assert(string_comparison_allowed::value, "xf"); TEST(strings, contains) { diff --git a/src/strings/fstring.cpp b/src/strings/fstring.cpp deleted file mode 100644 index 97ef4b0..0000000 --- a/src/strings/fstring.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "fstring.hpp" -// strings/fstring.cpp - Functions for fstring.hpp -// -// Copyright © 2013-2014 Ben Longbons -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include "mstring.hpp" -#include "tstring.hpp" -#include "sstring.hpp" -#include "zstring.hpp" -#include "xstring.hpp" -#include "vstring.hpp" - -namespace strings -{ - uint8_t FString::empty_string_rep[sizeof(Rep) + 1]; - - FString::FString() - : owned(reinterpret_cast(&empty_string_rep)) - { - owned->count++; - } - - FString::FString(const FString& r) - : owned(r.owned) - { - owned->count++; - } - FString::FString(FString&& r) - : owned(reinterpret_cast(&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() - { - 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(); - const char *xe = &*x.end(); - const char *fb = f ? &*f->begin() : nullptr; - const char *fe = f ? &*f->end() : nullptr; - if (f && xb == fb && xe == fe) - *this = *f; - else - _assign(x.begin(), x.end()); - } - - FString::iterator FString::begin() const - { - return owned->body; - } - FString::iterator FString::end() const - { - return owned->body + owned->size; - } - const FString *FString::base() const - { - return this; - } - const char *FString::c_str() const - { - return &*begin(); - } - - const char *decay_for_printf(const FString& fs) - { - return fs.c_str(); - } - - int do_vprint(FString& out, const char *fmt, va_list ap) - { - int len; - { - va_list ap2; - va_copy(ap2, ap); - len = vsnprintf(nullptr, 0, fmt, ap2); - va_end(ap2); - } - char buffer[len + 1]; - vsnprintf(buffer, len + 1, fmt, ap); - - out = FString(buffer, buffer + len); - return len; - } - - StringConverter::StringConverter(FString& s) - : out(s), mid(nullptr) - {} - - StringConverter::~StringConverter() - { - if (mid) - { - out = ZString(really_construct_from_a_pointer, mid, nullptr); - free(mid); - } - } - - char **StringConverter::operator &() - { - return ∣ - } - - StringConverter convert_for_scanf(FString& s) - { - return StringConverter(s); - } -} // namespace strings diff --git a/src/strings/fstring.hpp b/src/strings/fstring.hpp deleted file mode 100644 index 48da326..0000000 --- a/src/strings/fstring.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef TMWA_STRINGS_FSTRING_HPP -#define TMWA_STRINGS_FSTRING_HPP -// strings/fstring.hpp - An owned, reference-counted immutable string. -// -// Copyright © 2013-2014 Ben Longbons -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -# include -# include - -# include "base.hpp" - -namespace strings -{ - /// An owning string that has reached its final contents. - /// The storage is NUL-terminated - class FString : public _crtp_string - { - struct Rep - { - size_t count; - size_t size; - char body[]; - }; - static - uint8_t empty_string_rep[sizeof(Rep) + 1]; - - Rep *owned; - - template - 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); - - template - FString(char (&s)[n]) = delete; - - template - FString(const char (&s)[n]); - - template - FString(It b, It e); - - FString(XPair p); - //FString(const FString&) - FString(const TString&); - FString(const SString&); - FString(ZString); - FString(XString); - template - FString(const VString& v); - - iterator begin() const; - iterator end() const; - const FString *base() const; - const char *c_str() const; - }; - - // cxxstdio helpers - // I think the conversion will happen automatically. TODO test this. - // Nope, it doesn't, since there's a template - // Actually, it might now. - const char *decay_for_printf(const FString& fs); - - __attribute__((format(printf, 2, 0))) - int do_vprint(FString& out, const char *fmt, va_list ap); - - class StringConverter - { - FString& out; - char *mid; - public: - StringConverter(FString& s); - ~StringConverter(); - char **operator &(); - }; - - StringConverter convert_for_scanf(FString& s); -} // namespace strings - -# include "fstring.tcc" - -#endif // TMWA_STRINGS_FSTRING_HPP diff --git a/src/strings/fstring.py b/src/strings/fstring.py deleted file mode 100644 index 5418300..0000000 --- a/src/strings/fstring.py +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index 8072fb0..0000000 --- a/src/strings/fstring.tcc +++ /dev/null @@ -1,67 +0,0 @@ -// strings/fstring.tcc - Inline functions for fstring.hpp -// -// Copyright © 2013 Ben Longbons -// -// This file is part of The Mana World (Athena server) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include "mstring.hpp" - -namespace strings -{ - template - void FString::_assign(It b, It e) - { - owned = nullptr; - if (b == e) - { - *this = FString(); - return; - } - if (!std::is_base_of::iterator_category>::value) - { - // can't use std::distance - MString m; - for (; b != e; ++b) - m += *b; - *this = FString(m); // will recurse - return; - } - size_t diff = std::distance(b, e); - owned = static_cast(::operator new(sizeof(Rep) + diff + 1)); - owned->count = 0; - owned->size = diff; - std::copy(b, e, owned->body); - owned->body[diff] = '\0'; - } - - template - FString::FString(const char (&s)[n]) - { - _assign(s, s + strlen(s)); - } - - template - FString::FString(It b, It e) - { - _assign(b, e); - } - - template - FString::FString(const VString& v) - { - _assign(v.begin(), v.end()); - } -} // namespace strings diff --git a/src/strings/fwd.hpp b/src/strings/fwd.hpp index a865fc4..f2b4037 100644 --- a/src/strings/fwd.hpp +++ b/src/strings/fwd.hpp @@ -28,7 +28,8 @@ namespace strings { // owning class MString; - class FString; + class RString; + class AString; class TString; // C legacy version of SString class SString; // is this one really worth it? @@ -46,7 +47,8 @@ namespace strings } // namespace strings using strings::MString; -using strings::FString; +using strings::RString; +using strings::AString; using strings::TString; using strings::SString; diff --git a/src/strings/rstring.cpp b/src/strings/rstring.cpp new file mode 100644 index 0000000..eb9d88a --- /dev/null +++ b/src/strings/rstring.cpp @@ -0,0 +1,164 @@ +#include "rstring.hpp" +// strings/rstring.cpp - Functions for rstring.hpp +// +// Copyright © 2013-2014 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "mstring.hpp" +#include "tstring.hpp" +#include "sstring.hpp" +#include "zstring.hpp" +#include "xstring.hpp" +#include "vstring.hpp" + +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)) + { + owned->count++; + } + + RString::RString(const RString& r) + : owned(r.owned) + { + owned->count++; + } + RString::RString(RString&& r) + : owned(reinterpret_cast(&empty_string_rep)) + { + std::swap(owned, r.owned); + r.owned->count++; + } + RString& RString::operator = (const RString& 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; + } + RString& RString::operator = (RString&& r) + { + std::swap(owned, r.owned); + return *this; + } + RString::RString(AString a) + : owned(nullptr) + { + if (RString *r = const_cast(a.base())) + { + *this = std::move(*r); + } + else + { + *this = XPair(a); + } + } + RString::~RString() + { + if (owned && !owned->count--) + ::operator delete(owned); + owned = nullptr; + } + + RString::RString(const MString& s) + : owned(nullptr) + { + _assign(s.begin(), s.end()); + } + + RString::RString(XPair p) + : owned(nullptr) + { + _assign(p.begin(), p.end()); + } + + RString::RString(const TString& t) + : owned(nullptr) + { + *this = XString(t); + } + RString::RString(const SString& s) + : owned(nullptr) + { + *this = XString(s); + } + RString::RString(ZString z) + : owned(nullptr) + { + *this = XString(z); + } + RString::RString(XString x) + : owned(nullptr) + { + const RString *f = x.base(); + const char *xb = &*x.begin(); + const char *xe = &*x.end(); + const char *fb = f ? &*f->begin() : nullptr; + const char *fe = f ? &*f->end() : nullptr; + if (f && xb == fb && xe == fe) + *this = *f; + else + _assign(x.begin(), x.end()); + } + + RString::iterator RString::begin() const + { + return owned->body; + } + RString::iterator RString::end() const + { + return owned->body + owned->size; + } + const RString *RString::base() const + { + return this; + } + const char *RString::c_str() const + { + return &*begin(); + } + + const char *decay_for_printf(const RString& fs) + { + return fs.c_str(); + } + + int do_vprint(RString& out, const char *fmt, va_list ap) + { + int len; + { + va_list ap2; + va_copy(ap2, ap); + len = vsnprintf(nullptr, 0, fmt, ap2); + va_end(ap2); + } + char buffer[len + 1]; + vsnprintf(buffer, len + 1, fmt, ap); + + out = RString(buffer, buffer + len); + return len; + } +} // namespace strings diff --git a/src/strings/rstring.hpp b/src/strings/rstring.hpp new file mode 100644 index 0000000..b79c7f6 --- /dev/null +++ b/src/strings/rstring.hpp @@ -0,0 +1,93 @@ +#ifndef TMWA_STRINGS_RSTRING_HPP +#define TMWA_STRINGS_RSTRING_HPP +// strings/rstring.hpp - An owned, reference-counted immutable string. +// +// Copyright © 2013-2014 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +# include +# include + +# include "base.hpp" + +namespace strings +{ + /// An owning string that has reached its final contents. + /// The storage is NUL-terminated + class RString : public _crtp_string + { + struct Rep + { + size_t count; + size_t size; + char body[]; + }; + static + uint8_t empty_string_rep[sizeof(Rep) + 1]; + + Rep *owned; + + template + void _assign(It b, It e); + public: + RString(); + RString(const RString&); + RString(RString&&); + RString& operator = (const RString&); + RString& operator = (RString&&); + RString(AString); + ~RString(); + + explicit RString(const MString& s); + + template + RString(char (&s)[n]) = delete; + + template + RString(const char (&s)[n]); + + template + RString(It b, It e); + + RString(XPair p); + //RString(const RString&) + RString(const TString&); + RString(const SString&); + RString(ZString); + RString(XString); + template + RString(const VString& v); + + iterator begin() const; + iterator end() const; + const RString *base() const; + const char *c_str() const; + }; + + // cxxstdio helpers + // I think the conversion will happen automatically. TODO test this. + // Nope, it doesn't, since there's a template + // Actually, it might now. + const char *decay_for_printf(const RString& fs); + + __attribute__((format(printf, 2, 0))) + int do_vprint(RString& out, const char *fmt, va_list ap); +} // namespace strings + +# include "rstring.tcc" + +#endif // TMWA_STRINGS_RSTRING_HPP diff --git a/src/strings/rstring.py b/src/strings/rstring.py new file mode 100644 index 0000000..f0618d6 --- /dev/null +++ b/src/strings/rstring.py @@ -0,0 +1,19 @@ +class RString(object): + ''' print a RString + ''' + __slots__ = ('_value') + name = 'strings::RString' + 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/rstring.tcc b/src/strings/rstring.tcc new file mode 100644 index 0000000..8b4c0c0 --- /dev/null +++ b/src/strings/rstring.tcc @@ -0,0 +1,67 @@ +// strings/rstring.tcc - Inline functions for rstring.hpp +// +// Copyright © 2013 Ben Longbons +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "mstring.hpp" + +namespace strings +{ + template + void RString::_assign(It b, It e) + { + owned = nullptr; + if (b == e) + { + *this = RString(); + return; + } + if (!std::is_base_of::iterator_category>::value) + { + // can't use std::distance + MString m; + for (; b != e; ++b) + m += *b; + *this = RString(m); // will recurse + return; + } + size_t diff = std::distance(b, e); + owned = static_cast(::operator new(sizeof(Rep) + diff + 1)); + owned->count = 0; + owned->size = diff; + std::copy(b, e, owned->body); + owned->body[diff] = '\0'; + } + + template + RString::RString(const char (&s)[n]) + { + _assign(s, s + strlen(s)); + } + + template + RString::RString(It b, It e) + { + _assign(b, e); + } + + template + RString::RString(const VString& v) + { + _assign(v.begin(), v.end()); + } +} // namespace strings diff --git a/src/strings/sstring.cpp b/src/strings/sstring.cpp index 99f91ed..fee98f9 100644 --- a/src/strings/sstring.cpp +++ b/src/strings/sstring.cpp @@ -27,8 +27,11 @@ namespace strings SString::SString() : _s(), _b(), _e() {} - SString::SString(FString f) - : _s(std::move(f)), _b(), _e(_s.size()) + SString::SString(RString r) + : _s(std::move(r)), _b(), _e(_s.size()) + {} + SString::SString(AString a) + : _s(std::move(a)), _b(), _e(_s.size()) {} SString::SString(TString t) : _s(t._s), _b(0), _e(_s.size()) @@ -39,19 +42,39 @@ namespace strings } SString::SString(const XString& x) { - const FString *f = x.base(); + const RString *r = x.base(); const char *xb = &*x.begin(); const char *xe = &*x.end(); - const char *fb = f ? &*f->begin() : nullptr; - //const char *fe = f ? &*f->end() : nullptr; - if (f) - *this = SString(*f, xb - fb, xe - fb); + const char *rb = r ? &*r->begin() : nullptr; + //const char *re = r ? &*r->end() : nullptr; + if (r) + *this = SString(*r, xb - rb, xe - rb); else - *this = FString(x); + *this = RString(x); } - SString::SString(FString f, size_t b, size_t e) - : _s(std::move(f)), _b(b), _e(e) + SString::SString(RString r, size_t b, size_t e) + : _s(std::move(r)), _b(b), _e(e) + {} + static + RString get_owned_slice(AString a, size_t *b, size_t *e) + { + if (a.base()) + { + // it's futile + return std::move(a); + } + // have to allocate anyway, so cut first + size_t ob = *b; + size_t oe = *e; + *e -= *b; + *b = 0; + return a.xpslice(ob, oe); + } + SString::SString(AString a, size_t b, size_t e) + : _s(get_owned_slice(std::move(a), &b, &e)) + , _b(b) + , _e(e) {} SString::SString(XPair p) : _s(p), _b(0), _e(p.size()) @@ -65,7 +88,7 @@ namespace strings { return &_s.begin()[_e]; } - const FString *SString::base() const + const RString *SString::base() const { return &_s; } diff --git a/src/strings/sstring.hpp b/src/strings/sstring.hpp index 12fb96d..1836d69 100644 --- a/src/strings/sstring.hpp +++ b/src/strings/sstring.hpp @@ -1,6 +1,6 @@ #ifndef TMWA_STRINGS_SSTRING_HPP #define TMWA_STRINGS_SSTRING_HPP -// strings/sstring.hpp - A full slice of an FString. +// strings/sstring.hpp - A full slice of an RString. // // Copyright © 2013 Ben Longbons // @@ -20,19 +20,20 @@ // along with this program. If not, see . # include "base.hpp" -# include "fstring.hpp" +# include "rstring.hpp" namespace strings { - /// An owning string that represents a arbitrary slice of an FString. + /// An owning string that represents a arbitrary slice of an RString. /// Not guaranteed to be NUL-terminated. class SString : public _crtp_string { - FString _s; + RString _s; size_t _b, _e; public: SString(); - SString(FString f); + SString(RString f); + SString(AString f); SString(TString t); //SString(const SString&); SString(const ZString&); @@ -45,12 +46,13 @@ namespace strings SString(const char (&s)[n]); //template //SString(It b, It e) : _s(b, e), _b(0), _e(_s.size()) {} - SString(FString f, size_t b, size_t e); + SString(RString f, size_t b, size_t e); + SString(AString f, size_t b, size_t e); SString(XPair p); iterator begin() const; iterator end() const; - const FString *base() const; + const RString *base() const; }; } // namespace strings diff --git a/src/strings/strings2_test.cpp b/src/strings/strings2_test.cpp index 3f8662a..24bfc0c 100644 --- a/src/strings/strings2_test.cpp +++ b/src/strings/strings2_test.cpp @@ -6,7 +6,7 @@ TEST(StringTests, traits2) { ZString print_non = "\t\e"; ZString print_mix = "n\t"; - FString print_all = "n "; + RString print_all = "n "; EXPECT_FALSE(print_non.has_print()); EXPECT_TRUE(print_mix.has_print()); EXPECT_TRUE(print_all.has_print()); @@ -20,7 +20,7 @@ TEST(StringTests, traits2) ZString graph_non = " \e"; ZString graph_mix = "n "; - FString graph_all = "n."; + RString graph_all = "n."; EXPECT_FALSE(graph_non.has_graph()); EXPECT_TRUE(graph_mix.has_graph()); EXPECT_TRUE(graph_all.has_graph()); @@ -30,7 +30,7 @@ TEST(StringTests, traits2) ZString lower_non = "0A"; ZString lower_mix = "Oa"; - FString lower_all = "oa"; + RString lower_all = "oa"; EXPECT_FALSE(lower_non.has_lower()); EXPECT_TRUE(lower_mix.has_lower()); EXPECT_TRUE(lower_all.has_lower()); @@ -44,7 +44,7 @@ TEST(StringTests, traits2) ZString upper_non = "0a"; ZString upper_mix = "oA"; - FString upper_all = "OA"; + RString upper_all = "OA"; EXPECT_FALSE(upper_non.has_upper()); EXPECT_TRUE(upper_mix.has_upper()); EXPECT_TRUE(upper_all.has_upper()); @@ -58,7 +58,7 @@ TEST(StringTests, traits2) ZString alpha_non = " 0"; ZString alpha_mix = "n "; - FString alpha_all = "nA"; + RString alpha_all = "nA"; EXPECT_FALSE(alpha_non.has_alpha()); EXPECT_TRUE(alpha_mix.has_alpha()); EXPECT_TRUE(alpha_all.has_alpha()); @@ -68,7 +68,7 @@ TEST(StringTests, traits2) ZString digit2_non = "a9"; ZString digit2_mix = "20"; - FString digit2_all = "01"; + RString digit2_all = "01"; EXPECT_FALSE(digit2_non.has_digit2()); EXPECT_TRUE(digit2_mix.has_digit2()); EXPECT_TRUE(digit2_all.has_digit2()); @@ -78,7 +78,7 @@ TEST(StringTests, traits2) ZString digit8_non = "a9"; ZString digit8_mix = "80"; - FString digit8_all = "37"; + RString digit8_all = "37"; EXPECT_FALSE(digit8_non.has_digit8()); EXPECT_TRUE(digit8_mix.has_digit8()); EXPECT_TRUE(digit8_all.has_digit8()); @@ -88,7 +88,7 @@ TEST(StringTests, traits2) ZString digit10_non = "az"; ZString digit10_mix = "a9"; - FString digit10_all = "42"; + RString digit10_all = "42"; EXPECT_FALSE(digit10_non.has_digit10()); EXPECT_TRUE(digit10_mix.has_digit10()); EXPECT_TRUE(digit10_all.has_digit10()); @@ -98,7 +98,7 @@ TEST(StringTests, traits2) ZString digit16_non = "gz"; ZString digit16_mix = "ao"; - FString digit16_all = "be"; + RString digit16_all = "be"; EXPECT_FALSE(digit16_non.has_digit16()); EXPECT_TRUE(digit16_mix.has_digit16()); EXPECT_TRUE(digit16_all.has_digit16()); @@ -108,7 +108,7 @@ TEST(StringTests, traits2) ZString alnum_non = " ."; ZString alnum_mix = "n "; - FString alnum_all = "n0"; + RString alnum_all = "n0"; EXPECT_FALSE(alnum_non.has_alnum()); EXPECT_TRUE(alnum_mix.has_alnum()); EXPECT_TRUE(alnum_all.has_alnum()); @@ -116,3 +116,89 @@ TEST(StringTests, traits2) EXPECT_FALSE(alnum_mix.is_alnum()); EXPECT_TRUE(alnum_all.is_alnum()); } + +TEST(StringTests, rempty) +{ + const char empty_text[] = ""; + RString r = empty_text; + EXPECT_EQ(r.size(), 0); + AString a = empty_text; + EXPECT_EQ(r, a); + AString r2 = r, r3; + RString a2 = a, a3; + XString r1 = r2; + XString a1 = a2; + r3 = r1; + a3 = a1; + EXPECT_EQ(r, r1); + EXPECT_EQ(a, a1); + EXPECT_EQ(r, r2); + EXPECT_EQ(a, a2); + EXPECT_EQ(r, r3); + EXPECT_EQ(a, a3); + EXPECT_EQ(&*r.begin(), &*r1.begin()); + EXPECT_EQ(&*a.begin(), &*a1.begin()); + EXPECT_EQ(&*r.begin(), &*r2.begin()); + EXPECT_EQ(&*a.begin(), &*a2.begin()); + EXPECT_EQ(&*r.begin(), &*r3.begin()); + EXPECT_EQ(&*a.begin(), &*a3.begin()); +} +TEST(StringTests, rshort) +{ + const char short_text[] = "0123456789"; + RString r = short_text; + EXPECT_EQ(r.size(), 10); + AString a = short_text; + EXPECT_EQ(r, a); + AString r2 = r, r3; + RString a2 = a, a3; + XString r1 = r2; + XString a1 = a2; + r3 = r1; + a3 = a1; + EXPECT_EQ(r, r1); + EXPECT_EQ(a, a1); + EXPECT_EQ(r, r2); + EXPECT_EQ(a, a2); + EXPECT_EQ(r, r3); + EXPECT_EQ(a, a3); + EXPECT_EQ(&*r.begin(), &*r1.begin()); + EXPECT_NE(&*a.begin(), &*a1.begin()); + EXPECT_EQ(&*r.begin(), &*r2.begin()); + EXPECT_NE(&*a.begin(), &*a2.begin()); + EXPECT_EQ(&*r.begin(), &*r3.begin()); + EXPECT_NE(&*a.begin(), &*a3.begin()); +} + +TEST(StringTests, rlong) +{ + const char long_text[] = + "01234567890123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789012345 100" + "01234567890123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789012345 200" + "01234567890123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789012345 300"; + RString r = long_text; + EXPECT_EQ(r.size(), 300); + AString a = long_text; + EXPECT_EQ(r, a); + AString r2 = r, r3; + RString a2 = a, a3; + XString r1 = r2; + XString a1 = a2; + r3 = r1; + a3 = a1; + EXPECT_EQ(r, r1); + EXPECT_EQ(a, a1); + EXPECT_EQ(r, r2); + EXPECT_EQ(a, a2); + EXPECT_EQ(r, r3); + EXPECT_EQ(a, a3); + EXPECT_EQ(&*r.begin(), &*r1.begin()); + EXPECT_EQ(&*a.begin(), &*a1.begin()); + EXPECT_EQ(&*r.begin(), &*r2.begin()); + EXPECT_EQ(&*a.begin(), &*a2.begin()); + EXPECT_EQ(&*r.begin(), &*r3.begin()); + EXPECT_EQ(&*a.begin(), &*a3.begin()); +} diff --git a/src/strings/strings_test.cpp b/src/strings/strings_test.cpp index 82d39d8..55a2ffa 100644 --- a/src/strings/strings_test.cpp +++ b/src/strings/strings_test.cpp @@ -21,7 +21,7 @@ TYPED_TEST_P(StringTest, basic) EXPECT_EQ(0, hi0.size()); __attribute__((unused)) - const FString *base = hi.base(); + const RString *base = hi.base(); } TYPED_TEST_P(StringTest, order) @@ -168,7 +168,8 @@ TYPED_TEST_P(StringTest, convert) constexpr bool is_zstring = std::is_same::value; typedef typename std::conditional::type Sstring; typedef typename std::conditional::type Xstring; - FString f = "f"; + RString r = "r"; + AString a = "a"; TString t = "t"; Sstring s = "s"; ZString z = "z"; @@ -177,7 +178,8 @@ TYPED_TEST_P(StringTest, convert) const char l[] = "l"; VString<5> hi = "hello"; - TypeParam f2 = f; + TypeParam r2 = r; + TypeParam a2 = a; TypeParam t2 = t; TypeParam s2 = s; TypeParam z2 = z; @@ -186,7 +188,8 @@ TYPED_TEST_P(StringTest, convert) TypeParam l2 = l; TypeParam hi2 = hi; - EXPECT_EQ(f, f2); + EXPECT_EQ(r, r2); + EXPECT_EQ(a, a2); EXPECT_EQ(t, t2); EXPECT_EQ(s, s2); EXPECT_EQ(z, z2); @@ -195,8 +198,9 @@ TYPED_TEST_P(StringTest, convert) EXPECT_EQ(l, l2); EXPECT_EQ(hi, hi2); - TypeParam f3, t3, s3, z3, x3, v3, l3, hi3; - f3 = f; + TypeParam r3, a3, t3, s3, z3, x3, v3, l3, hi3; + r3 = r; + a3 = a; t3 = t; s3 = s; z3 = z; @@ -205,7 +209,8 @@ TYPED_TEST_P(StringTest, convert) l3 = l; hi3 = hi; - EXPECT_EQ(f, f3); + EXPECT_EQ(r, r3); + EXPECT_EQ(a, a3); EXPECT_EQ(t, t3); EXPECT_EQ(s, s3); EXPECT_EQ(z, z3); @@ -214,7 +219,8 @@ TYPED_TEST_P(StringTest, convert) EXPECT_EQ(l, l3); EXPECT_EQ(hi, hi3); - TypeParam f4(f); + TypeParam r4(r); + TypeParam a4(a); TypeParam t4(t); TypeParam s4(s); TypeParam z4(z); @@ -223,7 +229,8 @@ TYPED_TEST_P(StringTest, convert) TypeParam l4(l); TypeParam hi4(hi); - EXPECT_EQ(f, f4); + EXPECT_EQ(r, r4); + EXPECT_EQ(a, a4); EXPECT_EQ(t, t4); EXPECT_EQ(s, s4); EXPECT_EQ(z, z4); @@ -237,7 +244,7 @@ REGISTER_TYPED_TEST_CASE_P(StringTest, basic, order, iterators, xslice, convert); typedef ::testing::Types< - FString, TString, SString, ZString, XString, VString<255> + RString, AString, TString, SString, ZString, XString, VString<255> > MostStringTypes; INSTANTIATE_TYPED_TEST_CASE_P(StringStuff, StringTest, MostStringTypes); @@ -274,6 +281,6 @@ REGISTER_TYPED_TEST_CASE_P(NulStringTest, basic); typedef ::testing::Types< - FString, TString, ZString, VString<255> + RString, AString, TString, ZString, VString<255> > NulStringTypes; INSTANTIATE_TYPED_TEST_CASE_P(NulStringStuff, NulStringTest, NulStringTypes); diff --git a/src/strings/tstring.cpp b/src/strings/tstring.cpp index 2d13888..8be7112 100644 --- a/src/strings/tstring.cpp +++ b/src/strings/tstring.cpp @@ -27,9 +27,24 @@ namespace strings TString::TString() : _s(), _o() {} - TString::TString(FString b, size_t i) + TString::TString(RString b, size_t i) : _s(std::move(b)), _o(i) {} + static + RString get_owned_tlice(AString a, size_t *i) + { + if (a.base()) + { + return std::move(a); + } + size_t oi = *i; + *i = 0; + return a.xslice_t(oi); + } + TString::TString(AString b, size_t i) + : _s(get_owned_tlice(std::move(b), &i)) + , _o(i) + {} TString::TString(const SString& s) { *this = XString(s); @@ -40,15 +55,15 @@ namespace strings } TString::TString(const XString& x) { - const FString *f = x.base(); + const RString *r = x.base(); const char *xb = &*x.begin(); const char *xe = &*x.end(); - const char *fb = f ? &*f->begin() : nullptr; - const char *fe = f ? &*f->end() : nullptr; - if (f && xe == fe) - *this = TString(*f, xb - fb); + const char *rb = r ? &*r->begin() : nullptr; + const char *re = r ? &*r->end() : nullptr; + if (r && xe == re) + *this = TString(*r, xb - rb); else - *this = FString(x); + *this = RString(x); } TString::TString(XPair p) @@ -63,7 +78,7 @@ namespace strings { return &*_s.end(); } - const FString *TString::base() const + const RString *TString::base() const { return &_s; } diff --git a/src/strings/tstring.hpp b/src/strings/tstring.hpp index 49ec4ab..700ec3d 100644 --- a/src/strings/tstring.hpp +++ b/src/strings/tstring.hpp @@ -20,20 +20,21 @@ // along with this program. If not, see . # include "base.hpp" -# include "fstring.hpp" +# include "rstring.hpp" namespace strings { - /// An owning string that represents a tail slice of an FString. + /// An owning string that represents a tail slice of an RString. /// Guaranteed to be NUL-terminated. class TString : public _crtp_string { friend class SString; - FString _s; + RString _s; size_t _o; public: TString(); - TString(FString b, size_t i=0); + TString(RString b, size_t i=0); + TString(AString b, size_t i=0); //TString(const TString&) TString(const SString&); TString(const ZString&); @@ -50,7 +51,7 @@ namespace strings iterator begin() const; iterator end() const; - const FString *base() const; + const RString *base() const; const char *c_str() const; }; diff --git a/src/strings/vstring.hpp b/src/strings/vstring.hpp index c07c32a..183e782 100644 --- a/src/strings/vstring.hpp +++ b/src/strings/vstring.hpp @@ -31,7 +31,8 @@ namespace strings public: typedef typename _crtp_string, VString, ZPair>::iterator iterator; VString(XString x); - VString(FString f); + VString(RString f); + VString(AString f); VString(TString t); VString(SString s); VString(ZString z); @@ -48,7 +49,7 @@ namespace strings iterator begin() const; iterator end() const; - const FString *base() const; + const RString *base() const; const char *c_str() const; }; diff --git a/src/strings/vstring.tcc b/src/strings/vstring.tcc index 674b21d..69729d4 100644 --- a/src/strings/vstring.tcc +++ b/src/strings/vstring.tcc @@ -21,7 +21,8 @@ #include "../common/utils2.hpp" -#include "fstring.hpp" +#include "rstring.hpp" +#include "astring.hpp" #include "tstring.hpp" #include "sstring.hpp" #include "zstring.hpp" @@ -43,11 +44,16 @@ namespace strings // poor man's delegated constructors // needed for gcc 4.6 compatibility template - VString::VString(FString f) + VString::VString(RString f) { *this = XString(f); } template + VString::VString(AString a) + { + *this = XString(a); + } + template VString::VString(TString t) { *this = XString(t); @@ -109,7 +115,7 @@ namespace strings return std::end(_data) - _special; } template - const FString *VString::base() const + const RString *VString::base() const { return nullptr; } diff --git a/src/strings/xstring.cpp b/src/strings/xstring.cpp index 107217b..8a604c7 100644 --- a/src/strings/xstring.cpp +++ b/src/strings/xstring.cpp @@ -23,7 +23,10 @@ namespace strings XString::XString() : _b(""), _e(_b), _base() {} - XString::XString(const FString& s) + XString::XString(const RString& s) + : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) + {} + XString::XString(const AString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} XString::XString(const TString& s) @@ -36,10 +39,10 @@ namespace strings : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} - XString::XString(const char *b, const char *e, const FString *base_) + XString::XString(const char *b, const char *e, const RString *base_) : _b(b), _e(e), _base(base_) {} - XString::XString(decltype(really_construct_from_a_pointer) e, const char *s, const FString *base_) + XString::XString(decltype(really_construct_from_a_pointer) e, const char *s, const RString *base_) { *this = ZString(e, s, base_); } @@ -55,7 +58,7 @@ namespace strings { return _e; } - const FString *XString::base() const + const RString *XString::base() const { return _base; } diff --git a/src/strings/xstring.hpp b/src/strings/xstring.hpp index e96ef8a..2766810 100644 --- a/src/strings/xstring.hpp +++ b/src/strings/xstring.hpp @@ -25,17 +25,18 @@ namespace strings { /// A non-owning string that is not guaranteed to be NUL-terminated. /// This should be only used as a parameter. - class XString : public _crtp_string + class XString : public _crtp_string { iterator _b, _e; // optional - const FString *_base; + const RString *_base; public: // do I really want this? XString(); XString(std::nullptr_t) = delete; // no MString - XString(const FString& s); + XString(const RString& s); + XString(const AString& s); XString(const TString& s); XString(const SString& s); XString(const ZString& s); @@ -46,13 +47,13 @@ namespace strings template XString(const char (&s)[n]); // mostly internal - XString(const char *b, const char *e, const FString *base_); - XString(decltype(really_construct_from_a_pointer) e, const char *s, const FString *base_); + XString(const char *b, const char *e, const RString *base_); + XString(decltype(really_construct_from_a_pointer) e, const char *s, const RString *base_); XString(XPair p); iterator begin() const; iterator end() const; - const FString *base() const; + const RString *base() const; }; } // namespace strings diff --git a/src/strings/zstring.cpp b/src/strings/zstring.cpp index 0de836c..bfc0c96 100644 --- a/src/strings/zstring.cpp +++ b/src/strings/zstring.cpp @@ -26,16 +26,19 @@ namespace strings { *this = ZString(""); } - ZString::ZString(const FString& s) + ZString::ZString(const RString& s) + : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) + {} + ZString::ZString(const AString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} ZString::ZString(const TString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} - ZString::ZString(const char *b, const char *e, const FString *base_) + ZString::ZString(const char *b, const char *e, const RString *base_) : _b(b), _e(e), _base(base_) {} - ZString::ZString(decltype(really_construct_from_a_pointer), const char *s, const FString *base_) + ZString::ZString(decltype(really_construct_from_a_pointer), const char *s, const RString *base_) : _b(s), _e(s + strlen(s)), _base(base_) {} @@ -47,7 +50,7 @@ namespace strings { return _e; } - const FString *ZString::base() const + const RString *ZString::base() const { return _base; } diff --git a/src/strings/zstring.hpp b/src/strings/zstring.hpp index 72a227c..96aadc0 100644 --- a/src/strings/zstring.hpp +++ b/src/strings/zstring.hpp @@ -27,15 +27,16 @@ namespace strings { /// A non-owning string that is guaranteed to be NUL-terminated. /// This should be only used as a parameter. - class ZString : public _crtp_string + class ZString : public _crtp_string { iterator _b, _e; // optional - const FString *_base; + const RString *_base; public: ZString(); // no MString - ZString(const FString& s); + ZString(const RString& s); + ZString(const AString& s); ZString(const TString& s); ZString(const SString&) = delete; //ZString(ZString); @@ -43,16 +44,16 @@ namespace strings template ZString(const VString& s); // dangerous - ZString(const char *b, const char *e, const FString *base_); - ZString(decltype(really_construct_from_a_pointer), const char *s, const FString *base_); + ZString(const char *b, const char *e, const RString *base_); + ZString(decltype(really_construct_from_a_pointer), const char *s, const RString *base_); template ZString(char (&s)[n]) = delete; template - ZString(const char (&s)[n], const FString *base_=nullptr); + ZString(const char (&s)[n], const RString *base_=nullptr); iterator begin() const; iterator end() const; - const FString *base() const; + const RString *base() const; const char *c_str() const; }; diff --git a/src/strings/zstring.tcc b/src/strings/zstring.tcc index 1065b7c..fe0e9f3 100644 --- a/src/strings/zstring.tcc +++ b/src/strings/zstring.tcc @@ -29,7 +29,7 @@ namespace strings {} template - ZString::ZString(const char (&s)[n], const FString *base_) + ZString::ZString(const char (&s)[n], const RString *base_) : _b(s), _e(s + strlen(s)), _base(base_) {} } // namespace strings -- cgit v1.2.3-70-g09d2