diff options
Diffstat (limited to 'src/qcstring.h')
-rw-r--r-- | src/qcstring.h | 182 |
1 files changed, 146 insertions, 36 deletions
diff --git a/src/qcstring.h b/src/qcstring.h index 3efda9a..ba5ac95 100644 --- a/src/qcstring.h +++ b/src/qcstring.h @@ -27,6 +27,8 @@ #include <cstdint> #include <ostream> +#include "utf8.h" + #ifndef FALSE #define FALSE false #endif @@ -40,7 +42,7 @@ typedef unsigned long ulong; typedef int64_t int64; typedef uint64_t uint64; #define ASSERT(x) if ( !(x) )\ - fprintf(stderr,"ASSERT: \"%s\" in %s (%d)",#x,__FILE__,__LINE__) + fprintf(stderr,"ASSERT: \"%s\" in %s (%d)\n",#x,__FILE__,__LINE__) /***************************************************************************** @@ -74,15 +76,23 @@ char * qstrncpy(char *dst,const char *src, uint len); inline int cstrcmp( const char *str1, const char *str2 ) { return strcmp(str1,str2); } +inline bool qisempty( const char *s) +{ return s==0 || *s==0; } + inline int qstrcmp( const char *str1, const char *str2 ) -{ return (str1 && str2) ? strcmp(str1,str2) : (int)((intptr_t)str2 - (intptr_t)str1); } +{ return (str1 && str2) ? strcmp(str1,str2) : // both non-empty + (qisempty(str1) && qisempty(str2)) ? 0 : // both empty + qisempty(str1) ? -1 : 1; // one empty, other non-empty +} inline int cstrncmp( const char *str1, const char *str2, uint len ) { return strncmp(str1,str2,len); } inline int qstrncmp( const char *str1, const char *str2, uint len ) -{ return (str1 && str2) ? strncmp(str1,str2,len) : - (int)((intptr_t)str2 - (intptr_t)str1); } +{ return (str1 && str2) ? strncmp(str1,str2,len) : // both non-empty + (qisempty(str1) && qisempty(str2)) ? 0 : // both empty + qisempty(str1) ? -1 : 1; // one empty other non-empty +} inline bool qisspace(char c) { return c==' ' || c=='\t' || c=='\n' || c=='\r'; } @@ -105,7 +115,9 @@ class QCString QCString( QCString &&s ) = default; QCString &operator=( QCString &&s ) = default; - QCString( const std::string &s ) : m_rep(s) {} + explicit QCString( const std::string &s ) : m_rep(s) {} + + QCString( std::string &&s) { m_rep = std::move(s); } /** creates a string with room for size characters * @param[in] size the number of character to allocate (also counting the 0-terminator!) @@ -120,11 +132,11 @@ class QCString /** creates a string from \a str and copies over the first \a maxlen characters. */ QCString( const char *str, uint maxlen ) : m_rep(str?str:"") { m_rep.resize(maxlen); } - /** replaces the contents by that of string \a s. */ - /** replaces the contents by that of C string \a str. */ QCString &operator=( const char *str) { m_rep = str?str:""; return *this; } + QCString &operator=( const std::string &s) { m_rep = s; return *this; } + /** Returns TRUE iff the string is empty. Equivalent to isEmpty(). */ bool isNull() const { return m_rep.empty(); } @@ -138,13 +150,11 @@ class QCString uint size() const { return (uint)m_rep.size(); } /** Returns a pointer to the contents of the string in the form of a 0-terminated C string */ - const char *data() const { return m_rep.empty() ? 0 : m_rep.c_str(); } + const char *data() const { return m_rep.c_str(); } /** Returns a writable pointer to the data. - * @warning if the string is shared it will modifying the string directly and - * this will overwrite all copies as well! */ - char *rawData() const { return m_rep.empty() ? 0 : const_cast<char*>(&m_rep[0]); } + char *rawData() { return &m_rep[0]; } /** Resizes the string to hold \a newlen characters * (this value should also count the 0-terminator). @@ -169,9 +179,6 @@ class QCString return TRUE; } - /** Returns a deep copy of the string. */ - QCString copy() const { return *this; } - QCString &sprintf( const char *format, ... ); int find( char c, int index=0, bool cs=TRUE ) const; @@ -187,16 +194,20 @@ class QCString int contains( const char *str, bool cs=TRUE ) const; //int contains( const QRegExp &rx ) const; - bool stripPrefix(const char *prefix) + bool stripPrefix(const QCString &prefix) { - if (prefix==0 || m_rep.empty()) return FALSE; - if (m_rep.rfind(prefix,0)==0) // string starts with prefix + if (prefix.isEmpty() || m_rep.empty()) return FALSE; + if (m_rep.rfind(prefix.data(),0)==0) // string starts with prefix { - m_rep.erase(0,qstrlen(prefix)); + m_rep.erase(0,prefix.length()); return TRUE; } return FALSE; } + bool stripPrefix(const char *prefix) + { + return stripPrefix(QCString(prefix)); + } QCString left( uint len ) const { @@ -220,18 +231,12 @@ class QCString QCString lower() const { - std::string s = m_rep; - std::transform(s.begin(),s.end(),s.begin(), - [](unsigned char c){ return (unsigned char)std::tolower(c); }); - return s; + return QCString(convertUTF8ToLower(m_rep)); } QCString upper() const { - std::string s = m_rep; - std::transform(s.begin(),s.end(),s.begin(), - [](unsigned char c){ return (unsigned char)std::toupper(c); }); - return s; + return QCString(convertUTF8ToUpper(m_rep)); } QCString stripWhiteSpace() const @@ -247,6 +252,24 @@ class QCString QCString simplifyWhiteSpace() const; + QCString &insert( uint index, const QCString &s ) + { + if (s.length()>0) + { + uint ol = (uint)m_rep.size(); + if (index>ol) // insert beyond end of string and fill gap with spaces + { + m_rep.resize(index+s.length()); + std::memset(&m_rep[ol],' ',index-ol); + std::memcpy(&m_rep[index],s.data(),s.length()+1); + } + else // insert inside the string + { + m_rep.insert(index,s.str()); + } + } + return *this; + } QCString &insert( uint index, const char *s ) { uint len = s ? qstrlen(s) : 0; @@ -273,16 +296,42 @@ class QCString return insert(index,s); } + QCString &append( char c) + { + m_rep+=c; + return *this; + } + QCString &append( const char *s ) { return operator+=(s); } + QCString &append( const QCString &s ) + { + return operator+=(s); + } + + QCString &append( const std::string &s ) + { + return operator+=(s); + } + QCString &prepend( const char *s ) { return insert(0,s); } + QCString &prepend( const QCString &s ) + { + return insert(0,s.data()); + } + + QCString &prepend( const std::string &s ) + { + return insert(0,s.c_str()); + } + QCString &remove( uint index, uint len ) { uint ol = (uint)m_rep.size(); @@ -343,11 +392,20 @@ class QCString return m_rep.rfind(s,0)==0; // looking "backward" starting and ending at index 0 } + bool startsWith( const QCString &s ) const + { + if (m_rep.empty() || s.isEmpty()) return s.isEmpty(); + return m_rep.rfind(s.str(),0)==0; // looking "backward" starting and ending at index 0 + } + +#define HAS_IMPLICIT_CAST_TO_PLAIN_C_STRING 0 +#if HAS_IMPLICIT_CAST_TO_PLAIN_C_STRING /** Converts the string to a plain C string */ operator const char *() const { return data(); } +#endif std::string str() const { @@ -373,23 +431,36 @@ class QCString return *this; } +#define HAS_CHARACTER_APPEND_OPERATOR 1 +#if HAS_CHARACTER_APPEND_OPERATOR /** Appends character \a c to this string and returns a reference to the result. */ QCString &operator+=( char c ) { m_rep+=c; return *this; } +#endif /** Returns a reference to the character at index \a i. */ - char &at( uint i) const + char &at( uint i) { - return const_cast<char&>(m_rep[i]); + return m_rep[i]; + } + + const char &at( uint i) const + { + return m_rep[i]; } /** Indexing operator. Equivalent to at(). */ - char &operator[]( int i ) const + char &operator[]( int i ) { - return const_cast<char&>(m_rep[i]); + return m_rep[i]; + } + + const char &operator[]( int i ) const + { + return m_rep[i]; } private: @@ -454,31 +525,34 @@ inline QCString operator+( const QCString &s1, const QCString &s2 ) inline QCString operator+( const QCString &s1, const char *s2 ) { QCString tmp(s1); - tmp += s2; + tmp.append(s2); return tmp; } inline QCString operator+( const char *s1, const QCString &s2 ) { QCString tmp(s1); - tmp += s2; + tmp.append(s2); return tmp; } +#define HAD_PLUS_OPERATOR_FOR_CHAR 0 +#if HAS_PLUS_OPERATOR_FOR_CHAR inline QCString operator+( const QCString &s1, char c2 ) { QCString tmp( s1.data() ); - tmp += c2; + tmp.append(c2); return tmp; } inline QCString operator+( char c1, const QCString &s2 ) { QCString tmp; - tmp += c1; - tmp += s2; + tmp.append(c1); + tmp.append(s2); return tmp; } +#endif inline const char *qPrint(const char *s) { @@ -500,15 +574,51 @@ inline std::string toStdString(const QCString &s) return s.str(); } +//---- overloads + +inline int qstricmp( const QCString &str1, const char *str2 ) +{ + return qstricmp(str1.data(),str2); +} + +inline int qstricmp( const char *str1, const QCString &str2 ) +{ + return qstricmp(str1,str2.data()); +} + +inline int qstricmp( const QCString &str1, const QCString &str2 ) +{ + return qstricmp(str1.data(),str2.data()); +} + +inline int qstrnicmp( const QCString &str1, const char *str2, uint len ) +{ + return qstrnicmp(str1.data(),str2,len); +} + +inline int qstrnicmp( const char *str1, const QCString &str2, uint len ) +{ + return qstrnicmp(str1,str2.data(),len); +} + +inline int qstrnicmp( const QCString &str1, const QCString &str2, uint len ) +{ + return qstrnicmp(str1.data(),str2.data(),len); +} + // helper functions QCString substitute(const QCString &str,const QCString &find,const QCString &replace); +inline QCString substitute(const QCString &str,const char *find,const char *replace) +{ + return substitute(str,QCString(find),QCString(replace)); +} QCString substitute(const QCString &s,const QCString &src,const QCString &dst,int skip_seq); inline QCString substitute(const QCString &s,char srcChar,char dstChar) { std::string ss = s.str(); std::replace(ss.begin(),ss.end(),srcChar,dstChar); - return ss; + return QCString(ss); } inline std::ostream& operator<<(std::ostream& os, const QCString& s) |