summaryrefslogtreecommitdiff
path: root/zen/string_base.h
diff options
context:
space:
mode:
Diffstat (limited to 'zen/string_base.h')
-rw-r--r--zen/string_base.h378
1 files changed, 149 insertions, 229 deletions
diff --git a/zen/string_base.h b/zen/string_base.h
index b54c3b2e..1ee37563 100644
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -26,7 +26,7 @@ Allocator Policy:
*/
class AllocatorOptimalSpeed //exponential growth + min size
{
-public:
+protected:
//::operator new/ ::operator delete show same performance characterisics like malloc()/free()!
static void* allocate(size_t size) { return ::malloc(size); } //throw std::bad_alloc
static void deallocate(void* ptr) { ::free(ptr); }
@@ -38,7 +38,7 @@ public:
class AllocatorOptimalMemory //no wasted memory, but more reallocations required when manipulating string
{
-public:
+protected:
static void* allocate(size_t size) { return ::malloc(size); } //throw std::bad_alloc
static void deallocate(void* ptr) { ::free(ptr); }
static size_t calcCapacity(size_t length) { return length; }
@@ -81,8 +81,9 @@ protected:
Char* clone(Char* ptr)
{
- Char* newData = create(length(ptr)); //throw std::bad_alloc
- std::copy(ptr, ptr + length(ptr) + 1, newData);
+ const size_t len = length(ptr);
+ Char* newData = create(len); //throw std::bad_alloc
+ std::copy(ptr, ptr + len + 1, newData);
return newData;
}
@@ -207,25 +208,28 @@ private:
static const Descriptor* descr(const Char* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
};
+
+template <class Char>
+using DefaultStoragePolicy = StorageRefCountThreadSafe<Char, AllocatorOptimalSpeed>;
+
+
//################################################################################################################################################################
//perf note: interestingly StorageDeepCopy and StorageRefCountThreadSafe show same performance in FFS comparison
-template <class Char, //Character Type
- template <class, class> class SP = StorageRefCountThreadSafe, //Storage Policy
- class AP = AllocatorOptimalSpeed> //Allocator Policy
-class Zbase : public SP<Char, AP>
+template <class Char, //Character Type
+ template <class> class SP = DefaultStoragePolicy> //Storage Policy
+class Zbase : public SP<Char>
{
public:
Zbase();
- Zbase(const Char* source); //implicit conversion from a C-string
- Zbase(const Char* source, size_t length);
- Zbase(const Zbase& source);
+ Zbase(const Char* str) : Zbase(str, str + strLength(str)) {} //implicit conversion from a C-string!
+ Zbase(const Char* str, size_t len) : Zbase(str, str + len) {}
+ Zbase(const Zbase& str);
Zbase(Zbase&& tmp) noexcept;
- //explicit Zbase(Char source); //dangerous if implicit: Char buffer[]; return buffer[0]; ups... forgot &, but not a compiler error! //-> non-standard extension!!!
-
- //allow explicit construction from different string type, prevent ambiguity via SFINAE
- //template <class S> explicit Zbase(const S& other, typename S::value_type = 0);
+ template <class InputIterator>
+ Zbase(InputIterator first, InputIterator last);
+ //explicit Zbase(Char ch); //dangerous if implicit: Char buffer[]; return buffer[0]; ups... forgot &, but not a compiler error! //-> non-standard extension!!!
~Zbase();
@@ -238,19 +242,17 @@ public:
using const_reference = const Char&;
using value_type = Char;
- Zbase(const_iterator first, const_iterator last);
- Char* begin();
- Char* end ();
- const Char* begin() const;
- const Char* end () const;
- const Char* cbegin() const { return begin(); }
- const Char* cend () const { return end(); }
+ iterator begin();
+ iterator end ();
+ const_iterator begin () const { return rawStr_; }
+ const_iterator end () const { return rawStr_ + length(); }
+ const_iterator cbegin() const { return begin(); }
+ const_iterator cend () const { return end (); }
//std::string functions
size_t length() const;
size_t size () const { return length(); }
- const Char* c_str() const { return rawStr; } //C-string format with 0-termination
- const Char* data() const { return rawStr; } //internal representation, 0-termination not guaranteed
+ const Char* c_str() const { return rawStr_; } //C-string format with 0-termination
const Char operator[](size_t pos) const;
bool empty() const { return length() == 0; }
void clear();
@@ -261,20 +263,24 @@ public:
size_t rfind(const Char* str, size_t pos = npos) const; //
//Zbase& replace(size_t pos1, size_t n1, const Zbase& str);
void reserve(size_t minCapacity);
- Zbase& assign(const Char* source, size_t len);
- Zbase& append(const Char* source, size_t len);
+ Zbase& assign(const Char* str, size_t len) { return assign(str, str + len); }
+ Zbase& append(const Char* str, size_t len) { return append(str, str + len); }
+
+ template <class InputIterator> Zbase& assign(InputIterator first, InputIterator last);
+ template <class InputIterator> Zbase& append(InputIterator first, InputIterator last);
+
void resize(size_t newSize, Char fillChar = 0);
- void swap(Zbase& other);
+ void swap(Zbase& str) { std::swap(rawStr_, str.rawStr_); }
void push_back(Char val) { operator+=(val); } //STL access
void pop_back();
- Zbase& operator=(const Zbase& source);
+ Zbase& operator=(const Zbase& str);
Zbase& operator=(Zbase&& tmp) noexcept;
- Zbase& operator=(const Char* source);
- Zbase& operator=(Char source);
- Zbase& operator+=(const Zbase& other);
- Zbase& operator+=(const Char* other);
- Zbase& operator+=(Char ch);
+ Zbase& operator=(const Char* str) { return assign(str, strLength(str)); }
+ Zbase& operator=(Char ch) { return assign(&ch, 1); }
+ Zbase& operator+=(const Zbase& str) { return append(str.c_str(), str.length()); }
+ Zbase& operator+=(const Char* str) { return append(str, strLength(str)); }
+ Zbase& operator+=(Char ch) { return append(&ch, 1); }
static const size_t npos = static_cast<size_t>(-1);
@@ -284,32 +290,32 @@ private:
Zbase& operator+=(int) = delete; //
void push_back (int) = delete; //
- Char* rawStr;
+ Char* rawStr_;
};
-template <class Char, template <class, class> class SP, class AP> bool operator==(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs);
-template <class Char, template <class, class> class SP, class AP> bool operator==(const Zbase<Char, SP, AP>& lhs, const Char* rhs);
-template <class Char, template <class, class> class SP, class AP> inline bool operator==(const Char* lhs, const Zbase<Char, SP, AP>& rhs) { return operator==(rhs, lhs); }
+template <class Char, template <class> class SP> bool operator==(const Zbase<Char, SP>& lhs, const Zbase<Char, SP>& rhs);
+template <class Char, template <class> class SP> bool operator==(const Zbase<Char, SP>& lhs, const Char* rhs);
+template <class Char, template <class> class SP> inline bool operator==(const Char* lhs, const Zbase<Char, SP>& rhs) { return operator==(rhs, lhs); }
-template <class Char, template <class, class> class SP, class AP> inline bool operator!=(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs) { return !operator==(lhs, rhs); }
-template <class Char, template <class, class> class SP, class AP> inline bool operator!=(const Zbase<Char, SP, AP>& lhs, const Char* rhs) { return !operator==(lhs, rhs); }
-template <class Char, template <class, class> class SP, class AP> inline bool operator!=(const Char* lhs, const Zbase<Char, SP, AP>& rhs) { return !operator==(lhs, rhs); }
+template <class Char, template <class> class SP> inline bool operator!=(const Zbase<Char, SP>& lhs, const Zbase<Char, SP>& rhs) { return !operator==(lhs, rhs); }
+template <class Char, template <class> class SP> inline bool operator!=(const Zbase<Char, SP>& lhs, const Char* rhs) { return !operator==(lhs, rhs); }
+template <class Char, template <class> class SP> inline bool operator!=(const Char* lhs, const Zbase<Char, SP>& rhs) { return !operator==(lhs, rhs); }
-template <class Char, template <class, class> class SP, class AP> bool operator<(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs);
-template <class Char, template <class, class> class SP, class AP> bool operator<(const Zbase<Char, SP, AP>& lhs, const Char* rhs);
-template <class Char, template <class, class> class SP, class AP> bool operator<(const Char* lhs, const Zbase<Char, SP, AP>& rhs);
+template <class Char, template <class> class SP> bool operator<(const Zbase<Char, SP>& lhs, const Zbase<Char, SP>& rhs);
+template <class Char, template <class> class SP> bool operator<(const Zbase<Char, SP>& lhs, const Char* rhs);
+template <class Char, template <class> class SP> bool operator<(const Char* lhs, const Zbase<Char, SP>& rhs);
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs) { return Zbase<Char, SP, AP>(lhs) += rhs; }
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, const Char* rhs) { return Zbase<Char, SP, AP>(lhs) += rhs; }
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, Char rhs) { return Zbase<Char, SP, AP>(lhs) += rhs; }
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(const Zbase<Char, SP>& lhs, const Zbase<Char, SP>& rhs) { return Zbase<Char, SP>(lhs) += rhs; }
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(const Zbase<Char, SP>& lhs, const Char* rhs) { return Zbase<Char, SP>(lhs) += rhs; }
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(const Zbase<Char, SP>& lhs, Char rhs) { return Zbase<Char, SP>(lhs) += rhs; }
//don't use unified first argument but save one move-construction in the r-value case instead!
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(Zbase<Char, SP, AP>&& lhs, const Zbase<Char, SP, AP>& rhs) { return std::move(lhs += rhs); } //the move *is* needed!!!
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(Zbase<Char, SP, AP>&& lhs, const Char* rhs) { return std::move(lhs += rhs); } //lhs, is an l-value parameter...
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(Zbase<Char, SP, AP>&& lhs, Char rhs) { return std::move(lhs += rhs); } //and not a local variable => no copy elision
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(Zbase<Char, SP>&& lhs, const Zbase<Char, SP>& rhs) { return std::move(lhs += rhs); } //the move *is* needed!!!
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(Zbase<Char, SP>&& lhs, const Char* rhs) { return std::move(lhs += rhs); } //lhs, is an l-value parameter...
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(Zbase<Char, SP>&& lhs, Char rhs) { return std::move(lhs += rhs); } //and not a local variable => no copy elision
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+( Char lhs, const Zbase<Char, SP, AP>& rhs) { return Zbase<Char, SP, AP>(&lhs, 1) += rhs; }
-template <class Char, template <class, class> class SP, class AP> inline Zbase<Char, SP, AP> operator+(const Char* lhs, const Zbase<Char, SP, AP>& rhs) { return Zbase<Char, SP, AP>(lhs ) += rhs; }
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+( Char lhs, const Zbase<Char, SP>& rhs) { return Zbase<Char, SP>(&lhs, 1) += rhs; }
+template <class Char, template <class> class SP> inline Zbase<Char, SP> operator+(const Char* lhs, const Zbase<Char, SP>& rhs) { return Zbase<Char, SP>(lhs ) += rhs; }
@@ -324,82 +330,51 @@ template <class Char, template <class, class> class SP, class AP> inline Zbase<C
//################################# implementation ########################################
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>::Zbase()
+template <class Char, template <class> class SP> inline
+Zbase<Char, SP>::Zbase()
{
//resist the temptation to avoid this allocation by referening a static global: NO performance advantage, MT issues!
- rawStr = this->create(0);
- rawStr[0] = 0;
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>::Zbase(const Char* source)
-{
- const size_t sourceLen = strLength(source);
- rawStr = this->create(sourceLen);
- std::copy(source, source + sourceLen + 1, rawStr); //include null-termination
+ rawStr_ = this->create(0);
+ rawStr_[0] = 0;
}
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>::Zbase(const Char* source, size_t sourceLen)
+template <class Char, template <class> class SP>
+template <class InputIterator> inline
+Zbase<Char, SP>::Zbase(InputIterator first, InputIterator last)
{
- rawStr = this->create(sourceLen);
- std::copy(source, source + sourceLen, rawStr);
- rawStr[sourceLen] = 0;
+ rawStr_ = this->create(std::distance(first, last));
+ *std::copy(first, last, rawStr_) = 0;
}
-template <class Char, template <class, class> class SP, class AP>
-Zbase<Char, SP, AP>::Zbase(const_iterator first, const_iterator last)
+template <class Char, template <class> class SP> inline
+Zbase<Char, SP>::Zbase(const Zbase<Char, SP>& str)
{
- assert(first <= last);
- const size_t sourceLen = last - first;
- rawStr = this->create(sourceLen);
- std::copy(first, last, rawStr);
- rawStr[sourceLen] = 0;
+ rawStr_ = this->clone(str.rawStr_);
}
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>::Zbase(const Zbase<Char, SP, AP>& source)
+template <class Char, template <class> class SP> inline
+Zbase<Char, SP>::Zbase(Zbase<Char, SP>&& tmp) noexcept
{
- rawStr = this->clone(source.rawStr);
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>::Zbase(Zbase<Char, SP, AP>&& tmp) noexcept
-{
- rawStr = tmp.rawStr;
- tmp.rawStr = nullptr; //usually nullptr would violate the class invarants, but it is good enough for the destructor!
+ rawStr_ = tmp.rawStr_;
+ tmp.rawStr_ = nullptr; //usually nullptr would violate the class invarants, but it is good enough for the destructor!
//caveat: do not increment ref-count of an unshared string! We'd lose optimization opportunity of reusing its memory!
}
-/*
-template <class Char, template <class, class> class SP, class AP>
-template <class S> inline
-Zbase<Char, SP, AP>::Zbase(const S& other, typename S::value_type)
-{
- const size_t sourceLen = other.size();
- rawStr = this->create(sourceLen);
- std::copy(other.c_str(), other.c_str() + sourceLen, rawStr);
- rawStr[sourceLen] = 0;
-}
-*/
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>::~Zbase()
+template <class Char, template <class> class SP> inline
+Zbase<Char, SP>::~Zbase()
{
static_assert(noexcept(this->~Zbase()), ""); //has exception spec of compiler-generated destructor by default
- this->destroy(rawStr); //rawStr may be nullptr; see move constructor!
+ this->destroy(rawStr_); //rawStr_ may be nullptr; see move constructor!
}
-template <class Char, template <class, class> class SP, class AP> inline
-size_t Zbase<Char, SP, AP>::find(const Zbase& str, size_t pos) const
+template <class Char, template <class> class SP> inline
+size_t Zbase<Char, SP>::find(const Zbase& str, size_t pos) const
{
assert(pos <= length());
const size_t len = length();
@@ -410,8 +385,8 @@ size_t Zbase<Char, SP, AP>::find(const Zbase& str, size_t pos) const
}
-template <class Char, template <class, class> class SP, class AP> inline
-size_t Zbase<Char, SP, AP>::find(const Char* str, size_t pos) const
+template <class Char, template <class> class SP> inline
+size_t Zbase<Char, SP>::find(const Char* str, size_t pos) const
{
assert(pos <= length());
const size_t len = length();
@@ -422,8 +397,8 @@ size_t Zbase<Char, SP, AP>::find(const Char* str, size_t pos) const
}
-template <class Char, template <class, class> class SP, class AP> inline
-size_t Zbase<Char, SP, AP>::find(Char ch, size_t pos) const
+template <class Char, template <class> class SP> inline
+size_t Zbase<Char, SP>::find(Char ch, size_t pos) const
{
assert(pos <= length());
const size_t len = length();
@@ -433,8 +408,8 @@ size_t Zbase<Char, SP, AP>::find(Char ch, size_t pos) const
}
-template <class Char, template <class, class> class SP, class AP> inline
-size_t Zbase<Char, SP, AP>::rfind(Char ch, size_t pos) const
+template <class Char, template <class> class SP> inline
+size_t Zbase<Char, SP>::rfind(Char ch, size_t pos) const
{
assert(pos == npos || pos <= length());
const size_t len = length();
@@ -444,8 +419,8 @@ size_t Zbase<Char, SP, AP>::rfind(Char ch, size_t pos) const
}
-template <class Char, template <class, class> class SP, class AP> inline
-size_t Zbase<Char, SP, AP>::rfind(const Char* str, size_t pos) const
+template <class Char, template <class> class SP> inline
+size_t Zbase<Char, SP>::rfind(const Char* str, size_t pos) const
{
assert(pos == npos || pos <= length());
const size_t strLen = strLength(str);
@@ -457,126 +432,112 @@ size_t Zbase<Char, SP, AP>::rfind(const Char* str, size_t pos) const
}
-template <class Char, template <class, class> class SP, class AP> inline
-void Zbase<Char, SP, AP>::resize(size_t newSize, Char fillChar)
+template <class Char, template <class> class SP> inline
+void Zbase<Char, SP>::resize(size_t newSize, Char fillChar)
{
const size_t oldSize = length();
- if (this->canWrite(rawStr, newSize))
+ if (this->canWrite(rawStr_, newSize))
{
if (oldSize < newSize)
- std::fill(rawStr + oldSize, rawStr + newSize, fillChar);
- rawStr[newSize] = 0;
- this->setLength(rawStr, newSize);
+ std::fill(rawStr_ + oldSize, rawStr_ + newSize, fillChar);
+ rawStr_[newSize] = 0;
+ this->setLength(rawStr_, newSize);
}
else
{
Char* newStr = this->create(newSize);
if (oldSize < newSize)
{
- std::copy(rawStr, rawStr + oldSize, newStr);
+ std::copy(rawStr_, rawStr_ + oldSize, newStr);
std::fill(newStr + oldSize, newStr + newSize, fillChar);
}
else
- std::copy(rawStr, rawStr + newSize, newStr);
+ std::copy(rawStr_, rawStr_ + newSize, newStr);
newStr[newSize] = 0;
- this->destroy(rawStr);
- rawStr = newStr;
+ this->destroy(rawStr_);
+ rawStr_ = newStr;
}
}
-template <class Char, template <class, class> class SP, class AP> inline
-bool operator==(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs)
+template <class Char, template <class> class SP> inline
+bool operator==(const Zbase<Char, SP>& lhs, const Zbase<Char, SP>& rhs)
{
return lhs.length() == rhs.length() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); //respect embedded 0
}
-template <class Char, template <class, class> class SP, class AP> inline
-bool operator==(const Zbase<Char, SP, AP>& lhs, const Char* rhs)
+template <class Char, template <class> class SP> inline
+bool operator==(const Zbase<Char, SP>& lhs, const Char* rhs)
{
return lhs.length() == strLength(rhs) && std::equal(lhs.begin(), lhs.end(), rhs); //respect embedded 0
}
-template <class Char, template <class, class> class SP, class AP> inline
-bool operator<(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs)
+template <class Char, template <class> class SP> inline
+bool operator<(const Zbase<Char, SP>& lhs, const Zbase<Char, SP>& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), //respect embedded 0
rhs.begin(), rhs.end());
}
-template <class Char, template <class, class> class SP, class AP> inline
-bool operator<(const Zbase<Char, SP, AP>& lhs, const Char* rhs)
+template <class Char, template <class> class SP> inline
+bool operator<(const Zbase<Char, SP>& lhs, const Char* rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), //respect embedded 0
rhs, rhs + strLength(rhs));
}
-template <class Char, template <class, class> class SP, class AP> inline
-bool operator<(const Char* lhs, const Zbase<Char, SP, AP>& rhs)
+template <class Char, template <class> class SP> inline
+bool operator<(const Char* lhs, const Zbase<Char, SP>& rhs)
{
return std::lexicographical_compare(lhs, lhs + strLength(lhs), //respect embedded 0
rhs.begin(), rhs.end());
}
-template <class Char, template <class, class> class SP, class AP> inline
-size_t Zbase<Char, SP, AP>::length() const
+template <class Char, template <class> class SP> inline
+size_t Zbase<Char, SP>::length() const
{
- return SP<Char, AP>::length(rawStr);
+ return SP<Char>::length(rawStr_);
}
-template <class Char, template <class, class> class SP, class AP> inline
-const Char Zbase<Char, SP, AP>::operator[](size_t pos) const
+template <class Char, template <class> class SP> inline
+const Char Zbase<Char, SP>::operator[](size_t pos) const
{
assert(pos < length()); //design by contract! no runtime check!
- return rawStr[pos];
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-const Char* Zbase<Char, SP, AP>::begin() const
-{
- return rawStr;
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-const Char* Zbase<Char, SP, AP>::end() const
-{
- return rawStr + length();
+ return rawStr_[pos];
}
-template <class Char, template <class, class> class SP, class AP> inline
-Char* Zbase<Char, SP, AP>::begin()
+template <class Char, template <class> class SP> inline
+auto Zbase<Char, SP>::begin() -> iterator
{
reserve(length()); //make unshared!
- return rawStr;
+ return rawStr_;
}
-template <class Char, template <class, class> class SP, class AP> inline
-Char* Zbase<Char, SP, AP>::end()
+template <class Char, template <class> class SP> inline
+auto Zbase<Char, SP>::end() -> iterator
{
return begin() + length();
}
-template <class Char, template <class, class> class SP, class AP> inline
-void Zbase<Char, SP, AP>::clear()
+template <class Char, template <class> class SP> inline
+void Zbase<Char, SP>::clear()
{
if (!empty())
{
- if (this->canWrite(rawStr, 0))
+ if (this->canWrite(rawStr_, 0))
{
- rawStr[0] = 0; //keep allocated memory
- this->setLength(rawStr, 0); //
+ rawStr_[0] = 0; //keep allocated memory
+ this->setLength(rawStr_, 0); //
}
else
*this = Zbase();
@@ -584,111 +545,70 @@ void Zbase<Char, SP, AP>::clear()
}
-template <class Char, template <class, class> class SP, class AP> inline
-void Zbase<Char, SP, AP>::swap(Zbase<Char, SP, AP>& other)
+template <class Char, template <class> class SP> inline
+void Zbase<Char, SP>::reserve(size_t minCapacity) //make unshared and check capacity
{
- std::swap(rawStr, other.rawStr);
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-void Zbase<Char, SP, AP>::reserve(size_t minCapacity) //make unshared and check capacity
-{
- if (!this->canWrite(rawStr, minCapacity))
+ if (!this->canWrite(rawStr_, minCapacity))
{
//allocate a new string
const size_t len = length();
Char* newStr = this->create(len, std::max(len, minCapacity)); //reserve() must NEVER shrink the string: logical const!
- std::copy(rawStr, rawStr + len + 1, newStr); //include 0-termination
+ std::copy(rawStr_, rawStr_ + len + 1, newStr); //include 0-termination
- this->destroy(rawStr);
- rawStr = newStr;
+ this->destroy(rawStr_);
+ rawStr_ = newStr;
}
}
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::assign(const Char* source, size_t len)
+template <class Char, template <class> class SP>
+template <class InputIterator> inline
+Zbase<Char, SP>& Zbase<Char, SP>::assign(InputIterator first, InputIterator last)
{
- if (this->canWrite(rawStr, len))
+ const size_t len = std::distance(first, last);
+ if (this->canWrite(rawStr_, len))
{
- std::copy(source, source + len, rawStr);
- rawStr[len] = 0; //include null-termination
- this->setLength(rawStr, len);
+ *std::copy(first, last, rawStr_) = 0;
+ this->setLength(rawStr_, len);
}
else
- *this = Zbase(source, len);
+ *this = Zbase(first, last);
return *this;
}
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::append(const Char* source, size_t len)
+template <class Char, template <class> class SP>
+template <class InputIterator> inline
+Zbase<Char, SP>& Zbase<Char, SP>::append(InputIterator first, InputIterator last)
{
+ const size_t len = std::distance(first, last);
const size_t thisLen = length();
reserve(thisLen + len); //make unshared and check capacity
- std::copy(source, source + len, rawStr + thisLen);
- rawStr[thisLen + len] = 0;
- this->setLength(rawStr, thisLen + len);
+ *std::copy(first, last, rawStr_ + thisLen) = 0;
+ this->setLength(rawStr_, thisLen + len);
return *this;
}
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(const Zbase<Char, SP, AP>& other)
+template <class Char, template <class> class SP> inline
+Zbase<Char, SP>& Zbase<Char, SP>::operator=(const Zbase<Char, SP>& str)
{
- Zbase<Char, SP, AP>(other).swap(*this);
+ Zbase<Char, SP>(str).swap(*this);
return *this;
}
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(Zbase<Char, SP, AP>&& tmp) noexcept
+template <class Char, template <class> class SP> inline
+Zbase<Char, SP>& Zbase<Char, SP>::operator=(Zbase<Char, SP>&& tmp) noexcept
{
swap(tmp); //don't use unifying assignment but save one move-construction in the r-value case instead!
return *this;
}
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(const Char* source)
-{
- return assign(source, strLength(source));
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(Char ch)
-{
- return assign(&ch, 1);
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator+=(const Zbase<Char, SP, AP>& other)
-{
- return append(other.c_str(), other.length());
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator+=(const Char* other)
-{
- return append(other, strLength(other));
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator+=(Char ch)
-{
- return append(&ch, 1);
-}
-
-
-template <class Char, template <class, class> class SP, class AP> inline
-void Zbase<Char, SP, AP>::pop_back()
+template <class Char, template <class> class SP> inline
+void Zbase<Char, SP>::pop_back()
{
const size_t len = length();
assert(len > 0);
bgstack15