qcstring.cpp 13.2 KB
Newer Older
1 2 3 4 5
/******************************************************************************
 *
 * Copyright (C) 1997-2004 by Dimitri van Heesch.
 *
 * Permission to use, copy, modify, and distribute this software and its
6 7
 * documentation under the terms of the GNU General Public License is hereby
 * granted. No representations are made about the suitability of this software
8 9 10 11 12 13 14
 * for any purpose. It is provided "as is" without express or implied warranty.
 * See the GNU General Public License for more details.
 *
 * Documents produced by Doxygen are derivative works derived from the
 * input used in their production; they are not affected by this license.
 *
 */
15

16 17
#include "qcstring.h"
#include "qgstring.h"
18

19 20 21 22 23 24 25
#include <qstring.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <qregexp.h>
#include <qdatastream.h>
26

27
QCString &QCString::sprintf( const char *format, ... )
28
{
29 30 31
  va_list ap;
  va_start( ap, format );
  const int minlen=256;
32 33 34
  int l = length();
  if (l<minlen) { resize(minlen); l=minlen; }
  int n=vsnprintf( data(), l, format, ap);
35 36
  if (n<0) n=l;
  resize(n+1);
37
  va_end( ap );
38
  return *this;
39 40
}

41
int QCString::find( char c, int index, bool cs ) const
42
{
43 44 45
  if (index<0 || index>=(int)length()) return -1; // index outside string
  register const char *pos;
  if (cs)
46
  {
47
    pos = strchr(data()+index,c);
48 49 50
  }
  else
  {
51 52 53 54
    pos = data()+index;
    c = tolower((unsigned char)c);
    while (*pos && tolower((unsigned char)*pos)!=c) pos++;
    if (!*pos && c) pos=0; // not found
55
  }
56
  return pos ? (int)(pos - data()) : -1;
57
}
58

59
int QCString::find( const char *str, int index, bool cs ) const
60
{
61 62 63 64 65 66
  int l = length();
  if (index<0 || index>=l) return -1; // index outside string
  if (!str)  return -1;               // no string to search for
  if (!*str) return index;           // empty string matching at index
  register char *pos;
  if (cs) // case sensitive
67
  {
68
    pos = strstr(data()+index,str);
69
  }
70
  else // case insensitive
71
  {
72
    pos = data();
73
    int len = qstrlen(str);
74
    while (*pos)
75
    {
76
      if (qstrnicmp(pos,str,len)==0) break;
77
      pos++;
78
    }
79
    if (!*pos) pos = 0; // not found
80
  }
81
  return pos ? (int)(pos - data()) : -1;
82 83
}

84
int QCString::find( const QCString &str, int index, bool cs ) const
85 86 87 88
{
  return find(str.data(),index,cs);
}

89 90
int QCString::find( const QRegExp &rx, int index ) const
{
91
  QString d = QString::fromLatin1( data() );
92 93
  return d.find( rx, index );
}
94

95 96
int QCString::findRev( char c, int index, bool cs) const
{
97 98 99 100 101
  const char *b = data();
  const char *pos;
  int len = length();
  if (len==0) return -1; // empty string
  if (index<0) // start from end
102
  {
103
    if (cs)
104
    {
105 106
      pos = strrchr(b,c);
      return pos ? (int)(pos - b) : -1;
107
    }
108 109 110 111
    index=len;
  }
  else if (index>len) // bad index
  {
112 113
    return -1;
  }
114 115
  pos = b+index;
  if (cs)
116
  {
117 118 119
    while ( pos>=b && *pos!=c) pos--;
  }
  else
120
  {
121 122
    c = tolower((unsigned char)c);
    while ( pos>=b && tolower((unsigned char)*pos)!=c) pos--;
123
  }
124
  return pos>=b ? (int)(pos - b) : -1;
125 126 127 128
}

int QCString::findRev( const char *str, int index, bool cs) const
{
129
  int slen = qstrlen(str);
130 131 132 133 134 135 136 137
  int len = length();
  if (index<0) index = len-slen; // start from end
  else if (index>len) return -1; // bad index
  else if (index+slen>len) index=len-slen; // str would be too long
  if (index<0) return -1; // no match possible
  register char *pos = data()+index;
  if (cs) // case sensitive
  {
138
    for (int i=index; i>=0; i--) if (qstrncmp(pos--,str,slen)==0) return i;
139 140 141
  }
  else // case insensitive
  {
142
    for (int i=index; i>=0; i--) if (qstrnicmp(pos,str,slen)==0) return i;
143 144 145
  }
  return -1;
}
146

147
int QCString::findRev( const QRegExp &rx, int index ) const
148
{
149
  QString d = QString::fromLatin1( data() );
150
  return d.findRev( rx, index );
151 152
}

153 154
int QCString::contains( char c, bool cs ) const
{
155 156 157 158 159 160 161 162 163 164 165 166 167 168
  if (length()==0) return 0;
  int count=0;
  const char *pos = data();
  if (cs)
  {
    while (*pos) if (*pos++ == c) count++;
  }
  else
  {
    c = tolower((unsigned char)c);
    while (*pos)
    {
      if (tolower((unsigned char)*pos)==c) count++;
      pos++;
169 170 171 172
    }
  }
  return count;
}
173

174 175
int QCString::contains( const char *str, bool cs ) const
{
176 177 178
  if (str==0 || length()==0) return 0;
  int count=0;
  const char *pos = data();
179
  int len = qstrlen(str);
180
  while (*pos)
181
  {
182
    if (cs)
183
    {
184
      if (qstrncmp(pos,str,len)==0) count++;
185 186
    }
    else
187
    {
188
      if (qstrnicmp(pos,str,len)==0) count++;
189
    }
190
    pos++;
191 192 193
  }
  return count;
}
194

195
int QCString::contains( const QRegExp &rx ) const
196 197
{
  QString d = QString::fromLatin1( data() );
198 199
  return d.contains( rx );
}
200

201 202 203
bool QCString::stripPrefix(const char *prefix)
{
  if (prefix==0 || length()==0) return FALSE;
204 205
  int len = qstrlen(prefix);
  if (qstrncmp(prefix,data(),len)==0)
206 207 208 209 210 211 212 213 214
  {
    int newlen = length()-len+1;
    qmemmove(data(),data()+len,newlen);
    resize(newlen);
    return TRUE;
  }
  return FALSE;
}

215
QCString QCString::left( uint len )  const
216
{
217
  if (isEmpty())
218 219
  {
    return QCString();
220 221
  }
  else if (len>=length())
222
  {
223 224 225
    return QCString(data());
  }
  else
226 227
  {
    QCString s( len+1 );
228
    memcpy( s.data(), data(), len);
229 230
    return s;
  }
231 232
}

233
QCString QCString::right( uint len ) const
234
{
235
  if (isEmpty())
236 237
  {
    return QCString();
238 239
  }
  else
240
  {
241 242 243 244 245
    int l = length();
    if ((int)len>l) len=l;
    const char *pos = data() + (l-len);
    return QCString(pos);
  }
246 247 248 249
}

QCString QCString::mid( uint index, uint len) const
{
250 251
  int slen = length();
  if (len==0xffffffff) len = slen-index;
252
  if (isEmpty() || (int)index>=slen || len==0)
253 254
  {
    return QCString();
255 256
  }
  else
257 258
  {
    register char *p = data()+index;
259
    QCString s(len+1);
260
    qstrncpy( s.data(), p, len+1 );
261 262
    return s;
  }
263 264
}

265
QCString QCString::lower() const
266
{
267 268 269 270
  if (length()==0) return QCString();
  QCString s(data());
  register char *pos = s.data();
  if (pos)
271
  {
272
    while (*pos)
273
    {
274 275
      *pos = tolower((unsigned char)*pos);
      pos++;
276
    }
277 278
  }
  return s;
279 280
}

281 282
QCString QCString::upper() const
{
283 284 285 286 287 288 289 290 291
  if (length()==0) return QCString();
  QCString s(data());
  register char *pos = s.data();
  if (pos)
  {
    while (*pos)
    {
      *pos = toupper((unsigned char)*pos);
      pos++;
292 293 294 295
    }
  }
  return s;
}
296

297
QCString QCString::stripWhiteSpace() const
298
{
299
  if ( isEmpty() )                            // nothing to do
300
    return *this;
301

302
  register char *s = data();
303
  int reslen = length();
304 305
  if ( !isspace((uchar)s[0]) && !isspace((uchar)s[reslen-1]) )
    return *this;                             // returns a copy
306 307

  QCString result(s);
308
  s = result.data();
309 310 311
  int start = 0;
  int end = reslen - 1;
  while ( isspace((uchar) s[start]) )                 // skip white space from start
312 313
    start++;
  if ( s[start] == '\0' )
314 315 316 317 318 319
  {                                                   // only white space
    return QCString();
  }
  while ( end && isspace((uchar) s[end]) )            // skip white space from end
    end--;
  end -= start - 1;
320
  qmemmove( result.data(), &s[start], end );
321 322
  result.resize( end + 1 );
  return result;
323 324
}

325 326 327 328
QCString QCString::simplifyWhiteSpace() const
{
  if ( isEmpty() )                            // nothing to do
    return *this;
329

330 331 332 333
  QCString result( length()+1 );
  char *from  = data();
  char *to    = result.data();
  char *first = to;
334
  while ( TRUE )
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
  {
    while ( *from && isspace((uchar) *from) )
      from++;
    while ( *from && !isspace((uchar)*from) )
      *to++ = *from++;
    if ( *from )
      *to++ = 0x20;                       // ' '
    else
      break;
  }
  if ( to > first && *(to-1) == 0x20 )
    to--;
  *to = '\0';
  result.resize( (int)((long)to - (long)result.data()) + 1 );
  return result;
}
351

352 353 354 355 356
QCString &QCString::assign( const char *str )
{
  return operator=(str);
}

357
QCString &QCString::insert( uint index, const char *s )
358
{
359
  int len = s ? qstrlen(s) : 0;
360 361 362 363 364 365 366 367 368 369 370 371 372 373
  if ( len == 0 ) return *this;
  int olen = length();
  int nlen = olen + len;
  if ((int)index>=olen)
  {
    resize(nlen+index-olen+1);
    memset(data()+olen, ' ', index-olen);
    memcpy(data()+index,s, len+1);
  }
  else
  {
    resize(nlen+1);
    qmemmove(data()+index+len,data()+index,olen-index+1);
    memcpy(data()+index,s,len);
374 375 376
  }
  return *this;
}
377

378
QCString &QCString::insert( uint index, char c)
379
{
380 381 382 383
  char buf[2];
  buf[0] = c;
  buf[1] = '\0';
  return insert( index, buf );
384
}
385
QCString &QCString::append( const char *s )
386
{
387
  return operator+=(s);
388
}
389
QCString &QCString::prepend( const char *s )
390
{
391
  return insert(0,s);
392
}
393 394 395 396
QCString &QCString::remove( uint index, uint len )
{
  uint olen = length();
  if ( index + len >= olen ) // range problems
397
  {
398
    if ( index < olen )  // index ok
399
    {
400 401
      resize( index+1 );
    }
402 403
  }
  else if ( len != 0 )
404
  {
405
    qmemmove( data()+index, data()+index+len, olen-index-len+1 );
406 407 408 409
    resize( olen-len+1 );
  }
  return *this;
}
410

411
QCString &QCString::replace( uint index, uint len, const char *s)
412 413 414 415 416
{
  remove( index, len );
  insert( index, s );
  return *this;
}
417 418 419

QCString &QCString::replace( const QRegExp &rx, const char *str )
{
420
  QString d = QString::fromLatin1( data() );
421 422 423 424
  QString r = QString::fromLatin1( str );
  d.replace( rx, r );
  operator=( d.ascii() );
  return *this;
425 426
}

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
short QCString::toShort(bool *ok) const
{
  QString s(data());
  return s.toShort(ok);
}

ushort QCString::toUShort(bool *ok) const
{
  QString s(data());
  return s.toUShort(ok);
}

int QCString::toInt(bool *ok) const
{
  QString s(data());
  return s.toInt(ok);
}

uint QCString::toUInt(bool *ok) const
{
  QString s(data());
  return s.toUInt(ok);
}

long QCString::toLong(bool *ok) const
452
{
453
  QString s(data());
454
  return s.toLong(ok);
455 456
}

457
ulong QCString::toULong(bool *ok) const
458
{
459
  QString s(data());
460
  return s.toULong(ok);
461 462
}

463
QCString &QCString::setNum(short n)
464
{
465
  return setNum((long)n);
466 467
}

468
QCString &QCString::setNum(ushort n)
469
{
470
  return setNum((ulong)n);
471 472
}

473
QCString &QCString::setNum(int n)
474
{
475
  return setNum((long)n);
476 477
}

478
QCString &QCString::setNum(uint n)
479
{
480
  return setNum((ulong)n);
481 482
}

483
QCString &QCString::setNum(long n)
484
{
485 486 487
  char buf[20];
  register char *p = &buf[19];
  bool neg;
488
  if ( n < 0 )
489 490 491
  {
    neg = TRUE;
    n = -n;
492 493
  }
  else
494 495 496 497
  {
    neg = FALSE;
  }
  *p = '\0';
498
  do
499 500 501 502 503 504 505
  {
    *--p = ((int)(n%10)) + '0';
    n /= 10;
  } while ( n );
  if ( neg ) *--p = '-';
  operator=( p );
  return *this;
506 507
}

508
QCString &QCString::setNum( ulong n)
509
{
510 511 512
  char buf[20];
  register char *p = &buf[19];
  *p = '\0';
513
  do
514 515 516 517 518 519
  {
    *--p = ((int)(n%10)) + '0';
    n /= 10;
  } while ( n );
  operator=( p );
  return *this;
520 521
}

522
//-------------------------------------------------
523

524
void *qmemmove( void *dst, const void *src, uint len )
525
{
526 527 528 529 530 531 532 533 534 535 536 537
    register char *d;
    register char *s;
    if ( dst > src ) {
	d = (char *)dst + len - 1;
	s = (char *)src + len - 1;
	while ( len-- )
	    *d-- = *s--;
    } else if ( dst < src ) {
	d = (char *)dst;
	s = (char *)src;
	while ( len-- )
	    *d++ = *s++;
538
    }
539
    return dst;
540 541
}

542
char *qstrdup( const char *str )
543
{
544 545
    if ( !str )
	return 0;
546
    char *dst = new char[qstrlen(str)+1];
547 548
    CHECK_PTR( dst );
    return strcpy( dst, str );
549 550
}

551
char *qstrncpy( char *dst, const char *src, uint len )
552
{
553 554 555 556 557 558
    if ( !src )
	return 0;
    strncpy( dst, src, len );
    if ( len > 0 )
	dst[len-1] = '\0';
    return dst;
559 560
}

561 562 563 564 565 566 567 568 569 570 571 572 573
int qstricmp( const char *str1, const char *str2 )
{
    register const uchar *s1 = (const uchar *)str1;
    register const uchar *s2 = (const uchar *)str2;
    int res;
    uchar c;
    if ( !s1 || !s2 )
	return s1 == s2 ? 0 : (int)((long)s2 - (long)s1);
    for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ )
	if ( !c )				// strings are equal
	    break;
    return res;
}
574

575
int qstrnicmp( const char *str1, const char *str2, uint len )
576
{
577 578 579 580 581 582 583 584 585 586 587
    register const uchar *s1 = (const uchar *)str1;
    register const uchar *s2 = (const uchar *)str2;
    int res;
    uchar c;
    if ( !s1 || !s2 )
	return (int)((long)s2 - (long)s1);
    for ( ; len--; s1++, s2++ ) {
	if ( (res = (c=tolower(*s1)) - tolower(*s2)) )
	    return res;
	if ( !c )				// strings are equal
	    break;
588
    }
589
    return 0;
590 591
}

592
#ifndef QT_NO_DATASTREAM
593

594
QDataStream &operator<<( QDataStream &s, const QByteArray &a )
595
{
596
    return s.writeBytes( a.data(), a.size() );
597 598
}

599
QDataStream &operator>>( QDataStream &s, QByteArray &a )
600
{
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
    Q_UINT32 len;
    s >> len;					// read size of array
    if ( len == 0 || s.eof() ) {		// end of file reached
	a.resize( 0 );
	return s;
    }
    if ( !a.resize( (uint)len ) ) {		// resize array
#if defined(CHECK_NULL)
	qWarning( "QDataStream: Not enough memory to read QByteArray" );
#endif
	len = 0;
    }
    if ( len > 0 )				// not null array
	s.readRawBytes( a.data(), (uint)len );
    return s;
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
}

QDataStream &operator<<( QDataStream &s, const QCString &str )
{
    return s.writeBytes( str.data(), str.size() );
}

QDataStream &operator>>( QDataStream &s, QCString &str )
{
    Q_UINT32 len;
    s >> len;					// read size of string
    if ( len == 0 || s.eof() ) {		// end of file reached
	str.resize( 0 );
	return s;
    }
631
    if ( !str.resize( (uint)len )) {// resize string
632 633 634 635 636 637 638 639 640 641
#if defined(CHECK_NULL)
	qWarning( "QDataStream: Not enough memory to read QCString" );
#endif
	len = 0;
    }
    if ( len > 0 )				// not null array
	s.readRawBytes( str.data(), (uint)len );
    return s;
}

642
#endif //QT_NO_DATASTREAM
643

644 645 646 647 648 649
inline QCString operator+( const QCString &s1, const QGString &s2 )
{
    QCString tmp(s1);
    tmp += s2.data();
    return tmp;
}
650

651 652 653 654 655 656
inline QCString operator+( const QGString &s1, const QCString &s2 )
{
    QCString tmp(s1.data());
    tmp += s2;
    return tmp;
}
657