doxygen
qcstring.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 1997-2015 by Dimitri van Heesch.
4 **
5 ** Permission to use, copy, modify, and distribute this software and its
6 ** documentation under the terms of the GNU General Public License is hereby
7 ** granted. No representations are made about the suitability of this software
8 ** for any purpose. It is provided "as is" without express or implied warranty.
9 ** See the GNU General Public License for more details.
10 **
11 ** Note: this is a reimplementation of the qcstring.h that came with
12 ** an Qt version 2.2.3. For short strings it stores the string data inside
13 ** the object. For long strings it uses a separate array with reference counting.
14 **
15 **********************************************************************/
16 
17 #ifndef QCSTRING_H
18 #define QCSTRING_H
19 
20 #include <string>
21 #include <algorithm>
22 
23 #include <cctype>
24 #include <cstring>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstdint>
28 #include <ostream>
29 
30 #include "utf8.h"
31 
32 #ifndef FALSE
33 #define FALSE false
34 #endif
35 #ifndef TRUE
36 #define TRUE true
37 #endif
38 typedef unsigned char uchar;
39 typedef unsigned short ushort;
40 typedef unsigned uint;
41 typedef unsigned long ulong;
42 typedef int64_t int64;
43 typedef uint64_t uint64;
44 #define ASSERT(x) if ( !(x) )\
45  fprintf(stderr,"ASSERT: \"%s\" in %s (%d)\n",#x,__FILE__,__LINE__)
46 
47 
48 /*****************************************************************************
49  Safe and portable C string functions; extensions to standard string.h
50  *****************************************************************************/
51 
52 void *qmemmove( void *dst, const void *src, size_t len );
53 
54 #if defined(_OS_WIN32_)
55 #define qsnprintf _snprintf
56 #else
57 #define qsnprintf snprintf
58 #endif
59 
60 char *qstrdup( const char * );
61 
62 inline uint cstrlen( const char *str )
63 { return static_cast<uint>(strlen(str)); }
64 
65 inline uint qstrlen( const char *str )
66 { return str ? static_cast<uint>(strlen(str)) : 0; }
67 
68 inline char *cstrcpy( char *dst, const char *src )
69 { return strcpy(dst,src); }
70 
71 inline char *qstrcpy( char *dst, const char *src )
72 { return src ? strcpy(dst, src) : 0; }
73 
74 char * qstrncpy(char *dst,const char *src, size_t len);
75 
76 inline int cstrcmp( const char *str1, const char *str2 )
77 { return strcmp(str1,str2); }
78 
79 inline bool qisempty( const char *s)
80 { return s==0 || *s==0; }
81 
82 inline int qstrcmp( const char *str1, const char *str2 )
83 { return (str1 && str2) ? strcmp(str1,str2) : // both non-empty
84  (qisempty(str1) && qisempty(str2)) ? 0 : // both empty
85  qisempty(str1) ? -1 : 1; // one empty, other non-empty
86 }
87 
88 inline int cstrncmp( const char *str1, const char *str2, size_t len )
89 { return strncmp(str1,str2,len); }
90 
91 inline int qstrncmp( const char *str1, const char *str2, size_t len )
92 { return (str1 && str2) ? strncmp(str1,str2,len) : // both non-empty
93  (qisempty(str1) && qisempty(str2)) ? 0 : // both empty
94  qisempty(str1) ? -1 : 1; // one empty other non-empty
95 }
96 
97 inline bool qisspace(char c)
98 { return c==' ' || c=='\t' || c=='\n' || c=='\r'; }
99 
100 int qstricmp( const char *str1, const char *str2 );
101 
102 int qstrnicmp( const char *str1, const char *str2, size_t len );
103 
104 
108 class QCString
109 {
110  public:
111  QCString() = default;
112  ~QCString() = default;
113  QCString( const QCString &s ) = default;
114  QCString &operator=( const QCString &s ) = default;
115  QCString( QCString &&s ) = default;
116  QCString &operator=( QCString &&s ) = default;
117 
118  explicit QCString( const std::string &s ) : m_rep(s) {}
119 
120  QCString( std::string &&s) : m_rep(std::move(s)) {}
121 
125  explicit QCString( size_t size ) { m_rep.resize(size>0 ? size-1 : 0); }
126 
130  QCString( const char *str ) : m_rep(str?str:"") {}
131 
133  QCString( const char *str, size_t maxlen ) : m_rep(str?str:"") { m_rep.resize(maxlen); }
134 
136  QCString &operator=( const char *str) { m_rep = str?str:""; return *this; }
137 
138  QCString &operator=( const std::string &s) { m_rep = s; return *this; }
139 
141  bool isNull() const { return m_rep.empty(); }
142 
144  bool isEmpty() const { return m_rep.empty(); }
145 
147  uint length() const { return static_cast<uint>(m_rep.size()); }
148 
150  uint size() const { return static_cast<uint>(m_rep.size()); }
151 
153  const char *data() const { return m_rep.c_str(); }
154 
157  char *rawData() { return &m_rep[0]; }
158 
164  bool resize( size_t newlen ) { m_rep.resize( newlen>0 ? newlen-1 : 0 ); return TRUE; }
165 
167  bool truncate( size_t pos ) { return resize( pos + 1 ); }
168 
175  bool fill( char c, int len = -1 )
176  {
177  int l = len==-1 ? static_cast<int>(m_rep.size()) : len;
178  m_rep = std::string(l,c);
179  return TRUE;
180  }
181 
182  QCString &sprintf( const char *format, ... );
183 
184  int find( char c, int index=0, bool cs=TRUE ) const;
185  int find( const char *str, int index=0, bool cs=TRUE ) const;
186  int find( const QCString &str, int index=0, bool cs=TRUE ) const;
187  //int find( const QRegExp &rx, int index=0 ) const;
188 
189  int findRev( char c, int index=-1, bool cs=TRUE) const;
190  int findRev( const char *str, int index=-1, bool cs=TRUE) const;
191  //int findRev( const QRegExp &rx, int index=-1 ) const;
192 
193  int contains( char c, bool cs=TRUE ) const;
194  int contains( const char *str, bool cs=TRUE ) const;
195  //int contains( const QRegExp &rx ) const;
196 
197  bool stripPrefix(const QCString &prefix)
198  {
199  if (prefix.isEmpty() || m_rep.empty()) return FALSE;
200  if (m_rep.rfind(prefix.data(),0)==0) // string starts with prefix
201  {
202  m_rep.erase(0,prefix.length());
203  return TRUE;
204  }
205  return FALSE;
206  }
207  bool stripPrefix(const char *prefix)
208  {
209  return stripPrefix(QCString(prefix));
210  }
211 
212  QCString left( size_t len ) const
213  {
214  return m_rep.empty() ? QCString() : QCString(m_rep.substr(0,len));
215  }
216 
217  QCString right( size_t len ) const
218  {
219  return m_rep.empty() ? QCString() :
220  len<m_rep.size() ? QCString(m_rep.substr(m_rep.size()-len,len)) :
221  *this;
222  }
223 
224  QCString mid( size_t index, size_t len=static_cast<size_t>(-1)) const
225  {
226  size_t slen = m_rep.size();
227  if (len==static_cast<uint>(-1)) len = slen-index;
228  return m_rep.empty() || index>slen || len==0 ? QCString() :
229  QCString(m_rep.substr(index,len));
230  }
231 
232  QCString lower() const
233  {
234  return QCString(convertUTF8ToLower(m_rep));
235  }
236 
237  QCString upper() const
238  {
239  return QCString(convertUTF8ToUpper(m_rep));
240  }
241 
244  {
245  size_t sl = m_rep.size();
246  if (sl==0 || (!qisspace(m_rep[0]) && !qisspace(m_rep[sl-1]))) return *this;
247  size_t start=0,end=sl-1;
248  while (start<sl && qisspace(m_rep[start])) start++;
249  if (start==sl) return QCString(); // only whitespace
250  while (end>start && qisspace(m_rep[end])) end--;
251  return QCString(m_rep.substr(start,1+end-start));
252  }
253 
254  // Returns a quoted copy of this string, unless it is already quoted.
255  // Note that trailing and leading whitespace is removed.
256  QCString quoted() const
257  {
258  size_t start=0, sl=m_rep.size(), end=sl-1;
259  while (start<sl && qisspace(m_rep[start])) start++; // skip over leading whitespace
260  if (start==sl) return QCString(); // only whitespace
261  while (end>start && qisspace(m_rep[end])) end--; // skip over trailing whitespace
262  bool needsQuotes=false;
263  size_t i=start;
264  if (i<end && m_rep[i]!='"') // stripped string has at least non-whitespace unquoted character
265  {
266  while (i<end && !needsQuotes) // check if the to be quoted part has at least one whitespace character
267  {
268  needsQuotes = qisspace(m_rep[i++]);
269  }
270  }
271  QCString result(m_rep.substr(start,1+end-start));
272  if (needsQuotes)
273  {
274  result.prepend("\"");
275  result.append("\"");
276  }
277  return result;
278  }
279 
282  {
283  size_t sl = m_rep.size();
284  if (sl==0) return *this;
285  std::string result = m_rep;
286  size_t src=0,dst=0;
287  while (src<sl)
288  {
289  if (!qisspace(m_rep[src])) result[dst++]=m_rep[src];
290  src++;
291  }
292  if (dst<m_rep.size()) result.resize(dst);
293  return QCString(result);
294  }
295 
299 
300  QCString &insert( size_t index, const QCString &s )
301  {
302  if (s.length()>0)
303  {
304  size_t ol = m_rep.size();
305  if (index>ol) // insert beyond end of string and fill gap with spaces
306  {
307  m_rep.resize(index+s.length());
308  std::memset(&m_rep[ol],' ',index-ol);
309  std::memcpy(&m_rep[index],s.data(),s.length()+1);
310  }
311  else // insert inside the string
312  {
313  m_rep.insert(index,s.str());
314  }
315  }
316  return *this;
317  }
318  QCString &insert( size_t index, const char *s )
319  {
320  size_t len = s ? qstrlen(s) : 0;
321  if (len>0)
322  {
323  size_t ol = m_rep.size();
324  if (index>ol) // insert beyond end of string and fill gap with spaces
325  {
326  m_rep.resize(index+len);
327  std::memset(&m_rep[ol],' ',index-ol);
328  std::memcpy(&m_rep[index],s,len+1);
329  }
330  else // insert inside the string
331  {
332  m_rep.insert(index,s);
333  }
334  }
335  return *this;
336  }
337 
338  QCString &insert( size_t index, char c)
339  {
340  char s[2] = { c, '\0' };
341  return insert(index,s);
342  }
343 
344  QCString &append( char c)
345  {
346  m_rep+=c;
347  return *this;
348  }
349 
350  QCString &append( const char *s )
351  {
352  return operator+=(s);
353  }
354 
355  QCString &append( const QCString &s )
356  {
357  return operator+=(s);
358  }
359 
360  QCString &append( const std::string &s )
361  {
362  return operator+=(s);
363  }
364 
365  QCString &prepend( const char *s )
366  {
367  return insert(0,s);
368  }
369 
370  QCString &prepend( const QCString &s )
371  {
372  return insert(0,s.data());
373  }
374 
375  QCString &prepend( const std::string &s )
376  {
377  return insert(0,s.c_str());
378  }
379 
380  QCString &remove( size_t index, size_t len )
381  {
382  size_t ol = m_rep.size();
383  if (index<ol && len>0) m_rep.erase(index,index+len>=ol ? std::string::npos : len);
384  return *this;
385  }
386 
387  QCString &replace( size_t index, size_t len, const char *s);
388  //QCString &replace( const QRegExp &rx, const char *str );
389 
390  short toShort( bool *ok=0, int base=10 ) const;
391  ushort toUShort( bool *ok=0, int base=10 ) const;
392  int toInt( bool *ok=0, int base=10 ) const;
393  uint toUInt( bool *ok=0, int base=10 ) const;
394  long toLong( bool *ok=0, int base=10 ) const;
395  ulong toULong( bool *ok=0, int base=10 ) const;
396  uint64 toUInt64( bool *ok=0, int base=10 ) const;
397 
398  QCString &setNum(short n)
399  {
400  m_rep = std::to_string(n);
401  return *this;
402  }
403 
404  QCString &setNum(ushort n)
405  {
406  m_rep = std::to_string(n);
407  return *this;
408  }
409 
410  QCString &setNum(int n)
411  {
412  m_rep = std::to_string(n);
413  return *this;
414  }
415 
416  QCString &setNum(uint n)
417  {
418  m_rep = std::to_string(n);
419  return *this;
420  }
421 
422  QCString &setNum(long n)
423  {
424  m_rep = std::to_string(n);
425  return *this;
426  }
427 
428  QCString &setNum(ulong n)
429  {
430  m_rep = std::to_string(n);
431  return *this;
432  }
433 
434  bool startsWith( const char *s ) const
435  {
436  if (m_rep.empty() || s==0) return s==0;
437  return m_rep.rfind(s,0)==0; // looking "backward" starting and ending at index 0
438  }
439 
440  bool startsWith( const QCString &s ) const
441  {
442  if (m_rep.empty() || s.isEmpty()) return s.isEmpty();
443  return m_rep.rfind(s.str(),0)==0; // looking "backward" starting and ending at index 0
444  }
445 
446  bool endsWith(const char *s) const
447  {
448  if (m_rep.empty() || s==0) return s==0;
449  size_t l = strlen(s);
450  return m_rep.length()>=l && m_rep.compare(m_rep.length()-l, l, s, l)==0;
451  }
452 
453  bool endsWith(const QCString &s) const
454  {
455  size_t l = s.length();
456  return m_rep.length()>=l && m_rep.compare(m_rep.length()-l, l, s.str())==0;
457  }
458 
459 #define HAS_IMPLICIT_CAST_TO_PLAIN_C_STRING 0
460 #if HAS_IMPLICIT_CAST_TO_PLAIN_C_STRING
461 
462  operator const char *() const
463  {
464  return data();
465  }
466 #endif
467 
468  const std::string &str() const
469  {
470  return m_rep;
471  }
472 
473  QCString &operator+=( const QCString &s)
474  {
475  m_rep+=s.str();
476  return *this;
477  }
478 
479  QCString &operator+=( const std::string &s)
480  {
481  m_rep+=s;
482  return *this;
483  }
484 
486  QCString &operator+=( const char *s )
487  {
488  if (s) m_rep+=s;
489  return *this;
490  }
491 
492 #define HAS_CHARACTER_APPEND_OPERATOR 1
493 #if HAS_CHARACTER_APPEND_OPERATOR
494 
495  QCString &operator+=( char c )
496  {
497  m_rep+=c;
498  return *this;
499  }
500 #endif
501 
503  char &at( size_t i)
504  {
505  return m_rep[i];
506  }
507 
508  const char &at( size_t i) const
509  {
510  return m_rep[i];
511  }
512 
514  char &operator[]( int i )
515  {
516  return m_rep[i];
517  }
518 
519  const char &operator[]( int i ) const
520  {
521  return m_rep[i];
522  }
523 
524  private:
525  std::string m_rep;
526 };
527 
528 /*****************************************************************************
529  QCString non-member operators
530  *****************************************************************************/
531 
532 inline bool operator==( const QCString &s1, const QCString &s2 )
533 { return s1.str() == s2.str(); }
534 
535 inline bool operator==( const QCString &s1, const char *s2 )
536 { return qstrcmp(s1.data(),s2) == 0; }
537 
538 inline bool operator==( const char *s1, const QCString &s2 )
539 { return qstrcmp(s1,s2.data()) == 0; }
540 
541 inline bool operator!=( const QCString &s1, const QCString &s2 )
542 { return s1.str() != s2.str(); }
543 
544 inline bool operator!=( const QCString &s1, const char *s2 )
545 { return qstrcmp(s1.data(),s2) != 0; }
546 
547 inline bool operator!=( const char *s1, const QCString &s2 )
548 { return qstrcmp(s1,s2.data()) != 0; }
549 
550 inline bool operator<( const QCString &s1, const QCString& s2 )
551 { return qstrcmp(s1.data(),s2.data()) < 0; }
552 
553 inline bool operator<( const QCString &s1, const char *s2 )
554 { return qstrcmp(s1.data(),s2) < 0; }
555 
556 inline bool operator<( const char *s1, const QCString &s2 )
557 { return qstrcmp(s1,s2.data()) < 0; }
558 
559 inline bool operator<=( const QCString &s1, const char *s2 )
560 { return qstrcmp(s1.data(),s2) <= 0; }
561 
562 inline bool operator<=( const char *s1, const QCString &s2 )
563 { return qstrcmp(s1,s2.data()) <= 0; }
564 
565 inline bool operator>( const QCString &s1, const char *s2 )
566 { return qstrcmp(s1.data(),s2) > 0; }
567 
568 inline bool operator>( const char *s1, const QCString &s2 )
569 { return qstrcmp(s1,s2.data()) > 0; }
570 
571 inline bool operator>=( const QCString &s1, const char *s2 )
572 { return qstrcmp(s1.data(),s2) >= 0; }
573 
574 inline bool operator>=( const char *s1, const QCString &s2 )
575 { return qstrcmp(s1,s2.data()) >= 0; }
576 
577 inline QCString operator+( const QCString &s1, const QCString &s2 )
578 {
579  return QCString(s1.str()+s2.str());
580 }
581 
582 
583 inline QCString operator+( const QCString &s1, const char *s2 )
584 {
585  QCString tmp(s1);
586  tmp.append(s2);
587  return tmp;
588 }
589 
590 inline QCString operator+( const char *s1, const QCString &s2 )
591 {
592  QCString tmp(s1);
593  tmp.append(s2);
594  return tmp;
595 }
596 
597 #define HAD_PLUS_OPERATOR_FOR_CHAR 0
598 #if HAS_PLUS_OPERATOR_FOR_CHAR
599 inline QCString operator+( const QCString &s1, char c2 )
600 {
601  QCString tmp( s1.data() );
602  tmp.append(c2);
603  return tmp;
604 }
605 
606 inline QCString operator+( char c1, const QCString &s2 )
607 {
608  QCString tmp;
609  tmp.append(c1);
610  tmp.append(s2);
611  return tmp;
612 }
613 #endif
614 
615 inline const char *qPrint(const char *s)
616 {
617  if (s) return s; else return "";
618 }
619 
620 inline const char *qPrint(const QCString &s)
621 {
622  if (!s.isEmpty()) return s.data(); else return "";
623 }
624 
625 inline const char *qPrint(const std::string &s)
626 {
627  return s.c_str();
628 }
629 
630 inline std::string toStdString(const QCString &s)
631 {
632  return s.str();
633 }
634 
635 //---- overloads
636 
637 inline int qstricmp( const QCString &str1, const char *str2 )
638 {
639  return qstricmp(str1.data(),str2);
640 }
641 
642 inline int qstricmp( const char *str1, const QCString &str2 )
643 {
644  return qstricmp(str1,str2.data());
645 }
646 
647 inline int qstricmp( const QCString &str1, const QCString &str2 )
648 {
649  return qstricmp(str1.data(),str2.data());
650 }
651 
652 inline int qstrnicmp( const QCString &str1, const char *str2, size_t len )
653 {
654  return qstrnicmp(str1.data(),str2,len);
655 }
656 
657 inline int qstrnicmp( const char *str1, const QCString &str2, size_t len )
658 {
659  return qstrnicmp(str1,str2.data(),len);
660 }
661 
662 inline int qstrnicmp( const QCString &str1, const QCString &str2, size_t len )
663 {
664  return qstrnicmp(str1.data(),str2.data(),len);
665 }
666 
667 // helper functions
668 QCString substitute(const QCString &str,const QCString &find,const QCString &replace);
669 inline QCString substitute(const QCString &str,const char *find,const char *replace)
670 {
671  return substitute(str,QCString(find),QCString(replace));
672 }
673 QCString substitute(const QCString &s,const QCString &src,const QCString &dst,int skip_seq);
674 
675 inline QCString substitute(const QCString &s,char srcChar,char dstChar)
676 {
677  std::string ss = s.str();
678  std::replace(ss.begin(),ss.end(),srcChar,dstChar);
679  return QCString(ss);
680 }
681 
682 inline std::ostream& operator<<(std::ostream& os, const QCString& s)
683 {
684  os << s.str();
685  return os;
686 }
687 
688 #endif // QCSTRING_H
QCString & operator+=(char c)
Appends character c to this string and returns a reference to the result.
Definition: qcstring.h:495
QCString removeWhiteSpace() const
returns a copy of this string with all whitespace removed
Definition: qcstring.h:281
uint size() const
Returns the length of the string, not counting the 0-terminator.
Definition: qcstring.h:150
QCString & operator=(const char *str)
replaces the contents by that of C string str.
Definition: qcstring.h:136
uint length() const
Returns the length of the string, not counting the 0-terminator.
Definition: qcstring.h:147
Various UTF8 related helper functions.
QCString(const char *str)
creates a string from a plain C string.
Definition: qcstring.h:130
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition: qcstring.cpp:185
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition: qcstring.h:243
bool truncate(size_t pos)
Truncates the string at position pos.
Definition: qcstring.h:167
char & at(size_t i)
Returns a reference to the character at index i.
Definition: qcstring.h:503
std::string convertUTF8ToLower(const std::string &input)
Converts the input string into a lower case version, also taking into account non-ASCII characters th...
Definition: utf8.cpp:187
char * rawData()
Returns a writable pointer to the data.
Definition: qcstring.h:157
bool resize(size_t newlen)
Resizes the string to hold newlen characters (this value should also count the 0-terminator).
Definition: qcstring.h:164
bool isNull() const
Returns TRUE iff the string is empty.
Definition: qcstring.h:141
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition: qcstring.h:153
char & operator[](int i)
Indexing operator.
Definition: qcstring.h:514
QCString & operator+=(const char *s)
Appends string str to this string and returns a reference to the result.
Definition: qcstring.h:486
QCString(size_t size)
creates a string with room for size characters
Definition: qcstring.h:125
std::string convertUTF8ToUpper(const std::string &input)
Converts the input string into a upper case version, also taking into account non-ASCII characters th...
Definition: utf8.cpp:192
bool fill(char c, int len=-1)
Fills a string with a predefined character.
Definition: qcstring.h:175
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition: qcstring.h:144
This is an alternative implementation of QCString.
Definition: qcstring.h:108
QCString(const char *str, size_t maxlen)
creates a string from str and copies over the first maxlen characters.
Definition: qcstring.h:133