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.h497
1 files changed, 237 insertions, 260 deletions
diff --git a/zen/string_base.h b/zen/string_base.h
index 914e0434..ffc2f839 100644
--- a/zen/string_base.h
+++ b/zen/string_base.h
@@ -12,9 +12,11 @@
#include "string_tools.h"
#include <boost/detail/atomic_count.hpp>
-//Zbase - a policy based string class
+//Zbase - a policy based string class optimizing performance and genericity
+namespace zen
+{
/*
Allocator Policy:
-----------------
@@ -28,7 +30,7 @@ public:
//::operator new/ ::operator delete show same performance characterisics like malloc()/free()!
static void* allocate(size_t size) { return ::operator new(size); } //throw (std::bad_alloc)
static void deallocate(void* ptr) { ::operator delete(ptr); }
- static size_t calcCapacity(size_t length) { return std::max<size_t>(16, length + length / 2); }
+ static size_t calcCapacity(size_t length) { return std::max<size_t>(16, length + length / 2); } //any growth rate should not exceed golden ratio: 1.618033989
};
@@ -43,54 +45,54 @@ public:
/*
Storage Policy:
---------------
-template <typename T, //Character Type
- class AP> //Allocator Policy
-
- T* create(size_t size)
- T* create(size_t size, size_t minCapacity)
- T* clone(T* ptr)
- void destroy(T* ptr)
- bool canWrite(const T* ptr, size_t minCapacity) //needs to be checked before writing to "ptr"
- size_t length(const T* ptr)
- void setLength(T* ptr, size_t newLength)
+template <typename Char, //Character Type
+ class AP> //Allocator Policy
+
+ Char* create(size_t size)
+ Char* create(size_t size, size_t minCapacity)
+ Char* clone(Char* ptr)
+ void destroy(Char* ptr)
+ bool canWrite(const Char* ptr, size_t minCapacity) //needs to be checked before writing to "ptr"
+ size_t length(const Char* ptr)
+ void setLength(Char* ptr, size_t newLength)
*/
-template <typename T, //Character Type
- class AP> //Allocator Policy
+template <typename Char, //Character Type
+ class AP> //Allocator Policy
class StorageDeepCopy : public AP
{
protected:
~StorageDeepCopy() {}
- static T* create(size_t size) { return create(size, size); }
- static T* create(size_t size, size_t minCapacity)
+ static Char* create(size_t size) { return create(size, size); }
+ static Char* create(size_t size, size_t minCapacity)
{
const size_t newCapacity = AP::calcCapacity(minCapacity);
assert(newCapacity >= minCapacity);
assert(minCapacity >= size);
- Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(T)));
+ Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(Char)));
newDescr->length = size;
newDescr->capacity = newCapacity;
- return reinterpret_cast<T*>(newDescr + 1);
+ return reinterpret_cast<Char*>(newDescr + 1);
}
- static T* clone(T* ptr)
+ static Char* clone(Char* ptr)
{
- T* newData = create(length(ptr));
+ Char* newData = create(length(ptr));
std::copy(ptr, ptr + length(ptr) + 1, newData);
return newData;
}
- static void destroy(T* ptr) { AP::deallocate(descr(ptr)); }
+ static void destroy(Char* ptr) { AP::deallocate(descr(ptr)); }
//this needs to be checked before writing to "ptr"
- static bool canWrite(const T* ptr, size_t minCapacity) { return minCapacity <= descr(ptr)->capacity; }
- static size_t length(const T* ptr) { return descr(ptr)->length; }
+ static bool canWrite(const Char* ptr, size_t minCapacity) { return minCapacity <= descr(ptr)->capacity; }
+ static size_t length(const Char* ptr) { return descr(ptr)->length; }
- static void setLength(T* ptr, size_t newLength)
+ static void setLength(Char* ptr, size_t newLength)
{
assert(canWrite(ptr, newLength));
descr(ptr)->length = newLength;
@@ -103,43 +105,43 @@ private:
size_t capacity; //allocated size without null-termination
};
- static Descriptor* descr( T* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; }
- static const Descriptor* descr(const T* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
+ static Descriptor* descr( Char* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; }
+ static const Descriptor* descr(const Char* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
};
-template <typename T, //Character Type
- class AP> //Allocator Policy
+template <typename Char, //Character Type
+ class AP> //Allocator Policy
class StorageRefCountThreadSafe : public AP
{
protected:
~StorageRefCountThreadSafe() {}
- static T* create(size_t size)
+ static Char* create(size_t size)
{
return create(size, size);
}
- static T* create(size_t size, size_t minCapacity)
+ static Char* create(size_t size, size_t minCapacity)
{
const size_t newCapacity = AP::calcCapacity(minCapacity);
assert(newCapacity >= minCapacity);
assert(minCapacity >= size);
- Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(T)));
+ Descriptor* const newDescr = static_cast<Descriptor*>(AP::allocate(sizeof(Descriptor) + (newCapacity + 1) * sizeof(Char)));
new (newDescr) Descriptor(1, size, newCapacity);
- return reinterpret_cast<T*>(newDescr + 1);
+ return reinterpret_cast<Char*>(newDescr + 1);
}
- static T* clone(T* ptr)
+ static Char* clone(Char* ptr)
{
assert(descr(ptr)->refCount > 0);
++descr(ptr)->refCount;
return ptr;
}
- static void destroy(T* ptr)
+ static void destroy(Char* ptr)
{
if (--descr(ptr)->refCount == 0)
{
@@ -148,18 +150,18 @@ protected:
}
}
- static bool canWrite(const T* ptr, size_t minCapacity) //needs to be checked before writing to "ptr"
+ static bool canWrite(const Char* ptr, size_t minCapacity) //needs to be checked before writing to "ptr"
{
assert(descr(ptr)->refCount > 0);
return descr(ptr)->refCount == 1 && minCapacity <= descr(ptr)->capacity;
}
- static size_t length(const T* ptr)
+ static size_t length(const Char* ptr)
{
return descr(ptr)->length;
}
- static void setLength(T* ptr, size_t newLength)
+ static void setLength(Char* ptr, size_t newLength)
{
assert(canWrite(ptr, newLength));
descr(ptr)->length = newLength;
@@ -175,97 +177,99 @@ private:
size_t capacity; //allocated size without null-termination
};
- static Descriptor* descr( T* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; }
- static const Descriptor* descr(const T* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
+ static Descriptor* descr( Char* ptr) { return reinterpret_cast< Descriptor*>(ptr) - 1; }
+ static const Descriptor* descr(const Char* ptr) { return reinterpret_cast<const Descriptor*>(ptr) - 1; }
};
//################################################################################################################################################################
//perf note: interstingly StorageDeepCopy and StorageRefCountThreadSafe show same performance in FFS comparison
-template <class T, //Character Type
+template <class Char, //Character Type
template <class, class> class SP = StorageRefCountThreadSafe, //Storage Policy
- class AP = AllocatorOptimalSpeed> //Allocator Policy
-class Zbase : public SP<T, AP>
+ class AP = AllocatorOptimalSpeed> //Allocator Policy
+class Zbase : public SP<Char, AP>
{
public:
Zbase();
- Zbase(const T* source); //implicit conversion from a C-string
- Zbase(const T* source, size_t length);
+ Zbase(const Char* source); //implicit conversion from a C-string
+ Zbase(const Char* source, size_t length);
Zbase(const Zbase& source);
Zbase(Zbase&& tmp);
- explicit Zbase(T source); //dangerous if implicit: T buffer[]; Zbase name = buffer; ups...
+ explicit Zbase(Char source); //dangerous if implicit: Char buffer[]; Zbase name = buffer; ups...
//allow explicit construction from different string type, prevent ambiguity via SFINAE
template <class S> explicit Zbase(const S& other, typename S::value_type = 0);
~Zbase();
- //operator const T* () const; //NO implicit conversion to a C-string!! Many problems... one of them: if we forget to provide operator overloads, it'll just work with a T*...
+ //operator const Char* () const; //NO implicit conversion to a C-string!! Many problems... one of them: if we forget to provide operator overloads, it'll just work with a Char*...
//STL accessors
- typedef T* iterator;
- typedef const T* const_iterator;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
- const T* begin() const;
- const T* end() const;
- T* begin();
- T* end();
+ typedef Char* iterator;
+ typedef const Char* const_iterator;
+ typedef Char& reference;
+ typedef const Char& const_reference;
+ typedef Char value_type;
+ const Char* begin() const;
+ const Char* end() const;
+ Char* begin();
+ Char* end();
//std::string functions
size_t length() const;
size_t size() const;
- const T* c_str() const; //C-string format with NULL-termination
- const T* data() const; //internal representation, NULL-termination not guaranteed
- const T operator[](size_t pos) const;
+ const Char* c_str() const; //C-string format with NULL-termination
+ const Char* data() const; //internal representation, NULL-termination not guaranteed
+ const Char operator[](size_t pos) const;
bool empty() const;
void clear();
- size_t find(const Zbase& str, size_t pos = 0) const; //
- size_t find(const T* str, size_t pos = 0) const; //returns "npos" if not found
- size_t find(T ch, size_t pos = 0) const; //
- size_t rfind(T ch, size_t pos = npos) const; //
- size_t rfind(const T* str, size_t pos = npos) const; //
+ size_t find (const Zbase& str, size_t pos = 0) const; //
+ size_t find (const Char* str, size_t pos = 0) const; //returns "npos" if not found
+ size_t find (Char ch, size_t pos = 0) const; //
+ size_t rfind(Char ch, size_t pos = npos) const; //
+ 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 T* source, size_t len);
- void resize(size_t newSize, T fillChar = 0);
+ Zbase& assign(const Char* source, size_t len);
+ Zbase& append(const Char* source, size_t len);
+ void resize(size_t newSize, Char fillChar = 0);
void swap(Zbase& other);
- void push_back(T val); //STL access
+ void push_back(Char val); //STL access
- Zbase& operator=(const Zbase& source);
- Zbase& operator=(Zbase&& tmp);
- Zbase& operator=(const T* source);
- Zbase& operator=(T source);
+ Zbase& operator=(Zbase source);
+ Zbase& operator=(const Char* source);
+ Zbase& operator=(Char source);
Zbase& operator+=(const Zbase& other);
- Zbase& operator+=(const T* other);
- Zbase& operator+=(T ch);
+ Zbase& operator+=(const Char* other);
+ Zbase& operator+=(Char ch);
static const size_t npos = static_cast<size_t>(-1);
private:
- Zbase(int); //detect usage errors
- Zbase& operator=(int); //
+ Zbase(int); //
+ Zbase& operator=(int); //detect usage errors
+ Zbase& operator+=(int); //
+ void push_back(int); //
- T* rawStr;
+ Char* rawStr;
};
-template <class T, template <class, class> class SP, class AP> bool operator==(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs);
-template <class T, template <class, class> class SP, class AP> bool operator==(const Zbase<T, SP, AP>& lhs, const T* rhs);
-template <class T, template <class, class> class SP, class AP> bool operator==(const T* lhs, const Zbase<T, SP, AP>& 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 T, template <class, class> class SP, class AP> bool operator!=(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs);
-template <class T, template <class, class> class SP, class AP> bool operator!=(const Zbase<T, SP, AP>& lhs, const T* rhs);
-template <class T, template <class, class> class SP, class AP> bool operator!=(const T* lhs, const Zbase<T, SP, AP>& 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 T, template <class, class> class SP, class AP> bool operator< (const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs);
-template <class T, template <class, class> class SP, class AP> bool operator< (const Zbase<T, SP, AP>& lhs, const T* rhs);
-template <class T, template <class, class> class SP, class AP> bool operator< (const T* lhs, const Zbase<T, SP, AP>& 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 T, template <class, class> class SP, class AP> const Zbase<T, SP, AP> operator+(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs);
-template <class T, template <class, class> class SP, class AP> const Zbase<T, SP, AP> operator+(const Zbase<T, SP, AP>& lhs, const T* rhs);
-template <class T, template <class, class> class SP, class AP> const Zbase<T, SP, AP> operator+(const T* lhs, const Zbase<T, SP, AP>& rhs);
-template <class T, template <class, class> class SP, class AP> const Zbase<T, SP, AP> operator+( T lhs, const Zbase<T, SP, AP>& rhs);
-template <class T, template <class, class> class SP, class AP> const Zbase<T, SP, AP> operator+(const Zbase<T, SP, AP>& lhs, T rhs);
+template <class Char, template <class, class> class SP, class AP> const Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs);
+template <class Char, template <class, class> class SP, class AP> const Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, const Char* rhs);
+template <class Char, template <class, class> class SP, class AP> const Zbase<Char, SP, AP> operator+(const Char* lhs, const Zbase<Char, SP, AP>& rhs);
+template <class Char, template <class, class> class SP, class AP> const Zbase<Char, SP, AP> operator+( Char lhs, const Zbase<Char, SP, AP>& rhs);
+template <class Char, template <class, class> class SP, class AP> const Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, Char rhs);
@@ -304,8 +308,8 @@ template <class T, template <class, class> class SP, class AP> const Zbase<T, SP
//################################# inline implementation ########################################
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::Zbase()
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::Zbase()
{
//resist the temptation to avoid this allocation by referening a static global: NO performance advantage, MT issues!
rawStr = this->create(0);
@@ -313,8 +317,8 @@ Zbase<T, SP, AP>::Zbase()
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::Zbase(T source)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::Zbase(Char source)
{
rawStr = this->create(1);
rawStr[0] = source;
@@ -322,17 +326,17 @@ Zbase<T, SP, AP>::Zbase(T source)
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::Zbase(const T* source)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::Zbase(const Char* source)
{
- const size_t sourceLen = zen::strLength(source);
+ const size_t sourceLen = strLength(source);
rawStr = this->create(sourceLen);
std::copy(source, source + sourceLen + 1, rawStr); //include null-termination
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::Zbase(const T* source, size_t sourceLen)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::Zbase(const Char* source, size_t sourceLen)
{
rawStr = this->create(sourceLen);
std::copy(source, source + sourceLen, rawStr);
@@ -340,23 +344,23 @@ Zbase<T, SP, AP>::Zbase(const T* source, size_t sourceLen)
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::Zbase(const Zbase<T, SP, AP>& source)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::Zbase(const Zbase<Char, SP, AP>& source)
{
rawStr = this->clone(source.rawStr);
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::Zbase(Zbase<T, SP, AP>&& tmp)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::Zbase(Zbase<Char, SP, AP>&& tmp)
{
rawStr = this->clone(tmp.rawStr); //for a ref-counting string there probably isn't a faster way, even with r-value references
}
-template <class T, template <class, class> class SP, class AP>
+template <class Char, template <class, class> class SP, class AP>
template <class S> inline
-Zbase<T, SP, AP>::Zbase(const S& other, typename S::value_type)
+Zbase<Char, SP, AP>::Zbase(const S& other, typename S::value_type)
{
const size_t sourceLen = other.size();
rawStr = this->create(sourceLen);
@@ -365,80 +369,73 @@ Zbase<T, SP, AP>::Zbase(const S& other, typename S::value_type)
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>::~Zbase()
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>::~Zbase()
{
this->destroy(rawStr);
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, 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 Zbase& str, size_t pos) const
{
assert(pos <= length());
- const T* thisEnd = end(); //respect embedded 0
- const T* iter = std::search(begin() + pos, thisEnd,
- str.begin(), str.end());
+ const Char* thisEnd = end(); //respect embedded 0
+ const Char* iter = std::search(begin() + pos, thisEnd,
+ str.begin(), str.end());
return iter == thisEnd ? npos : iter - begin();
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, SP, AP>::find(const T* 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
{
assert(pos <= length());
- const T* thisEnd = end(); //respect embedded 0
- const T* iter = std::search(begin() + pos, thisEnd,
- str, str + zen::strLength(str));
+ const Char* thisEnd = end(); //respect embedded 0
+ const Char* iter = std::search(begin() + pos, thisEnd,
+ str, str + strLength(str));
return iter == thisEnd ? npos : iter - begin();
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, SP, AP>::find(T ch, 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
{
assert(pos <= length());
- const T* thisEnd = end();
- const T* iter = std::find(begin() + pos, thisEnd, ch); //respect embedded 0
+ const Char* thisEnd = end();
+ const Char* iter = std::find(begin() + pos, thisEnd, ch); //respect embedded 0
return iter == thisEnd ? npos : iter - begin();
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, SP, AP>::rfind(T 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
{
assert(pos == npos || pos <= length());
- const size_t thisLen = length();
- if (thisLen == 0) return npos;
- pos = std::min(thisLen - 1, pos); //handle "npos" and "pos == length()" implicitly
+ const Char* currEnd = pos == npos ? end() : begin() + std::min(pos + 1, length());
- while (rawStr[pos] != ch) //pos points to last char of the string
- {
- if (pos == 0)
- return npos;
- --pos;
- }
- return pos;
+ const Char* iter = find_last(begin(), currEnd, ch);
+ return iter == currEnd ? npos : iter - begin();
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, SP, AP>::rfind(const T* str, 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
{
assert(pos == npos || pos <= length());
- const size_t strLen = zen::strLength(str);
- const T* currEnd = pos == npos ? end() : begin() + std::min(pos + strLen, length());
+ const size_t strLen = strLength(str);
+ const Char* currEnd = pos == npos ? end() : begin() + std::min(pos + strLen, length());
- const T* iter = std::find_end(begin(), currEnd,
- str, str + strLen);
+ const Char* iter = search_last(begin(), currEnd,
+ str, str + strLen);
return iter == currEnd ? npos : iter - begin();
}
-template <class T, template <class, class> class SP, class AP>
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::replace(size_t pos1, size_t n1, const Zbase& str)
+template <class Char, template <class, class> class SP, class AP>
+Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::replace(size_t pos1, size_t n1, const Zbase& str)
{
assert(str.data() < rawStr || rawStr + length() < str.data()); //str mustn't point to data in this string
assert(pos1 + n1 <= length());
@@ -469,7 +466,7 @@ Zbase<T, SP, AP>& Zbase<T, SP, AP>::replace(size_t pos1, size_t n1, const Zbase&
else
{
//copy directly into new string
- T* const newStr = this->create(newLen);
+ Char* const newStr = this->create(newLen);
std::copy(rawStr, rawStr + pos1, newStr);
std::copy(str.data(), str.data() + n2, newStr + pos1);
@@ -482,8 +479,8 @@ Zbase<T, SP, AP>& Zbase<T, SP, AP>::replace(size_t pos1, size_t n1, const Zbase&
}
-template <class T, template <class, class> class SP, class AP> inline
-void Zbase<T, SP, AP>::resize(size_t newSize, T fillChar)
+template <class Char, template <class, class> class SP, class AP> inline
+void Zbase<Char, SP, AP>::resize(size_t newSize, Char fillChar)
{
if (canWrite(rawStr, newSize))
{
@@ -494,7 +491,7 @@ void Zbase<T, SP, AP>::resize(size_t newSize, T fillChar)
}
else
{
- T* newStr = this->create(newSize);
+ Char* newStr = this->create(newSize);
newStr[newSize] = 0;
if (length() < newSize)
@@ -511,153 +508,153 @@ void Zbase<T, SP, AP>::resize(size_t newSize, T fillChar)
}
-template <class T, template <class, class> class SP, class AP> inline
-bool operator==(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs)
+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 lhs.length() == rhs.length() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); //respect embedded 0
}
-template <class T, template <class, class> class SP, class AP> inline
-bool operator==(const Zbase<T, SP, AP>& lhs, const T* rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+bool operator==(const Zbase<Char, SP, AP>& lhs, const Char* rhs)
{
- return lhs.length() == zen::strLength(rhs) && std::equal(lhs.begin(), lhs.end(), rhs); //respect embedded 0
+ return lhs.length() == strLength(rhs) && std::equal(lhs.begin(), lhs.end(), rhs); //respect embedded 0
}
-template <class T, template <class, class> class SP, class AP> inline
-bool operator==(const T* lhs, const Zbase<T, SP, AP>& 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 T, template <class, class> class SP, class AP> inline
-bool operator!=(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs)
+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 T, template <class, class> class SP, class AP> inline
-bool operator!=(const Zbase<T, SP, AP>& lhs, const T* 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 T, template <class, class> class SP, class AP> inline
-bool operator!=(const T* lhs, const Zbase<T, SP, AP>& 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 T, template <class, class> class SP, class AP> inline
-bool operator<(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs)
+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 std::lexicographical_compare(lhs.begin(), lhs.end(), //respect embedded 0
rhs.begin(), rhs.end());
}
-template <class T, template <class, class> class SP, class AP> inline
-bool operator<(const Zbase<T, SP, AP>& lhs, const T* rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+bool operator<(const Zbase<Char, SP, AP>& lhs, const Char* rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), //respect embedded 0
- rhs, rhs + zen::strLength(rhs));
+ rhs, rhs + strLength(rhs));
}
-template <class T, template <class, class> class SP, class AP> inline
-bool operator<(const T* lhs, const Zbase<T, SP, AP>& rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+bool operator<(const Char* lhs, const Zbase<Char, SP, AP>& rhs)
{
- return std::lexicographical_compare(lhs, lhs + zen::strLength(lhs), //respect embedded 0
+ return std::lexicographical_compare(lhs, lhs + strLength(lhs), //respect embedded 0
rhs.begin(), rhs.end());
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, SP, AP>::length() const
+template <class Char, template <class, class> class SP, class AP> inline
+size_t Zbase<Char, SP, AP>::length() const
{
- return SP<T, AP>::length(rawStr);
+ return SP<Char, AP>::length(rawStr);
}
-template <class T, template <class, class> class SP, class AP> inline
-size_t Zbase<T, SP, AP>::size() const
+template <class Char, template <class, class> class SP, class AP> inline
+size_t Zbase<Char, SP, AP>::size() const
{
return length();
}
-template <class T, template <class, class> class SP, class AP> inline
-const T* Zbase<T, SP, AP>::c_str() const
+template <class Char, template <class, class> class SP, class AP> inline
+const Char* Zbase<Char, SP, AP>::c_str() const
{
return rawStr;
}
-template <class T, template <class, class> class SP, class AP> inline
-const T* Zbase<T, SP, AP>::data() const
+template <class Char, template <class, class> class SP, class AP> inline
+const Char* Zbase<Char, SP, AP>::data() const
{
return rawStr;
}
-template <class T, template <class, class> class SP, class AP> inline
-const T Zbase<T, SP, AP>::operator[](size_t pos) const
+template <class Char, template <class, class> class SP, class AP> inline
+const Char Zbase<Char, SP, AP>::operator[](size_t pos) const
{
assert(pos < length());
return rawStr[pos];
}
-template <class T, template <class, class> class SP, class AP> inline
-const T* Zbase<T, SP, AP>::begin() const
+template <class Char, template <class, class> class SP, class AP> inline
+const Char* Zbase<Char, SP, AP>::begin() const
{
return rawStr;
}
-template <class T, template <class, class> class SP, class AP> inline
-const T* Zbase<T, SP, AP>::end() const
+template <class Char, template <class, class> class SP, class AP> inline
+const Char* Zbase<Char, SP, AP>::end() const
{
return rawStr + length();
}
-template <class T, template <class, class> class SP, class AP> inline
-T* Zbase<T, SP, AP>::begin()
+template <class Char, template <class, class> class SP, class AP> inline
+Char* Zbase<Char, SP, AP>::begin()
{
- reserve(length());
+ reserve(length()); //make unshared!
return rawStr;
}
-template <class T, template <class, class> class SP, class AP> inline
-T* Zbase<T, SP, AP>::end()
+template <class Char, template <class, class> class SP, class AP> inline
+Char* Zbase<Char, SP, AP>::end()
{
return begin() + length();
}
-template <class T, template <class, class> class SP, class AP> inline
-void Zbase<T, SP, AP>::push_back(T val)
+template <class Char, template <class, class> class SP, class AP> inline
+void Zbase<Char, SP, AP>::push_back(Char val)
{
operator+=(val);
}
-template <class T, template <class, class> class SP, class AP> inline
-bool Zbase<T, SP, AP>::empty() const
+template <class Char, template <class, class> class SP, class AP> inline
+bool Zbase<Char, SP, AP>::empty() const
{
return length() == 0;
}
-template <class T, template <class, class> class SP, class AP> inline
-void Zbase<T, SP, AP>::clear()
+template <class Char, template <class, class> class SP, class AP> inline
+void Zbase<Char, SP, AP>::clear()
{
if (!empty())
{
@@ -672,55 +669,55 @@ void Zbase<T, SP, AP>::clear()
}
-template <class T, template <class, class> class SP, class AP> inline
-const Zbase<T, SP, AP> operator+(const Zbase<T, SP, AP>& lhs, const Zbase<T, SP, AP>& rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+const Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, const Zbase<Char, SP, AP>& rhs)
{
- return Zbase<T, SP, AP>(lhs) += rhs;
+ return Zbase<Char, SP, AP>(lhs) += rhs;
}
-template <class T, template <class, class> class SP, class AP> inline
-const Zbase<T, SP, AP> operator+(const Zbase<T, SP, AP>& lhs, const T* rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+const Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, const Char* rhs)
{
- return Zbase<T, SP, AP>(lhs) += rhs;
+ return Zbase<Char, SP, AP>(lhs) += rhs;
}
-template <class T, template <class, class> class SP, class AP> inline
-const Zbase<T, SP, AP> operator+(const T* lhs, const Zbase<T, SP, AP>& rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+const Zbase<Char, SP, AP> operator+(const Char* lhs, const Zbase<Char, SP, AP>& rhs)
{
- return Zbase<T, SP, AP>(lhs) += rhs;
+ return Zbase<Char, SP, AP>(lhs) += rhs;
}
-template <class T, template <class, class> class SP, class AP> inline
-const Zbase<T, SP, AP> operator+(T lhs, const Zbase<T, SP, AP>& rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+const Zbase<Char, SP, AP> operator+(Char lhs, const Zbase<Char, SP, AP>& rhs)
{
- return (Zbase<T, SP, AP>() += lhs) += rhs;
+ return Zbase<Char, SP, AP>(lhs) += rhs;
}
-template <class T, template <class, class> class SP, class AP> inline
-const Zbase<T, SP, AP> operator+(const Zbase<T, SP, AP>& lhs, T rhs)
+template <class Char, template <class, class> class SP, class AP> inline
+const Zbase<Char, SP, AP> operator+(const Zbase<Char, SP, AP>& lhs, Char rhs)
{
- return Zbase<T, SP, AP>(lhs) += rhs;
+ return Zbase<Char, SP, AP>(lhs) += rhs;
}
-template <class T, template <class, class> class SP, class AP> inline
-void Zbase<T, SP, AP>::swap(Zbase<T, SP, AP>& other)
+template <class Char, template <class, class> class SP, class AP> inline
+void Zbase<Char, SP, AP>::swap(Zbase<Char, SP, AP>& other)
{
std::swap(rawStr, other.rawStr);
}
-template <class T, template <class, class> class SP, class AP> inline
-void Zbase<T, SP, AP>::reserve(size_t minCapacity) //make unshared and check capacity
+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 (!canWrite(rawStr, minCapacity))
{
//allocate a new string
- T* newStr = create(length(), std::max(minCapacity, length())); //reserve() must NEVER shrink the string: logical const!
+ Char* newStr = create(length(), std::max(minCapacity, length())); //reserve() must NEVER shrink the string: logical const!
std::copy(rawStr, rawStr + length() + 1, newStr); //include NULL-termination
destroy(rawStr);
@@ -729,8 +726,8 @@ void Zbase<T, SP, AP>::reserve(size_t minCapacity) //make unshared and check cap
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::assign(const T* source, size_t len)
+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)
{
if (canWrite(rawStr, len))
{
@@ -745,80 +742,60 @@ Zbase<T, SP, AP>& Zbase<T, SP, AP>::assign(const T* source, size_t len)
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(const Zbase<T, SP, AP>& source)
+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)
{
- Zbase(source).swap(*this);
+ const size_t thisLen = length();
+ reserve(thisLen + len); //make unshared and check capacity
+
+ std::copy(source, source + len, rawStr + thisLen);
+ rawStr[thisLen + len] = 0;
+ setLength(rawStr, thisLen + len);
return *this;
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(Zbase<T, SP, AP>&& tmp)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(Zbase<Char, SP, AP> other) //unifying assignment: no need for r-value reference optimization!
{
- swap(tmp);
+ swap(other);
return *this;
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(const T* source)
+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, zen::strLength(source));
+ return assign(source, strLength(source));
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator=(T source)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator=(Char ch)
{
- if (canWrite(rawStr, 1))
- {
- rawStr[0] = source;
- rawStr[1] = 0; //include null-termination
- setLength(rawStr, 1);
- }
- else
- *this = Zbase(source);
-
- return *this;
+ return assign(&ch, 1);
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator+=(const Zbase<T, SP, AP>& other)
+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)
{
- const size_t thisLen = length();
- const size_t otherLen = other.length();
- reserve(thisLen + otherLen); //make unshared and check capacity
-
- std::copy(other.rawStr, other.rawStr + otherLen + 1, rawStr + thisLen); //include null-termination
- setLength(rawStr, thisLen + otherLen);
- return *this;
+ return append(other.c_str(), other.length());
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator+=(const T* other)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator+=(const Char* other)
{
- const size_t thisLen = length();
- const size_t otherLen = zen::strLength(other);
- reserve(thisLen + otherLen); //make unshared and check capacity
-
- std::copy(other, other + otherLen + 1, rawStr + thisLen); //include null-termination
- setLength(rawStr, thisLen + otherLen);
- return *this;
+ return append(other, strLength(other));
}
-template <class T, template <class, class> class SP, class AP> inline
-Zbase<T, SP, AP>& Zbase<T, SP, AP>::operator+=(T ch)
+template <class Char, template <class, class> class SP, class AP> inline
+Zbase<Char, SP, AP>& Zbase<Char, SP, AP>::operator+=(Char ch)
{
- const size_t thisLen = length();
- reserve(thisLen + 1); //make unshared and check capacity
- rawStr[thisLen] = ch;
- rawStr[thisLen + 1] = 0;
- setLength(rawStr, thisLen + 1);
- return *this;
+ return append(&ch, 1);
+}
}
#endif //Z_BASE_H_INCLUDED
bgstack15