From 01eb8253196672c969a39587e90b49321a182428 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:19:14 +0200 Subject: 5.1 --- zen/string_base.h | 187 +++++++++++++----------------------------------------- 1 file changed, 43 insertions(+), 144 deletions(-) (limited to 'zen/string_base.h') diff --git a/zen/string_base.h b/zen/string_base.h index ef0d9059..82793a49 100644 --- a/zen/string_base.h +++ b/zen/string_base.h @@ -118,11 +118,7 @@ class StorageRefCountThreadSafe : public AP protected: ~StorageRefCountThreadSafe() {} - static Char* create(size_t size) - { - return create(size, size); - } - + 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); @@ -157,23 +153,24 @@ protected: return descr(ptr)->refCount == 1 && minCapacity <= descr(ptr)->capacity; } - static size_t length(const Char* ptr) - { - return descr(ptr)->length; - } + static size_t length(const Char* ptr) { return descr(ptr)->length; } static void setLength(Char* ptr, size_t newLength) { assert(canWrite(ptr, newLength)); - descr(ptr)->length = newLength; + descr(ptr)->length = static_cast(newLength); } private: struct Descriptor { - Descriptor(long rc, size_t len, size_t cap) : refCount(rc), length(len), capacity(cap) {} + Descriptor(long rc, size_t len, size_t cap) : + refCount(rc), + length(static_cast(len)), + capacity(static_cast(cap)) {} boost::detail::atomic_count refCount; //practically no perf loss: ~0.2%! (FFS comparison) + //replace by #include std::atomic_int when finally getting rid of VS2010 std::uint32_t length; std::uint32_t capacity; //allocated size without null-termination }; @@ -197,7 +194,7 @@ public: Zbase(const Char* source, size_t length); Zbase(const Zbase& source); Zbase(Zbase&& tmp); - explicit Zbase(Char source); //dangerous if implicit: Char buffer[]; Zbase name = buffer; ups... + explicit Zbase(Char source); //dangerous if implicit: Char buffer[]; return buffer[0]; ups... //allow explicit construction from different string type, prevent ambiguity via SFINAE template explicit Zbase(const S& other, typename S::value_type = 0); ~Zbase(); @@ -217,15 +214,15 @@ public: //std::string functions size_t length() const; - size_t size() const; - const Char* c_str() const; //C-string format with NULL-termination - const Char* data() const; //internal representation, NULL-termination not guaranteed + 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 operator[](size_t pos) const; - bool empty() const; + bool empty() const { return length() == 0; } void clear(); 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 find (const Char* str, size_t pos = 0) const; // + size_t find (Char ch, size_t pos = 0) const; //returns "npos" if not found 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); @@ -234,7 +231,7 @@ public: Zbase& append(const Char* source, size_t len); void resize(size_t newSize, Char fillChar = 0); void swap(Zbase& other); - void push_back(Char val); //STL access + void push_back(Char val) { operator+=(val); } //STL access Zbase& operator=(Zbase source); Zbase& operator=(const Char* source); @@ -254,27 +251,24 @@ private: Char* rawStr; }; -template class SP, class AP> bool operator==(const Zbase& lhs, const Zbase& rhs); -template class SP, class AP> bool operator==(const Zbase& lhs, const Char* rhs); -template class SP, class AP> bool operator==(const Char* lhs, const Zbase& rhs); - -template class SP, class AP> bool operator!=(const Zbase& lhs, const Zbase& rhs); -template class SP, class AP> bool operator!=(const Zbase& lhs, const Char* rhs); -template class SP, class AP> bool operator!=(const Char* lhs, const Zbase& rhs); - -template class SP, class AP> bool operator< (const Zbase& lhs, const Zbase& rhs); -template class SP, class AP> bool operator< (const Zbase& lhs, const Char* rhs); -template class SP, class AP> bool operator< (const Char* lhs, const Zbase& rhs); - -template class SP, class AP> const Zbase operator+(const Zbase& lhs, const Zbase& rhs); -template class SP, class AP> const Zbase operator+(const Zbase& lhs, const Char* rhs); -template class SP, class AP> const Zbase operator+(const Char* lhs, const Zbase& rhs); -template class SP, class AP> const Zbase operator+( Char lhs, const Zbase& rhs); -template class SP, class AP> const Zbase operator+(const Zbase& lhs, Char rhs); - +template class SP, class AP> bool operator==(const Zbase& lhs, const Zbase& rhs); +template class SP, class AP> bool operator==(const Zbase& lhs, const Char* rhs); +template class SP, class AP> inline bool operator==(const Char* lhs, const Zbase& rhs) { return operator==(rhs, lhs); } +template class SP, class AP> inline bool operator!=(const Zbase& lhs, const Zbase& rhs) { return !operator==(lhs, rhs); } +template class SP, class AP> inline bool operator!=(const Zbase& lhs, const Char* rhs) { return !operator==(lhs, rhs); } +template class SP, class AP> inline bool operator!=(const Char* lhs, const Zbase& rhs) { return !operator==(lhs, rhs); } +template class SP, class AP> bool operator<(const Zbase& lhs, const Zbase& rhs); +template class SP, class AP> bool operator<(const Zbase& lhs, const Char* rhs); +template class SP, class AP> bool operator<(const Char* lhs, const Zbase& rhs); +//rvalue references: unified first argument! +template class SP, class AP> inline Zbase operator+(Zbase lhs, const Zbase& rhs) { return lhs += rhs; } +template class SP, class AP> inline Zbase operator+(Zbase lhs, const Char* rhs) { return lhs += rhs; } +template class SP, class AP> inline Zbase operator+(Zbase lhs, Char rhs) { return lhs += rhs; } +template class SP, class AP> inline Zbase operator+( Char lhs, const Zbase& rhs) { return Zbase(lhs) += rhs; } +template class SP, class AP> inline Zbase operator+(const Char* lhs, const Zbase& rhs) { return Zbase(lhs) += rhs; } @@ -302,13 +296,7 @@ template class SP, class AP> const Zbase class SP, class AP> inline Zbase::Zbase() { @@ -355,7 +343,16 @@ Zbase::Zbase(const Zbase& source) template class SP, class AP> inline Zbase::Zbase(Zbase&& tmp) { - rawStr = this->clone(tmp.rawStr); //for a ref-counting string there probably isn't a faster way, even with r-value references + //rawStr = this->clone(tmp.rawStr); NO! do not increment ref-count of a potentially unshared string! We'd lose optimization opportunity of reusing it! + //instead create a dummy string and swap: + if (canWrite(tmp.rawStr, 0)) //perf: this check saves about 4% + { + rawStr = this->create(0); //no perf issue! see comment in default constructor + rawStr[0] = 0; + swap(tmp); + } + else //shared representation: yet another "add ref" won't hurt + rawStr = this->clone(tmp.rawStr); } @@ -523,34 +520,6 @@ bool operator==(const Zbase& lhs, const Char* rhs) } -template class SP, class AP> inline -bool operator==(const Char* lhs, const Zbase& rhs) -{ - return operator==(rhs, lhs); -} - - -template class SP, class AP> inline -bool operator!=(const Zbase& lhs, const Zbase& rhs) -{ - return !operator==(lhs, rhs); -} - - -template class SP, class AP> inline -bool operator!=(const Zbase& lhs, const Char* rhs) -{ - return !operator==(lhs, rhs); -} - - -template class SP, class AP> inline -bool operator!=(const Char* lhs, const Zbase& rhs) -{ - return !operator==(lhs, rhs); -} - - template class SP, class AP> inline bool operator<(const Zbase& lhs, const Zbase& rhs) { @@ -582,27 +551,6 @@ size_t Zbase::length() const } -template class SP, class AP> inline -size_t Zbase::size() const -{ - return length(); -} - - -template class SP, class AP> inline -const Char* Zbase::c_str() const -{ - return rawStr; -} - - -template class SP, class AP> inline -const Char* Zbase::data() const -{ - return rawStr; -} - - template class SP, class AP> inline const Char Zbase::operator[](size_t pos) const { @@ -640,20 +588,6 @@ Char* Zbase::end() } -template class SP, class AP> inline -void Zbase::push_back(Char val) -{ - operator+=(val); -} - - -template class SP, class AP> inline -bool Zbase::empty() const -{ - return length() == 0; -} - - template class SP, class AP> inline void Zbase::clear() { @@ -670,41 +604,6 @@ void Zbase::clear() } -template class SP, class AP> inline -const Zbase operator+(const Zbase& lhs, const Zbase& rhs) -{ - return Zbase(lhs) += rhs; -} - - -template class SP, class AP> inline -const Zbase operator+(const Zbase& lhs, const Char* rhs) -{ - return Zbase(lhs) += rhs; -} - - -template class SP, class AP> inline -const Zbase operator+(const Char* lhs, const Zbase& rhs) -{ - return Zbase(lhs) += rhs; -} - - -template class SP, class AP> inline -const Zbase operator+(Char lhs, const Zbase& rhs) -{ - return Zbase(lhs) += rhs; -} - - -template class SP, class AP> inline -const Zbase operator+(const Zbase& lhs, Char rhs) -{ - return Zbase(lhs) += rhs; -} - - template class SP, class AP> inline void Zbase::swap(Zbase& other) { @@ -719,7 +618,7 @@ void Zbase::reserve(size_t minCapacity) //make unshared and check { //allocate a new string 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 + std::copy(rawStr, rawStr + length() + 1, newStr); //include 0-termination destroy(rawStr); rawStr = newStr; -- cgit