summaryrefslogtreecommitdiffstats
path: root/src/qcstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qcstring.h')
-rw-r--r--src/qcstring.h182
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)