2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <unicode/uchar.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include "misc/main_thread_malloc.h"
32 #include "KWQCString.h"
34 // Make htmltokenizer.cpp happy
35 #define QT_VERSION 300
49 DirL = 0, DirR, DirEN, DirES, DirET, DirAN, DirCS, DirB, DirS, DirWS, DirON,
50 DirLRE, DirLRO, DirAL, DirRLE, DirRLO, DirPDF, DirNSM, DirBN
53 static const char null = 0; // not a QChar as in Qt (can't have static constructor), but close enough to be compatible in most cases
63 ushort unicode() const;
70 bool isLetter() const;
71 bool isNumber() const;
72 bool isLetterOrNumber() const;
74 int digitValue() const;
77 Direction direction() const;
79 bool mirrored() const;
80 QChar mirroredChar() const;
82 operator char() const;
84 friend bool operator==(QChar, QChar);
85 friend bool operator==(QChar, char);
86 friend bool operator==(char, QChar);
88 friend bool operator!=(QChar, QChar);
89 friend bool operator!=(QChar, char);
90 friend bool operator!=(char, QChar);
92 friend bool operator>(QChar, QChar);
93 friend bool operator>(QChar, char);
94 friend bool operator>(char, QChar);
96 friend bool operator>=(QChar, QChar);
97 friend bool operator>=(QChar, char);
98 friend bool operator>=(char, QChar);
100 friend bool operator<(QChar, QChar);
101 friend bool operator<(QChar, char);
102 friend bool operator<(char, QChar);
104 friend bool operator<=(QChar, QChar);
105 friend bool operator<=(QChar, char);
106 friend bool operator<=(char, QChar);
111 friend class QString;
112 friend class QConstString;
115 inline QChar::QChar() : c(0)
119 inline QChar::QChar(char ch) : c((uchar) ch)
123 inline QChar::QChar(uchar uch) : c(uch)
127 inline QChar::QChar(short n) : c(n)
131 inline QChar::QChar(ushort n) : c(n)
135 inline QChar::QChar(uint n) : c(n)
139 inline QChar::QChar(int n) : c(n)
143 inline ushort QChar::unicode() const
148 inline uchar QChar::cell() const
153 inline bool QChar::isNull() const
158 inline bool QChar::isSpace() const
160 // Use isspace() for basic Latin-1.
161 // This will include newlines, which aren't included in unicode DirWS.
162 return c <= 0x7F ? isspace(c) : direction() == DirWS;
165 inline bool QChar::isDigit() const
167 // FIXME: If fast enough, we should just call u_isdigit directly.
168 return c <= 0x7F ? isdigit(c) : u_isdigit(c);
171 inline bool QChar::isLetter() const
173 // FIXME: If fast enough, we should just call u_isalpha directly.
174 return c <= 0x7F ? isalpha(c) : u_isalpha(c);
177 inline bool QChar::isNumber() const
179 // FIXME: If fast enough, we should just call u_isdigit directly.
180 return c <= 0x7F ? isdigit(c) : u_isdigit(c);
183 inline bool QChar::isLetterOrNumber() const
185 // FIXME: If fast enough, we should just call u_isalnum directly.
186 return c <= 0x7F ? isalnum(c) : u_isalnum(c);
189 inline bool QChar::isPunct() const
194 inline int QChar::digitValue() const
196 // FIXME: If fast enough, we should just call u_charDigitValue directly.
197 return c <= '9' ? c - '0' : u_charDigitValue(c);
200 inline QChar QChar::lower() const
202 // FIXME: If fast enough, we should just call u_tolower directly.
203 return c <= 0x7F ? tolower(c) : u_tolower(c);
206 inline QChar QChar::upper() const
208 // FIXME: If fast enough, we should just call u_toupper directly.
209 return c <= 0x7F ? toupper(c) : u_toupper(c);
212 inline QChar::Direction QChar::direction() const
214 #if BUILDING_ON_PANTHER
215 // Panther gets the direction of the hyphen wrong.
216 // It returns "ET" (European Terminator) when it should return "ES" (European Separator).
220 return static_cast<Direction>(u_charDirection(c));
223 inline bool QChar::mirrored() const
225 return u_isMirrored(c);
228 inline QChar QChar::mirroredChar() const
230 return QChar(static_cast<uint>(u_charMirror(c)));
233 inline uchar QChar::row() const
238 inline char QChar::latin1() const
240 return c > 0xff ? 0 : c;
243 inline QChar::operator char() const
245 return c > 0xff ? 0 : c;
248 inline bool operator==(QChar qc1, QChar qc2)
250 return qc1.c == qc2.c;
253 inline bool operator==(QChar qc, char ch)
255 return qc.c == (uchar) ch;
258 inline bool operator==(char ch, QChar qc)
260 return (uchar) ch == qc.c;
263 inline bool operator!=(QChar qc1, QChar qc2)
265 return qc1.c != qc2.c;
268 inline bool operator!=(QChar qc, char ch)
270 return qc.c != (uchar) ch;
273 inline bool operator!=(char ch, QChar qc)
275 return (uchar) ch != qc.c;
278 inline bool operator>=(QChar qc1, QChar qc2)
280 return qc1.c >= qc2.c;
283 inline bool operator>=(QChar qc, char ch)
285 return qc.c >= (uchar) ch;
288 inline bool operator>=(char ch, QChar qc)
290 return (uchar) ch >= qc.c;
293 inline bool operator>(QChar qc1, QChar qc2)
295 return qc1.c > qc2.c;
298 inline bool operator>(QChar qc, char ch)
300 return qc.c > (uchar) ch;
303 inline bool operator>(char ch, QChar qc)
305 return (uchar) ch > qc.c;
308 inline bool operator<=(QChar qc1, QChar qc2)
310 return qc1.c <= qc2.c;
313 inline bool operator<=(QChar qc, char ch)
315 return qc.c <= (uchar) ch;
318 inline bool operator<=(char ch, QChar qc)
320 return (uchar) ch <= qc.c;
323 inline bool operator<(QChar qc1, QChar qc2)
325 return qc1.c < qc2.c;
328 inline bool operator<(QChar qc, char ch)
330 return qc.c < (uchar) ch;
333 inline bool operator<(char ch, QChar qc)
335 return (uchar) ch < qc.c;
338 // Keep this struct to <= 46 bytes, that's what the system will allocate.
339 // Will be rounded up to a multiple of 4, so we're stuck at 44.
341 #define QS_INTERNAL_BUFFER_SIZE 20
342 #define QS_INTERNAL_BUFFER_CHARS QS_INTERNAL_BUFFER_SIZE-1
343 #define QS_INTERNAL_BUFFER_UCHARS QS_INTERNAL_BUFFER_SIZE/2
345 struct KWQStringData {
346 // Uses shared null data.
351 KWQStringData(QChar *u, uint l, uint m);
352 void initialize(QChar *u, uint l, uint m);
355 KWQStringData(const QChar *u, uint l);
356 void initialize(const QChar *u, uint l);
359 KWQStringData(const char *u, uint l);
360 void initialize(const char *u, uint l);
362 // Move from destination to source.
363 KWQStringData(KWQStringData &);
367 #ifdef QSTRING_DEBUG_ALLOCATIONS
368 void* operator new(size_t s);
369 void operator delete(void*p);
371 MAIN_THREAD_ALLOCATED;
374 inline void ref() { refCount++; }
375 inline void deref() { if (--refCount == 0 && _isHeapAllocated) delete this; }
379 void increaseAsciiSize(uint size);
382 QChar *makeUnicode();
383 void increaseUnicodeSize(uint size);
385 bool isUnicodeInternal() const { return (char *)_unicode == _internalBuffer; }
386 bool isAsciiInternal() const { return _ascii == _internalBuffer; }
390 mutable QChar *_unicode;
391 mutable char *_ascii;
393 uint _isUnicodeValid:1;
394 uint _isHeapAllocated:1; // Fragile, but the only way we can be sure the instance was created with 'new'.
396 uint _isAsciiValid:1;
398 char _internalBuffer[QS_INTERNAL_BUFFER_SIZE]; // Pad out to a (((size + 1) & ~15) + 14) size
401 KWQStringData(const KWQStringData &);
402 KWQStringData &operator=(const KWQStringData &);
405 #define QSTRING_NULL QString()
409 static const char * const null; // not a QString as in Qt (can't have static constructor), but close enough to be compatible in most cases
413 QString(const QByteArray &);
414 QString(const QChar *, uint);
415 QString(const char *);
416 QString(const char *, int len);
418 QString(const QString &);
419 QString &operator=(const QString &);
423 static QString fromLatin1(const char *);
424 static QString fromLatin1(const char *, int len);
425 static QString fromUtf8(const char *);
426 static QString fromUtf8(const char *, int len);
427 static QString fromCFString(CFStringRef);
428 static QString fromNSString(NSString *);
430 QString &operator=(char);
431 QString &operator=(QChar);
432 QString &operator=(const char *);
433 QString &operator=(const QCString &);
437 const QChar *unicode() const;
438 const QChar *stableUnicode();
439 const char *latin1() const;
440 const char *ascii() const;
441 bool isAllASCII() const;
442 bool isAllLatin1() const;
443 bool hasFastLatin1() const;
444 void copyLatin1(char *buffer, uint position = 0, uint length = 0xffffffff) const;
445 QCString utf8() const { int length; return utf8(length); }
446 QCString utf8(int &length) const;
447 QCString local8Bit() const;
450 bool isEmpty() const;
452 QChar at(uint) const;
454 int compare(const QString &) const;
455 int compare(const char *) const;
457 bool startsWith(const QString &) const;
458 bool startsWith(const char *) const;
459 bool startsWith(const char *, bool caseSensitive) const;
461 int find(char, int index = 0) const;
462 int find(QChar, int index = 0) const;
463 int find(const char *, int index = 0, bool cs = true) const;
464 int find(const QString &, int index = 0, bool cs = true) const;
465 int find(const QRegExp &, int index = 0) const;
467 int findRev(char, int index = -1) const;
468 int findRev(const QString& str, int index, bool cs = true) const;
469 int findRev(const char *, int index = -1) const;
471 int contains(char) const;
472 int contains(const char *, bool cs = true) const;
473 int contains(const QString &, bool cs = true) const;
474 int contains(QChar c, bool cs = true) const;
476 bool endsWith(const QString &) const;
478 // NOTE: toXXXXX integer functions only support base 10 and base 16
479 // NOTE: toShort, toUShort, toULong, and toDouble are NOT used but are kept
481 short toShort(bool *ok=NULL, int base=10) const;
482 // NOTE: ok and base NOT used for toUShort
483 ushort toUShort(bool *ok=NULL, int base=10) const;
484 int toInt(bool *ok=NULL, int base=10) const;
485 // NOTE: base NOT used for toUInt
486 uint toUInt(bool *ok=NULL, int base=10) const;
487 long toLong(bool *ok=NULL, int base=10) const;
488 ulong toULong(bool *ok=NULL, int base=10) const;
489 float toFloat(bool *ok=NULL) const;
490 double toDouble(bool *ok=NULL) const;
492 static QString number(int);
493 static QString number(uint);
494 static QString number(long);
495 static QString number(ulong);
496 static QString number(double);
498 bool findArg(int& pos, int& len) const;
500 QString arg(const QString &, int width=0) const;
501 QString arg(short, int width=0) const;
502 QString arg(ushort, int width=0) const;
503 QString arg(int, int width=0) const;
504 QString arg(uint, int width=0) const;
505 QString arg(long, int width=0) const;
506 QString arg(ulong, int width=0) const;
507 QString arg(double, int width=0) const;
509 QString left(uint) const;
510 QString right(uint) const;
511 QString mid(uint, uint len=0xffffffff) const;
513 QString copy() const;
515 QString lower() const;
516 QString stripWhiteSpace() const;
517 QString simplifyWhiteSpace() const;
519 QString &setUnicode(const QChar *, uint);
520 QString &setLatin1(const char *, int len=-1);
522 QString &setNum(short);
523 QString &setNum(ushort);
524 QString &setNum(int);
525 QString &setNum(uint);
526 QString &setNum(long);
527 QString &setNum(ulong);
528 QString &setNum(double);
530 QString &sprintf(const char *, ...) __attribute__ ((format (printf, 2, 3)));
532 QString &append(const QString &);
533 QString &append(QChar);
534 QString &append(char);
535 QString &insert(uint, const QString &);
536 QString &insert(uint, QChar);
537 QString &insert(uint, char);
538 QString &insert(uint index, const char *insertChars, uint insertLength);
539 QString &prepend(const QString &);
540 QString &remove(uint, uint);
541 QString &replace(uint index, uint len, const QString &s);
542 QString &replace(char, const QString &);
543 QString &replace(QChar, const QString &);
544 QString &replace(const QString &, const QString &);
545 QString &replace(const QRegExp &, const QString &);
546 QString &replace(QChar, QChar);
548 QString &append(const QChar *, uint length);
549 QString &append(const char *, uint length);
550 QString &insert(uint position, const QChar *, uint length);
551 QString &prepend(const QChar *, uint length);
553 void fill(QChar, int len=-1);
560 bool operator!() const;
562 const QChar operator[](int) const;
564 QString &operator+=(const QString &s) { return append(s); }
565 QString &operator+=(QChar c) { return append(c); }
566 QString &operator+=(char c) { return append(c); }
568 CFStringRef getCFString() const;
569 NSString *getNSString() const;
571 void setBufferFromCFString(CFStringRef);
574 // Used by QConstString.
575 QString(KWQStringData *constData, bool /*dummy*/);
577 void detachAndDiscardCharacters();
578 void detachIfInternal();
579 void detachInternal();
581 QChar *forceUnicode();
582 void setLength(uint);
584 KWQStringData **dataHandle;
585 KWQStringData internalData;
587 static KWQStringData *shared_null;
588 static KWQStringData *makeSharedNull();
589 static KWQStringData **shared_null_handle;
590 static KWQStringData **makeSharedNullHandle();
592 friend bool operator==(const QString &, const QString &);
593 friend bool operator==(const QString &, const char *);
595 friend class QConstString;
597 friend struct KWQStringData;
600 QString operator+(const QString &, const QString &);
601 QString operator+(const QString &, const char *);
602 QString operator+(const QString &, QChar);
603 QString operator+(const QString &, char);
604 QString operator+(const char *, const QString &);
605 QString operator+(QChar, const QString &);
606 QString operator+(char, const QString &);
608 inline char *KWQStringData::ascii()
610 return _isAsciiValid ? _ascii : makeAscii();
613 inline QChar *KWQStringData::unicode()
615 return _isUnicodeValid ? _unicode : makeUnicode();
618 inline uint QString::length() const
620 return dataHandle[0]->_length;
623 inline bool QString::isEmpty() const
625 return dataHandle[0]->_length == 0;
628 inline const char *QString::latin1() const
630 return dataHandle[0]->ascii();
633 inline const QChar *QString::unicode() const
635 return dataHandle[0]->unicode();
638 inline CFStringRef QString::getCFString() const
640 return (CFStringRef)getNSString();
643 inline QString QString::fromLatin1(const char *chs)
648 inline QString QString::fromLatin1(const char *chs, int length)
650 return QString(chs, length);
653 inline const char *QString::ascii() const
658 inline float QString::toFloat(bool *ok) const
663 inline bool QString::operator!() const
668 inline const QChar QString::operator[](int index) const
673 inline bool operator==(const char *chs, const QString &qs)
678 inline bool operator!=(const QString &qs1, const QString &qs2)
680 return !(qs1 == qs2);
683 inline bool operator!=(const QString &qs, const char *chs)
688 inline bool operator!=(const char *chs, const QString &qs)
693 inline bool operator<(const QString &qs1, const QString &qs2)
695 return qs1.compare(qs2) < 0;
698 inline bool operator<(const QString &qs, const char *chs)
700 return qs.compare(chs) < 0;
703 inline bool operator<(const char *chs, const QString &qs)
705 return qs.compare(chs) > 0;
708 inline bool operator<=(const QString &qs1, const QString &qs2)
710 return qs1.compare(qs2) <= 0;
713 inline bool operator<=(const QString &qs, const char *chs)
715 return qs.compare(chs) <= 0;
718 inline bool operator<=(const char *chs, const QString &qs)
720 return qs.compare(chs) >= 0;
723 inline bool operator>(const QString &qs1, const QString &qs2)
725 return qs1.compare(qs2) > 0;
728 inline bool operator>(const QString &qs, const char *chs)
730 return qs.compare(chs) > 0;
733 inline bool operator>(const char *chs, const QString &qs)
735 return qs.compare(chs) < 0;
738 inline bool operator>=(const QString &qs1, const QString &qs2)
740 return qs1.compare(qs2) >= 0;
743 inline bool operator>=(const QString &qs, const char *chs)
745 return qs.compare(chs) >= 0;
748 inline bool operator>=(const char *chs, const QString &qs)
750 return qs.compare(chs) <= 0;
753 class QConstString : private QString {
755 QConstString(const QChar *, uint);
757 const QString &string() const { return *this; }
760 extern const CFDictionaryKeyCallBacks CFDictionaryQStringKeyCallBacks;