PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/qtools/qcstring.cpp

https://bitbucket.org/pbetkier/cutecpp
C++ | 794 lines | 713 code | 66 blank | 15 comment | 168 complexity | 2fa76f5403f79565546e9d9ad8960e8e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 1997-2004 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. * Documents produced by Doxygen are derivative works derived from the
  12. * input used in their production; they are not affected by this license.
  13. *
  14. */
  15. #include "qcstring.h"
  16. #include "qgstring.h"
  17. #include <qstring.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #include <ctype.h>
  22. #include <qregexp.h>
  23. #include <qdatastream.h>
  24. QCString::QCString(int size)
  25. {
  26. if (size>0)
  27. {
  28. m_data = (char *)malloc(size);
  29. if (m_data)
  30. {
  31. if (size>1) memset(m_data,' ',size-1);
  32. m_data[size-1]='\0';
  33. }
  34. }
  35. else
  36. {
  37. m_data=0;
  38. }
  39. }
  40. QCString::QCString( const QCString &s )
  41. {
  42. duplicate(s);
  43. }
  44. QCString::QCString( const char *str )
  45. {
  46. duplicate(str);
  47. }
  48. QCString::QCString( const char *str, uint maxlen )
  49. {
  50. uint l;
  51. if (str && ( l = QMIN(qstrlen(str),maxlen) ))
  52. {
  53. m_data=(char *)malloc(l+1);
  54. strncpy(m_data,str,l+1);
  55. m_data[l]='\0';
  56. }
  57. else
  58. {
  59. m_data=0;
  60. }
  61. }
  62. QCString::~QCString()
  63. {
  64. if (m_data) free(m_data);
  65. m_data=0;
  66. }
  67. QCString &QCString::assign( const char *str )
  68. {
  69. if (m_data) free(m_data);
  70. duplicate(str);
  71. return *this;
  72. }
  73. bool QCString::resize( uint newlen )
  74. {
  75. if (newlen==0)
  76. {
  77. if (m_data) { free(m_data); m_data=0; }
  78. return TRUE;
  79. }
  80. if (m_data==0) // newlen>0
  81. {
  82. m_data = (char *)malloc(newlen);
  83. }
  84. else
  85. {
  86. m_data = (char *)realloc(m_data,newlen);
  87. }
  88. if (m_data==0) return FALSE;
  89. m_data[newlen-1]='\0';
  90. return TRUE;
  91. }
  92. bool QCString::fill( char c, int len )
  93. {
  94. uint l=length();
  95. if (len<0) len=l;
  96. if ((uint)len!=l)
  97. {
  98. if (m_data) free(m_data);
  99. if (len>0)
  100. {
  101. m_data=(char *)malloc(len+1);
  102. if (m_data==0) return FALSE;
  103. m_data[len]='\0';
  104. }
  105. else
  106. {
  107. m_data=0;
  108. }
  109. }
  110. if (len>0)
  111. {
  112. uint i;
  113. for (i=0;i<(uint)len;i++) m_data[i]=c;
  114. }
  115. return TRUE;
  116. }
  117. QCString &QCString::sprintf( const char *format, ... )
  118. {
  119. va_list ap;
  120. va_start( ap, format );
  121. uint l = length();
  122. const uint minlen=256;
  123. if (l<minlen)
  124. {
  125. if (m_data)
  126. m_data = (char *)realloc(m_data,minlen);
  127. else
  128. m_data = (char *)malloc(minlen);
  129. }
  130. vsprintf( m_data, format, ap );
  131. resize( qstrlen(m_data) + 1 ); // truncate
  132. va_end( ap );
  133. return *this;
  134. }
  135. int QCString::find( char c, int index, bool cs ) const
  136. {
  137. uint len = length();
  138. if ( m_data==0 || (uint)index>len ) // index outside string
  139. return -1;
  140. register const char *d;
  141. if ( cs ) // case sensitive
  142. {
  143. d = strchr( m_data+index, c );
  144. }
  145. else
  146. {
  147. d = m_data+index;
  148. c = tolower( (uchar) c );
  149. while ( *d && tolower((uchar) *d) != c )
  150. d++;
  151. if ( !*d && c ) // not found
  152. d = 0;
  153. }
  154. return d ? (int)(d - m_data) : -1;
  155. }
  156. int QCString::find( const char *str, int index, bool cs ) const
  157. {
  158. uint l = length();
  159. if ( m_data==0 || (uint)index > l ) // index outside string
  160. return -1;
  161. if ( !str ) // no search string
  162. return -1;
  163. if ( !*str ) // zero-length search string
  164. return index;
  165. register const char *d;
  166. if ( cs ) // case sensitive
  167. {
  168. d = strstr( m_data+index, str );
  169. }
  170. else // case insensitive
  171. {
  172. d = m_data+index;
  173. int len = qstrlen( str );
  174. while ( *d )
  175. {
  176. if ( qstrnicmp(d, str, len) == 0 )
  177. break;
  178. d++;
  179. }
  180. if ( !*d ) // not found
  181. d = 0;
  182. }
  183. return d ? (int)(d - m_data) : -1;
  184. }
  185. int QCString::find( const QRegExp &rx, int index ) const
  186. {
  187. QString d = QString::fromLatin1( m_data );
  188. return d.find( rx, index );
  189. }
  190. int QCString::findRev( char c, int index, bool cs) const
  191. {
  192. const char *b = m_data;
  193. const char *d;
  194. uint len = length();
  195. if ( b == 0 ) return -1; // empty string
  196. if ( index < 0 ) // neg index ==> start from end
  197. {
  198. if ( len == 0 ) return -1;
  199. if ( cs )
  200. {
  201. d = strrchr( b, c );
  202. return d ? (int)(d - b) : -1;
  203. }
  204. index = len;
  205. }
  206. else if ( (uint)index > len ) // bad index
  207. {
  208. return -1;
  209. }
  210. d = b+index;
  211. if ( cs ) // case sensitive
  212. {
  213. while ( d >= b && *d != c )
  214. d--;
  215. }
  216. else // case insensitive
  217. {
  218. c = tolower( (uchar) c );
  219. while ( d >= b && tolower((uchar) *d) != c )
  220. d--;
  221. }
  222. return d >= b ? (int)(d - b) : -1;
  223. }
  224. int QCString::findRev( const char *str, int index, bool cs) const
  225. {
  226. int slen = qstrlen(str);
  227. uint len = length();
  228. if ( index < 0 ) // neg index ==> start from end
  229. index = len-slen;
  230. else if ( (uint)index > len ) // bad index
  231. return -1;
  232. else if ( (uint)(index + slen) > len ) // str would be too long
  233. index = len - slen;
  234. if ( index < 0 )
  235. return -1;
  236. register char *d = m_data + index;
  237. if ( cs ) // case sensitive
  238. {
  239. for ( int i=index; i>=0; i-- )
  240. if ( qstrncmp(d--,str,slen)==0 )
  241. return i;
  242. }
  243. else // case insensitive
  244. {
  245. for ( int i=index; i>=0; i-- )
  246. if ( qstrnicmp(d--,str,slen)==0 )
  247. return i;
  248. }
  249. return -1;
  250. }
  251. int QCString::findRev( const QRegExp &rx, int index ) const
  252. {
  253. QString d = QString::fromLatin1( m_data );
  254. return d.findRev( rx, index );
  255. }
  256. int QCString::contains( char c, bool cs ) const
  257. {
  258. int count = 0;
  259. char *d = m_data;
  260. if ( !d )
  261. return 0;
  262. if ( cs ) // case sensitive
  263. {
  264. while ( *d )
  265. if ( *d++ == c )
  266. count++;
  267. }
  268. else // case insensitive
  269. {
  270. c = tolower( (uchar) c );
  271. while ( *d ) {
  272. if ( tolower((uchar) *d) == c )
  273. count++;
  274. d++;
  275. }
  276. }
  277. return count;
  278. }
  279. int QCString::contains( const char *str, bool cs ) const
  280. {
  281. int count = 0;
  282. char *d = data();
  283. if ( !d )
  284. return 0;
  285. int len = qstrlen( str );
  286. while ( *d ) // counts overlapping strings
  287. {
  288. if ( cs )
  289. {
  290. if ( qstrncmp( d, str, len ) == 0 )
  291. count++;
  292. }
  293. else
  294. {
  295. if ( qstrnicmp(d, str, len) == 0 )
  296. count++;
  297. }
  298. d++;
  299. }
  300. return count;
  301. }
  302. int QCString::contains( const QRegExp &rx ) const
  303. {
  304. QString d = QString::fromLatin1( m_data );
  305. return d.contains( rx );
  306. }
  307. QCString QCString::left( uint len ) const
  308. {
  309. if ( isEmpty() )
  310. {
  311. return QCString();
  312. }
  313. else if ( len >= length() )
  314. {
  315. return *this;
  316. }
  317. else
  318. {
  319. QCString s( len+1 );
  320. strncpy( s.data(), m_data, len );
  321. *(s.data()+len) = '\0';
  322. return s;
  323. }
  324. }
  325. QCString QCString::right( uint len ) const
  326. {
  327. if ( isEmpty() )
  328. {
  329. return QCString();
  330. }
  331. else
  332. {
  333. uint l = length();
  334. if ( len > l ) len = l;
  335. char *p = m_data + (l - len);
  336. return QCString( p );
  337. }
  338. }
  339. QCString QCString::mid( uint index, uint len) const
  340. {
  341. uint slen = length();
  342. if ( len == 0xffffffff ) len = slen-index;
  343. if ( isEmpty() || index >= slen )
  344. {
  345. return QCString();
  346. }
  347. else
  348. {
  349. register char *p = data()+index;
  350. QCString s( len+1 );
  351. strncpy( s.data(), p, len );
  352. *(s.data()+len) = '\0';
  353. return s;
  354. }
  355. }
  356. QCString QCString::lower() const
  357. {
  358. QCString s( m_data );
  359. register char *p = s.data();
  360. if ( p )
  361. {
  362. while ( *p )
  363. {
  364. *p = tolower((uchar) *p);
  365. p++;
  366. }
  367. }
  368. return s;
  369. }
  370. QCString QCString::upper() const
  371. {
  372. QCString s( m_data );
  373. register char *p = s.data();
  374. if ( p ) {
  375. while ( *p ) {
  376. *p = toupper((uchar)*p);
  377. p++;
  378. }
  379. }
  380. return s;
  381. }
  382. QCString QCString::stripWhiteSpace() const
  383. {
  384. if ( isEmpty() ) // nothing to do
  385. return *this;
  386. register char *s = m_data;
  387. int reslen = length();
  388. if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) )
  389. return *this; // returns a copy
  390. QCString result(s);
  391. s = result.data();
  392. int start = 0;
  393. int end = reslen - 1;
  394. while ( isspace((uchar) s[start]) ) // skip white space from start
  395. start++;
  396. if ( s[start] == '\0' )
  397. { // only white space
  398. return QCString();
  399. }
  400. while ( end && isspace((uchar) s[end]) ) // skip white space from end
  401. end--;
  402. end -= start - 1;
  403. memmove( result.data(), &s[start], end );
  404. result.resize( end + 1 );
  405. return result;
  406. }
  407. QCString QCString::simplifyWhiteSpace() const
  408. {
  409. if ( isEmpty() ) // nothing to do
  410. return *this;
  411. QCString result( length()+1 );
  412. char *from = data();
  413. char *to = result.data();
  414. char *first = to;
  415. while ( TRUE )
  416. {
  417. while ( *from && isspace((uchar) *from) )
  418. from++;
  419. while ( *from && !isspace((uchar)*from) )
  420. *to++ = *from++;
  421. if ( *from )
  422. *to++ = 0x20; // ' '
  423. else
  424. break;
  425. }
  426. if ( to > first && *(to-1) == 0x20 )
  427. to--;
  428. *to = '\0';
  429. result.resize( (int)((long)to - (long)result.data()) + 1 );
  430. return result;
  431. }
  432. QCString &QCString::insert( uint index, const char *s )
  433. {
  434. int len = s ? qstrlen(s) : 0;
  435. if ( len == 0 )
  436. return *this;
  437. uint olen = length();
  438. int nlen = olen + len;
  439. if ( index >= olen ) // insert after end of string
  440. {
  441. m_data = (char *)realloc(m_data,nlen+index-olen+1);
  442. if ( m_data )
  443. {
  444. memset( m_data+olen, ' ', index-olen );
  445. memcpy( m_data+index, s, len+1 );
  446. }
  447. }
  448. else if ( (m_data = (char *)realloc(m_data,nlen+1)) ) // normal insert
  449. {
  450. memmove( m_data+index+len, m_data+index, olen-index+1 );
  451. memcpy( m_data+index, s, len );
  452. }
  453. return *this;
  454. }
  455. QCString &QCString::insert( uint index, char c ) // insert char
  456. {
  457. char buf[2];
  458. buf[0] = c;
  459. buf[1] = '\0';
  460. return insert( index, buf );
  461. }
  462. QCString& QCString::operator+=( const char *str )
  463. {
  464. if ( !str ) return *this; // nothing to append
  465. uint len1 = length();
  466. uint len2 = qstrlen(str);
  467. char *newData = (char *)realloc( m_data, len1 + len2 + 1 );
  468. if (newData)
  469. {
  470. m_data = newData;
  471. memcpy( m_data + len1, str, len2 + 1 );
  472. }
  473. return *this;
  474. }
  475. QCString &QCString::operator+=( char c )
  476. {
  477. uint len = length();
  478. char *newData = (char *)realloc( m_data, length()+2 );
  479. if (newData)
  480. {
  481. m_data = newData;
  482. m_data[len] = c;
  483. m_data[len+1] = '\0';
  484. }
  485. return *this;
  486. }
  487. QCString &QCString::remove( uint index, uint len )
  488. {
  489. uint olen = length();
  490. if ( index + len >= olen ) // range problems
  491. {
  492. if ( index < olen ) // index ok
  493. {
  494. resize( index+1 );
  495. }
  496. }
  497. else if ( len != 0 )
  498. {
  499. memmove( m_data+index, m_data+index+len, olen-index-len+1 );
  500. resize( olen-len+1 );
  501. }
  502. return *this;
  503. }
  504. QCString &QCString::replace( uint index, uint len, const char *s )
  505. {
  506. remove( index, len );
  507. insert( index, s );
  508. return *this;
  509. }
  510. QCString &QCString::replace( const QRegExp &rx, const char *str )
  511. {
  512. QString d = QString::fromLatin1( m_data );
  513. QString r = QString::fromLatin1( str );
  514. d.replace( rx, r );
  515. operator=( d.ascii() );
  516. return *this;
  517. }
  518. long QCString::toLong( bool *ok ) const
  519. {
  520. QString s(m_data);
  521. return s.toLong(ok);
  522. }
  523. ulong QCString::toULong( bool *ok ) const
  524. {
  525. QString s(m_data);
  526. return s.toULong(ok);
  527. }
  528. short QCString::toShort( bool *ok ) const
  529. {
  530. QString s(m_data);
  531. return s.toShort(ok);
  532. }
  533. ushort QCString::toUShort( bool *ok ) const
  534. {
  535. QString s(m_data);
  536. return s.toUShort(ok);
  537. }
  538. int QCString::toInt( bool *ok ) const
  539. {
  540. QString s(m_data);
  541. return s.toInt(ok);
  542. }
  543. uint QCString::toUInt( bool *ok ) const
  544. {
  545. QString s(m_data);
  546. return s.toUInt(ok);
  547. }
  548. QCString &QCString::setNum( long n )
  549. {
  550. char buf[20];
  551. register char *p = &buf[19];
  552. bool neg;
  553. if ( n < 0 )
  554. {
  555. neg = TRUE;
  556. n = -n;
  557. }
  558. else
  559. {
  560. neg = FALSE;
  561. }
  562. *p = '\0';
  563. do
  564. {
  565. *--p = ((int)(n%10)) + '0';
  566. n /= 10;
  567. } while ( n );
  568. if ( neg ) *--p = '-';
  569. operator=( p );
  570. return *this;
  571. }
  572. QCString &QCString::setNum( ulong n )
  573. {
  574. char buf[20];
  575. register char *p = &buf[19];
  576. *p = '\0';
  577. do
  578. {
  579. *--p = ((int)(n%10)) + '0';
  580. n /= 10;
  581. } while ( n );
  582. operator=( p );
  583. return *this;
  584. }
  585. void QCString::msg_index( uint index )
  586. {
  587. #if defined(CHECK_RANGE)
  588. qWarning( "QCString::at: Absolute index %d out of range", index );
  589. #else
  590. Q_UNUSED( index )
  591. #endif
  592. }
  593. bool QCString::stripPrefix(const char *prefix)
  594. {
  595. if (prefix==0) return FALSE;
  596. uint plen = qstrlen(prefix);
  597. if (m_data && qstrncmp(prefix,m_data,plen)==0) // prefix matches
  598. {
  599. uint len = qstrlen(m_data);
  600. uint newlen = len-plen+1;
  601. qmemmove(m_data,m_data+plen,newlen);
  602. resize(newlen);
  603. return TRUE;
  604. }
  605. return FALSE;
  606. }
  607. //---------------------------------------------------------------------------
  608. void *qmemmove( void *dst, const void *src, uint len )
  609. {
  610. register char *d;
  611. register char *s;
  612. if ( dst > src ) {
  613. d = (char *)dst + len - 1;
  614. s = (char *)src + len - 1;
  615. while ( len-- )
  616. *d-- = *s--;
  617. } else if ( dst < src ) {
  618. d = (char *)dst;
  619. s = (char *)src;
  620. while ( len-- )
  621. *d++ = *s++;
  622. }
  623. return dst;
  624. }
  625. char *qstrdup( const char *str )
  626. {
  627. if ( !str )
  628. return 0;
  629. char *dst = new char[strlen(str)+1];
  630. CHECK_PTR( dst );
  631. return strcpy( dst, str );
  632. }
  633. char *qstrncpy( char *dst, const char *src, uint len )
  634. {
  635. if ( !src )
  636. return 0;
  637. strncpy( dst, src, len );
  638. if ( len > 0 )
  639. dst[len-1] = '\0';
  640. return dst;
  641. }
  642. int qstricmp( const char *str1, const char *str2 )
  643. {
  644. register const uchar *s1 = (const uchar *)str1;
  645. register const uchar *s2 = (const uchar *)str2;
  646. int res;
  647. uchar c;
  648. if ( !s1 || !s2 )
  649. return s1 == s2 ? 0 : (int)((long)s2 - (long)s1);
  650. for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ )
  651. if ( !c ) // strings are equal
  652. break;
  653. return res;
  654. }
  655. int qstrnicmp( const char *str1, const char *str2, uint len )
  656. {
  657. register const uchar *s1 = (const uchar *)str1;
  658. register const uchar *s2 = (const uchar *)str2;
  659. int res;
  660. uchar c;
  661. if ( !s1 || !s2 )
  662. return (int)((long)s2 - (long)s1);
  663. for ( ; len--; s1++, s2++ ) {
  664. if ( (res = (c=tolower(*s1)) - tolower(*s2)) )
  665. return res;
  666. if ( !c ) // strings are equal
  667. break;
  668. }
  669. return 0;
  670. }
  671. #ifndef QT_NO_DATASTREAM
  672. QDataStream &operator<<( QDataStream &s, const QByteArray &a )
  673. {
  674. return s.writeBytes( a.data(), a.size() );
  675. }
  676. QDataStream &operator>>( QDataStream &s, QByteArray &a )
  677. {
  678. Q_UINT32 len;
  679. s >> len; // read size of array
  680. if ( len == 0 || s.eof() ) { // end of file reached
  681. a.resize( 0 );
  682. return s;
  683. }
  684. if ( !a.resize( (uint)len ) ) { // resize array
  685. #if defined(CHECK_NULL)
  686. qWarning( "QDataStream: Not enough memory to read QByteArray" );
  687. #endif
  688. len = 0;
  689. }
  690. if ( len > 0 ) // not null array
  691. s.readRawBytes( a.data(), (uint)len );
  692. return s;
  693. }
  694. QDataStream &operator<<( QDataStream &s, const QCString &str )
  695. {
  696. return s.writeBytes( str.data(), str.size() );
  697. }
  698. QDataStream &operator>>( QDataStream &s, QCString &str )
  699. {
  700. Q_UINT32 len;
  701. s >> len; // read size of string
  702. if ( len == 0 || s.eof() ) { // end of file reached
  703. str.resize( 0 );
  704. return s;
  705. }
  706. if ( !str.resize( (uint)len )) {// resize string
  707. #if defined(CHECK_NULL)
  708. qWarning( "QDataStream: Not enough memory to read QCString" );
  709. #endif
  710. len = 0;
  711. }
  712. if ( len > 0 ) // not null array
  713. s.readRawBytes( str.data(), (uint)len );
  714. return s;
  715. }
  716. #endif //QT_NO_DATASTREAM
  717. inline QCString operator+( const QCString &s1, const QGString &s2 )
  718. {
  719. QCString tmp(s1);
  720. tmp += s2.data();
  721. return tmp;
  722. }
  723. inline QCString operator+( const QGString &s1, const QCString &s2 )
  724. {
  725. QCString tmp(s1.data());
  726. tmp += s2;
  727. return tmp;
  728. }