PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/qtools/scstring.cpp

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