summaryrefslogtreecommitdiff
path: root/shared/zstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/zstring.h')
-rw-r--r--shared/zstring.h264
1 files changed, 102 insertions, 162 deletions
diff --git a/shared/zstring.h b/shared/zstring.h
index 0403a00c..018ca42e 100644
--- a/shared/zstring.h
+++ b/shared/zstring.h
@@ -11,27 +11,21 @@
#include <cctype>
#include <assert.h>
#include <new>
+#include <stdlib.h>
+#include <vector>
+
#ifdef __WXDEBUG__
#include <set>
+#include <wx/thread.h>
#endif
-namespace FreeFileSync
-{
-#ifdef FFS_WIN
- //super fast case-insensitive string comparison: way faster than wxString::CmpNoCase()!!!
- int compareStringsWin32(const wchar_t* a, const wchar_t* b, const int aCount = -1, const int bCount = -1);
-#endif //FFS_WIN
-}
-
-
#ifdef ZSTRING_CHAR
typedef char DefaultChar; //use char strings
#elif defined ZSTRING_WIDE_CHAR
typedef wchar_t DefaultChar; //use wide character strings
#endif
-class Zsubstr;
class Zstring
{
@@ -44,8 +38,9 @@ public:
operator const DefaultChar*() const; //implicit conversion to C string
- //wxWidgets functions
+ //wxWidgets-like functions
bool StartsWith(const DefaultChar* begin) const;
+ bool StartsWith(DefaultChar begin) const;
bool StartsWith(const Zstring& begin) const;
bool EndsWith(const DefaultChar* end) const;
bool EndsWith(const DefaultChar end) const;
@@ -54,23 +49,25 @@ public:
#ifdef FFS_WIN
int CmpNoCase(const DefaultChar* other) const;
int CmpNoCase(const Zstring& other) const;
+ Zstring& MakeLower();
#endif
int Cmp(const DefaultChar* other) const;
int Cmp(const Zstring& other) const;
Zstring& Replace(const DefaultChar* old, const DefaultChar* replacement, bool replaceAll = true);
- Zstring AfterLast(DefaultChar ch) const; //returns the whole string if ch not found
- Zstring BeforeLast(DefaultChar ch) const; //returns empty string if ch not found
+ Zstring AfterLast( DefaultChar ch) const; //returns the whole string if ch not found
+ Zstring BeforeLast( DefaultChar ch) const; //returns empty string if ch not found
+ Zstring AfterFirst( DefaultChar ch) const; //returns empty string if ch not found
+ Zstring BeforeFirst(DefaultChar ch) const; //returns the whole string if ch not found
size_t Find(DefaultChar ch, bool fromEnd) const;
bool Matches(const DefaultChar* mask) const;
static bool Matches(const DefaultChar* name, const DefaultChar* mask);
Zstring& Trim(bool fromRight); //from right or left
- Zstring& MakeLower();
+ std::vector<Zstring> Tokenize(const DefaultChar delimiter) const;
//std::string functions
size_t length() const;
const DefaultChar* c_str() const;
Zstring substr(size_t pos = 0, size_t len = npos) const; //allocate new string
- Zsubstr zsubstr(size_t pos = 0) const; //use ref-counting!
bool empty() const;
void clear();
int compare(const DefaultChar* other) const;
@@ -81,16 +78,18 @@ public:
size_t rfind(const DefaultChar ch, size_t pos = npos) const;
Zstring& replace(size_t pos1, size_t n1, const DefaultChar* str, size_t n2);
size_t size() const;
+ void reserve(size_t minCapacity);
+ Zstring& assign(const DefaultChar* source, size_t len);
Zstring& operator=(const Zstring& source);
Zstring& operator=(const DefaultChar* source);
- bool operator == (const Zstring& other) const;
- bool operator == (const DefaultChar* other) const;
- bool operator < (const Zstring& other) const;
- bool operator < (const DefaultChar* other) const;
- bool operator != (const Zstring& other) const;
- bool operator != (const DefaultChar* other) const;
+ bool operator==(const Zstring& other) const;
+ bool operator==(const DefaultChar* other) const;
+ bool operator< (const Zstring& other) const;
+ bool operator< (const DefaultChar* other) const;
+ bool operator!=(const Zstring& other) const;
+ bool operator!=(const DefaultChar* other) const;
const DefaultChar operator[](const size_t pos) const;
@@ -106,11 +105,11 @@ public:
private:
Zstring(int); //indicates usage error
+ DefaultChar* data();
void initAndCopy(const DefaultChar* source, size_t length);
- void incRef() const; //support for reference-counting
- void decRef(); //
- void copyBeforeWrite(const size_t capacityNeeded); //and copy-on-write
+ void incRef() const; //support for reference-counting
+ void decRef(); //
struct StringDescriptor
{
@@ -118,28 +117,9 @@ private:
size_t length;
size_t capacity; //allocated length without null-termination
};
- static void allocate(const size_t newLength, StringDescriptor*& newDescr, DefaultChar*& newData);
+ static StringDescriptor* allocate(const size_t newLength);
StringDescriptor* descr;
- DefaultChar* data;
-};
-
-
-class Zsubstr //ref-counted substring of a Zstring
-{
-public:
- Zsubstr();
- Zsubstr(const Zstring& ref, const size_t pos);
-
- const DefaultChar* c_str() const;
- size_t length() const;
- bool StartsWith(const Zstring& begin) const;
- size_t findFromEnd(const DefaultChar ch) const;
-
-private:
- Zstring m_ref;
- const DefaultChar* m_data;
- size_t m_length;
};
@@ -181,15 +161,15 @@ inline
bool defaultIsWhiteSpace(const char ch)
{
// some compilers (e.g. VC++ 6.0) return true for a call to isspace('\xEA') => exclude char(128) to char(255)
- return ((unsigned char)ch < 128) && isspace((unsigned char)ch) != 0;
-}
-
-inline
-char defaultToLower(const char ch)
-{
- return tolower((unsigned char)ch); //caution: although tolower() has int as input parameter it expects unsigned chars!
+ return (static_cast<unsigned char>(ch) < 128) && isspace((unsigned char)ch) != 0;
}
+//inline
+//char defaultToLower(const char ch)
+//{
+// return tolower(static_cast<unsigned char>(ch)); //caution: although tolower() has int as input parameter it expects unsigned chars!
+//}
+//
#elif defined ZSTRING_WIDE_CHAR
inline
size_t defaultLength(const wchar_t* input)
@@ -228,11 +208,11 @@ bool defaultIsWhiteSpace(const wchar_t ch)
return (ch < 128 || ch > 255) && iswspace(ch) != 0;
}
-inline
-wchar_t defaultToLower(const wchar_t ch)
-{
- return towlower(ch);
-}
+//inline
+//wchar_t defaultToLower(const wchar_t ch)
+//{
+// return towlower(ch);
+//}
#endif
@@ -242,11 +222,13 @@ class AllocationCount //small test for memory leaks in Zstring
public:
void inc(const DefaultChar* object)
{
+ wxCriticalSectionLocker dummy(lockActStrings);
activeStrings.insert(object);
}
void dec(const DefaultChar* object)
{
+ wxCriticalSectionLocker dummy(lockActStrings);
activeStrings.erase(object);
}
@@ -256,6 +238,7 @@ private:
AllocationCount() {}
~AllocationCount();
+ wxCriticalSection lockActStrings;
std::set<const DefaultChar*> activeStrings;
};
#endif
@@ -269,23 +252,23 @@ size_t getCapacityToAllocate(const size_t length)
inline
-void Zstring::allocate(const size_t newLength,
- StringDescriptor*& newDescr,
- DefaultChar*& newData)
+Zstring::StringDescriptor* Zstring::allocate(const size_t newLength)
{ //allocate and set data for new string
const size_t newCapacity = getCapacityToAllocate(newLength);
assert(newCapacity);
- newDescr = static_cast<StringDescriptor*>(operator new [] (sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar)));
- newData = reinterpret_cast<DefaultChar*>(newDescr + 1);
+ StringDescriptor* newDescr = static_cast<StringDescriptor*>(::malloc(sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar))); //use C-memory functions because of realloc()
+ if (newDescr == NULL)
+ throw std::bad_alloc();
newDescr->refCount = 1;
newDescr->length = newLength;
newDescr->capacity = newCapacity;
#ifdef __WXDEBUG__
- AllocationCount::getInstance().inc(newData); //test Zstring for memory leaks
+ AllocationCount::getInstance().inc(reinterpret_cast<DefaultChar*>(newDescr + 1)); //test Zstring for memory leaks
#endif
+ return newDescr;
}
@@ -301,7 +284,6 @@ Zstring::Zstring()
emptyString.incRef();
descr = emptyString.descr;
- data = emptyString.data;
}
@@ -323,7 +305,6 @@ inline
Zstring::Zstring(const Zstring& source)
{
descr = source.descr;
- data = source.data;
incRef(); //reference counting!
}
@@ -338,9 +319,9 @@ Zstring::~Zstring()
inline
void Zstring::initAndCopy(const DefaultChar* source, size_t sourceLen)
{
- allocate(sourceLen, descr, data);
- memcpy(data, source, sourceLen * sizeof(DefaultChar));
- data[sourceLen] = 0;
+ descr = allocate(sourceLen);
+ ::memcpy(data(), source, sourceLen * sizeof(DefaultChar));
+ data()[sourceLen] = 0;
}
@@ -358,31 +339,15 @@ void Zstring::decRef()
assert(descr && descr->refCount >= 1); //descr points to the begin of the allocated memory block
if (--descr->refCount == 0)
{
- operator delete [] (descr); //this must NEVER be changed!! E.g. Trim() relies on descr being start of allocated memory block
- descr = NULL;
#ifdef __WXDEBUG__
- AllocationCount::getInstance().dec(data); //test Zstring for memory leaks
+ AllocationCount::getInstance().dec(c_str()); //test Zstring for memory leaks
#endif
+ ::free(descr); //beginning of whole memory block
+ descr = NULL;
}
}
-#ifdef FFS_WIN
-inline
-int Zstring::CmpNoCase(const DefaultChar* other) const
-{
- return FreeFileSync::compareStringsWin32(c_str(), other); //way faster than wxString::CmpNoCase()!!
-}
-
-
-inline
-int Zstring::CmpNoCase(const Zstring& other) const
-{
- return FreeFileSync::compareStringsWin32(c_str(), other.c_str(), length(), other.length()); //way faster than wxString::CmpNoCase()!!
-}
-#endif
-
-
inline
Zstring::operator const DefaultChar*() const
{
@@ -396,7 +361,6 @@ Zstring& Zstring::operator=(const Zstring& source)
source.incRef(); //implicitly handle case "this == &source" and avoid this check
decRef(); //
descr = source.descr;
- data = source.data;
return *this;
}
@@ -417,11 +381,11 @@ size_t Zstring::Find(DefaultChar ch, bool fromEnd) const
inline
Zstring Zstring::AfterLast(DefaultChar ch) const
{
- size_t pos = rfind(ch, npos);
- if (pos == npos )
- return *this;
+ const size_t pos = rfind(ch, npos);
+ if (pos != npos )
+ return Zstring(c_str() + pos + 1, length() - pos - 1);
else
- return c_str() + pos + 1;
+ return *this;
}
@@ -430,12 +394,35 @@ Zstring Zstring::AfterLast(DefaultChar ch) const
inline
Zstring Zstring::BeforeLast(DefaultChar ch) const
{
- size_t pos = rfind(ch, npos);
+ const size_t pos = rfind(ch, npos);
+ if (pos != npos)
+ return Zstring(c_str(), pos); //data is non-empty string in this context: else ch would not have been found!
+ else
+ return Zstring();
+}
- if (pos != npos && pos != 0 )
- return Zstring(data, pos); //data is non-empty string in this context: else ch would not have been found!
+
+//returns empty string if ch not found
+inline
+Zstring Zstring::AfterFirst(DefaultChar ch) const
+{
+ const size_t pos = find(ch, 0);
+ if (pos != npos)
+ return Zstring(c_str() + pos + 1, length() - pos - 1);
else
return Zstring();
+
+}
+
+//returns the whole string if ch not found
+inline
+Zstring Zstring::BeforeFirst(DefaultChar ch) const
+{
+ const size_t pos = find(ch, 0);
+ if (pos != npos)
+ return Zstring(c_str(), pos); //data is non-empty string in this context: else ch would not have been found!
+ else
+ return *this;
}
@@ -450,12 +437,20 @@ bool Zstring::StartsWith(const DefaultChar* begin) const
inline
+bool Zstring::StartsWith(DefaultChar begin) const
+{
+ const size_t len = length();
+ return len && (this->operator[](0) == begin);
+}
+
+
+inline
bool Zstring::StartsWith(const Zstring& begin) const
{
const size_t beginLength = begin.length();
if (length() < beginLength)
return false;
- return compare(0, beginLength, begin) == 0;
+ return compare(0, beginLength, begin.c_str()) == 0;
}
@@ -485,7 +480,7 @@ bool Zstring::EndsWith(const Zstring& end) const
const size_t endLength = end.length();
if (thisLength < endLength)
return false;
- return compare(thisLength - endLength, endLength, end) == 0;
+ return compare(thisLength - endLength, endLength, end.c_str()) == 0;
}
@@ -498,8 +493,8 @@ Zstring& Zstring::Truncate(size_t newLen)
return *this = Zstring(c_str(), newLen);
else //overwrite this string
{
- descr->length = newLen;
- data[newLen] = DefaultChar(0);
+ descr->length = newLen;
+ data()[newLen] = 0;
}
}
@@ -622,7 +617,14 @@ size_t Zstring::size() const
inline
const DefaultChar* Zstring::c_str() const
{
- return data;
+ return reinterpret_cast<DefaultChar*>(descr + 1);
+}
+
+
+inline
+DefaultChar* Zstring::data()
+{
+ return reinterpret_cast<DefaultChar*>(descr + 1);
}
@@ -644,7 +646,7 @@ inline
const DefaultChar Zstring::operator[](const size_t pos) const
{
assert(pos < length());
- return data[pos];
+ return c_str()[pos];
}
@@ -668,67 +670,5 @@ const Zstring Zstring::operator+(const DefaultChar ch) const
return Zstring(*this)+=ch;
}
-//##################### Zsubstr #############################
-inline
-Zsubstr Zstring::zsubstr(size_t pos) const
-{
- assert(pos <= length());
- return Zsubstr(*this, pos); //return reference counted string
-}
-
-
-inline
-Zsubstr::Zsubstr()
-{
- m_data = m_ref.c_str();
- m_length = 0;
-}
-
-
-inline
-Zsubstr::Zsubstr(const Zstring& ref, const size_t pos) :
- m_ref(ref),
- m_data(ref.c_str() + pos),
- m_length(ref.length() - pos) {}
-
-
-inline
-const DefaultChar* Zsubstr::c_str() const
-{
- return m_data;
-}
-
-
-inline
-size_t Zsubstr::length() const
-{
- return m_length;
-}
-
-
-inline
-bool Zsubstr::StartsWith(const Zstring& begin) const
-{
- const size_t beginLength = begin.length();
- if (length() < beginLength)
- return false;
-
- return defaultCompare(m_data, begin.c_str(), beginLength) == 0;
-}
-
-
-inline
-size_t Zsubstr::findFromEnd(const DefaultChar ch) const
-{
- size_t pos = length();
- while (--pos != static_cast<size_t>(-1))
- {
- if (m_data[pos] == ch)
- return pos;
- }
- return Zstring::npos;
-}
-
-
#endif // ZSTRING_H_INCLUDED
bgstack15