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

/sources/doxmlparser/src/qtools/scstring.cpp

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