diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/strings.hpp | 113 | ||||
-rw-r--r-- | src/common/strings_test.cpp | 47 |
2 files changed, 132 insertions, 28 deletions
diff --git a/src/common/strings.hpp b/src/common/strings.hpp index 37d4ee7..8562ec4 100644 --- a/src/common/strings.hpp +++ b/src/common/strings.hpp @@ -103,6 +103,7 @@ namespace strings const T& _ref() const { return static_cast<const T&>(*this); } iterator begin() const { return _ref().begin(); } iterator end() const { return _ref().end(); } + const FString *base() const { return _ref().base(); } public: size_t size() const { return end() - begin(); } reverse_iterator rbegin() const { return reverse_iterator(end()); } @@ -110,7 +111,6 @@ namespace strings operator bool() { return size(); } bool operator !() { return !size(); } - char operator[](size_t i) const { return begin()[i]; } char front() const { return *begin(); } char back() const { return end()[-1]; } @@ -181,6 +181,7 @@ namespace strings iterator begin() const { return &*_hack.begin(); } iterator end() const { return &*_hack.end(); } + const FString *base() const { return this; } const char *c_str() const { return &*begin(); } TString oslice_t(size_t o) const; @@ -201,9 +202,14 @@ namespace strings public: TString() : _s(), _o() {} TString(FString b, size_t i=0) : _s(std::move(b)), _o(i) {} + template<size_t n> + TString(char (&s)[n]) = delete; + template<size_t n> + TString(const char (&s)[n]) : _s(s), _o(0) {} iterator begin() const { return &_s.begin()[_o]; } iterator end() const { return &*_s.end(); } + const FString *base() const { return &_s; } const char *c_str() const { return &*begin(); } TString oslice_t(size_t o) const; @@ -227,10 +233,16 @@ namespace strings SString() : _s(), _b(), _e() {} SString(FString f) : _s(std::move(f)), _b(), _e(_s.size()) {} SString(TString t) : _s(t._s), _e(_s.size()) {} + template<size_t n> + SString(char (&s)[n]) = delete; + template<size_t n> + SString(const char (&s)[n]) : _s(s), _b(0), _e(_s.size()) {} + SString(FString f, size_t b, size_t e) : _s(std::move(f)), _b(b), _e(e) {} iterator begin() const { return &_s.begin()[_b]; } iterator end() const { return &_s.begin()[_e]; } + const FString *base() const { return &_s; } SString oslice_t(size_t o) const; SString oslice_h(size_t o) const; @@ -250,26 +262,29 @@ namespace strings class ZString : public _crtp_string<ZString> { iterator _b, _e; + // optional + const FString *_base; public: #ifndef __clang__ __attribute__((warning("This should be removed in the next diff"))) #endif - ZString(const std::string& s) : _b(&*s.begin()), _e(&*s.end()) {} + ZString(const std::string& s) : _b(&*s.begin()), _e(&*s.end()), _base(nullptr) {} enum { really_construct_from_a_pointer }; ZString() { *this = ZString(""); } // no MString - ZString(const FString& s) : _b(&*s.begin()), _e(&*s.end()) {} - ZString(const TString& s) : _b(&*s.begin()), _e(&*s.end()) {} - // no SString - ZString(decltype(really_construct_from_a_pointer), const char *s) : _b(s), _e(s + strlen(s)) {} + ZString(const FString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + ZString(const TString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + ZString(const SString&) = delete; + ZString(decltype(really_construct_from_a_pointer), const char *s, const FString *base_) : _b(s), _e(s + strlen(s)), _base(base_) {} template<size_t n> ZString(char (&s)[n]) = delete; template<size_t n> - ZString(const char (&s)[n]) : _b(s), _e(s + strlen(s)) {} + ZString(const char (&s)[n], const FString *base_=nullptr) : _b(s), _e(s + strlen(s)), _base(base_) {} iterator begin() const { return _b; } iterator end() const { return _e; } + const FString *base() const { return _base; } const char *c_str() const { return &*begin(); } ZString oslice_t(size_t o) const; @@ -278,6 +293,13 @@ namespace strings XString orslice_h(size_t no) const; XString olslice(size_t o, size_t l) const; XString opslice(size_t b, size_t e) const; + + operator FString() + { if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); } + operator TString() + { if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); } + operator SString() + { if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); } }; /// A non-owning string that is not guaranteed to be NUL-terminated. @@ -285,24 +307,31 @@ namespace strings class XString : public _crtp_string<XString> { iterator _b, _e; + // optional + const FString *_base; public: // do I really want this? XString() : _b(nullptr), _e(nullptr) {} XString(std::nullptr_t) = delete; // no MString - XString(const FString& s) : _b(&*s.begin()), _e(&*s.end()) {} - XString(const TString& s) : _b(&*s.begin()), _e(&*s.end()) {} - XString(const SString& s) : _b(&*s.begin()), _e(&*s.end()) {} - XString(const ZString& s) : _b(&*s.begin()), _e(&*s.end()) {} + XString(const FString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + XString(const TString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + XString(const SString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} + XString(const ZString& s) : _b(&*s.begin()), _e(&*s.end()), _base(s.base()) {} template<size_t n> XString(char (&s)[n]) = delete; template<size_t n> - XString(const char (&s)[n]) : _b(s), _e(s + strlen(s)) {} + XString(const char (&s)[n]) : _b(s), _e(s + strlen(s)), _base(nullptr) {} // mostly internal - XString(const char *b, const char *e) : _b(b), _e(e) {} + XString(const char *b, const char *e, const FString *base_) : _b(b), _e(e), _base(base_) {} + XString(decltype(ZString::really_construct_from_a_pointer) e, const char *s, const FString *base_) + { + *this = ZString(e, s, base_); + } iterator begin() const { return _b; } iterator end() const { return _e; } + const FString *base() const { return _base; }; XString oslice_t(size_t o) const { return xslice_t(o); } XString oslice_h(size_t o) const { return xslice_h(o); } @@ -310,6 +339,14 @@ namespace strings XString orslice_h(size_t no) const { return xrslice_h(no); } XString olslice(size_t o, size_t l) const { return xlslice(o, l); } XString opslice(size_t b, size_t e) const { return xpslice(b, e); } + + operator FString() + { if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); } + operator TString() + { if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); } + operator SString() + { if (_base) return SString(*_base, &*_b - &*_base->begin(), &*_e - &*_base->begin()); else return FString(_b, _e); } + operator ZString() = delete; }; template<uint8_t n> @@ -332,6 +369,22 @@ namespace strings } // poor man's delegated constructors // needed for gcc 4.6 compatibility + VString(FString f) + { + *this = XString(f); + } + VString(TString t) + { + *this = XString(t); + } + VString(SString s) + { + *this = XString(s); + } + VString(ZString z) + { + *this = XString(z); + } template<size_t m> VString(char (&s)[m]) = delete; template<size_t m> @@ -342,7 +395,7 @@ namespace strings } VString(decltype(ZString::really_construct_from_a_pointer) e, const char *s) { - *this = XString(ZString(e, s)); + *this = XString(e, s, nullptr); } VString() { @@ -351,6 +404,7 @@ namespace strings // hopefully this is obvious iterator begin() const { return std::begin(_data); } iterator end() const { return std::end(_data) - _special; } + const FString *base() const { return nullptr; }; const char *c_str() const { return &*begin(); } VString oslice_t(size_t o) const { return this->xslice_t(o); } @@ -359,7 +413,12 @@ namespace strings VString orslice_h(size_t no) const { return this->xrslice_h(no); } VString olslice(size_t o, size_t l) const { return this->xlslice(o, l); } VString opslice(size_t b, size_t e) const { return this->xpslice(b, e); } - operator XString() const { return XString(&*begin(), &*end()); } + + operator FString() const { return FString(begin(), end()); } + operator TString() const { return FString(begin(), end()); } + operator SString() const { return FString(begin(), end()); } + operator ZString() const { return ZString(_data); } + operator XString() const { return XString(&*begin(), &*end(), nullptr); } }; @@ -415,22 +474,22 @@ namespace strings // _crtp_string template<class T> XS _crtp_string<T>::xslice_t(size_t o) const - { return XS(&begin()[o], &*end()); } + { return XS(&begin()[o], &*end(), base()); } template<class T> XS _crtp_string<T>::xslice_h(size_t o) const - { return XS(&*begin(), &begin()[o]); } + { return XS(&*begin(), &begin()[o], base()); } template<class T> XS _crtp_string<T>::xrslice_t(size_t no) const - { return XS(&end()[-no], &*end()); } + { return XS(&end()[-no], &*end(), base()); } template<class T> XS _crtp_string<T>::xrslice_h(size_t no) const - { return XS(&*begin(), &end()[-no]); } + { return XS(&*begin(), &end()[-no], base()); } template<class T> XS _crtp_string<T>::xlslice(size_t o, size_t l) const - { return XS(&begin()[o], &begin()[o + l]); } + { return XS(&begin()[o], &begin()[o + l], base()); } template<class T> XS _crtp_string<T>::xpslice(size_t b, size_t e) const - { return XS(&begin()[b], &begin()[e]); } + { return XS(&begin()[b], &begin()[e], base()); } template<class T> bool _crtp_string<T>::startswith(XS x) const { return size() > x.size() && xslice_h(x.size()) == x; } @@ -501,22 +560,22 @@ namespace strings // ZString inline ZS ZS::oslice_t(size_t o) const - { return ZS(really_construct_from_a_pointer, &begin()[o]); } + { return ZS(really_construct_from_a_pointer, &begin()[o], base()); } inline XS ZS::oslice_h(size_t o) const - { return XS(&*begin(), &begin()[o]); } + { return XS(&*begin(), &begin()[o], base()); } inline ZS ZS::orslice_t(size_t no) const - { return ZS(really_construct_from_a_pointer, &end()[-no]); } + { return ZS(really_construct_from_a_pointer, &end()[-no], base()); } inline XS ZS::orslice_h(size_t no) const - { return XS(&*begin(), &end()[-no]); } + { return XS(&*begin(), &end()[-no], base()); } inline XS ZS::olslice(size_t o, size_t l) const - { return XS(&begin()[o], &begin()[o + l]); } + { return XS(&begin()[o], &begin()[o + l], base()); } inline XS ZS::opslice(size_t b, size_t e) const - { return XS(&begin()[b], &begin()[e]); } + { return XS(&begin()[b], &begin()[e], base()); } // cxxstdio helpers diff --git a/src/common/strings_test.cpp b/src/common/strings_test.cpp index e83d283..b6a6f67 100644 --- a/src/common/strings_test.cpp +++ b/src/common/strings_test.cpp @@ -17,6 +17,9 @@ TYPED_TEST_P(StringTest, basic) EXPECT_EQ(hi, hi2); TypeParam hi0; EXPECT_EQ(0, hi0.size()); + + __attribute__((unused)) + const FString *base = hi.base(); } TYPED_TEST_P(StringTest, iterators) @@ -53,8 +56,50 @@ TYPED_TEST_P(StringTest, oslice) EXPECT_EQ("World", hi.opslice(7, 12)); } +TYPED_TEST_P(StringTest, convert) +{ + constexpr bool is_zstring = std::is_same<TypeParam, ZString>::value; + typedef typename std::conditional<is_zstring, TString, SString>::type Sstring; + typedef typename std::conditional<is_zstring, ZString, XString>::type Xstring; + FString f = "f"; + TString t = "t"; + Sstring s = "s"; + ZString z = "z"; + Xstring x = "x"; + VString<255> v = "v"; + + TypeParam f2 = f; + TypeParam t2 = t; + TypeParam s2 = s; + TypeParam z2 = z; + TypeParam x2 = x; + TypeParam v2 = v; + + EXPECT_EQ(f2, f); + EXPECT_EQ(t2, t); + EXPECT_EQ(s2, s); + EXPECT_EQ(z2, z); + EXPECT_EQ(x2, x); + EXPECT_EQ(v2, v); + + TypeParam f3, t3, s3, z3, x3, v3; + f3 = f; + t3 = t; + s3 = s; + z3 = z; + x3 = x; + v3 = v; + + EXPECT_EQ(f3, f); + EXPECT_EQ(t3, t); + EXPECT_EQ(s3, s); + EXPECT_EQ(z3, z); + EXPECT_EQ(x3, x); + EXPECT_EQ(v3, v); +} + REGISTER_TYPED_TEST_CASE_P(StringTest, - basic, iterators, xslice, oslice); + basic, iterators, xslice, oslice, convert); typedef ::testing::Types< FString, TString, SString, ZString, XString, VString<255> |