diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
commit | d796c9dd933ab96ec83b9a634feedd5d32e1ba3f (patch) | |
tree | 6e3dcca4f77e20ec8966c666aac7c35bd4704053 /src/tools/qstring.cpp | |
download | tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.tar.gz tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.zip |
Test conversion to TQt3 from Qt3 8c6fc1f8e35fd264dd01c582ca5e7549b32ab731
Diffstat (limited to 'src/tools/qstring.cpp')
-rw-r--r-- | src/tools/qstring.cpp | 7179 |
1 files changed, 7179 insertions, 0 deletions
diff --git a/src/tools/qstring.cpp b/src/tools/qstring.cpp new file mode 100644 index 000000000..00e4b2390 --- /dev/null +++ b/src/tools/qstring.cpp @@ -0,0 +1,7179 @@ +/**************************************************************************** +** +** Implementation of the TQString class and related Unicode functions +** +** Created : 920722 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the TQt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free TQt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.TQPL +** included in the packaging of this file. Licensees holding valid TQt +** Commercial licenses may use this file in accordance with the TQt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +// Don't define it while compiling this module, or USERS of TQt will +// not be able to link. +#ifdef QT_NO_CAST_ASCII +#undef QT_NO_CAST_ASCII +#endif + +#include "qstring.h" +#include "qregexp.h" +#include "qdatastream.h" +#ifndef QT_NO_TEXTCODEC +#include "qtextcodec.h" +#endif +#include "qlocale.h" +#include "qlocale_p.h" + +#include "qunicodetables_p.h" +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef Q_OS_TEMP +#include <locale.h> +#endif +#if defined(Q_WS_WIN) +#include "qt_windows.h" +#endif +#if !defined( QT_NO_COMPONENT ) && !defined( QT_LITE_COMPONENT ) +#include "qcleanuphandler.h" +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX Q_INT64_C(9223372036854775807) +#endif +#ifndef LLONG_MIN +#define LLONG_MIN (-LLONG_MAX - Q_INT64_C(1)) +#endif +#ifndef ULLONG_MAX +#define ULLONG_MAX Q_UINT64_C(18446744073709551615) +#endif + +static int ucstrcmp( const TQString &as, const TQString &bs ) +{ + const TQChar *a = as.unicode(); + const TQChar *b = bs.unicode(); + if ( a == b ) + return 0; + if ( a == 0 ) + return 1; + if ( b == 0 ) + return -1; + int l=TQMIN(as.length(),bs.length()); + while ( l-- && *a == *b ) + a++,b++; + if ( l==-1 ) + return ( as.length()-bs.length() ); + return a->unicode() - b->unicode(); +} + +static int ucstrncmp( const TQChar *a, const TQChar *b, int l ) +{ + while ( l-- && *a == *b ) + a++,b++; + if ( l==-1 ) + return 0; + return a->unicode() - b->unicode(); +} + +static int ucstrnicmp( const TQChar *a, const TQChar *b, int l ) +{ + while ( l-- && ::lower( *a ) == ::lower( *b ) ) + a++,b++; + if ( l==-1 ) + return 0; + return ::lower( *a ).unicode() - ::lower( *b ).unicode(); +} + +static uint computeNewMax( uint len ) +{ + if (len >= 0x80000000) + return len; + + uint newMax = 4; + while ( newMax < len ) + newMax *= 2; + // try to save some memory + if ( newMax >= 1024 * 1024 && len <= newMax - (newMax >> 2) ) + newMax -= newMax >> 2; + return newMax; +} + +static bool qIsUpper(char c) +{ + return c >= 'A' && c <= 'Z'; +} + +static bool qIsDigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static char qToLower(char c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + else + return c; +} + +/*! + \class TQCharRef qstring.h + \reentrant + \brief The TQCharRef class is a helper class for TQString. + + \ingroup text + + When you get an object of type TQCharRef, if you can assign to it, + the assignment will apply to the character in the string from + which you got the reference. That is its whole purpose in life. + The TQCharRef becomes invalid once modifications are made to the + string: if you want to keep the character, copy it into a TQChar. + + Most of the TQChar member functions also exist in TQCharRef. + However, they are not explicitly documented here. + + \sa TQString::operator[]() TQString::at() TQChar +*/ + +/*! + \class TQChar qstring.h + \reentrant + \brief The TQChar class provides a lightweight Unicode character. + + \ingroup text + + Unicode characters are (so far) 16-bit entities without any markup + or structure. This class represents such an entity. It is + lightweight, so it can be used everywhere. Most compilers treat it + like a "short int". (In a few years it may be necessary to make + TQChar 32-bit when more than 65536 Unicode code points have been + defined and come into use.) + + TQChar provides a full complement of testing/classification + functions, converting to and from other formats, converting from + composed to decomposed Unicode, and trying to compare and + case-convert if you ask it to. + + The classification functions include functions like those in + ctype.h, but operating on the full range of Unicode characters. + They all return TRUE if the character is a certain type of + character; otherwise they return FALSE. These classification + functions are isNull() (returns TRUE if the character is U+0000), + isPrint() (TRUE if the character is any sort of printable + character, including whitespace), isPunct() (any sort of + punctation), isMark() (Unicode Mark), isLetter (a letter), + isNumber() (any sort of numeric character), isLetterOrNumber(), + and isDigit() (decimal digits). All of these are wrappers around + category() which return the Unicode-defined category of each + character. + + TQChar further provides direction(), which indicates the "natural" + writing direction of this character. The joining() function + indicates how the character joins with its neighbors (needed + mostly for Arabic) and finally mirrored(), which indicates whether + the character needs to be mirrored when it is printed in its + "unnatural" writing direction. + + Composed Unicode characters (like å) can be converted to + decomposed Unicode ("a" followed by "ring above") by using + decomposition(). + + In Unicode, comparison is not necessarily possible and case + conversion is very difficult at best. Unicode, covering the + "entire" world, also includes most of the world's case and sorting + problems. TQt tries, but not very hard: operator==() and friends + will do comparison based purely on the numeric Unicode value (code + point) of the characters, and upper() and lower() will do case + changes when the character has a well-defined upper/lower-case + equivalent. There is no provision for locale-dependent case + folding rules or comparison; these functions are meant to be fast + so they can be used unambiguously in data structures. (See + TQString::localeAwareCompare() though.) + + The conversion functions include unicode() (to a scalar), latin1() + (to scalar, but converts all non-Latin-1 characters to 0), row() + (gives the Unicode row), cell() (gives the Unicode cell), + digitValue() (gives the integer value of any of the numerous digit + characters), and a host of constructors. + + More information can be found in the document \link unicode.html + About Unicode. \endlink + + \sa TQString TQCharRef +*/ + +/*! + \enum TQChar::Category + + This enum maps the Unicode character categories. + + The following characters are normative in Unicode: + + \value Mark_NonSpacing Unicode class name Mn + + \value Mark_SpacingCombining Unicode class name Mc + + \value Mark_Enclosing Unicode class name Me + + \value Number_DecimalDigit Unicode class name Nd + + \value Number_Letter Unicode class name Nl + + \value Number_Other Unicode class name No + + \value Separator_Space Unicode class name Zs + + \value Separator_Line Unicode class name Zl + + \value Separator_Paragraph Unicode class name Zp + + \value Other_Control Unicode class name Cc + + \value Other_Format Unicode class name Cf + + \value Other_Surrogate Unicode class name Cs + + \value Other_PrivateUse Unicode class name Co + + \value Other_NotAssigned Unicode class name Cn + + + The following categories are informative in Unicode: + + \value Letter_Uppercase Unicode class name Lu + + \value Letter_Lowercase Unicode class name Ll + + \value Letter_Titlecase Unicode class name Lt + + \value Letter_Modifier Unicode class name Lm + + \value Letter_Other Unicode class name Lo + + \value Punctuation_Connector Unicode class name Pc + + \value Punctuation_Dash Unicode class name Pd + + \value Punctuation_Open Unicode class name Ps + + \value Punctuation_Close Unicode class name Pe + + \value Punctuation_InitialQuote Unicode class name Pi + + \value Punctuation_FinalQuote Unicode class name Pf + + \value Punctuation_Other Unicode class name Po + + \value Symbol_Math Unicode class name Sm + + \value Symbol_Currency Unicode class name Sc + + \value Symbol_Modifier Unicode class name Sk + + \value Symbol_Other Unicode class name So + + + There are two categories that are specific to TQt: + + \value NoCategory used when TQt is dazed and confused and cannot + make sense of anything. + + \value Punctuation_Dask old typo alias for Punctuation_Dash + +*/ + +/*! + \enum TQChar::Direction + + This enum type defines the Unicode direction attributes. See \link + http://www.unicode.org/ the Unicode Standard\endlink for a + description of the values. + + In order to conform to C/C++ naming conventions "Dir" is prepended + to the codes used in the Unicode Standard. +*/ + +/*! + \enum TQChar::Decomposition + + This enum type defines the Unicode decomposition attributes. See + \link http://www.unicode.org/ the Unicode Standard\endlink for a + description of the values. +*/ + +/*! + \enum TQChar::Joining + + This enum type defines the Unicode joining attributes. See \link + http://www.unicode.org/ the Unicode Standard\endlink for a + description of the values. +*/ + +/*! + \enum TQChar::CombiningClass + + This enum type defines names for some of the Unicode combining + classes. See \link http://www.unicode.org/ the Unicode + Standard\endlink for a description of the values. +*/ + +/*! + \fn void TQChar::setCell( uchar cell ) + \internal +*/ + +/*! + \fn void TQChar::setRow( uchar row ) + \internal +*/ + + +/*! + \fn TQChar::TQChar() + + Constructs a null TQChar (one that isNull()). +*/ + + +/*! + \fn TQChar::TQChar( char c ) + + Constructs a TQChar corresponding to ASCII/Latin-1 character \a c. +*/ + + +/*! + \fn TQChar::TQChar( uchar c ) + + Constructs a TQChar corresponding to ASCII/Latin-1 character \a c. +*/ + + +/*! + \fn TQChar::TQChar( uchar c, uchar r ) + + Constructs a TQChar for Unicode cell \a c in row \a r. +*/ + + +/*! + \fn TQChar::TQChar( const TQChar& c ) + + Constructs a copy of \a c. This is a deep copy, if such a + lightweight object can be said to have deep copies. +*/ + + +/*! + \fn TQChar::TQChar( ushort rc ) + + Constructs a TQChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn TQChar::TQChar( short rc ) + + Constructs a TQChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn TQChar::TQChar( uint rc ) + + Constructs a TQChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn TQChar::TQChar( int rc ) + + Constructs a TQChar for the character with Unicode code point \a rc. +*/ + + +/*! + \fn bool TQChar::networkOrdered () + + \obsolete + + Returns TRUE if this character is in network byte order (MSB + first); otherwise returns FALSE. This is platform dependent. +*/ + + +/*! + \fn bool TQChar::isNull() const + + Returns TRUE if the character is the Unicode character 0x0000 + (ASCII NUL); otherwise returns FALSE. +*/ + +/*! + \fn uchar TQChar::cell () const + + Returns the cell (least significant byte) of the Unicode + character. +*/ + +/*! + \fn uchar TQChar::row () const + + Returns the row (most significant byte) of the Unicode character. +*/ + +/*! + Returns TRUE if the character is a printable character; otherwise + returns FALSE. This is any character not of category Cc or Cn. + + Note that this gives no indication of whether the character is + available in a particular \link TQFont font\endlink. +*/ +bool TQChar::isPrint() const +{ + Category c = ::category( *this ); + return !(c == Other_Control || c == Other_NotAssigned); +} + +/*! + Returns TRUE if the character is a separator character + (Separator_* categories); otherwise returns FALSE. +*/ +bool TQChar::isSpace() const +{ + return ::isSpace( *this ); +} + +/*! + Returns TRUE if the character is a mark (Mark_* categories); + otherwise returns FALSE. +*/ +bool TQChar::isMark() const +{ + Category c = ::category( *this ); + return c >= Mark_NonSpacing && c <= Mark_Enclosing; +} + +/*! + Returns TRUE if the character is a punctuation mark (Punctuation_* + categories); otherwise returns FALSE. +*/ +bool TQChar::isPunct() const +{ + Category c = ::category( *this ); + return (c >= Punctuation_Connector && c <= Punctuation_Other); +} + +/*! + Returns TRUE if the character is a letter (Letter_* categories); + otherwise returns FALSE. +*/ +bool TQChar::isLetter() const +{ + Category c = ::category( *this ); + return (c >= Letter_Uppercase && c <= Letter_Other); +} + +/*! + Returns TRUE if the character is a number (of any sort - Number_* + categories); otherwise returns FALSE. + + \sa isDigit() +*/ +bool TQChar::isNumber() const +{ + Category c = ::category( *this ); + return c >= Number_DecimalDigit && c <= Number_Other; +} + +/*! + Returns TRUE if the character is a letter or number (Letter_* or + Number_* categories); otherwise returns FALSE. +*/ +bool TQChar::isLetterOrNumber() const +{ + Category c = ::category( *this ); + return (c >= Letter_Uppercase && c <= Letter_Other) + || (c >= Number_DecimalDigit && c <= Number_Other); +} + + +/*! + Returns TRUE if the character is a decimal digit + (Number_DecimalDigit); otherwise returns FALSE. +*/ +bool TQChar::isDigit() const +{ + return (::category( *this ) == Number_DecimalDigit); +} + + +/*! + Returns TRUE if the character is a symbol (Symbol_* categories); + otherwise returns FALSE. +*/ +bool TQChar::isSymbol() const +{ + Category c = ::category( *this ); + return c >= Symbol_Math && c <= Symbol_Other; +} + +/*! + Returns the numeric value of the digit, or -1 if the character is + not a digit. +*/ +int TQChar::digitValue() const +{ +#ifndef QT_NO_UNICODETABLES + register int pos = TQUnicodeTables::decimal_info[row()]; + if( !pos ) + return -1; + return TQUnicodeTables::decimal_info[(pos<<8) + cell()]; +#else + // ##### just latin1 + if ( ucs < '0' || ucs > '9' ) + return -1; + else + return ucs - '0'; +#endif +} + +/*! + Returns the character category. + + \sa Category +*/ +TQChar::Category TQChar::category() const +{ + return ::category( *this ); +} + +/*! + Returns the character's direction. + + \sa Direction +*/ +TQChar::Direction TQChar::direction() const +{ + return ::direction( *this ); +} + +/*! + \warning This function is not supported (it may change to use + Unicode character classes). + + Returns information about the joining properties of the character + (needed for example, for Arabic). +*/ +TQChar::Joining TQChar::joining() const +{ + return ::joining( *this ); +} + + +/*! + Returns TRUE if the character is a mirrored character (one that + should be reversed if the text direction is reversed); otherwise + returns FALSE. +*/ +bool TQChar::mirrored() const +{ + return ::mirrored( *this ); +} + +/*! + Returns the mirrored character if this character is a mirrored + character, otherwise returns the character itself. +*/ +TQChar TQChar::mirroredChar() const +{ + return ::mirroredChar( *this ); +} + +#ifndef QT_NO_UNICODETABLES +// ### REMOVE ME 4.0 +static TQString shared_decomp; +#endif +/*! + \nonreentrant + + Decomposes a character into its parts. Returns TQString::null if no + decomposition exists. +*/ +const TQString &TQChar::decomposition() const +{ +#ifndef QT_NO_UNICODETABLES + register int pos = TQUnicodeTables::decomposition_info[row()]; + if(!pos) return TQString::null; + + pos = TQUnicodeTables::decomposition_info[(pos<<8)+cell()]; + if(!pos) return TQString::null; + pos+=2; + + TQString s; + Q_UINT16 c; + while ( (c = TQUnicodeTables::decomposition_map[pos++]) != 0 ) + s += TQChar( c ); + // ### In 4.0, return s, and not shared_decomp. shared_decomp + // prevents this function from being reentrant. + shared_decomp = s; + return shared_decomp; +#else + return TQString::null; +#endif +} + +/*! + Returns the tag defining the composition of the character. Returns + TQChar::Single if no decomposition exists. +*/ +TQChar::Decomposition TQChar::decompositionTag() const +{ +#ifndef QT_NO_UNICODETABLES + register int pos = TQUnicodeTables::decomposition_info[row()]; + if(!pos) return TQChar::Single; + + pos = TQUnicodeTables::decomposition_info[(pos<<8)+cell()]; + if(!pos) return TQChar::Single; + + return (TQChar::Decomposition) TQUnicodeTables::decomposition_map[pos]; +#else + return Single; // ########### FIX eg. just latin1 +#endif +} + +/*! + Returns the combining class for the character as defined in the + Unicode standard. This is mainly useful as a positioning hint for + marks attached to a base character. + + The TQt text rendering engine uses this information to correctly + position non spacing marks around a base character. +*/ +unsigned char TQChar::combiningClass() const +{ + return ::combiningClass( *this ); +} + + +/*! + Returns the lowercase equivalent if the character is uppercase; + otherwise returns the character itself. +*/ +TQChar TQChar::lower() const +{ + return ::lower( *this ); +} + +/*! + Returns the uppercase equivalent if the character is lowercase; + otherwise returns the character itself. +*/ +TQChar TQChar::upper() const +{ + return ::upper( *this ); +} + +/*! + \fn TQChar::operator char() const + + Returns the Latin-1 character equivalent to the TQChar, or 0. This + is mainly useful for non-internationalized software. + + \sa unicode() +*/ + +/*! + \fn ushort TQChar::unicode() const + + Returns the numeric Unicode value equal to the TQChar. Normally, + you should use TQChar objects as they are equivalent, but for some + low-level tasks (e.g. indexing into an array of Unicode + information), this function is useful. +*/ + +/*! + \fn ushort & TQChar::unicode() + + \overload + + Returns a reference to the numeric Unicode value equal to the + TQChar. +*/ + +/***************************************************************************** + Documentation of TQChar related functions + *****************************************************************************/ + +/*! + \fn bool operator==( TQChar c1, TQChar c2 ) + + \relates TQChar + + Returns TRUE if \a c1 and \a c2 are the same Unicode character; + otherwise returns FALSE. +*/ + +/*! + \fn bool operator==( char ch, TQChar c ) + + \overload + \relates TQChar + + Returns TRUE if \a c is the ASCII/Latin-1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn bool operator==( TQChar c, char ch ) + + \overload + \relates TQChar + + Returns TRUE if \a c is the ASCII/Latin-1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn int operator!=( TQChar c1, TQChar c2 ) + + \relates TQChar + + Returns TRUE if \a c1 and \a c2 are not the same Unicode + character; otherwise returns FALSE. +*/ + +/*! + \fn int operator!=( char ch, TQChar c ) + + \overload + \relates TQChar + + Returns TRUE if \a c is not the ASCII/Latin-1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn int operator!=( TQChar c, char ch ) + + \overload + \relates TQChar + + Returns TRUE if \a c is not the ASCII/Latin-1 character \a ch; + otherwise returns FALSE. +*/ + +/*! + \fn int operator<=( TQChar c1, TQChar c2 ) + + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c1 is less than + that of \a c2, or they are the same Unicode character; otherwise + returns FALSE. +*/ + +/*! + \fn int operator<=( TQChar c, char ch ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c is less than or + equal to that of the ASCII/Latin-1 character \a ch; otherwise + returns FALSE. +*/ + +/*! + \fn int operator<=( char ch, TQChar c ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin-1 + character \a ch is less than or equal to that of \a c; otherwise + returns FALSE. +*/ + +/*! + \fn int operator>=( TQChar c1, TQChar c2 ) + + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c1 is greater than + that of \a c2, or they are the same Unicode character; otherwise + returns FALSE. +*/ + +/*! + \fn int operator>=( TQChar c, char ch ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c is greater than + or equal to that of the ASCII/Latin-1 character \a ch; otherwise + returns FALSE. +*/ + +/*! + \fn int operator>=( char ch, TQChar c ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin-1 + character \a ch is greater than or equal to that of \a c; + otherwise returns FALSE. +*/ + +/*! + \fn int operator<( TQChar c1, TQChar c2 ) + + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c1 is less than + that of \a c2; otherwise returns FALSE. +*/ + +/*! + \fn int operator<( TQChar c, char ch ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c is less than that + of the ASCII/Latin-1 character \a ch; otherwise returns FALSE. +*/ + +/*! + \fn int operator<( char ch, TQChar c ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin-1 + character \a ch is less than that of \a c; otherwise returns + FALSE. +*/ + +/*! + \fn int operator>( TQChar c1, TQChar c2 ) + + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c1 is greater than + that of \a c2; otherwise returns FALSE. +*/ + +/*! + \fn int operator>( TQChar c, char ch ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of \a c is greater than + that of the ASCII/Latin-1 character \a ch; otherwise returns FALSE. +*/ + +/*! + \fn int operator>( char ch, TQChar c ) + + \overload + \relates TQChar + + Returns TRUE if the numeric Unicode value of the ASCII/Latin-1 + character \a ch is greater than that of \a c; otherwise returns + FALSE. +*/ + +#ifndef QT_NO_UNICODETABLES + +// small class used internally in TQString::Compose() +class TQLigature +{ +public: + TQLigature( TQChar c ); + + Q_UINT16 first() { cur = ligatures; return cur ? *cur : 0; } + Q_UINT16 next() { return cur && *cur ? *(cur++) : 0; } + Q_UINT16 current() { return cur ? *cur : 0; } + + int match(TQString & str, unsigned int index); + TQChar head(); + TQChar::Decomposition tag(); + +private: + Q_UINT16 *ligatures; + Q_UINT16 *cur; +}; + +TQLigature::TQLigature( TQChar c ) +{ + register int pos = TQUnicodeTables::ligature_info[c.row()]; + if( !pos ) + ligatures = 0; + else + { + pos = TQUnicodeTables::ligature_info[(pos<<8)+c.cell()]; + ligatures = (Q_UINT16 *)&(TQUnicodeTables::ligature_map[pos]); + } + cur = ligatures; +} + +TQChar TQLigature::head() +{ + if(current()) + return TQChar(TQUnicodeTables::decomposition_map[current()+1]); + + return TQChar::null; +} + +TQChar::Decomposition TQLigature::tag() +{ + if(current()) + return (TQChar::Decomposition) TQUnicodeTables::decomposition_map[current()]; + + return TQChar::Canonical; +} + +int TQLigature::match(TQString & str, unsigned int index) +{ + unsigned int i=index; + + if(!current()) return 0; + + Q_UINT16 lig = current() + 2; + Q_UINT16 ch; + + while ((i < str.length()) && (ch = TQUnicodeTables::decomposition_map[lig])) { + if (str[(int)i] != TQChar(ch)) + return 0; + i++; + lig++; + } + + if (!TQUnicodeTables::decomposition_map[lig]) + { + return i-index; + } + return 0; +} + + +// this function is just used in TQString::compose() +static inline bool format(TQChar::Decomposition tag, TQString & str, + int index, int len) +{ + unsigned int l = index + len; + unsigned int r = index; + + bool left = FALSE, right = FALSE; + + left = ((l < str.length()) && + ((str[(int)l].joining() == TQChar::Dual) || + (str[(int)l].joining() == TQChar::Right))); + if (r > 0) { + r--; + //printf("joining(right) = %d\n", str[(int)r].joining()); + right = (str[(int)r].joining() == TQChar::Dual); + } + + + switch (tag) { + case TQChar::Medial: + return (left & right); + case TQChar::Initial: + return (left && !right); + case TQChar::Final: + return (right);// && !left); + case TQChar::Isolated: + default: + return (!right && !left); + } +} // format() +#endif + +/* + TQString::compose() and visual() were developed by Gordon Tisher + <tisher@uniserve.ca>, with input from Lars Knoll <knoll@mpi-hd.mpg.de>, + who developed the unicode data tables. +*/ +/*! + \warning This function is not supported in TQt 3.x. It is provided + for experimental and illustrative purposes only. It is mainly of + interest to those experimenting with Arabic and other + composition-rich texts. + + Applies possible ligatures to a TQString. Useful when + composition-rich text retquires rendering with glyph-poor fonts, + but it also makes compositions such as TQChar(0x0041) ('A') and + TQChar(0x0308) (Unicode accent diaresis), giving TQChar(0x00c4) + (German A Umlaut). +*/ +void TQString::compose() +{ +#ifndef QT_NO_UNICODETABLES + unsigned int index=0, len; + unsigned int cindex = 0; + + TQChar code, head; + + TQMemArray<TQChar> dia; + + TQString composed = *this; + + while (index < length()) { + code = at(index); + //printf("\n\nligature for 0x%x:\n", code.unicode()); + TQLigature ligature(code); + ligature.first(); + while ( ligature.current() ) { + if ((len = ligature.match(*this, index)) != 0) { + head = ligature.head(); + unsigned short code = head.unicode(); + // we exclude Arabic presentation forms A and a few + // other ligatures, which are undefined in most fonts + if(!(code > 0xfb50 && code < 0xfe80) && + !(code > 0xfb00 && code < 0xfb2a)) { + // joining info is only needed for Arabic + if (format(ligature.tag(), *this, index, len)) { + //printf("using ligature 0x%x, len=%d\n",code,len); + // replace letter + composed.replace(cindex, len, TQChar(head)); + index += len-1; + // we continue searching in case we have a final + // form because medial ones are preferred. + if ( len != 1 || ligature.tag() !=TQChar::Final ) + break; + } + } + } + ligature.next(); + } + cindex++; + index++; + } + *this = composed; +#endif +} + + +// These macros are used for efficient allocation of TQChar strings. +// IMPORTANT! If you change these, make sure you also change the +// "delete unicode" statement in ~TQStringData() in qstring.h correspondingly! + +#define QT_ALLOC_QCHAR_VEC( N ) (TQChar*) new char[ sizeof(TQChar)*( N ) ] +#define QT_DELETE_QCHAR_VEC( P ) delete[] ((char*)( P )) + + +/*! + This utility function converts the 8-bit string \a ba to Unicode, + returning the result. + + The caller is responsible for deleting the return value with + delete[]. +*/ + +TQChar* TQString::latin1ToUnicode( const TQByteArray& ba, uint* len ) +{ + if ( ba.isNull() ) { + *len = 0; + return 0; + } + int l = 0; + while ( l < (int)ba.size() && ba[l] ) + l++; + char* str = ba.data(); + TQChar *uc = new TQChar[ l ]; // Can't use macro, since function is public + TQChar *result = uc; + if ( len ) + *len = l; + while (l--) + *uc++ = *str++; + return result; +} + +static TQChar* internalLatin1ToUnicode( const TQByteArray& ba, uint* len ) +{ + if ( ba.isNull() ) { + *len = 0; + return 0; + } + int l = 0; + while ( l < (int)ba.size() && ba[l] ) + l++; + char* str = ba.data(); + TQChar *uc = QT_ALLOC_QCHAR_VEC( l ); + TQChar *result = uc; + if ( len ) + *len = l; + while (l--) + *uc++ = *str++; + return result; +} + +/*! + \overload + + This utility function converts the '\0'-terminated 8-bit string \a + str to Unicode, returning the result and setting \a *len to the + length of the Unicode string. + + The caller is responsible for deleting the return value with + delete[]. +*/ + +TQChar* TQString::latin1ToUnicode( const char *str, uint* len, uint maxlen ) +{ + TQChar* result = 0; + uint l = 0; + if ( str ) { + if ( maxlen != (uint)-1 ) { + while ( l < maxlen && str[l] ) + l++; + } else { + // Faster? + l = int(strlen( str )); + } + TQChar *uc = new TQChar[ l ]; // Can't use macro since function is public + result = uc; + uint i = l; + while ( i-- ) + *uc++ = *str++; + } + if ( len ) + *len = l; + return result; +} + +static TQChar* internalLatin1ToUnicode( const char *str, uint* len, + uint maxlen = (uint)-1 ) +{ + TQChar* result = 0; + uint l = 0; + if ( str ) { + if ( maxlen != (uint)-1 ) { + while ( l < maxlen && str[l] ) + l++; + } else { + // Faster? + l = int(strlen( str )); + } + TQChar *uc = QT_ALLOC_QCHAR_VEC( l ); + result = uc; + uint i = l; + while ( i-- ) + *uc++ = *str++; + } + if ( len ) + *len = l; + return result; +} + +/*! + This utility function converts \a l 16-bit characters from \a uc + to ASCII, returning a '\0'-terminated string. + + The caller is responsible for deleting the resultant string with + delete[]. +*/ +char* TQString::unicodeToLatin1(const TQChar *uc, uint l) +{ + if (!uc) { + return 0; + } + char *a = new char[l+1]; + char *result = a; + while (l--) { + *a++ = (uc->unicode() > 0xff) ? '?' : (char)uc->unicode(); + uc++; + } + *a = '\0'; + return result; +} + +/***************************************************************************** + TQString member functions + *****************************************************************************/ + +/*! + \class TQString qstring.h + \reentrant + + \brief The TQString class provides an abstraction of Unicode text + and the classic C '\0'-terminated char array. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + + TQString uses \link shclass.html implicit sharing\endlink, which + makes it very efficient and easy to use. + + In all of the TQString methods that take \c {const char *} + parameters, the \c {const char *} is interpreted as a classic + C-style '\0'-terminated ASCII string. It is legal for the \c + {const char *} parameter to be 0. If the \c {const char *} is not + '\0'-terminated, the results are undefined. Functions that copy + classic C strings into a TQString will not copy the terminating + '\0' character. The TQChar array of the TQString (as returned by + unicode()) is generally not terminated by a '\0'. If you need to + pass a TQString to a function that retquires a C '\0'-terminated + string use latin1(). + + \keyword TQString::null + A TQString that has not been assigned to anything is \e null, i.e. + both the length and data pointer is 0. A TQString that references + the empty string ("", a single '\0' char) is \e empty. Both null + and empty TQStrings are legal parameters to the methods. Assigning + \c{(const char *) 0} to TQString gives a null TQString. For + convenience, \c TQString::null is a null TQString. When sorting, + empty strings come first, followed by non-empty strings, followed + by null strings. We recommend using \c{if ( !str.isNull() )} to + check for a non-null string rather than \c{if ( !str )}; see \l + operator!() for an explanation. + + Note that if you find that you are mixing usage of \l TQCString, + TQString, and \l TQByteArray, this causes lots of unnecessary + copying and might indicate that the true nature of the data you + are dealing with is uncertain. If the data is '\0'-terminated 8-bit + data, use \l TQCString; if it is unterminated (i.e. contains '\0's) + 8-bit data, use \l TQByteArray; if it is text, use TQString. + + Lists of strings are handled by the TQStringList class. You can + split a string into a list of strings using TQStringList::split(), + and join a list of strings into a single string with an optional + separator using TQStringList::join(). You can obtain a list of + strings from a string list that contain a particular substring or + that match a particular \link qregexp.html regex\endlink using + TQStringList::grep(). + + <b>Note for C programmers</b> + + Due to C++'s type system and the fact that TQString is implicitly + shared, TQStrings can be treated like ints or other simple base + types. For example: + + \code + TQString boolToString( bool b ) + { + TQString result; + if ( b ) + result = "True"; + else + result = "False"; + return result; + } + \endcode + + The variable, result, is an auto variable allocated on the stack. + When return is called, because we're returning by value, The copy + constructor is called and a copy of the string is returned. (No + actual copying takes place thanks to the implicit sharing, see + below.) + + Throughout TQt's source code you will encounter TQString usages like + this: + \code + TQString func( const TQString& input ) + { + TQString output = input; + // process output + return output; + } + \endcode + + The 'copying' of input to output is almost as fast as copying a + pointer because behind the scenes copying is achieved by + incrementing a reference count. TQString (like all TQt's implicitly + shared classes) operates on a copy-on-write basis, only copying if + an instance is actually changed. + + If you wish to create a deep copy of a TQString without losing any + Unicode information then you should use TQDeepCopy. + + \sa TQChar TQCString TQByteArray TQConstString +*/ + +/*! \enum TQt::ComparisonFlags +\internal +*/ +/*! + \enum TQt::StringComparisonMode + + This enum type is used to set the string comparison mode when + searching for an item. It is used by TQListBox, TQListView and + TQIconView, for example. We'll refer to the string being searched + as the 'target' string. + + \value CaseSensitive The strings must match case sensitively. + \value ExactMatch The target and search strings must match exactly. + \value BeginsWith The target string begins with the search string. + \value EndsWith The target string ends with the search string. + \value Contains The target string contains the search string. + + If you OR these flags together (excluding \c CaseSensitive), the + search criteria be applied in the following order: \c ExactMatch, + \c BeginsWith, \c EndsWith, \c Contains. + + Matching is case-insensitive unless \c CaseSensitive is set. \c + CaseSensitive can be OR-ed with any combination of the other + flags. + +*/ +Q_EXPORT TQStringData *TQString::shared_null = 0; +QT_STATIC_CONST_IMPL TQString TQString::null; +QT_STATIC_CONST_IMPL TQChar TQChar::null; +QT_STATIC_CONST_IMPL TQChar TQChar::replacement((ushort)0xfffd); +QT_STATIC_CONST_IMPL TQChar TQChar::byteOrderMark((ushort)0xfeff); +QT_STATIC_CONST_IMPL TQChar TQChar::byteOrderSwapped((ushort)0xfffe); +QT_STATIC_CONST_IMPL TQChar TQChar::nbsp((ushort)0x00a0); + +TQStringData* TQString::makeSharedNull() +{ + TQString::shared_null = new TQStringData; +#if defined( Q_OS_MAC ) || defined(Q_OS_SOLARIS) || defined(Q_OS_HPUX) || defined(Q_OS_AIX) + TQString *that = const_cast<TQString *>(&TQString::null); + that->d = TQString::shared_null; +#endif + return TQString::shared_null; +} + +/*! + \fn TQString::TQString() + + Constructs a null string, i.e. both the length and data pointer + are 0. + + \sa isNull() +*/ + +/*! + Constructs a string of length one, containing the character \a ch. +*/ +TQString::TQString( TQChar ch ) +{ + d = new TQStringData( QT_ALLOC_QCHAR_VEC( 1 ), 1, 1 ); + d->unicode[0] = ch; +} + +/*! + Constructs an implicitly shared copy of \a s. This is very fast + since it only involves incrementing a reference count. +*/ +TQString::TQString( const TQString &s ) : + d(s.d) +{ + d->ref(); +} + +/*! + \internal + + Private function. + + Constructs a string with preallocated space for \a size characters. + + The string is empty. + + \sa isNull() +*/ + +TQString::TQString( int size, bool /*dummy*/ ) +{ + if ( size ) { + int l = size; + TQChar* uc = QT_ALLOC_QCHAR_VEC( l ); + d = new TQStringData( uc, 0, l ); + } else { + d = shared_null ? shared_null : (shared_null=new TQStringData); + d->ref(); + } +} + +/*! + Constructs a string that is a deep copy of \a ba interpreted as a + classic C string. +*/ + +TQString::TQString( const TQByteArray& ba ) +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) { + d = 0; + *this = fromAscii( ba.data(), ba.size() ); + return; + } +#endif + uint l; + TQChar *uc = internalLatin1ToUnicode(ba,&l); + d = new TQStringData(uc,l,l); +} + +/*! + Constructs a string that is a deep copy of the first \a length + characters in the TQChar array. + + If \a unicode and \a length are 0, then a null string is created. + + If only \a unicode is 0, the string is empty but has \a length + characters of space preallocated: TQString expands automatically + anyway, but this may speed up some cases a little. We recommend + using the plain constructor and setLength() for this purpose since + it will result in more readable code. + + \sa isNull() setLength() +*/ + +TQString::TQString( const TQChar* unicode, uint length ) +{ + if ( !unicode && !length ) { + d = shared_null ? shared_null : makeSharedNull(); + d->ref(); + } else { + TQChar* uc = QT_ALLOC_QCHAR_VEC( length ); + if ( unicode ) + memcpy(uc, unicode, length*sizeof(TQChar)); + d = new TQStringData(uc,unicode ? length : 0,length); + } +} + +/*! + Constructs a string that is a deep copy of \a str, interpreted as + a classic C string. The encoding is assumed to be Latin-1, unless + you change it using TQTextCodec::setCodecForCStrings(). + + If \a str is 0, then a null string is created. + + This is a cast constructor, but it is perfectly safe: converting a + Latin-1 \c{const char *} to TQString preserves all the information. You + can disable this constructor by defining \c QT_NO_CAST_ASCII when + you compile your applications. You can also make TQString objects + by using setLatin1(), fromLatin1(), fromLocal8Bit(), and + fromUtf8(). Or whatever encoding is appropriate for the 8-bit data + you have. + + \sa isNull(), fromAscii() +*/ + +TQString::TQString( const char *str ) +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) { + d = 0; + *this = fromAscii( str ); + return; + } +#endif + uint l; + TQChar *uc = internalLatin1ToUnicode(str,&l); + d = new TQStringData(uc,l,l); +} + +#ifndef QT_NO_STL +/*! + Constructs a string that is a deep copy of \a str. + + This is the same as fromAscii(\a str). +*/ + +TQString::TQString( const std::string &str ) +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) { + d = 0; + *this = fromAscii( str.c_str() ); + return; + } +#endif + uint l; + TQChar *uc = internalLatin1ToUnicode(str.c_str(),&l); + d = new TQStringData(uc,l,l); +} +#endif + +/*! + \fn TQString::~TQString() + + Destroys the string and frees the string's data if this is the + last reference to the string. +*/ + + +/*! + Deallocates any space reserved solely by this TQString. + + If the string does not share its data with another TQString + instance, nothing happens; otherwise the function creates a new, + unique copy of this string. This function is called whenever the + string is modified. +*/ + +void TQString::real_detach() +{ + setLength( length() ); +} + +void TQString::deref() +{ + if ( d && d->deref() ) { + if ( d != shared_null ) + delete d; + d = 0; + } +} + +void TQStringData::deleteSelf() +{ + delete this; +} + +/*! + \fn TQString& TQString::operator=( TQChar c ) + + Sets the string to contain just the single character \a c. +*/ + +/*! + \fn TQString& TQString::operator=( const std::string& s ) + + \overload + + Makes a deep copy of \a s and returns a reference to the deep + copy. +*/ + +/*! + \fn TQString& TQString::operator=( char c ) + + \overload + + Sets the string to contain just the single character \a c. +*/ + +/*! + \overload + + Assigns a shallow copy of \a s to this string and returns a + reference to this string. This is very fast because the string + isn't actually copied. +*/ +TQString &TQString::operator=( const TQString &s ) +{ + s.d->ref(); + deref(); + d = s.d; + return *this; +} + +/*! + \overload + + Assigns a deep copy of \a cstr, interpreted as a classic C + string, to this string. Returns a reference to this string. +*/ +TQString &TQString::operator=( const TQCString& cstr ) +{ + return setAscii( cstr ); +} + + +/*! + \overload + + Assigns a deep copy of \a str, interpreted as a classic C string + to this string and returns a reference to this string. + + If \a str is 0, then a null string is created. + + \sa isNull() +*/ +TQString &TQString::operator=( const char *str ) +{ + return setAscii(str); +} + + +/*! + \fn bool TQString::isNull() const + + Returns TRUE if the string is null; otherwise returns FALSE. A + null string is always empty. + + \code + TQString a; // a.unicode() == 0, a.length() == 0 + a.isNull(); // TRUE, because a.unicode() == 0 + a.isEmpty(); // TRUE, because a.length() == 0 + \endcode + + \sa isEmpty(), length() +*/ + +/*! + \fn bool TQString::isEmpty() const + + Returns TRUE if the string is empty, i.e. if length() == 0; + otherwise returns FALSE. Null strings are also empty. + + \code + TQString a( "" ); + a.isEmpty(); // TRUE + a.isNull(); // FALSE + + TQString b; + b.isEmpty(); // TRUE + b.isNull(); // TRUE + \endcode + + \sa isNull(), length() +*/ + +/*! + \fn uint TQString::length() const + + Returns the length of the string. + + Null strings and empty strings have zero length. + + \sa isNull(), isEmpty() +*/ + +/*! + If \a newLen is less than the length of the string, then the + string is truncated at position \a newLen. Otherwise nothing + happens. + + \code + TQString s = "truncate me"; + s.truncate( 5 ); // s == "trunc" + \endcode + + \sa setLength() +*/ + +void TQString::truncate( uint newLen ) +{ + if ( newLen < d->len ) + setLength( newLen ); +} + +/*! + Ensures that at least \a newLen characters are allocated to the + string, and sets the length of the string to \a newLen. Any new + space allocated contains arbitrary data. + + \sa reserve(), truncate() +*/ +void TQString::setLength( uint newLen ) +{ + if ( d->count != 1 || newLen > d->maxl || + ( newLen * 4 < d->maxl && d->maxl > 4 ) ) { + // detach, grow or shrink + uint newMax = computeNewMax( newLen ); + TQChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + if ( nd ) { + uint len = TQMIN( d->len, newLen ); + memcpy( nd, d->unicode, sizeof(TQChar) * len ); + deref(); + d = new TQStringData( nd, newLen, newMax ); + } + } else { + d->len = newLen; + d->setDirty(); + } +} + +/*! + \fn uint TQString::capacity() const + + Returns the number of characters this string can hold + in the allocated memory. + + \sa reserve(), squeeze() +*/ + +/*! + Ensures that at least \a minCapacity characters are allocated to + the string. + + This function is useful for code that needs to build up a long + string and wants to avoid repeated reallocation. In this example, + we want to add to the string until some condition is true, and + we're fairly sure that size is big enough: + \code + TQString result; + int len = 0; + result.reserve(maxLen); + while (...) { + result[len++] = ... // fill part of the space + } + result.squeeze(); + \endcode + + If \e maxLen is an underestimate, the worst that will happen is + that the loop will slow down. + + If it is not possible to allocate enough memory, the string + remains unchanged. + + \sa capacity(), squeeze(), setLength() +*/ + +void TQString::reserve( uint minCapacity ) +{ + if ( d->maxl < minCapacity ) { + TQChar *nd = QT_ALLOC_QCHAR_VEC( minCapacity ); + if ( nd ) { + uint len = d->len; + if ( len ) + memcpy( nd, d->unicode, sizeof(TQChar) * len ); + deref(); + d = new TQStringData( nd, len, minCapacity ); + } + } +} + + +/*! + Squeezes the string's capacity to the current content. + + \sa capacity(), reserve() +*/ +void TQString::squeeze() +{ + if ( d->maxl > d->len ) { + TQChar *nd = QT_ALLOC_QCHAR_VEC( d->len ); + if ( nd ) { + uint len = d->len; + if ( len ) + memcpy( nd, d->unicode, sizeof(TQChar) * len ); + deref(); + d = new TQStringData( nd, len, len ); + } + } +} + +/*! + \internal + + Like setLength, but doesn't shrink the allocated memory. +*/ +void TQString::grow( uint newLen ) +{ + if ( d->count != 1 || newLen > d->maxl ) { + setLength( newLen ); + } else { + d->len = newLen; + d->setDirty(); + } +} + +struct ArgEscapeData +{ + uint min_escape; // lowest escape sequence number + uint occurrences; // number of occurences of the lowest escape + // sequence number + uint locale_occurrences; // number of occurences of the lowest escape + // sequence number which contain 'L' + uint escape_len; // total length of escape sequences which will + // be replaced +}; + +static ArgEscapeData findArgEscapes(const TQString &s) +{ + const TQChar *uc_begin = s.unicode(); + const TQChar *uc_end = uc_begin + s.length(); + + ArgEscapeData d; + + d.min_escape = 10; + d.occurrences = 0; + d.escape_len = 0; + d.locale_occurrences = 0; + + const TQChar *c = uc_begin; + while (c != uc_end) { + while (c != uc_end && c->unicode() != '%') + ++c; + + if (c == uc_end || ++c == uc_end) + break; + + bool locale_arg = FALSE; + if (c->unicode() == 'L') { + locale_arg = TRUE; + if (++c == uc_end) + break; + } + + if (c->unicode() < '0' || c->unicode() > '9') + continue; + + uint escape = c->unicode() - '0'; + ++c; + + if (escape > d.min_escape) + continue; + + if (escape < d.min_escape) { + d.min_escape = escape; + d.occurrences = 0; + d.escape_len = 0; + d.locale_occurrences = 0; + } + +#if QT_VERSION < 0x040000 + // ### remove preprocessor in TQt 4.0 + /* Since in TQt < 4.0 only the first instance is replaced, + escape_len should hold the length of only the first escape + sequence */ + if (d.occurrences == 0) +#endif + { + ++d.occurrences; + if (locale_arg) { + ++d.locale_occurrences; + d.escape_len += 3; + } + else + d.escape_len += 2; + } + } + + return d; +} + +static TQString replaceArgEscapes(const TQString &s, const ArgEscapeData &d, int field_width, + const TQString &arg, const TQString &larg) +{ + const TQChar *uc_begin = s.unicode(); + const TQChar *uc_end = uc_begin + s.length(); + + uint abs_field_width = TQABS(field_width); + uint result_len = s.length() + - d.escape_len + + (d.occurrences - d.locale_occurrences) + *TQMAX(abs_field_width, arg.length()) + + d.locale_occurrences + *TQMAX(abs_field_width, larg.length()); + + TQString result; + result.setLength(result_len); + TQChar *result_buff = (TQChar*) result.unicode(); + + TQChar *rc = result_buff; + const TQChar *c = uc_begin; + uint repl_cnt = 0; + while (c != uc_end) { + /* We don't have to check if we run off the end of the string with c, + because as long as d.occurrences > 0 we KNOW there are valid escape + sequences. */ + + const TQChar *text_start = c; + + while (c->unicode() != '%') + ++c; + + const TQChar *escape_start = c++; + + bool locale_arg = FALSE; + if (c->unicode() == 'L') { + locale_arg = TRUE; + ++c; + } + + if (c->unicode() != '0' + d.min_escape) { + memcpy(rc, text_start, (c - text_start)*sizeof(TQChar)); + rc += c - text_start; + } + else { + ++c; + + memcpy(rc, text_start, (escape_start - text_start)*sizeof(TQChar)); + rc += escape_start - text_start; + + uint pad_chars; + if (locale_arg) + pad_chars = TQMAX(abs_field_width, larg.length()) - larg.length(); + else + pad_chars = TQMAX(abs_field_width, arg.length()) - arg.length(); + + if (field_width > 0) { // left padded + for (uint i = 0; i < pad_chars; ++i) + (rc++)->unicode() = ' '; + } + + if (locale_arg) { + memcpy(rc, larg.unicode(), larg.length()*sizeof(TQChar)); + rc += larg.length(); + } + else { + memcpy(rc, arg.unicode(), arg.length()*sizeof(TQChar)); + rc += arg.length(); + } + + if (field_width < 0) { // right padded + for (uint i = 0; i < pad_chars; ++i) + (rc++)->unicode() = ' '; + } + + if (++repl_cnt == d.occurrences) { + memcpy(rc, c, (uc_end - c)*sizeof(TQChar)); + rc += uc_end - c; + Q_ASSERT(rc - result_buff == (int)result_len); + c = uc_end; + } + } + } + + return result; +} + +/*! + This function will return a string that replaces the lowest + numbered occurrence of \c %1, \c %2, ..., \c %9 with \a a. + + The \a fieldWidth value specifies the minimum amount of space that + \a a is padded to. A positive value will produce right-aligned + text, whereas a negative value will produce left-aligned text. + + The following example shows how we could create a 'status' string + when processing a list of files: + \code + TQString status = TQString( "Processing file %1 of %2: %3" ) + .arg( i ) // current file's number + .arg( total ) // number of files to process + .arg( fileName ); // current file's name + \endcode + + It is generally fine to use filenames and numbers as we have done + in the example above. But note that using arg() to construct + natural language sentences does not usually translate well into + other languages because sentence structure and word order often + differ between languages. + + If there is no place marker (\c %1, \c %2, etc.), a warning + message (qWarning()) is output and the result is undefined. + + \warning If any placeholder occurs more than once, the result is undefined. + +*/ +TQString TQString::arg( const TQString& a, int fieldWidth ) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning( "TQString::arg(): Argument missing: %s, %s", latin1(), + a.latin1() ); + return *this; + } + + return replaceArgEscapes(*this, d, fieldWidth, a, a); +} + +/*! + \fn TQString TQString::arg( const TQString& a1, const TQString& a2 ) const + + \overload + + This is the same as str.arg(\a a1).arg(\a a2), except that + the strings are replaced in one pass. This can make a difference + if \a a1 contains e.g. \c{%1}: + + \code + TQString str( "%1 %2" ); + str.arg( "Hello", "world" ); // returns "Hello world" + str.arg( "Hello" ).arg( "world" ); // returns "Hello world" + + str.arg( "(%1)", "Hello" ); // returns "(%1) Hello" + str.arg( "(%1)" ).arg( "Hello" ); // returns "(Hello) %2" + \endcode +*/ + +/*! + \fn TQString TQString::arg( const TQString& a1, const TQString& a2, + const TQString& a3 ) const + \overload + + This is the same as calling str.arg(\a a1).arg(\a a2).arg(\a a3), + except that the strings are replaced in one pass. +*/ + +/*! + \fn TQString TQString::arg( const TQString& a1, const TQString& a2, + const TQString& a3, const TQString& a4 ) const + \overload + + This is the same as calling + str.arg(\a a1).arg(\a a2).arg(\a a3).arg(\a a4), + except that the strings are replaced in one pass. +*/ + +/*! + \overload + + The \a fieldWidth value specifies the minimum amount of space that + \a a is padded to. A positive value will produce a right-aligned + number, whereas a negative value will produce a left-aligned + number. + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. + + The '%' can be followed by an 'L', in which case the sequence is + replaced with a localized representation of \a a. The conversion + uses the default locale. The default locale is determined from the + system's locale settings at application startup. It can be changed + using TQLocale::setDefault(). The 'L' flag is ignored if \a base is + not 10. + + \code + TQString str; + str = TQString( "Decimal 63 is %1 in hexadecimal" ) + .arg( 63, 0, 16 ); + // str == "Decimal 63 is 3f in hexadecimal" + + TQLocale::setDefault(TQLocale::English, TQLocale::UnitedStates); + str = TQString( "%1 %L2 %L3" ) + .arg( 12345 ) + .arg( 12345 ) + .arg( 12345, 0, 16 ); + // str == "12345 12,345 3039" + \endcode +*/ +TQString TQString::arg( long a, int fieldWidth, int base ) const +{ + return arg((Q_LLONG)a, fieldWidth, base); +} + +/*! + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ +TQString TQString::arg( ulong a, int fieldWidth, int base ) const +{ + return arg((Q_ULLONG)a, fieldWidth, base); +} + +/*! + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ +TQString TQString::arg( Q_LLONG a, int fieldWidth, int base ) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning( "TQString::arg(): Argument missing: %s, %lld", latin1(), + a ); + return *this; + } + + TQString arg; + if (d.occurrences > d.locale_occurrences) + arg = number(a, base); + + TQString locale_arg; + if (d.locale_occurrences > 0) { + TQLocale locale; + locale_arg = locale.d->longLongToString(a, -1, base, -1, TQLocalePrivate::ThousandsGroup); + } + + return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg); +} + +/*! + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ +TQString TQString::arg( Q_ULLONG a, int fieldWidth, int base ) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning( "TQString::arg(): Argument missing: %s, %llu", latin1(), + a ); + return *this; + } + + TQString arg; + if (d.occurrences > d.locale_occurrences) + arg = number(a, base); + + TQString locale_arg; + if (d.locale_occurrences > 0) { + TQLocale locale; + locale_arg = locale.d->unsLongLongToString(a, -1, base, -1, TQLocalePrivate::ThousandsGroup); + } + + return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg); +} + +/*! + \fn TQString TQString::arg( int a, int fieldWidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ + +/*! + \fn TQString TQString::arg( uint a, int fieldWidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ + +/*! + \fn TQString TQString::arg( short a, int fieldWidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ + +/*! + \fn TQString TQString::arg( ushort a, int fieldWidth, int base ) const + + \overload + + \a a is expressed in base \a base, which is 10 by default and must + be between 2 and 36. If \a base is 10, the '%L' syntax can be used + to produce localized strings. +*/ + + +/*! + \overload + + \a a is assumed to be in the Latin-1 character set. +*/ +TQString TQString::arg( char a, int fieldWidth ) const +{ + TQString c; + c += a; + return arg( c, fieldWidth ); +} + +/*! + \overload +*/ +TQString TQString::arg( TQChar a, int fieldWidth ) const +{ + TQString c; + c += a; + return arg( c, fieldWidth ); +} + +/*! + \overload + + \target arg-formats + + Argument \a a is formatted according to the \a fmt format specified, + which is 'g' by default and can be any of the following: + + \table + \header \i Format \i Meaning + \row \i \c e \i format as [-]9.9e[+|-]999 + \row \i \c E \i format as [-]9.9E[+|-]999 + \row \i \c f \i format as [-]9.9 + \row \i \c g \i use \c e or \c f format, whichever is the most concise + \row \i \c G \i use \c E or \c f format, whichever is the most concise + \endtable + + With 'e', 'E', and 'f', \a prec is the number of digits after the + decimal point. With 'g' and 'G', \a prec is the maximum number of + significant digits (trailing zeroes are omitted). + + \code + double d = 12.34; + TQString ds = TQString( "'E' format, precision 3, gives %1" ) + .arg( d, 0, 'E', 3 ); + // ds == "'E' format, precision 3, gives 1.234E+01" + \endcode + + The '%L' syntax can be used to produce localized strings. +*/ +TQString TQString::arg( double a, int fieldWidth, char fmt, int prec ) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning( "TQString::arg(): Argument missing: %s, %g", latin1(), + a ); + return *this; + } + + TQString arg; + if (d.occurrences > d.locale_occurrences) + arg = number(a, fmt, prec); + + TQString locale_arg; + if (d.locale_occurrences > 0) { + TQLocale locale; + + TQLocalePrivate::DoubleForm form = TQLocalePrivate::DFDecimal; + uint flags = 0; + + if (qIsUpper(fmt)) + flags = TQLocalePrivate::CapitalEorX; + fmt = qToLower(fmt); + + switch (fmt) { + case 'f': + form = TQLocalePrivate::DFDecimal; + break; + case 'e': + form = TQLocalePrivate::DFExponent; + break; + case 'g': + form = TQLocalePrivate::DFSignificantDigits; + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning( "TQString::setNum: Invalid format char '%c'", fmt ); +#endif + break; + } + + flags |= TQLocalePrivate::ThousandsGroup; + + locale_arg = locale.d->doubleToString(a, prec, form, -1, flags); + } + + return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg); +} + +TQString TQString::multiArg( int numArgs, const TQString& a1, const TQString& a2, + const TQString& a3, const TQString& a4 ) const +{ + TQString result; + union { + int digitUsed[10]; + int argForDigit[10]; + }; + register const TQChar *uc = d->unicode; + const TQString *args[4]; + const int len = (int) length(); + const int end = len - 1; + int lastDigit = -1; + int i; + + memset( digitUsed, 0, sizeof(digitUsed) ); + args[0] = &a1; + args[1] = &a2; + args[2] = &a3; + args[3] = &a4; + + for ( i = 0; i < end; i++ ) { + if ( uc[i] == '%' ) { + int digit = uc[i + 1].unicode() - '0'; + if ( digit >= 0 && digit <= 9 ) + digitUsed[digit]++; + } + } + + for ( i = 0; i < numArgs; i++ ) { + do { + ++lastDigit; + } while ( lastDigit < 10 && digitUsed[lastDigit] == 0 ); + + if ( lastDigit == 10 ) { + qWarning( "TQString::arg(): Argument missing: %s, %s", + latin1(), args[i]->latin1() ); + numArgs = i; + lastDigit = 9; + break; + } + argForDigit[lastDigit] = i; + } + + i = 0; + while ( i < len ) { + if ( uc[i] == '%' && i != end ) { + int digit = uc[i + 1].unicode() - '0'; + if ( digit >= 0 && digit <= lastDigit ) { + result += *args[argForDigit[digit]]; + i += 2; + continue; + } + } + result += uc[i++]; + } + return result; +} + + +/*! + Safely builds a formatted string from the format string \a cformat + and an arbitrary list of arguments. The format string supports all + the escape sequences of printf() in the standard C library. + + The %s escape sequence expects a utf8() encoded string. The format + string \e cformat is expected to be in latin1. If you need a + Unicode format string, use arg() instead. For typesafe string + building, with full Unicode support, you can use TQTextOStream like + this: + + \code + TQString str; + TQString s = ...; + int x = ...; + TQTextOStream( &str ) << s << " : " << x; + \endcode + + For \link TQObject::tr() translations,\endlink especially if the + strings contains more than one escape sequence, you should + consider using the arg() function instead. This allows the order + of the replacements to be controlled by the translator, and has + Unicode support. + + The %lc escape sequence expects a unicode character of type ushort + (as returned by TQChar::unicode()). + The %ls escape sequence expects a pointer to a zero-terminated + array of unicode characters of type ushort (as returned by + TQString::ucs2()). + + \sa arg() +*/ + +#ifndef QT_NO_SPRINTF +TQString &TQString::sprintf( const char* cformat, ... ) +{ + TQLocale locale(TQLocale::C); + + va_list ap; + va_start( ap, cformat ); + + if ( !cformat || !*cformat ) { + // TQt 1.x compat + *this = fromLatin1( "" ); + return *this; + } + + // Parse cformat + + TQString result; + const char *c = cformat; + for (;;) { + // Copy non-escape chars to result + while (*c != '\0' && *c != '%') + result.append(*c++); + + if (*c == '\0') + break; + + // Found '%' + const char *escape_start = c; + ++c; + + if (*c == '\0') { + result.append('%'); // a % at the end of the string - treat as non-escape text + break; + } + if (*c == '%') { + result.append('%'); // %% + ++c; + continue; + } + + // Parse flag characters + unsigned flags = 0; + bool no_more_flags = FALSE; + do { + switch (*c) { + case '#': flags |= TQLocalePrivate::Alternate; break; + case '0': flags |= TQLocalePrivate::ZeroPadded; break; + case '-': flags |= TQLocalePrivate::LeftAdjusted; break; + case ' ': flags |= TQLocalePrivate::BlankBeforePositive; break; + case '+': flags |= TQLocalePrivate::AlwaysShowSign; break; + case '\'': flags |= TQLocalePrivate::ThousandsGroup; break; + default: no_more_flags = TRUE; break; + } + + if (!no_more_flags) + ++c; + } while (!no_more_flags); + + if (*c == '\0') { + result.append(escape_start); // incomplete escape, treat as non-escape text + break; + } + + // Parse field width + int width = -1; // -1 means unspecified + if (qIsDigit(*c)) { + TQString width_str; + while (*c != '\0' && qIsDigit(*c)) + width_str.append(*c++); + + // can't be negative - started with a digit + // contains at least one digit + width = width_str.toInt(); + } + else if (*c == '*') { + width = va_arg(ap, int); + if (width < 0) + width = -1; // treat all negative numbers as unspecified + ++c; + } + + if (*c == '\0') { + result.append(escape_start); // incomplete escape, treat as non-escape text + break; + } + + // Parse precision + int precision = -1; // -1 means unspecified + if (*c == '.') { + ++c; + if (qIsDigit(*c)) { + TQString precision_str; + while (*c != '\0' && qIsDigit(*c)) + precision_str.append(*c++); + + // can't be negative - started with a digit + // contains at least one digit + precision = precision_str.toInt(); + } + else if (*c == '*') { + precision = va_arg(ap, int); + if (precision < 0) + precision = -1; // treat all negative numbers as unspecified + ++c; + } + } + + if (*c == '\0') { + result.append(escape_start); // incomplete escape, treat as non-escape text + break; + } + + // Parse the length modifier + enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t }; + LengthMod length_mod = lm_none; + switch (*c) { + case 'h': + ++c; + if (*c == 'h') { + length_mod = lm_hh; + ++c; + } + else + length_mod = lm_h; + break; + + case 'l': + ++c; + if (*c == 'l') { + length_mod = lm_ll; + ++c; + } + else + length_mod = lm_l; + break; + + case 'L': + ++c; + length_mod = lm_L; + break; + + case 'j': + ++c; + length_mod = lm_j; + break; + + case 'z': + case 'Z': + ++c; + length_mod = lm_z; + break; + + case 't': + ++c; + length_mod = lm_t; + break; + + default: break; + } + + if (*c == '\0') { + result.append(escape_start); // incomplete escape, treat as non-escape text + break; + } + + // Parse the conversion specifier and do the conversion + TQString subst; + switch (*c) { + case 'd': + case 'i': { + Q_LLONG i; + switch (length_mod) { + case lm_none: i = va_arg(ap, int); break; + case lm_hh: i = va_arg(ap, int); break; + case lm_h: i = va_arg(ap, int); break; + case lm_l: i = va_arg(ap, long int); break; + case lm_ll: i = va_arg(ap, Q_LLONG); break; + case lm_j: i = va_arg(ap, long int); break; + case lm_z: i = va_arg(ap, size_t); break; + case lm_t: i = va_arg(ap, int); break; + default: i = 0; break; + } + subst = locale.d->longLongToString(i, precision, 10, width, flags); + ++c; + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { + Q_ULLONG u; + switch (length_mod) { + case lm_none: u = va_arg(ap, unsigned int); break; + case lm_hh: u = va_arg(ap, unsigned int); break; + case lm_h: u = va_arg(ap, unsigned int); break; + case lm_l: u = va_arg(ap, unsigned long int); break; + case lm_ll: u = va_arg(ap, Q_ULLONG); break; + default: u = 0; break; + } + + if (qIsUpper(*c)) + flags |= TQLocalePrivate::CapitalEorX; + + int base = 10; + switch (qToLower(*c)) { + case 'o': + base = 8; break; + case 'u': + base = 10; break; + case 'x': + base = 16; break; + default: break; + } + subst = locale.d->unsLongLongToString(u, precision, base, width, flags); + ++c; + break; + } + case 'E': + case 'e': + case 'F': + case 'f': + case 'G': + case 'g': + case 'A': + case 'a': { + double d; + if (length_mod == lm_L) + d = va_arg(ap, long double); // not supported - converted to a double + else + d = va_arg(ap, double); + + if (qIsUpper(*c)) + flags |= TQLocalePrivate::CapitalEorX; + + TQLocalePrivate::DoubleForm form = TQLocalePrivate::DFDecimal; + switch (qToLower(*c)) { + case 'e': form = TQLocalePrivate::DFExponent; break; + case 'a': // not supported - decimal form used instead + case 'f': form = TQLocalePrivate::DFDecimal; break; + case 'g': form = TQLocalePrivate::DFSignificantDigits; break; + default: break; + } + subst = locale.d->doubleToString(d, precision, form, width, flags); + ++c; + break; + } + case 'c': { + if (length_mod == lm_l) + subst = TQChar((ushort) va_arg(ap, int)); + else + subst = (uchar) va_arg(ap, int); + ++c; + break; + } + case 's': { + if (length_mod == lm_l) { + const ushort *buff = va_arg(ap, const ushort*); + const ushort *ch = buff; + while (*ch != 0) + ++ch; + subst.setUnicodeCodes(buff, ch - buff); + } else + subst = TQString::fromUtf8(va_arg(ap, const char*)); + if (precision != -1) + subst.truncate(precision); + ++c; + break; + } + case 'p': { + Q_ULLONG i; +#ifdef Q_OS_WIN64 + i = (Q_ULLONG) va_arg(ap, void*); +#else + i = (Q_ULONG) va_arg(ap, void*); +#endif + +#ifdef Q_OS_WIN32 + flags |= TQLocalePrivate::CapitalEorX; // Windows does 1234ABCD +#else + flags |= TQLocalePrivate::Alternate; // Unix and Mac do 0x1234abcd +#endif + + subst = locale.d->unsLongLongToString(i, precision, 16, width, flags); + ++c; + break; + } + case 'n': + switch (length_mod) { + case lm_hh: { + signed char *n = va_arg(ap, signed char*); + *n = result.length(); + break; + } + case lm_h: { + short int *n = va_arg(ap, short int*); + *n = result.length(); + break; + } + case lm_l: { + long int *n = va_arg(ap, long int*); + *n = result.length(); + break; + } + case lm_ll: { + Q_LLONG *n = va_arg(ap, Q_LLONG*); + volatile uint tmp = result.length(); // egcs-2.91.66 gets internal + *n = tmp; // compiler error without volatile + break; + } + default: { + int *n = va_arg(ap, int*); + *n = result.length(); + break; + } + } + ++c; + break; + + default: // bad escape, treat as non-escape text + for (const char *cc = escape_start; cc != c; ++cc) + result.append(*cc); + continue; + } + + if (flags & TQLocalePrivate::LeftAdjusted) + result.append(subst.leftJustify(width)); + else + result.append(subst.rightJustify(width)); + } + + va_end(ap); + *this = result; + + return *this; +} +#endif + +/*! + Fills the string with \a len characters of value \a c, and returns + a reference to the string. + + If \a len is negative (the default), the current string length is + used. + + \code + TQString str; + str.fill( 'g', 5 ); // string == "ggggg" + \endcode +*/ + +TQString& TQString::fill( TQChar c, int len ) +{ + if ( len < 0 ) + len = length(); + if ( len == 0 ) { + *this = ""; + } else { + deref(); + TQChar * nd = QT_ALLOC_QCHAR_VEC( len ); + d = new TQStringData(nd,len,len); + while (len--) *nd++ = c; + } + return *this; +} + + +/*! + \fn TQString TQString::copy() const + + \obsolete + + In TQt 2.0 and later, all calls to this function are needless. Just + remove them. +*/ + +/*! + \overload + + Finds the first occurrence of the character \a c, starting at + position \a index. If \a index is -1, the search starts at the + last character; if -2, at the next to last character and so on. + (See findRev() for searching backwards.) + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + Returns the position of \a c or -1 if \a c could not be found. +*/ + +int TQString::find( TQChar c, int index, bool cs ) const +{ + const uint l = length(); + if ( index < 0 ) + index += l; + if ( (uint)index >= l ) + return -1; + register const TQChar *uc = unicode()+index; + const TQChar *end = unicode() + l; + if ( cs ) { + while ( uc < end && *uc != c ) + uc++; + } else { + c = ::lower( c ); + while ( uc < end && ::lower( *uc ) != c ) + uc++; + } + if ( uint(uc - unicode()) >= l ) + return -1; + return (int)(uc - unicode()); +} + +/* an implementation of the Boyer-Moore search algorithm +*/ + +/* initializes the skiptable to know haw far ahead we can skip on a wrong match +*/ +static void bm_init_skiptable( const TQString &pattern, uint *skiptable, bool cs ) +{ + int i = 0; + register uint *st = skiptable; + int l = pattern.length(); + while ( i++ < 0x100/8 ) { + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + *(st++) = l; + } + const TQChar *uc = pattern.unicode(); + if ( cs ) { + while ( l-- ) { + skiptable[ uc->cell() ] = l; + uc++; + } + } else { + while ( l-- ) { + skiptable[ ::lower( *uc ).cell() ] = l; + uc++; + } + } +} + +static int bm_find( const TQString &str, int index, const TQString &pattern, uint *skiptable, bool cs ) +{ + const uint l = str.length(); + if ( pattern.isEmpty() ) + return index > (int)l ? -1 : index; + + const TQChar *uc = str.unicode(); + const TQChar *puc = pattern.unicode(); + const uint pl = pattern.length(); + const uint pl_minus_one = pl - 1; + + register const TQChar *current = uc + index + pl_minus_one; + const TQChar *end = uc + l; + if ( cs ) { + while ( current < end ) { + uint skip = skiptable[ current->cell() ]; + if ( !skip ) { + // possible match + while ( skip < pl ) { + if ( *(current - skip ) != puc[pl_minus_one-skip] ) + break; + skip++; + } + if ( skip > pl_minus_one ) { // we have a match + return (current - uc) - skip + 1; + } + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if ( skiptable[ (current-skip)->cell() ] == pl ) + skip = pl - skip; + else + skip = 1; + } + current += skip; + } + } else { + while ( current < end ) { + uint skip = skiptable[ ::lower( *current ).cell() ]; + if ( !skip ) { + // possible match + while ( skip < pl ) { + if ( ::lower( *(current - skip) ) != ::lower( puc[pl_minus_one-skip] ) ) + break; + skip++; + } + if ( skip > pl_minus_one ) // we have a match + return (current - uc) - skip + 1; + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if ( skiptable[ ::lower(*(current - skip)).cell() ] == pl ) + skip = pl - skip; + else + skip = 1; + } + current += skip; + } + } + // not found + return -1; +} + + +#define REHASH( a ) \ + if ( sl_minus_1 < sizeof(uint) * CHAR_BIT ) \ + hashHaystack -= (a) << sl_minus_1; \ + hashHaystack <<= 1 + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index. If \a index is -1, the search starts at the + last character, if it is -2, at the next to last character and so + on. (See findRev() for searching backwards.) + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + Returns the position of \a str or -1 if \a str could not be found. +*/ + +int TQString::find( const TQString& str, int index, bool cs ) const +{ + const uint l = length(); + const uint sl = str.length(); + if ( index < 0 ) + index += l; + if ( sl + index > l ) + return -1; + if ( !sl ) + return index; + if (!l) + return -1; + +#if defined(Q_OS_MACX) && defined(QT_MACOSX_VERSION) && QT_MACOSX_VERSION >= 0x1020 + if ( sl == 1 ) + return find( *str.unicode(), index, cs ); +#endif + + // we use the Boyer-Moore algorithm in cases where the overhead + // for the hash table should pay off, otherwise we use a simple + // hash function + if ( l > 500 && sl > 5 ) { + uint skiptable[0x100]; + bm_init_skiptable( str, skiptable, cs ); + return bm_find( *this, index, str, skiptable, cs ); + } + + /* + We use some hashing for efficiency's sake. Instead of + comparing strings, we compare the hash value of str with that of + a part of this TQString. Only if that matches, we call ucstrncmp + or ucstrnicmp. + */ + const TQChar* needle = str.unicode(); + const TQChar* haystack = unicode() + index; + const TQChar* end = unicode() + (l-sl); + const uint sl_minus_1 = sl-1; + uint hashNeedle = 0, hashHaystack = 0, i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + needle[i].unicode() ); + hashHaystack = ((hashHaystack<<1) + haystack[i].unicode() ); + } + hashHaystack -= (haystack+sl_minus_1)->unicode(); + + while ( haystack <= end ) { + hashHaystack += (haystack+sl_minus_1)->unicode(); + if ( hashHaystack == hashNeedle + && ucstrncmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + + REHASH( haystack->unicode() ); + ++haystack; + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + + ::lower( needle[i].unicode() ).unicode() ); + hashHaystack = ((hashHaystack<<1) + + ::lower( haystack[i].unicode() ).unicode() ); + } + + hashHaystack -= ::lower(*(haystack+sl_minus_1)).unicode(); + while ( haystack <= end ) { + hashHaystack += ::lower(*(haystack+sl_minus_1)).unicode(); + if ( hashHaystack == hashNeedle + && ucstrnicmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + + REHASH( ::lower(*haystack).unicode() ); + ++haystack; + } + } + return -1; +} + +/*! + \fn int TQString::findRev( const char* str, int index ) const + + Equivalent to findRev(TQString(\a str), \a index). +*/ + +/*! + \fn int TQString::find( const char* str, int index ) const + + \overload + + Equivalent to find(TQString(\a str), \a index). +*/ + +/*! + \overload + + Finds the first occurrence of the character \a c, starting at + position \a index and searching backwards. If the index is -1, the + search starts at the last character, if it is -2, at the next to + last character and so on. + + Returns the position of \a c or -1 if \a c could not be found. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + \code + TQString string( "bananas" ); + int i = string.findRev( 'a' ); // i == 5 + \endcode +*/ + +int TQString::findRev( TQChar c, int index, bool cs ) const +{ +#if defined(Q_OS_MACX) && defined(QT_MACOSX_VERSION) && QT_MACOSX_VERSION < 0x1020 + return findRev( TQString( c ), index, cs ); +#else + const uint l = length(); + if ( index < 0 ) + index += l; + if ( (uint)index >= l ) + return -1; + const TQChar *end = unicode(); + register const TQChar *uc = end + index; + if ( cs ) { + while ( uc >= end && *uc != c ) + uc--; + } else { + c = ::lower( c ); + while ( uc >= end && ::lower( *uc ) != c ) + uc--; + } + return uc - end; +#endif +} + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index and searching backwards. If the index is -1, the + search starts at the last character, if it is -2, at the next to + last character and so on. + + Returns the position of \a str or -1 if \a str could not be found. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + \code + TQString string("bananas"); + int i = string.findRev( "ana" ); // i == 3 + \endcode +*/ + +int TQString::findRev( const TQString& str, int index, bool cs ) const +{ + /* + See TQString::find() for explanations. + */ + const uint l = length(); + if ( index < 0 ) + index += l; + const uint sl = str.length(); + int delta = l-sl; + if ( index < 0 || index > (int)l || delta < 0 ) + return -1; + if ( index > delta ) + index = delta; + +#if defined(Q_OS_MACX) && defined(QT_MACOSX_VERSION) && QT_MACOSX_VERSION >= 0x1020 + if ( sl == 1 ) + return findRev( *str.unicode(), index, cs ); +#endif + + const TQChar* needle = str.unicode(); + const TQChar* haystack = unicode() + index; + const TQChar* end = unicode(); + const uint sl_minus_1 = sl-1; + const TQChar* n = needle+sl_minus_1; + const TQChar* h = haystack+sl_minus_1; + uint hashNeedle = 0, hashHaystack = 0, i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + (n-i)->unicode() ); + hashHaystack = ((hashHaystack<<1) + (h-i)->unicode() ); + } + hashHaystack -= haystack->unicode(); + + while ( haystack >= end ) { + hashHaystack += haystack->unicode(); + if ( hashHaystack == hashNeedle + && ucstrncmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + --haystack; + REHASH( (haystack+sl)->unicode() ); + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + + ::lower( (n-i)->unicode() ).unicode() ); + hashHaystack = ((hashHaystack<<1) + + ::lower( (h-i)->unicode() ).unicode() ); + } + hashHaystack -= ::lower(*haystack).unicode(); + + while ( haystack >= end ) { + hashHaystack += ::lower(*haystack).unicode(); + if ( hashHaystack == hashNeedle + && ucstrnicmp( needle, haystack, sl ) == 0 ) + return haystack-unicode(); + --haystack; + REHASH( ::lower(*(haystack+sl)).unicode() ); + } + } + return -1; +} + +#undef REHASH + +/*! + \enum TQString::SectionFlags + + \value SectionDefault Empty fields are counted, leading and + trailing separators are not included, and the separator is + compared case sensitively. + + \value SectionSkipEmpty Treat empty fields as if they don't exist, + i.e. they are not considered as far as \e start and \e end are + concerned. + + \value SectionIncludeLeadingSep Include the leading separator (if + any) in the result string. + + \value SectionIncludeTrailingSep Include the trailing separator + (if any) in the result string. + + \value SectionCaseInsensitiveSeps Compare the separator + case-insensitively. + + Any of the last four values can be OR-ed together to form a flag. + + \sa section() +*/ + +/*! + \fn TQString TQString::section( TQChar sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + character, \a sep. The returned string consists of the fields from + position \a start to position \a end inclusive. If \a end is not + specified, all fields from position \a start to the end of the + string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behaviour, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \code + TQString csv( "forename,middlename,surname,phone" ); + TQString s = csv.section( ',', 2, 2 ); // s == "surname" + + TQString path( "/usr/local/bin/myapp" ); // First field is empty + TQString s = path.section( '/', 3, 4 ); // s == "bin/myapp" + TQString s = path.section( '/', 3, 3, SectionSkipEmpty ); // s == "myapp" + \endcode + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \code + TQString csv( "forename,middlename,surname,phone" ); + TQString s = csv.section( ',', -3, -2 ); // s == "middlename,surname" + + TQString path( "/usr/local/bin/myapp" ); // First field is empty + TQString s = path.section( '/', -1 ); // s == "myapp" + \endcode + + \sa TQStringList::split() +*/ + +/*! + \overload + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + string, \a sep. The returned string consists of the fields from + position \a start to position \a end inclusive. If \a end is not + specified, all fields from position \a start to the end of the + string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behaviour, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \code + TQString data( "forename**middlename**surname**phone" ); + TQString s = data.section( "**", 2, 2 ); // s == "surname" + \endcode + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \code + TQString data( "forename**middlename**surname**phone" ); + TQString s = data.section( "**", -3, -2 ); // s == "middlename**surname" + \endcode + + \sa TQStringList::split() +*/ + +TQString TQString::section( const TQString &sep, int start, int end, int flags ) const +{ + TQStringList sections = TQStringList::split(sep, *this, TRUE); + if(sections.isEmpty()) + return TQString(); + if(!(flags & SectionSkipEmpty)) { + if(start < 0) + start += int(sections.count()); + if(end < 0) + end += int(sections.count()); + } else { + int skip = 0; + for(TQStringList::Iterator it = sections.begin(); it != sections.end(); ++it) { + if((*it).isEmpty()) + skip++; + } + if(start < 0) + start += int(sections.count()) - skip; + if(end < 0) + end += int(sections.count()) - skip; + } + int x = 0, run = 0; + TQString ret; + for(TQStringList::Iterator it = sections.begin(); x <= end && it != sections.end(); ++it) { + if(x >= start) { + if((*it).isEmpty()) { + run++; + } else { + if(!ret.isEmpty() || !(flags & SectionSkipEmpty)) { + int i_end = run; + if(!ret.isEmpty() && !(flags & SectionIncludeTrailingSep)) + i_end++; + if((flags & SectionIncludeLeadingSep) && it != sections.begin() && x == start) + i_end++; + for(int i = 0; i < i_end; i++) + ret += sep; + } else if((flags & SectionIncludeLeadingSep) && it != sections.begin()) { + ret += sep; + } + run = 0; + ret += (*it); + if((flags & SectionIncludeTrailingSep) && it != sections.end()) + ret += sep; + } + } + if(!(*it).isEmpty() || !(flags & SectionSkipEmpty)) + x++; + } + return ret; +} + +#ifndef QT_NO_REGEXP +class section_chunk { +public: + section_chunk(int l, TQString s) { length = l; string = s; } + int length; + TQString string; +}; +/*! + \overload + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + regular expression, \a reg. The returned string consists of the + fields from position \a start to position \a end inclusive. If \a + end is not specified, all fields from position \a start to the end + of the string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behaviour, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \code + TQString line( "forename\tmiddlename surname \t \t phone" ); + TQRegExp sep( "\s+" ); + TQString s = line.section( sep, 2, 2 ); // s == "surname" + \endcode + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \code + TQString line( "forename\tmiddlename surname \t \t phone" ); + TQRegExp sep( "\\s+" ); + TQString s = line.section( sep, -3, -2 ); // s == "middlename surname" + \endcode + + \warning Using this TQRegExp version is much more expensive than + the overloaded string and character versions. + + \sa TQStringList::split() simplifyWhiteSpace() +*/ + +TQString TQString::section( const TQRegExp ®, int start, int end, int flags ) const +{ + const TQChar *uc = unicode(); + if(!uc) + return TQString(); + + TQRegExp sep(reg); + sep.setCaseSensitive(!(flags & SectionCaseInsensitiveSeps)); + + TQPtrList<section_chunk> l; + l.setAutoDelete(TRUE); + int n = length(), m = 0, last_m = 0, last = 0, last_len = 0; + + while ( ( m = sep.search( *this, m ) ) != -1 ) { + l.append(new section_chunk(last_len, TQString(uc + last_m, m - last_m))); + last_m = m; + last_len = sep.matchedLength(); + if((m += TQMAX(sep.matchedLength(), 1)) >= n) { + last = 1; + break; + } + } + if(!last) + l.append(new section_chunk(last_len, TQString(uc + last_m, n - last_m))); + + if(start < 0) + start = l.count() + start; + if(end == -1) + end = l.count(); + else if(end < 0) + end = l.count() + end; + + int i = 0; + TQString ret; + for ( section_chunk *chk=l.first(); chk; chk=l.next(), i++ ) { + if((flags & SectionSkipEmpty) && chk->length == (int)chk->string.length()) { + if(i <= start) + start++; + end++; + } + if(i == start) { + ret = (flags & SectionIncludeLeadingSep) ? chk->string : chk->string.mid(chk->length); + } else if(i > start) { + ret += chk->string; + } + if(i == end) { + if((chk=l.next()) && flags & SectionIncludeTrailingSep) + ret += chk->string.left(chk->length); + break; + } + } + return ret; +} +#endif + +/*! + \fn TQString TQString::section( char sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const + + \overload +*/ + +/*! + \fn TQString TQString::section( const char *sep, int start, int end = 0xffffffff, int flags = SectionDefault ) const + + \overload +*/ + + +/*! + Returns the number of times the character \a c occurs in the + string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + \code + TQString string( "Trolltech and TQt" ); + int n = string.contains( 't', FALSE ); + // n == 3 + \endcode +*/ + +int TQString::contains( TQChar c, bool cs ) const +{ + int count = 0; + const TQChar *uc = unicode(); + if ( !uc ) + return 0; + int n = length(); + if ( cs ) { + while ( n-- ) { + if ( *uc == c ) + count++; + uc++; + } + } else { + c = ::lower( c ); + while ( n-- ) { + if ( ::lower( *uc ) == c ) + count++; + uc++; + } + } + return count; +} + +/*! + \overload + + Returns the number of times the string \a str occurs in the string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. +*/ +int TQString::contains( const char* str, bool cs ) const +{ + return contains( TQString(str), cs ); +} + +/*! + \fn int TQString::contains( char c, bool cs ) const + + \overload +*/ + +/*! + \fn int TQString::find( char c, int index, bool cs ) const + + \overload + + Find character \a c starting from position \a index. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. +*/ + +/*! + \fn int TQString::findRev( char c, int index, bool cs ) const + + \overload + + Find character \a c starting from position \a index and working + backwards. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. +*/ + +/*! + \overload + + Returns the number of times \a str occurs in the string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + This function counts overlapping strings, so in the example below, + there are two instances of "ana" in "bananas". + + \code + TQString str( "bananas" ); + int i = str.contains( "ana" ); // i == 2 + \endcode + + \sa findRev() +*/ + +int TQString::contains( const TQString &str, bool cs ) const +{ + if ( isNull() ) + return 0; + int count = 0; + uint skiptable[0x100]; + bm_init_skiptable( str, skiptable, cs ); + int i = -1; + // use boyer-moore for the ultimate speed experience + while ( ( i = bm_find( *this, i + 1, str, skiptable, cs ) ) != -1 ) + count++; + return count; +} + +/*! + Returns a substring that contains the \a len leftmost characters + of the string. + + The whole string is returned if \a len exceeds the length of the + string. + + \code + TQString s = "Pineapple"; + TQString t = s.left( 4 ); // t == "Pine" + \endcode + + \sa right(), mid(), isEmpty() +*/ + +TQString TQString::left( uint len ) const +{ + if ( isEmpty() ) { + return TQString(); + } else if ( len == 0 ) { // ## just for 1.x compat: + return fromLatin1( "" ); + } else if ( len >= length() ) { + return *this; + } else { + TQString s( len, TRUE ); + memcpy( s.d->unicode, d->unicode, len * sizeof(TQChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a string that contains the \a len rightmost characters of + the string. + + If \a len is greater than the length of the string then the whole + string is returned. + + \code + TQString string( "Pineapple" ); + TQString t = string.right( 5 ); // t == "apple" + \endcode + + \sa left(), mid(), isEmpty() +*/ + +TQString TQString::right( uint len ) const +{ + if ( isEmpty() ) { + return TQString(); + } else if ( len == 0 ) { // ## just for 1.x compat: + return fromLatin1( "" ); + } else { + uint l = length(); + if ( len >= l ) + return *this; + TQString s( len, TRUE ); + memcpy( s.d->unicode, d->unicode+(l-len), len*sizeof(TQChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a string that contains the \a len characters of this + string, starting at position \a index. + + Returns a null string if the string is empty or \a index is out of + range. Returns the whole string from \a index if \a index + \a len + exceeds the length of the string. + + \code + TQString s( "Five pineapples" ); + TQString t = s.mid( 5, 4 ); // t == "pine" + \endcode + + \sa left(), right() +*/ + +TQString TQString::mid( uint index, uint len ) const +{ + uint slen = length(); + if ( isEmpty() || index >= slen ) { + return TQString(); + } else if ( len == 0 ) { // ## just for 1.x compat: + return fromLatin1( "" ); + } else { + if ( len > slen-index ) + len = slen - index; + if ( index == 0 && len == slen ) + return *this; + register const TQChar *p = unicode()+index; + TQString s( len, TRUE ); + memcpy( s.d->unicode, p, len * sizeof(TQChar) ); + s.d->len = len; + return s; + } +} + +/*! + Returns a string of length \a width that contains this string + padded by the \a fill character. + + If \a truncate is FALSE and the length of the string is more than + \a width, then the returned string is a copy of the string. + + If \a truncate is TRUE and the length of the string is more than + \a width, then any characters in a copy of the string after length + \a width are removed, and the copy is returned. + + \code + TQString s( "apple" ); + TQString t = s.leftJustify( 8, '.' ); // t == "apple..." + \endcode + + \sa rightJustify() +*/ + +TQString TQString::leftJustify( uint width, TQChar fill, bool truncate ) const +{ + TQString result; + int len = length(); + int padlen = width - len; + if ( padlen > 0 ) { + result.setLength(len+padlen); + if ( len ) + memcpy( result.d->unicode, unicode(), sizeof(TQChar)*len ); + TQChar* uc = result.d->unicode + len; + while (padlen--) + *uc++ = fill; + } else { + if ( truncate ) + result = left( width ); + else + result = *this; + } + return result; +} + +/*! + Returns a string of length \a width that contains the \a fill + character followed by the string. + + If \a truncate is FALSE and the length of the string is more than + \a width, then the returned string is a copy of the string. + + If \a truncate is TRUE and the length of the string is more than + \a width, then the resulting string is truncated at position \a + width. + + \code + TQString string( "apple" ); + TQString t = string.rightJustify( 8, '.' ); // t == "...apple" + \endcode + + \sa leftJustify() +*/ + +TQString TQString::rightJustify( uint width, TQChar fill, bool truncate ) const +{ + TQString result; + int len = length(); + int padlen = width - len; + if ( padlen > 0 ) { + result.setLength( len+padlen ); + TQChar* uc = result.d->unicode; + while (padlen--) + *uc++ = fill; + if ( len ) + memcpy( uc, unicode(), sizeof(TQChar)*len ); + } else { + if ( truncate ) + result = left( width ); + else + result = *this; + } + return result; +} + +/*! + Returns a lowercase copy of the string. + + \code + TQString string( "TROlltECH" ); + str = string.lower(); // str == "trolltech" + \endcode + + \sa upper() +*/ + +TQString TQString::lower() const +{ + int l = length(); + register TQChar *p = d->unicode; + while ( l ) { + if ( *p != ::lower(*p) ) { + TQString s( *this ); + s.real_detach(); + p = s.d->unicode + ( p - d->unicode ); + while ( l ) { + *p = ::lower( *p ); + l--; + p++; + } + return s; + } + l--; + p++; + } + return *this; +} + +/*! + Returns an uppercase copy of the string. + + \code + TQString string( "TeXt" ); + str = string.upper(); // t == "TEXT" + \endcode + + \sa lower() +*/ + +TQString TQString::upper() const +{ + int l = length(); + register TQChar *p = d->unicode; + while ( l ) { + if ( *p != ::upper(*p) ) { + TQString s( *this ); + s.real_detach(); + p = s.d->unicode + ( p - d->unicode ); + while ( l ) { + *p = ::upper( *p ); + l--; + p++; + } + return s; + } + l--; + p++; + } + return *this; +} + + +/*! + Returns a string that has whitespace removed from the start and + the end. + + Whitespace means any character for which TQChar::isSpace() returns + TRUE. This includes Unicode characters with decimal values 9 + (TAB), 10 (LF), 11 (VT), 12 (FF), 13 (CR) and 32 (Space), and may + also include other Unicode characters. + + \code + TQString string = " white space "; + TQString s = string.stripWhiteSpace(); // s == "white space" + \endcode + + \sa simplifyWhiteSpace() +*/ + +TQString TQString::stripWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return *this; + register const TQChar *s = unicode(); + if ( !s->isSpace() && !s[length()-1].isSpace() ) + return *this; + + int start = 0; + int end = length() - 1; + while ( start<=end && s[start].isSpace() ) // skip white space from start + start++; + if ( start <= end ) { // only white space + while ( end && s[end].isSpace() ) // skip white space from end + end--; + } + int l = end - start + 1; + if ( l <= 0 ) + return TQString::fromLatin1(""); + + TQString result( l, TRUE ); + memcpy( result.d->unicode, &s[start], sizeof(TQChar)*l ); + result.d->len = l; + return result; +} + + +/*! + Returns a string that has whitespace removed from the start and + the end, and which has each sequence of internal whitespace + replaced with a single space. + + Whitespace means any character for which TQChar::isSpace() returns + TRUE. This includes Unicode characters with decimal values 9 + (TAB), 10 (LF), 11 (VT), 12 (FF), 13 (CR), and 32 (Space). + + \code + TQString string = " lots\t of\nwhite space "; + TQString t = string.simplifyWhiteSpace(); + // t == "lots of white space" + \endcode + + \sa stripWhiteSpace() +*/ + +TQString TQString::simplifyWhiteSpace() const +{ + if ( isEmpty() ) + return *this; + TQString result; + result.setLength( length() ); + const TQChar *from = unicode(); + const TQChar *fromend = from+length(); + int outc=0; + TQChar *to = result.d->unicode; + for (;;) { + while ( from!=fromend && from->isSpace() ) + from++; + while ( from!=fromend && !from->isSpace() ) + to[outc++] = *from++; + if ( from!=fromend ) + to[outc++] = ' '; + else + break; + } + if ( outc > 0 && to[outc-1] == ' ' ) + outc--; + result.truncate( outc ); + return result; +} + + +/*! + Inserts \a s into the string at position \a index. + + If \a index is beyond the end of the string, the string is + extended with spaces to length \a index and \a s is then appended + and returns a reference to the string. + + \code + TQString string( "I like fish" ); + str = string.insert( 2, "don't " ); + // str == "I don't like fish" + \endcode + + \sa remove(), replace() +*/ + +TQString &TQString::insert( uint index, const TQString &s ) +{ + // the sub function takes care of &s == this case. + return insert( index, s.unicode(), s.length() ); +} + +/*! \fn TQString &TQString::insert( uint index, const TQByteArray &s ) + \overload + + Inserts \a s into the string at position \a index and returns + a reference to the string. +*/ + +/*! \fn TQString &TQString::insert( uint index, const char *s ) + \overload + + Inserts \a s into the string at position \a index and returns + a reference to the string. +*/ + +#ifndef QT_NO_CAST_ASCII +TQString &TQString::insertHelper( uint index, const char *s, uint len ) +{ + if ( s ) { +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) + return insert( index, fromAscii( s, len ) ); +#endif + if ( len == UINT_MAX ) + len = int(strlen( s )); + if ( len == 0 ) + return *this; + + uint olen = length(); + int nlen = olen + len; + + if ( index >= olen ) { // insert after end of string + grow( len + index ); + int n = index - olen; + TQChar* uc = d->unicode + olen; + while ( n-- ) + *uc++ = ' '; + + uc = d->unicode + index; + while ( len-- ) + *uc++ = *s++; + } else { // normal insert + grow( nlen ); + memmove( d->unicode + index + len, unicode() + index, + sizeof(TQChar) * (olen - index) ); + + TQChar* uc = d->unicode + index; + while ( len-- ) + *uc++ = *s++; + } + } + return *this; +} +#endif + +/*! + \overload + + Inserts the first \a len characters in \a s into the string at + position \a index and returns a reference to the string. +*/ + +TQString &TQString::insert( uint index, const TQChar* s, uint len ) +{ + if ( len == 0 ) + return *this; + uint olen = length(); + int nlen = olen + len; + + if ( s >= d->unicode && (uint)(s - d->unicode) < d->maxl ) { + // Part of me - take a copy. + TQChar *tmp = QT_ALLOC_QCHAR_VEC( len ); + memcpy(tmp,s,len*sizeof(TQChar)); + insert(index,tmp,len); + QT_DELETE_QCHAR_VEC( tmp ); + return *this; + } + + if ( index >= olen ) { // insert after end of string + grow( len + index ); + int n = index - olen; + TQChar* uc = d->unicode+olen; + while (n--) + *uc++ = ' '; + memcpy( d->unicode+index, s, sizeof(TQChar)*len ); + } else { // normal insert + grow( nlen ); + memmove( d->unicode + index + len, unicode() + index, + sizeof(TQChar) * (olen - index) ); + memcpy( d->unicode + index, s, sizeof(TQChar) * len ); + } + return *this; +} + +/*! + \overload + + Insert \a c into the string at position \a index and returns a + reference to the string. + + If \a index is beyond the end of the string, the string is + extended with spaces (ASCII 32) to length \a index and \a c is + then appended. +*/ + +TQString &TQString::insert( uint index, TQChar c ) // insert char +{ + TQString s( c ); + return insert( index, s ); +} + +/*! + \fn TQString& TQString::insert( uint index, char c ) + + \overload + + Insert character \a c at position \a index. +*/ + +/*! + \fn TQString &TQString::prepend( const TQString &s ) + + Inserts \a s at the beginning of the string and returns a + reference to the string. + + Equivalent to insert(0, \a s). + + \code + TQString string = "42"; + string.prepend( "The answer is " ); + // string == "The answer is 42" + \endcode + + \sa insert() +*/ + +/*! + \fn TQString& TQString::prepend( char ch ) + + \overload + + Inserts \a ch at the beginning of the string and returns a + reference to the string. + + Equivalent to insert(0, \a ch). + + \sa insert() +*/ + +/*! + \fn TQString& TQString::prepend( TQChar ch ) + + \overload + + Inserts \a ch at the beginning of the string and returns a + reference to the string. + + Equivalent to insert(0, \a ch). + + \sa insert() +*/ + +/*! \fn TQString& TQString::prepend( const TQByteArray &s ) + \overload + + Inserts \a s at the beginning of the string and returns a reference to the string. + + Equivalent to insert(0, \a s). + + \sa insert() + */ + +/*! \fn TQString& TQString::prepend( const std::string &s ) + \overload + + Inserts \a s at the beginning of the string and returns a reference to the string. + + Equivalent to insert(0, \a s). + + \sa insert() +*/ + +/*! + \overload + + Inserts \a s at the beginning of the string and returns a reference to the string. + + Equivalent to insert(0, \a s). + + \sa insert() + */ +TQString &TQString::prepend( const char *s ) +{ + return insert( 0, TQString(s) ); +} + +/*! + Removes \a len characters from the string starting at position \a + index, and returns a reference to the string. + + If \a index is beyond the length of the string, nothing happens. + If \a index is within the string, but \a index + \a len is beyond + the end of the string, the string is truncated at position \a + index. + + \code + TQString string( "Montreal" ); + string.remove( 1, 4 ); // string == "Meal" + \endcode + + \sa insert(), replace() +*/ + +TQString &TQString::remove( uint index, uint len ) +{ + uint olen = length(); + if ( index >= olen ) { + // range problems + } else if ( index + len >= olen ) { // index ok + setLength( index ); + } else if ( len != 0 ) { + real_detach(); + memmove( d->unicode+index, d->unicode+index+len, + sizeof(TQChar)*(olen-index-len) ); + setLength( olen-len ); + } + return *this; +} + +/*! \overload + + Removes every occurrence of the character \a c in the string. + Returns a reference to the string. + + This is the same as replace(\a c, ""). +*/ +TQString &TQString::remove( TQChar c ) +{ + int i = 0; + while ( i < (int) length() ) { + if ( constref(i) == c ) { + remove( i, 1 ); + } else { + i++; + } + } + return *this; +} + +/*! \overload + + \fn TQString &TQString::remove( char c ) + + Removes every occurrence of the character \a c in the string. + Returns a reference to the string. + + This is the same as replace(\a c, ""). +*/ + +/*! \overload + + Removes every occurrence of \a str in the string. Returns a + reference to the string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + This is the same as replace(\a str, "", \a cs). +*/ +TQString &TQString::remove( const TQString & str, bool cs ) +{ + if ( str.isEmpty() ) { + if ( isNull() ) + real_detach(); + } else { + int index = 0; + while ( (index = find(str, index, cs)) != -1 ) + remove( index, str.length() ); + } + return *this; +} + +TQString &TQString::remove( const TQString & str ) +{ + return remove( str, TRUE ); +} + +/*! \overload + + Replaces every occurrence of \a c1 with the char \a c2. Returns a + reference to the string. +*/ +TQString &TQString::replace( TQChar c1, TQChar c2 ) +{ + if ( isEmpty() ) + return *this; + + real_detach(); + uint i = 0; + while ( i < d->len ) { + if ( d->unicode[i] == c1 ) + d->unicode[i] = c2; + i++; + } + return *this; +} + +#ifndef QT_NO_REGEXP_CAPTURE + +/*! \overload + + Removes every occurrence of the regular expression \a rx in the + string. Returns a reference to the string. + + This is the same as replace(\a rx, ""). +*/ + +TQString &TQString::remove( const TQRegExp & rx ) +{ + return replace( rx, TQString::null ); +} + +#endif + +/*! + \overload + + Removes every occurrence of \a str in the string. Returns a + reference to the string. +*/ +TQString &TQString::remove( const char *str ) +{ + return remove( TQString::fromAscii(str), TRUE ); +} + +/*! + Replaces \a len characters from the string with \a s, starting at + position \a index, and returns a reference to the string. + + If \a index is beyond the length of the string, nothing is deleted + and \a s is appended at the end of the string. If \a index is + valid, but \a index + \a len is beyond the end of the string, + the string is truncated at position \a index, then \a s is + appended at the end. + + \code + TQString string( "Say yes!" ); + string = string.replace( 4, 3, "NO" ); + // string == "Say NO!" + \endcode + + \warning TQt 3.3.3 and earlier had different semantics for the + case \a index >= length(), which contradicted the documentation. + To avoid portability problems between TQt 3 versions and with TQt + 4, we recommend that you never call the function with \a index >= + length(). + + \sa insert(), remove() +*/ + +TQString &TQString::replace( uint index, uint len, const TQString &s ) +{ + return replace( index, len, s.unicode(), s.length() ); +} + +/*! \overload + + This is the same as replace(\a index, \a len, TQString(\a c)). +*/ +TQString &TQString::replace( uint index, uint len, TQChar c ) +{ + return replace( index, len, &c, 1 ); +} + +/*! \overload + \fn TQString &TQString::replace( uint index, uint len, char c ) + + This is the same as replace(\a index, \a len, TQChar(\a c)). +*/ + +/*! + \overload + + Replaces \a len characters with \a slen characters of TQChar data + from \a s, starting at position \a index, and returns a reference + to the string. + + \sa insert(), remove() +*/ + +TQString &TQString::replace( uint index, uint len, const TQChar* s, uint slen ) +{ + if (index > length()) + index = length(); + real_detach(); + if ( len == slen && index + len <= length() ) { + // Optimized common case: replace without size change + memcpy( d->unicode+index, s, len * sizeof(TQChar) ); + } else if ( s >= d->unicode && (uint)(s - d->unicode) < d->maxl ) { + // Part of me - take a copy. + TQChar *tmp = QT_ALLOC_QCHAR_VEC( slen ); + memcpy( tmp, s, slen * sizeof(TQChar) ); + replace( index, len, tmp, slen ); + QT_DELETE_QCHAR_VEC( tmp ); + } else { + remove( index, len ); + insert( index, s, slen ); + } + return *this; +} + +/*! \overload + + Replaces every occurrence of the character \a c in the string + with \a after. Returns a reference to the string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + Example: + \code + TQString s = "a,b,c"; + s.replace( TQChar(','), " or " ); + // s == "a or b or c" + \endcode +*/ +TQString &TQString::replace( TQChar c, const TQString & after, bool cs ) +{ + return replace( TQString( c ), after, cs ); +} + +TQString &TQString::replace( TQChar c, const TQString & after ) +{ + return replace( TQString( c ), after, TRUE ); +} + +/*! \overload + \fn TQString &TQString::replace( char c, const TQString & after, bool cs ) + + Replaces every occurrence of the character \a c in the string + with \a after. Returns a reference to the string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. +*/ + +/*! \overload + + Replaces every occurrence of the string \a before in the string + with the string \a after. Returns a reference to the string. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + Example: + \code + TQString s = "Greek is Greek"; + s.replace( "Greek", "English" ); + // s == "English is English" + \endcode +*/ +TQString &TQString::replace( const TQString & before, const TQString & after, + bool cs ) +{ + if ( isEmpty() ) { + if ( !before.isEmpty() ) + return *this; + } else { + if ( cs && before == after ) + return *this; + } + + real_detach(); + + int index = 0; + uint skiptable[256]; + bm_init_skiptable( before, skiptable, cs ); + const int bl = before.length(); + const int al = after.length(); + + if ( bl == al ) { + if ( bl ) { + const TQChar *auc = after.unicode(); + while ( (index = bm_find(*this, index, before, skiptable, cs) ) != -1 ) { + memcpy( d->unicode + index, auc, al * sizeof(TQChar) ); + index += bl; + } + } + } else if ( al < bl ) { + const TQChar *auc = after.unicode(); + uint to = 0; + uint movestart = 0; + uint num = 0; + while ( (index = bm_find(*this, index, before, skiptable, cs)) != -1 ) { + if ( num ) { + int msize = index - movestart; + if ( msize > 0 ) { + memmove( d->unicode + to, d->unicode + movestart, msize*sizeof(TQChar) ); + to += msize; + } + } else { + to = index; + } + if ( al ) { + memcpy( d->unicode+to, auc, al*sizeof(TQChar) ); + to += al; + } + index += bl; + movestart = index; + num++; + } + if ( num ) { + int msize = d->len - movestart; + if ( msize > 0 ) + memmove( d->unicode + to, d->unicode + movestart, msize*sizeof(TQChar) ); + setLength( d->len - num*(bl-al) ); + } + } else { + // the most complex case. We don't want to loose performance by doing repeated + // copies and reallocs of the string. + while ( index != -1 ) { + uint indices[4096]; + uint pos = 0; + while ( pos < 4095 ) { + index = bm_find( *this, index, before, skiptable, cs ); + if ( index == -1 ) + break; + indices[pos++] = index; + index += bl; + // avoid infinite loop + if ( !bl ) + index++; + } + if ( !pos ) + break; + + // we have a table of replacement positions, use them for fast replacing + int adjust = pos*(al-bl); + // index has to be adjusted in case we get back into the loop above. + if ( index != -1 ) + index += adjust; + uint newlen = d->len + adjust; + int moveend = d->len; + if ( newlen > d->len ) + setLength( newlen ); + + while ( pos ) { + pos--; + int movestart = indices[pos] + bl; + int insertstart = indices[pos] + pos*(al-bl); + int moveto = insertstart + al; + memmove( d->unicode + moveto, d->unicode + movestart, (moveend - movestart)*sizeof(TQChar) ); + memcpy( d->unicode + insertstart, after.unicode(), al*sizeof(TQChar) ); + moveend = movestart-bl; + } + } + } + return *this; +} + +TQString &TQString::replace( const TQString & before, const TQString & after ) +{ + return replace( before, after, TRUE ); +} + +#ifndef QT_NO_REGEXP_CAPTURE +/*! \overload + + Replaces every occurrence of the regexp \a rx in the string with + \a after. Returns a reference to the string. For example: + \code + TQString s = "banana"; + s.replace( TQRegExp("an"), "" ); + // s == "ba" + \endcode + + For regexps containing \link qregexp.html#capturing-text capturing + parentheses \endlink, occurrences of <b>\\1</b>, <b>\\2</b>, ..., + in \a after are replaced with \a{rx}.cap(1), cap(2), ... + + \code + TQString t = "A <i>bon mot</i>."; + t.replace( TQRegExp("<i>([^<]*)</i>"), "\\emph{\\1}" ); + // t == "A \\emph{bon mot}." + \endcode + + \sa find(), findRev(), TQRegExp::cap() +*/ + +TQString &TQString::replace( const TQRegExp &rx, const TQString &after ) +{ + TQRegExp rx2 = rx; + + if ( isEmpty() && rx2.search(*this) == -1 ) + return *this; + + real_detach(); + + int index = 0; + int numCaptures = rx2.numCaptures(); + int al = after.length(); + TQRegExp::CaretMode caretMode = TQRegExp::CaretAtZero; + + if ( numCaptures > 0 ) { + if ( numCaptures > 9 ) + numCaptures = 9; + + const TQChar *uc = after.unicode(); + int numBackRefs = 0; + + for ( int i = 0; i < al - 1; i++ ) { + if ( uc[i] == '\\' ) { + int no = uc[i + 1].digitValue(); + if ( no > 0 && no <= numCaptures ) + numBackRefs++; + } + } + + /* + This is the harder case where we have back-references. + We don't try to optimize it. + */ + if ( numBackRefs > 0 ) { + int *capturePositions = new int[numBackRefs]; + int *captureNumbers = new int[numBackRefs]; + int j = 0; + + for ( int i = 0; i < al - 1; i++ ) { + if ( uc[i] == '\\' ) { + int no = uc[i + 1].digitValue(); + if ( no > 0 && no <= numCaptures ) { + capturePositions[j] = i; + captureNumbers[j] = no; + j++; + } + } + } + + while ( index <= (int)length() ) { + index = rx2.search( *this, index, caretMode ); + if ( index == -1 ) + break; + + TQString after2 = after; + for ( j = numBackRefs - 1; j >= 0; j-- ) + after2.replace( capturePositions[j], 2, + rx2.cap(captureNumbers[j]) ); + + replace( index, rx2.matchedLength(), after2 ); + index += after2.length(); + + if ( rx2.matchedLength() == 0 ) { + // avoid infinite loop on 0-length matches (e.g., [a-z]*) + index++; + } + caretMode = TQRegExp::CaretWontMatch; + } + delete[] capturePositions; + delete[] captureNumbers; + return *this; + } + } + + /* + This is the simple and optimized case where we don't have + back-references. + */ + while ( index != -1 ) { + struct { + int pos; + int length; + } replacements[2048]; + + uint pos = 0; + int adjust = 0; + while ( pos < 2047 ) { + index = rx2.search( *this, index, caretMode ); + if ( index == -1 ) + break; + int ml = rx2.matchedLength(); + replacements[pos].pos = index; + replacements[pos++].length = ml; + index += ml; + adjust += al - ml; + // avoid infinite loop + if ( !ml ) + index++; + } + if ( !pos ) + break; + replacements[pos].pos = d->len; + uint newlen = d->len + adjust; + + // to continue searching at the right position after we did + // the first round of replacements + if ( index != -1 ) + index += adjust; + TQChar *newuc = QT_ALLOC_QCHAR_VEC( newlen + 1 ); + TQChar *uc = newuc; + int copystart = 0; + uint i = 0; + while ( i < pos ) { + int copyend = replacements[i].pos; + int size = copyend - copystart; + memcpy( uc, d->unicode + copystart, size * sizeof(TQChar) ); + uc += size; + memcpy( uc, after.unicode(), al * sizeof(TQChar) ); + uc += al; + copystart = copyend + replacements[i].length; + i++; + } + memcpy( uc, d->unicode + copystart, + (d->len - copystart) * sizeof(TQChar) ); + QT_DELETE_QCHAR_VEC( d->unicode ); + d->unicode = newuc; + d->len = newlen; + d->maxl = newlen + 1; + d->setDirty(); + caretMode = TQRegExp::CaretWontMatch; + } + return *this; +} +#endif + +#ifndef QT_NO_REGEXP +/*! + Finds the first match of the regular expression \a rx, starting + from position \a index. If \a index is -1, the search starts at + the last character; if -2, at the next to last character and so + on. (See findRev() for searching backwards.) + + Returns the position of the first match of \a rx or -1 if no match + was found. + + \code + TQString string( "bananas" ); + int i = string.find( TQRegExp("an"), 0 ); // i == 1 + \endcode + + \sa findRev() replace() contains() +*/ + +int TQString::find( const TQRegExp &rx, int index ) const +{ + return rx.search( *this, index ); +} + +/*! + \overload + + Finds the first match of the regexp \a rx, starting at position \a + index and searching backwards. If the index is -1, the search + starts at the last character, if it is -2, at the next to last + character and so on. (See findRev() for searching backwards.) + + Returns the position of the match or -1 if no match was found. + + \code + TQString string( "bananas" ); + int i = string.findRev( TQRegExp("an") ); // i == 3 + \endcode + + \sa find() +*/ + +int TQString::findRev( const TQRegExp &rx, int index ) const +{ + return rx.searchRev( *this, index ); +} + +/*! + \overload + + Returns the number of times the regexp, \a rx, matches in the + string. + + This function counts overlapping matches, so in the example below, + there are four instances of "ana" or "ama". + + \code + TQString str = "banana and panama"; + TQRegExp rxp = TQRegExp( "a[nm]a", TRUE, FALSE ); + int i = str.contains( rxp ); // i == 4 + \endcode + + \sa find() findRev() +*/ + +int TQString::contains( const TQRegExp &rx ) const +{ + int count = 0; + int index = -1; + int len = length(); + while ( index < len - 1 ) { // count overlapping matches + index = rx.search( *this, index + 1 ); + if ( index == -1 ) + break; + count++; + } + return count; +} + +#endif //QT_NO_REGEXP + +/*! + Returns the string converted to a \c long using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +long TQString::toLong( bool *ok, int base ) const +{ + Q_LLONG v = toLongLong( ok, base ); + if ( v < LONG_MIN || v > LONG_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return long(v); +} + +/*! + Returns the string converted to a \c {long long} using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +Q_LLONG TQString::toLongLong( bool *ok, int base ) const +{ +#if defined(QT_CHECK_RANGE) + if ( base != 0 && (base < 2 || base > 36) ) { + qWarning( "TQString::toLongLong: Invalid base (%d)", base ); + base = 10; + } +#endif + + bool my_ok; + TQLocale def_locale; + Q_LLONG result = def_locale.d->stringToLongLong(*this, base, &my_ok, TQLocalePrivate::FailOnGroupSeparators); + if (my_ok) { + if (ok != 0) + *ok = TRUE; + return result; + } + + // If the default was not "C", try the "C" locale + if (def_locale.language() == TQLocale::C) { + if (ok != 0) + *ok = FALSE; + return 0; + } + + TQLocale c_locale(TQLocale::C); + return c_locale.d->stringToLongLong(*this, base, ok, TQLocalePrivate::FailOnGroupSeparators); +} + +/*! + Returns the string converted to an \c {unsigned long} using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +ulong TQString::toULong( bool *ok, int base ) const +{ + Q_ULLONG v = toULongLong( ok, base ); + if ( v > ULONG_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return ulong(v); +} + +/*! + Returns the string converted to an \c {unsigned long long} using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +Q_ULLONG TQString::toULongLong( bool *ok, int base ) const +{ +#if defined(QT_CHECK_RANGE) + if ( base != 0 && (base < 2 || base > 36) ) { + qWarning( "TQString::toULongLong: Invalid base %d", base ); + base = 10; + } +#endif + + bool my_ok; + TQLocale def_locale; + Q_ULLONG result = def_locale.d->stringToUnsLongLong(*this, base, &my_ok, TQLocalePrivate::FailOnGroupSeparators); + if (my_ok) { + if (ok != 0) + *ok = TRUE; + return result; + } + + // If the default was not "C", try the "C" locale + if (def_locale.language() == TQLocale::C) { + if (ok != 0) + *ok = FALSE; + return 0; + } + + TQLocale c_locale(TQLocale::C); + return c_locale.d->stringToUnsLongLong(*this, base, ok, TQLocalePrivate::FailOnGroupSeparators); +} + +/*! + Returns the string converted to a \c short using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + + +short TQString::toShort( bool *ok, int base ) const +{ + Q_LLONG v = toLongLong( ok, base ); + if ( v < SHRT_MIN || v > SHRT_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return (short)v; +} + +/*! + Returns the string converted to an \c {unsigned short} using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +ushort TQString::toUShort( bool *ok, int base ) const +{ + Q_ULLONG v = toULongLong( ok, base ); + if ( v > USHRT_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return (ushort)v; +} + + +/*! + Returns the string converted to an \c int using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \code + TQString str( "FF" ); + bool ok; + int hex = str.toInt( &ok, 16 ); // hex == 255, ok == TRUE + int dec = str.toInt( &ok, 10 ); // dec == 0, ok == FALSE + \endcode + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +int TQString::toInt( bool *ok, int base ) const +{ + Q_LLONG v = toLongLong( ok, base ); + if ( v < INT_MIN || v > INT_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return (int)v; +} + +/*! + Returns the string converted to an \c {unsigned int} using base \a + base, which is 10 by default and must be between 2 and 36 or 0. If + \a base is 0, the base is determined automatically using the + following rules: + <ul> + <li>If the string begins with "0x", it is assumed to + be hexadecimal; + <li>If it begins with "0", it is assumed to be octal; + <li>Otherwise it is assumed to be decimal. + </ul> + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + Leading and trailing whitespace is ignored by this function. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \sa number() +*/ + +uint TQString::toUInt( bool *ok, int base ) const +{ + Q_ULLONG v = toULongLong( ok, base ); + if ( v > UINT_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return (uint)v; +} + +/*! + Returns the string converted to a \c double value. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + \code + TQString string( "1234.56" ); + double a = string.toDouble(); // a == 1234.56 + \endcode + + The string-to-number functions: + \list + \i toShort() + \i toUShort() + \i toInt() + \i toUInt() + \i toLong() + \i toULong() + \i toLongLong() + \i toULongLong() + \i toFloat() + \i toDouble() + \endlist + can handle numbers + represented in various locales. These representations may use different + characters for the decimal point, thousands group sepearator + and even individual digits. TQString's functions try to interpret + the string according to the current locale. The current locale is + determined from the system at application startup and can be changed + by calling TQLocale::setDefault(). If the string cannot be interpreted + according to the current locale, this function falls back + on the "C" locale. + + \code + bool ok; + double d; + + TQLocale::setDefault(TQLocale::C); + d = TQString( "1234,56" ).toDouble(&ok); // ok == false + d = TQString( "1234.56" ).toDouble(&ok); // ok == true, d == 1234.56 + + TQLocale::setDefault(TQLocale::German); + d = TQString( "1234,56" ).toDouble(&ok); // ok == true, d == 1234.56 + d = TQString( "1234.56" ).toDouble(&ok); // ok == true, d == 1234.56 + \endcode + + Due to the ambiguity between the decimal point and thousands group + separator in various locales, these functions do not handle + thousands group separators. If you need to convert such numbers, + use the corresponding function in TQLocale. + + \code + bool ok; + TQLocale::setDefault(TQLocale::C); + double d = TQString( "1,234,567.89" ).toDouble(&ok); // ok == false + \endcode + + \warning If the string contains trailing whitespace this function + will fail, and set \a *ok to false if \a ok is not 0. Leading + whitespace is ignored. + + \sa number() TQLocale::setDefault() TQLocale::toDouble() stripWhiteSpace() +*/ + +double TQString::toDouble( bool *ok ) const +{ + // If there is trailing whitespace, set ok to false but return the correct + // result anyway to preserve behavour of pervious versions of TQt + if (length() > 0 && unicode()[length() - 1].isSpace()) { + TQString tmp = stripWhiteSpace(); + if (ok != 0) + *ok = FALSE; + return tmp.toDouble(); + } + + // Try the default locale + bool my_ok; + TQLocale def_locale; + double result = def_locale.d->stringToDouble(*this, &my_ok, TQLocalePrivate::FailOnGroupSeparators); + if (my_ok) { + if (ok != 0) + *ok = TRUE; + return result; + } + + // If the default was not "C", try the "C" locale + if (def_locale.language() == TQLocale::C) { + if (ok != 0) + *ok = FALSE; + return 0.0; + } + + TQLocale c_locale(TQLocale::C); + return c_locale.d->stringToDouble(*this, ok, TQLocalePrivate::FailOnGroupSeparators); +} + +/*! + Returns the string converted to a \c float value. + + Returns 0.0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, \a *ok is set to + FALSE; otherwise \a *ok is set to TRUE. + + For information on how string-to-number functions in TQString handle + localized input, see toDouble(). + + \warning If the string contains trailing whitespace this function + will fail, settings \a *ok to false if \a ok is not 0. + Leading whitespace is ignored. + + \sa number() +*/ + +#define QT_MAX_FLOAT 3.4028234663852886e+38 + +float TQString::toFloat( bool *ok ) const +{ + bool myOk; + double d = toDouble(&myOk); + if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) { + if (ok != 0) + *ok = FALSE; + return 0.0; + } + if (ok != 0) + *ok = TRUE; + return (float) d; +} + +/*! + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. The returned string is in "C" locale. + + The base is 10 by default and must be between 2 and 36. + + \code + TQString string; + string = string.setNum( 1234 ); // string == "1234" + \endcode +*/ + +TQString &TQString::setNum( Q_LLONG n, int base ) +{ +#if defined(QT_CHECK_RANGE) + if ( base < 2 || base > 36 ) { + qWarning( "TQString::setNum: Invalid base %d", base ); + base = 10; + } +#endif + TQLocale locale(TQLocale::C); + *this = locale.d->longLongToString(n, -1, base); + return *this; +} + +/*! + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +TQString &TQString::setNum( Q_ULLONG n, int base ) +{ +#if defined(QT_CHECK_RANGE) + if ( base < 2 || base > 36 ) { + qWarning( "TQString::setNum: Invalid base %d", base ); + base = 10; + } +#endif + TQLocale locale(TQLocale::C); + *this = locale.d->unsLongLongToString(n, -1, base); + return *this; +} + +/*! + \fn TQString &TQString::setNum( long n, int base ) + + \overload +*/ +// ### 4.0: inline +TQString &TQString::setNum( long n, int base ) +{ + return setNum( (Q_LLONG)n, base ); +} + +/*! + \fn TQString &TQString::setNum( ulong n, int base ) + + \overload +*/ +// ### 4.0: inline +TQString &TQString::setNum( ulong n, int base ) +{ + return setNum( (Q_ULLONG)n, base ); +} + +/*! + \fn TQString &TQString::setNum( int n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \fn TQString &TQString::setNum( uint n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \fn TQString &TQString::setNum( short n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \fn TQString &TQString::setNum( ushort n, int base ) + + \overload + + Sets the string to the printed value of \a n in base \a base and + returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. +*/ + +/*! + \overload + + Sets the string to the printed value of \a n, formatted in format + \a f with precision \a prec, and returns a reference to the + string. + + The format \a f can be 'f', 'F', 'e', 'E', 'g' or 'G'. See \link + #arg-formats arg \endlink() for an explanation of the formats. +*/ + +TQString &TQString::setNum( double n, char f, int prec ) +{ + TQLocalePrivate::DoubleForm form = TQLocalePrivate::DFDecimal; + uint flags = 0; + + if (qIsUpper(f)) + flags = TQLocalePrivate::CapitalEorX; + f = qToLower(f); + + switch (f) { + case 'f': + form = TQLocalePrivate::DFDecimal; + break; + case 'e': + form = TQLocalePrivate::DFExponent; + break; + case 'g': + form = TQLocalePrivate::DFSignificantDigits; + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning( "TQString::setNum: Invalid format char '%c'", f ); +#endif + break; + } + + TQLocale locale(TQLocale::C); + *this = locale.d->doubleToString(n, prec, form, -1, flags); + return *this; +} + +/*! + \fn TQString &TQString::setNum( float n, char f, int prec ) + + \overload + + Sets the string to the printed value of \a n, formatted in format + \a f with precision \a prec, and returns a reference to the + string. + + The format \a f can be 'f', 'F', 'e', 'E', 'g' or 'G'. See \link + #arg-formats arg \endlink() for an explanation of the formats. +*/ + + +/*! + A convenience function that returns a string equivalent of the + number \a n to base \a base, which is 10 by default and must be + between 2 and 36. The returned string is in "C" locale. + + \code + long a = 63; + TQString str = TQString::number( a, 16 ); // str == "3f" + TQString str = TQString::number( a, 16 ).upper(); // str == "3F" + \endcode + + \sa setNum() +*/ +TQString TQString::number( long n, int base ) +{ + TQString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + \sa setNum() +*/ +TQString TQString::number( ulong n, int base ) +{ + TQString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + \sa setNum() +*/ +TQString TQString::number( Q_LLONG n, int base ) +{ + TQString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + \sa setNum() +*/ +TQString TQString::number( Q_ULLONG n, int base ) +{ + TQString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + \sa setNum() +*/ +TQString TQString::number( int n, int base ) +{ + TQString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + A convenience factory function that returns a string + representation of the number \a n to the base \a base, which is 10 + by default and must be between 2 and 36. + + \sa setNum() +*/ +TQString TQString::number( uint n, int base ) +{ + TQString s; + s.setNum( n, base ); + return s; +} + +/*! + \overload + + Argument \a n is formatted according to the \a f format specified, + which is \c g by default, and can be any of the following: + + \table + \header \i Format \i Meaning + \row \i \c e \i format as [-]9.9e[+|-]999 + \row \i \c E \i format as [-]9.9E[+|-]999 + \row \i \c f \i format as [-]9.9 + \row \i \c g \i use \c e or \c f format, whichever is the most concise + \row \i \c G \i use \c E or \c f format, whichever is the most concise + \endtable + + With 'e', 'E', and 'f', \a prec is the number of digits after the + decimal point. With 'g' and 'G', \a prec is the maximum number of + significant digits (trailing zeroes are omitted). + + \code + double d = 12.34; + TQString ds = TQString( "'E' format, precision 3, gives %1" ) + .arg( d, 0, 'E', 3 ); + // ds == "1.234E+001" + \endcode + + \sa setNum() + */ +TQString TQString::number( double n, char f, int prec ) +{ + TQString s; + s.setNum( n, f, prec ); + return s; +} + + +/*! \obsolete + + Sets the character at position \a index to \a c and expands the + string if necessary, filling with spaces. + + This method is redundant in TQt 3.x, because operator[] will expand + the string as necessary. +*/ + +void TQString::setExpand( uint index, TQChar c ) +{ + int spaces = index - d->len; + at(index) = c; + while (spaces-->0) + d->unicode[--index]=' '; +} + + +/*! + \fn const char* TQString::data() const + + \obsolete + + Returns a pointer to a '\0'-terminated classic C string. + + In TQt 1.x, this returned a char* allowing direct manipulation of the + string as a sequence of bytes. In TQt 2.x where TQString is a Unicode + string, char* conversion constructs a temporary string, and hence + direct character operations are meaningless. +*/ + +/*! + \fn bool TQString::operator!() const + + Returns TRUE if this is a null string; otherwise returns FALSE. + + \code + TQString name = getName(); + if ( !name ) + name = "Rodney"; + \endcode + + Note that if you say + + \code + TQString name = getName(); + if ( name ) + doSomethingWith(name); + \endcode + + It will call "operator const char*()", which is inefficent; you + may wish to define the macro \c QT_NO_ASCII_CAST when writing code + which you wish to remain Unicode-clean. + + When you want the above semantics, use: + + \code + TQString name = getName(); + if ( !name.isNull() ) + doSomethingWith(name); + \endcode + + \sa isEmpty() +*/ + + +/*! + \fn TQString& TQString::append( const TQString& str ) + + Appends \a str to the string and returns a reference to the + result. + + \code + string = "Test"; + string.append( "ing" ); // string == "Testing" + \endcode + + Equivalent to operator+=(). +*/ + +/*! + \fn TQString& TQString::append( char ch ) + + \overload + + Appends character \a ch to the string and returns a reference to + the result. + + Equivalent to operator+=(). +*/ + +/*! + \fn TQString& TQString::append( TQChar ch ) + + \overload + + Appends character \a ch to the string and returns a reference to + the result. + + Equivalent to operator+=(). +*/ + +/*! \fn TQString& TQString::append( const TQByteArray &str ) + \overload + + Appends \a str to the string and returns a reference to the result. + + Equivalent to operator+=(). +*/ + +/*! \fn TQString& TQString::append( const std::string &str ) + \overload + + Appends \a str to the string and returns a reference to the result. + + Equivalent to operator+=(). +*/ + +/*! \fn TQString& TQString::append( const char *str ) + \overload + + Appends \a str to the string and returns a reference to the result. + + Equivalent to operator+=(). +*/ + +/*! + Appends \a str to the string and returns a reference to the string. +*/ +TQString& TQString::operator+=( const TQString &str ) +{ + uint len1 = length(); + uint len2 = str.length(); + if ( len2 ) { + if ( isEmpty() ) { + operator=( str ); + } else { + grow( len1+len2 ); + memcpy( d->unicode+len1, str.unicode(), sizeof(TQChar)*len2 ); + } + } else if ( isNull() && !str.isNull() ) { // ## just for 1.x compat: + *this = fromLatin1( "" ); + } + return *this; +} + +#ifndef QT_NO_CAST_ASCII +TQString &TQString::operatorPlusEqHelper( const char *s, uint len2 ) +{ + if ( s ) { +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) + return operator+=( fromAscii( s, len2 ) ); +#endif + + uint len1 = length(); + if ( len2 == UINT_MAX ) + len2 = int(strlen( s )); + if ( len2 ) { + grow( len1 + len2 ); + TQChar* uc = d->unicode + len1; + while ( len2-- ) + *uc++ = *s++; + } else if ( isNull() ) { // ## just for 1.x compat: + *this = fromLatin1( "" ); + } + } + return *this; +} +#endif + +/*! + \overload + + Appends \a str to the string and returns a reference to the string. +*/ +#ifndef QT_NO_CAST_ASCII +TQString& TQString::operator+=( const char *str ) +{ + // ### TQt 4: make this function inline + return operatorPlusEqHelper( str ); +} +#endif + +/*! \overload + + Appends \a c to the string and returns a reference to the string. +*/ + +TQString &TQString::operator+=( TQChar c ) +{ + grow( length()+1 ); + d->unicode[length()-1] = c; + return *this; +} + +/*! + \overload + + Appends \a c to the string and returns a reference to the string. +*/ + +TQString &TQString::operator+=( char c ) +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) + return operator+=( fromAscii( &c, 1 ) ); +#endif + grow( length()+1 ); + d->unicode[length()-1] = c; + return *this; +} + +/*! + \fn TQString &TQString::operator+=( const TQByteArray &str ) + \overload + + Appends \a str to the string and returns a reference to the string. +*/ + +/*! + \fn TQString &TQString::operator+=( const std::string &str ) + \overload + + Appends \a str to the string and returns a reference to the string. +*/ + +/*! + \fn char TQChar::latin1() const + + Returns the Latin-1 value of this character, or 0 if it + cannot be represented in Latin-1. +*/ + + +/*! + Returns a Latin-1 representation of the string. The + returned value is undefined if the string contains non-Latin-1 + characters. If you want to convert strings into formats other than + Unicode, see the TQTextCodec classes. + + This function is mainly useful for boot-strapping legacy code to + use Unicode. + + The result remains valid so long as one unmodified copy of the + source string exists. + + \sa fromLatin1(), ascii(), utf8(), local8Bit() +*/ +const char* TQString::latin1() const +{ + if ( !d->ascii || !d->islatin1 ) { + delete [] d->ascii; + d->ascii = unicodeToLatin1( d->unicode, d->len ); + d->islatin1 = TRUE; + } + return d->ascii; +} + +/*! + Returns an 8-bit ASCII representation of the string. + + If a codec has been set using TQTextCodec::codecForCStrings(), + it is used to convert Unicode to 8-bit char. Otherwise, this function + does the same as latin1(). + + \sa fromAscii(), latin1(), utf8(), local8Bit() +*/ +const char* TQString::ascii() const +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) { + if ( !d->ascii || d->islatin1 ) { + delete [] d->ascii; + if (d->unicode) { + TQCString s = TQTextCodec::codecForCStrings()->fromUnicode( *this ); + d->ascii = new char[s.length() + 1]; + memcpy(d->ascii, s.data(), s.length() + 1); + } else { + d->ascii = 0; + } + d->islatin1 = FALSE; + } + return d->ascii; + } +#endif // QT_NO_TEXTCODEC + return latin1(); +} + +/*! + Returns the string encoded in UTF-8 format. + + See TQTextCodec for more diverse coding/decoding of Unicode strings. + + \sa fromUtf8(), ascii(), latin1(), local8Bit() +*/ +TQCString TQString::utf8() const +{ + int l = length(); + int rlen = l*3+1; + TQCString rstr(rlen); + uchar* cursor = (uchar*)rstr.data(); + const TQChar *ch = d->unicode; + for (int i=0; i < l; i++) { + uint u = ch->unicode(); + if ( u < 0x80 ) { + *cursor++ = (uchar)u; + } else { + if ( u < 0x0800 ) { + *cursor++ = 0xc0 | ((uchar) (u >> 6)); + } else { + if (u >= 0xd800 && u < 0xdc00 && i < l-1) { + unsigned short low = ch[1].unicode(); + if (low >= 0xdc00 && low < 0xe000) { + ++ch; + ++i; + u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + } + } + if (u > 0xffff) { + // if people are working in utf8, but strings are encoded in eg. latin1, the resulting + // name might be invalid utf8. This and the corresponding code in fromUtf8 takes care + // we can handle this without loosing information. This can happen with latin filenames + // and a utf8 locale under Unix. + if (u > 0x10fe00 && u < 0x10ff00) { + *cursor++ = (u - 0x10fe00); + ++ch; + continue; + } else { + *cursor++ = 0xf0 | ((uchar) (u >> 18)); + *cursor++ = 0x80 | ( ((uchar) (u >> 12)) & 0x3f); + } + } else { + *cursor++ = 0xe0 | ((uchar) (u >> 12)); + } + *cursor++ = 0x80 | ( ((uchar) (u >> 6)) & 0x3f); + } + *cursor++ = 0x80 | ((uchar) (u&0x3f)); + } + ++ch; + } + rstr.truncate( cursor - (uchar*)rstr.data() ); + return rstr; +} + +static TQChar *addOne(TQChar *qch, TQString &str) +{ + long sidx = qch - str.unicode(); + str.setLength(str.length()+1); + return (TQChar *)str.unicode() + sidx; +} + +/*! + Returns the Unicode string decoded from the first \a len + bytes of \a utf8, ignoring the rest of \a utf8. If \a len is + -1 then the length of \a utf8 is used. If \a len is bigger than + the length of \a utf8 then it will use the length of \a utf8. + + \code + TQString str = TQString::fromUtf8( "123456789", 5 ); + // str == "12345" + \endcode + + See TQTextCodec for more diverse coding/decoding of Unicode strings. +*/ +TQString TQString::fromUtf8( const char* utf8, int len ) +{ + if ( !utf8 ) + return TQString::null; + + int slen = 0; + if (len >= 0) { + while (slen < len && utf8[slen]) + slen++; + } else { + slen = int(strlen(utf8)); + } + len = len < 0 ? slen : TQMIN(slen, len); + TQString result; + result.setLength( len ); // worst case + TQChar *qch = (TQChar *)result.unicode(); + uint uc = 0; + uint min_uc = 0; + int need = 0; + int error = -1; + uchar ch; + for (int i=0; i<len; i++) { + ch = utf8[i]; + if (need) { + if ( (ch&0xc0) == 0x80 ) { + uc = (uc << 6) | (ch & 0x3f); + need--; + if ( !need ) { + if (uc > 0xffff) { + // surrogate pair + uc -= 0x10000; + unsigned short high = uc/0x400 + 0xd800; + unsigned short low = uc%0x400 + 0xdc00; + *qch++ = TQChar(high); + *qch++ = TQChar(low); + } else if (uc < min_uc || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) { + // overlong seqence, UTF16 surrogate or BOM + i = error; + qch = addOne(qch, result); + *qch++ = TQChar(0xdbff); + *qch++ = TQChar(0xde00+((uchar)utf8[i])); + } else { + *qch++ = uc; + } + } + } else { + // See TQString::utf8() for explanation. + // + // The surrogate below corresponds to a Unicode value of (0x10fe00+ch) which + // is in one of the private use areas of Unicode. + i = error; + qch = addOne(qch, result); + *qch++ = TQChar(0xdbff); + *qch++ = TQChar(0xde00+((uchar)utf8[i])); + need = 0; + } + } else { + if ( ch < 128 ) { + *qch++ = ch; + } else if ((ch & 0xe0) == 0xc0) { + uc = ch & 0x1f; + need = 1; + error = i; + min_uc = 0x80; + } else if ((ch & 0xf0) == 0xe0) { + uc = ch & 0x0f; + need = 2; + error = i; + min_uc = 0x800; + } else if ((ch&0xf8) == 0xf0) { + uc = ch & 0x07; + need = 3; + error = i; + min_uc = 0x10000; + } else { + // Error + qch = addOne(qch, result); + *qch++ = TQChar(0xdbff); + *qch++ = TQChar(0xde00+((uchar)utf8[i])); + } + } + } + if (need) { + // we have some invalid characters remaining we need to add to the string + for (int i = error; i < len; ++i) { + qch = addOne(qch, result); + *qch++ = TQChar(0xdbff); + *qch++ = TQChar(0xde00+((uchar)utf8[i])); + } + } + + result.truncate( qch - result.unicode() ); + return result; +} + +/*! + Returns the Unicode string decoded from the first \a len + bytes of \a ascii, ignoring the rest of \a ascii. If \a len + is -1 then the length of \a ascii is used. If \a len is bigger + than the length of \a ascii then it will use the length of \a + ascii. + + If a codec has been set using TQTextCodec::codecForCStrings(), + it is used to convert the string from 8-bit characters to Unicode. + Otherwise, this function does the same as fromLatin1(). + + This is the same as the TQString(const char*) constructor, but you + can make that constructor invisible if you compile with the define + \c QT_NO_CAST_ASCII, in which case you can explicitly create a + TQString from 8-bit ASCII text using this function. + + \code + TQString str = TQString::fromAscii( "123456789", 5 ); + // str == "12345" + \endcode + */ +TQString TQString::fromAscii( const char* ascii, int len ) +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) { + if ( !ascii ) + return TQString::null; + if ( len < 0 ) + len = (int)strlen( ascii ); + if ( len == 0 || *ascii == '\0' ) + return TQString::fromLatin1( "" ); + return TQTextCodec::codecForCStrings()->toUnicode( ascii, len ); + } +#endif + return fromLatin1( ascii, len ); +} + + +/*! + Returns the Unicode string decoded from the first \a len + bytes of \a chars, ignoring the rest of \a chars. If \a len + is -1 then the length of \a chars is used. If \a len is bigger + than the length of \a chars then it will use the length of \a + chars. + + \sa fromAscii() +*/ +TQString TQString::fromLatin1( const char* chars, int len ) +{ + uint l; + TQChar *uc; + if ( len < 0 ) + len = -1; + uc = internalLatin1ToUnicode( chars, &l, len ); + return TQString( new TQStringData(uc, l, l), TRUE ); +} + +/*! + \fn const TQChar* TQString::unicode() const + + Returns the Unicode representation of the string. The result + remains valid until the string is modified. +*/ + +/*! + Returns the string encoded in a locale-specific format. On X11, + this is the TQTextCodec::codecForLocale(). On Windows, it is a + system-defined encoding. On Mac OS X, this always uses UTF-8 as + the encoding. + + See TQTextCodec for more diverse coding/decoding of Unicode + strings. + + \sa fromLocal8Bit(), ascii(), latin1(), utf8() +*/ + +TQCString TQString::local8Bit() const +{ +#ifdef QT_NO_TEXTCODEC + return latin1(); +#else +#ifdef Q_WS_X11 + TQTextCodec* codec = TQTextCodec::codecForLocale(); + return codec + ? codec->fromUnicode(*this) + : TQCString(latin1()); +#endif +#if defined( Q_WS_MACX ) + return utf8(); +#endif +#if defined( Q_WS_MAC9 ) + return TQCString(latin1()); //I'm evil.. +#endif +#ifdef Q_WS_WIN + return isNull() ? TQCString("") : qt_winTQString2MB( *this ); +#endif +#ifdef Q_WS_QWS + return utf8(); // ### if there is any 8 bit format supported? +#endif +#endif +} + +/*! + Returns the Unicode string decoded from the first \a len + bytes of \a local8Bit, ignoring the rest of \a local8Bit. If + \a len is -1 then the length of \a local8Bit is used. If \a len is + bigger than the length of \a local8Bit then it will use the length + of \a local8Bit. + + \code + TQString str = TQString::fromLocal8Bit( "123456789", 5 ); + // str == "12345" + \endcode + + \a local8Bit is assumed to be encoded in a locale-specific format. + + See TQTextCodec for more diverse coding/decoding of Unicode strings. +*/ +TQString TQString::fromLocal8Bit( const char* local8Bit, int len ) +{ +#ifdef QT_NO_TEXTCODEC + return fromLatin1( local8Bit, len ); +#else + + if ( !local8Bit ) + return TQString::null; +#ifdef Q_WS_X11 + TQTextCodec* codec = TQTextCodec::codecForLocale(); + if ( len < 0 ) + len = strlen( local8Bit ); + return codec + ? codec->toUnicode( local8Bit, len ) + : fromLatin1( local8Bit, len ); +#endif +#if defined( Q_WS_MAC ) + return fromUtf8(local8Bit,len); +#endif +// Should this be OS_WIN32? +#ifdef Q_WS_WIN + if ( len >= 0 ) { + TQCString s(local8Bit,len+1); + return qt_winMB2TQString(s); + } + return qt_winMB2TQString( local8Bit ); +#endif +#ifdef Q_WS_QWS + return fromUtf8(local8Bit,len); +#endif +#endif // QT_NO_TEXTCODEC +} + +/*! + \fn TQString::operator const char *() const + + Returns ascii(). Be sure to see the warnings documented in the + ascii() function. Note that for new code which you wish to be + strictly Unicode-clean, you can define the macro \c + QT_NO_ASCII_CAST when compiling your code to hide this function so + that automatic casts are not done. This has the added advantage + that you catch the programming error described in operator!(). +*/ + +/*! + \fn TQString::operator std::string() const + + Returns ascii() as a std::string. + + \warning The function may cause an application to crash if a static C run-time is in use. + This can happen in Microsoft Visual C++ if TQt is configured as single-threaded. A safe + alternative is to call ascii() directly and construct a std::string manually. +*/ + +/*! + Returns the TQString as a zero terminated array of unsigned shorts + if the string is not null; otherwise returns zero. + + The result remains valid so long as one unmodified + copy of the source string exists. +*/ +const unsigned short *TQString::ucs2() const +{ + if ( ! d->unicode ) + return 0; + unsigned int len = d->len; + if ( d->maxl < len + 1 ) { + // detach, grow or shrink + uint newMax = computeNewMax( len + 1 ); + TQChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + if ( nd ) { + if ( d->unicode ) + memcpy( nd, d->unicode, sizeof(TQChar)*len ); + ((TQString *)this)->deref(); + ((TQString *)this)->d = new TQStringData( nd, len, newMax ); + } + } + d->unicode[len] = 0; + return (unsigned short *) d->unicode; +} + +/*! + Constructs a string that is a deep copy of \a str, interpreted as a + UCS2 encoded, zero terminated, Unicode string. + + If \a str is 0, then a null string is created. + + \sa isNull() +*/ +TQString TQString::fromUcs2( const unsigned short *str ) +{ + if ( !str ) { + return TQString::null; + } else { + int length = 0; + while ( str[length] != 0 ) + length++; + TQChar* uc = QT_ALLOC_QCHAR_VEC( length ); + memcpy( uc, str, length*sizeof(TQChar) ); + return TQString( new TQStringData( uc, length, length ), TRUE ); + } +} + +/*! + \fn TQChar TQString::at( uint ) const + + Returns the character at index \a i, or 0 if \a i is beyond the + length of the string. + + \code + const TQString string( "abcdefgh" ); + TQChar ch = string.at( 4 ); + // ch == 'e' + \endcode + + If the TQString is not const (i.e. const TQString) or const& (i.e. + const TQString &), then the non-const overload of at() will be used + instead. +*/ + +/*! + \fn TQChar TQString::constref(uint i) const + + Returns the TQChar at index \a i by value. + + Equivalent to at(\a i). + + \sa ref() +*/ + +/*! + \fn TQChar& TQString::ref(uint i) + + Returns the TQChar at index \a i by reference, expanding the string + with TQChar::null if necessary. The resulting reference can be + assigned to, or otherwise used immediately, but becomes invalid + once furher modifications are made to the string. + + \code + TQString string("ABCDEF"); + TQChar ch = string.ref( 3 ); // ch == 'D' + \endcode + + \sa constref() +*/ + +/*! + \fn TQChar TQString::operator[]( int ) const + + Returns the character at index \a i, or TQChar::null if \a i is + beyond the length of the string. + + If the TQString is not const (i.e., const TQString) or const\& + (i.e., const TQString\&), then the non-const overload of operator[] + will be used instead. +*/ + +/*! + \fn TQCharRef TQString::operator[]( int ) + + \overload + + The function returns a reference to the character at index \a i. + The resulting reference can then be assigned to, or used + immediately, but it will become invalid once further modifications + are made to the original string. + + If \a i is beyond the length of the string then the string is + expanded with TQChar::nulls, so that the TQCharRef references a + valid (null) character in the string. + + The TQCharRef internal class can be used much like a constant + TQChar, but if you assign to it, you change the original string + (which will detach itself because of TQString's copy-on-write + semantics). You will get compilation errors if you try to use the + result as anything but a TQChar. +*/ + +/*! + \fn TQCharRef TQString::at( uint i ) + + \overload + + The function returns a reference to the character at index \a i. + The resulting reference can then be assigned to, or used + immediately, but it will become invalid once further modifications + are made to the original string. + + If \a i is beyond the length of the string then the string is + expanded with TQChar::null. +*/ + +/* + Internal chunk of code to handle the + uncommon cases of at() above. +*/ +void TQString::subat( uint i ) +{ + uint olen = d->len; + if ( i >= olen ) { + setLength( i+1 ); // i is index; i+1 is needed length + for ( uint j=olen; j<=i; j++ ) + d->unicode[j] = TQChar::null; + } else { + // Just be sure to detach + real_detach(); + } +} + + +/*! + Resizes the string to \a len characters and copies \a unicode into + the string. If \a unicode is 0, nothing is copied, but the + string is still resized to \a len. If \a len is zero, then the + string becomes a \link isNull() null\endlink string. + + \sa setLatin1(), isNull() +*/ + +TQString& TQString::setUnicode( const TQChar *unicode, uint len ) +{ + if ( len == 0 ) { // set to null string + if ( d != shared_null ) { // beware of nullstring being set to nullstring + deref(); + d = shared_null ? shared_null : makeSharedNull(); + d->ref(); + } + } else if ( d->count != 1 || len > d->maxl || + ( len * 4 < d->maxl && d->maxl > 4 ) ) { + // detach, grown or shrink + uint newMax = computeNewMax( len ); + TQChar* nd = QT_ALLOC_QCHAR_VEC( newMax ); + if ( unicode ) + memcpy( nd, unicode, sizeof(TQChar)*len ); + deref(); + d = new TQStringData( nd, len, newMax ); + } else { + d->len = len; + d->setDirty(); + if ( unicode ) + memcpy( d->unicode, unicode, sizeof(TQChar)*len ); + } + return *this; +} + +/*! + Resizes the string to \a len characters and copies \a + unicode_as_ushorts into the string (on some X11 client platforms + this will involve a byte-swapping pass). + + If \a unicode_as_ushorts is 0, nothing is copied, but the string + is still resized to \a len. If \a len is zero, the string becomes + a \link isNull() null\endlink string. + + \sa setLatin1(), isNull() +*/ +TQString& TQString::setUnicodeCodes( const ushort* unicode_as_ushorts, uint len ) +{ + return setUnicode((const TQChar*)unicode_as_ushorts, len); +} + + +/*! + Sets this string to \a str, interpreted as a classic 8-bit ASCII C + string. If \a len is -1 (the default), then it is set to + strlen(str). + + If \a str is 0 a null string is created. If \a str is "", an empty + string is created. + + \sa isNull(), isEmpty() +*/ + +TQString &TQString::setAscii( const char *str, int len ) +{ +#ifndef QT_NO_TEXTCODEC + if ( TQTextCodec::codecForCStrings() ) { + *this = TQString::fromAscii( str, len ); + return *this; + } +#endif // QT_NO_TEXTCODEC + return setLatin1( str, len ); +} + +/*! + Sets this string to \a str, interpreted as a classic Latin-1 C + string. If \a len is -1 (the default), then it is set to + strlen(str). + + If \a str is 0 a null string is created. If \a str is "", an empty + string is created. + + \sa isNull(), isEmpty() +*/ + +TQString &TQString::setLatin1( const char *str, int len ) +{ + if ( str == 0 ) + return setUnicode(0,0); + if ( len < 0 ) + len = int(strlen( str )); + if ( len == 0 ) { // won't make a null string + *this = TQString::fromLatin1( "" ); + } else { + setUnicode( 0, len ); // resize but not copy + TQChar *p = d->unicode; + while ( len-- ) + *p++ = *str++; + } + return *this; +} + +/*! \internal + */ +void TQString::checkSimpleText() const +{ + TQChar *p = d->unicode; + TQChar *end = p + d->len; + while ( p < end ) { + ushort uc = p->unicode(); + // sort out regions of complex text formatting + if ( uc > 0x058f && ( uc < 0x1100 || uc > 0xfb0f ) ) { + d->issimpletext = FALSE; + return; + } + p++; + } + d->issimpletext = TRUE; +} + +/*! \fn bool TQString::simpleText() const + \internal +*/ + +/*! \internal + */ +bool TQString::isRightToLeft() const +{ + int len = length(); + TQChar *p = d->unicode; + while ( len-- ) { + switch( ::direction( *p ) ) + { + case TQChar::DirL: + case TQChar::DirLRO: + case TQChar::DirLRE: + return FALSE; + case TQChar::DirR: + case TQChar::DirAL: + case TQChar::DirRLO: + case TQChar::DirRLE: + return TRUE; + default: + break; + } + ++p; + } + return FALSE; +} + + +/*! + \fn int TQString::compare( const TQString & s1, const TQString & s2 ) + + Lexically compares \a s1 with \a s2 and returns an integer less + than, equal to, or greater than zero if \a s1 is less than, equal + to, or greater than \a s2. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + TQString::localeAwareCompare(). + + \code + int a = TQString::compare( "def", "abc" ); // a > 0 + int b = TQString::compare( "abc", "def" ); // b < 0 + int c = TQString::compare( "abc", "abc" ); // c == 0 + \endcode +*/ + +/*! + \overload + + Lexically compares this string with \a s and returns an integer + less than, equal to, or greater than zero if it is less than, equal + to, or greater than \a s. +*/ +int TQString::compare( const TQString& s ) const +{ + return ucstrcmp( *this, s ); +} + +/*! + \fn int TQString::localeAwareCompare( const TQString & s1, const TQString & s2 ) + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + + \sa TQString::compare() TQTextCodec::locale() +*/ + +/*! + \overload + + Compares this string with \a s. +*/ + +#if !defined(CSTR_LESS_THAN) +#define CSTR_LESS_THAN 1 +#define CSTR_ETQUAL 2 +#define CSTR_GREATER_THAN 3 +#endif + +int TQString::localeAwareCompare( const TQString& s ) const +{ + // do the right thing for null and empty + if ( isEmpty() || s.isEmpty() ) + return compare( s ); + +#if defined(Q_WS_WIN) + int res; + QT_WA( { + const TCHAR* s1 = (TCHAR*)ucs2(); + const TCHAR* s2 = (TCHAR*)s.ucs2(); + res = CompareStringW( LOCALE_USER_DEFAULT, 0, s1, length(), s2, s.length() ); + } , { + TQCString s1 = local8Bit(); + TQCString s2 = s.local8Bit(); + res = CompareStringA( LOCALE_USER_DEFAULT, 0, s1.data(), s1.length(), s2.data(), s2.length() ); + } ); + + switch ( res ) { + case CSTR_LESS_THAN: + return -1; + case CSTR_GREATER_THAN: + return 1; + default: + return 0; + } +#elif defined(Q_WS_MACX) + int delta = 0; +#if !defined(QT_NO_TEXTCODEC) + TQTextCodec *codec = TQTextCodec::codecForLocale(); + if (codec) + delta = strcoll(codec->fromUnicode(*this), codec->fromUnicode(s)); + if (delta == 0) +#endif + delta = ucstrcmp(*this, s); + return delta; +#elif defined(Q_WS_X11) + // declared in <string.h> + int delta = strcoll( local8Bit(), s.local8Bit() ); + if ( delta == 0 ) + delta = ucstrcmp( *this, s ); + return delta; +#else + return ucstrcmp( *this, s ); +#endif +} + +bool operator==( const TQString &s1, const TQString &s2 ) +{ + if ( s1.unicode() == s2.unicode() ) + return TRUE; + return (s1.length() == s2.length()) && s1.isNull() == s2.isNull() && + (memcmp((char*)s1.unicode(),(char*)s2.unicode(), + s1.length()*sizeof(TQChar)) == 0 ); +} + +bool operator!=( const TQString &s1, const TQString &s2 ) +{ return !(s1==s2); } + +bool operator<( const TQString &s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) < 0; } + +bool operator<=( const TQString &s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) <= 0; } + +bool operator>( const TQString &s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) > 0; } + +bool operator>=( const TQString &s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) >= 0; } + + +bool operator==( const TQString &s1, const char *s2 ) +{ + if ( !s2 ) + return s1.isNull(); + + int len = s1.length(); + const TQChar *uc = s1.unicode(); + while ( len ) { + if ( !(*s2) || uc->unicode() != (uchar) *s2 ) + return FALSE; + ++uc; + ++s2; + --len; + } + return !*s2; +} + +bool operator==( const char *s1, const TQString &s2 ) +{ return (s2 == s1); } + +bool operator!=( const TQString &s1, const char *s2 ) +{ return !(s1==s2); } + +bool operator!=( const char *s1, const TQString &s2 ) +{ return !(s1==s2); } + +bool operator<( const TQString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) < 0; } + +bool operator<( const char *s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) < 0; } + +bool operator<=( const TQString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) <= 0; } + +bool operator<=( const char *s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) <= 0; } + +bool operator>( const TQString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) > 0; } + +bool operator>( const char *s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) > 0; } + +bool operator>=( const TQString &s1, const char *s2 ) +{ return ucstrcmp(s1,s2) >= 0; } + +bool operator>=( const char *s1, const TQString &s2 ) +{ return ucstrcmp(s1,s2) >= 0; } + + +/***************************************************************************** + Documentation for TQString related functions + *****************************************************************************/ + +/*! + \fn bool operator==( const TQString &s1, const TQString &s2 ) + + \relates TQString + + Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) == 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator==( const TQString &s1, const char *s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) == 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator==( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) == 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator!=( const TQString &s1, const TQString &s2 ) + + \relates TQString + + Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator!=( const TQString &s1, const char *s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator!=( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is not equal to \a s2; otherwise returns FALSE. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) != 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator<( const TQString &s1, const char *s2 ) + + \relates TQString + + Returns TRUE if \a s1 is lexically less than \a s2; otherwise returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \< 0. +*/ + +/*! + \fn bool operator<( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is lexically less than \a s2; otherwise returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \< 0. +*/ + +/*! + \fn bool operator<=( const TQString &s1, const char *s2 ) + + \relates TQString + + Returns TRUE if \a s1 is lexically less than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1,\a s2) \<= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator<=( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is lexically less than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) \<= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator>( const TQString &s1, const char *s2 ) + + \relates TQString + + Returns TRUE if \a s1 is lexically greater than \a s2; otherwise + returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \> 0. +*/ + +/*! + \fn bool operator>( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is lexically greater than \a s2; otherwise + returns FALSE. + The comparison is case sensitive. + + Equivalent to compare(\a s1, \a s2) \> 0. +*/ + +/*! + \fn bool operator>=( const TQString &s1, const char *s2 ) + + \relates TQString + + Returns TRUE if \a s1 is lexically greater than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) \>= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn bool operator>=( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns TRUE if \a s1 is lexically greater than or equal to \a s2; + otherwise returns FALSE. + The comparison is case sensitive. + Note that a null string is not equal to a not-null empty string. + + Equivalent to compare(\a s1, \a s2) \>= 0. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn const TQString operator+( const TQString &s1, const TQString &s2 ) + + \relates TQString + + Returns a string which is the result of concatenating the string + \a s1 and the string \a s2. + + Equivalent to \a {s1}.append(\a s2). +*/ + +/*! + \fn const TQString operator+( const TQString &s1, const char *s2 ) + + \overload + \relates TQString + + Returns a string which is the result of concatenating the string + \a s1 and character \a s2. + + Equivalent to \a {s1}.append(\a s2). +*/ + +/*! + \fn const TQString operator+( const char *s1, const TQString &s2 ) + + \overload + \relates TQString + + Returns a string which is the result of concatenating the + character \a s1 and string \a s2. +*/ + +/*! + \fn const TQString operator+( const TQString &s, char c ) + + \overload + \relates TQString + + Returns a string which is the result of concatenating the string + \a s and character \a c. + + Equivalent to \a {s}.append(\a c). +*/ + +/*! + \fn const TQString operator+( char c, const TQString &s ) + + \overload + \relates TQString + + Returns a string which is the result of concatenating the + character \a c and string \a s. + + Equivalent to \a {s}.prepend(\a c). +*/ + + +/***************************************************************************** + TQString stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \relates TQString + + Writes the string \a str to the stream \a s. + + See also \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ + +TQDataStream &operator<<( TQDataStream &s, const TQString &str ) +{ + if ( s.version() == 1 ) { + TQCString l( str.latin1() ); + s << l; + } + else { + int byteOrder = s.byteOrder(); + const TQChar* ub = str.unicode(); + if ( ub || s.version() < 3 ) { + static const uint auto_size = 1024; + char t[auto_size]; + char *b; + if ( str.length()*sizeof(TQChar) > auto_size ) { + b = new char[str.length()*sizeof(TQChar)]; + } else { + b = t; + } + int l = str.length(); + char *c=b; + while ( l-- ) { + if ( byteOrder == TQDataStream::BigEndian ) { + *c++ = (char)ub->row(); + *c++ = (char)ub->cell(); + } else { + *c++ = (char)ub->cell(); + *c++ = (char)ub->row(); + } + ub++; + } + s.writeBytes( b, sizeof(TQChar)*str.length() ); + if ( str.length()*sizeof(TQChar) > auto_size ) + delete [] b; + } else { + // write null marker + s << (Q_UINT32)0xffffffff; + } + } + return s; +} + +/*! + \relates TQString + + Reads a string from the stream \a s into string \a str. + + See also \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ + +TQDataStream &operator>>( TQDataStream &s, TQString &str ) +{ +#ifdef QT_QSTRING_UCS_4 +#if defined(Q_CC_GNU) +#warning "operator>> not working properly" +#endif +#endif + if ( s.version() == 1 ) { + TQCString l; + s >> l; + str = TQString( l ); + } + else { + Q_UINT32 bytes = 0; + s >> bytes; // read size of string + if ( bytes == 0xffffffff ) { // null string + str = TQString::null; + } else if ( bytes > 0 ) { // not empty + int byteOrder = s.byteOrder(); + str.setLength( bytes/2 ); + TQChar* ch = str.d->unicode; + static const uint auto_size = 1024; + char t[auto_size]; + char *b; + if ( bytes > auto_size ) { + b = new char[bytes]; + } else { + b = t; + } + s.readRawBytes( b, bytes ); + int bt = bytes/2; + char *oldb = b; + while ( bt-- ) { + if ( byteOrder == TQDataStream::BigEndian ) + *ch++ = (ushort) (((ushort)b[0])<<8) | (uchar)b[1]; + else + *ch++ = (ushort) (((ushort)b[1])<<8) | (uchar)b[0]; + b += 2; + } + if ( bytes > auto_size ) + delete [] oldb; + } else { + str = ""; + } + } + return s; +} +#endif // QT_NO_DATASTREAM + +/***************************************************************************** + TQConstString member functions + *****************************************************************************/ + +/*! + \class TQConstString qstring.h + \reentrant + \ingroup text + \brief The TQConstString class provides string objects using constant Unicode data. + + In order to minimize copying, highly optimized applications can + use TQConstString to provide a TQString-compatible object from + existing Unicode data. It is then the programmer's responsibility + to ensure that the Unicode data exists for the entire lifetime of + the TQConstString object. + + A TQConstString is created with the TQConstString constructor. The + string held by the object can be obtained by calling string(). +*/ + +/*! + Constructs a TQConstString that uses the first \a length Unicode + characters in the array \a unicode. Any attempt to modify copies + of the string will cause it to create a copy of the data, thus it + remains forever unmodified. + + The data in \a unicode is not copied. The caller must be able to + guarantee that \a unicode will not be deleted or modified. +*/ +TQConstString::TQConstString( const TQChar* unicode, uint length ) : + TQString( new TQStringData( (TQChar*)unicode, length, length ), TRUE ) +{ +} + +/*! + Destroys the TQConstString, creating a copy of the data if other + strings are still using it. +*/ +TQConstString::~TQConstString() +{ + if ( d->count > 1 ) { + TQChar* cp = QT_ALLOC_QCHAR_VEC( d->len ); + memcpy( cp, d->unicode, d->len*sizeof(TQChar) ); + d->unicode = cp; + } else { + d->unicode = 0; + } + + // The original d->unicode is now unlinked. +} + +/*! + \fn const TQString& TQConstString::string() const + + Returns a constant string referencing the data passed during + construction. +*/ + +/*! + Returns TRUE if the string starts with \a s; otherwise returns + FALSE. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + \code + TQString str( "Bananas" ); + str.startsWith( "Ban" ); // returns TRUE + str.startsWith( "Car" ); // returns FALSE + \endcode + + \sa endsWith() +*/ +bool TQString::startsWith( const TQString& s, bool cs ) const +{ + if ( isNull() ) + return s.isNull(); + if ( s.length() > length() ) + return FALSE; + if ( cs ) { + return memcmp((char*)d->unicode, (char*)s.d->unicode, s.length()*sizeof(TQChar)) == 0; + } else { + for ( int i = 0; i < (int) s.length(); i++ ) { + if ( ::lower(d->unicode[i]) != ::lower(s.d->unicode[i]) ) + return FALSE; + } + } + return TRUE; +} + +bool TQString::startsWith( const TQString& s ) const +{ + return startsWith( s, TRUE ); +} + +/*! + Returns TRUE if the string ends with \a s; otherwise returns + FALSE. + + If \a cs is TRUE (the default), the search is case sensitive; + otherwise the search is case insensitive. + + \code + TQString str( "Bananas" ); + str.endsWith( "anas" ); // returns TRUE + str.endsWith( "pple" ); // returns FALSE + \endcode + + \sa startsWith() +*/ +bool TQString::endsWith( const TQString& s, bool cs ) const +{ + if ( isNull() ) + return s.isNull(); + int pos = length() - s.length(); + if ( pos < 0 ) + return FALSE; + if ( cs ) { + return memcmp((char*)&d->unicode[pos], (char*)s.d->unicode, s.length()*sizeof(TQChar)) == 0; + } else { + for ( int i = 0; i < (int) s.length(); i++ ) { + if ( ::lower(d->unicode[pos + i]) != ::lower(s.d->unicode[i]) ) + return FALSE; + } + } + return TRUE; +} + +bool TQString::endsWith( const TQString& s ) const +{ + return endsWith( s, TRUE ); +} + +/*! \fn void TQString::detach() + If the string does not share its data with another TQString instance, + nothing happens; otherwise the function creates a new, unique copy of + this string. This function is called whenever the string is modified. The + implicit sharing mechanism is implemented this way. +*/ + +#if defined(Q_OS_WIN32) + +#include <windows.h> + +/*! + \obsolete + + Returns a static Windows TCHAR* from a TQString, adding NUL if \a + addnul is TRUE. + + The lifetime of the return value is until the next call to this function, + or until the last copy of str is deleted, whatever comes first. + + Use ucs2() instead. +*/ +const void* qt_winTchar(const TQString& str, bool) +{ + // So that the return value lives long enough. + static TQString str_cache; + str_cache = str; +#ifdef UNICODE + return str_cache.ucs2(); +#else + return str_cache.latin1(); +#endif +} + +/*! + Makes a new '\0'-terminated Windows TCHAR* from a TQString. +*/ +void* qt_winTchar_new(const TQString& str) +{ + if ( str.isNull() ) + return 0; + int l = str.length()+1; + TCHAR *tc = new TCHAR[ l ]; +#ifdef UNICODE + memcpy( tc, str.ucs2(), sizeof(TCHAR)*l ); +#else + memcpy( tc, str.latin1(), sizeof(TCHAR)*l ); +#endif + return tc; +} + +/*! + Makes a TQString from a Windows TCHAR*. +*/ +TQString qt_winTQString(void* tc) +{ +#ifdef UNICODE + return TQString::fromUcs2( (ushort*)tc ); +#else + return TQString::fromLatin1( (TCHAR *)tc ); +#endif +} + +TQCString qt_winTQString2MB( const TQString& s, int uclen ) +{ + if ( uclen < 0 ) + uclen = s.length(); + if ( s.isNull() ) + return TQCString(); + if ( uclen == 0 ) + return TQCString(""); + BOOL used_def; + TQCString mb(4096); + int len; + while ( !(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)s.unicode(), uclen, + mb.data(), mb.size()-1, 0, &used_def)) ) + { + int r = GetLastError(); + if ( r == ERROR_INSUFFICIENT_BUFFER ) { + mb.resize(1+WideCharToMultiByte( CP_ACP, 0, + (const WCHAR*)s.unicode(), uclen, + 0, 0, 0, &used_def)); + // and try again... + } else { +#ifndef QT_NO_DEBUG + // Fail. + qWarning("WideCharToMultiByte cannot convert multibyte text (error %d): %s (UTF8)", + r, s.utf8().data()); +#endif + break; + } + } + mb[len]='\0'; + return mb; +} + +// WATCH OUT: mblen must include the NUL (or just use -1) +TQString qt_winMB2TQString( const char* mb, int mblen ) +{ + if ( !mb || !mblen ) + return TQString::null; + const int wclen_auto = 4096; + WCHAR wc_auto[wclen_auto]; + int wclen = wclen_auto; + WCHAR *wc = wc_auto; + int len; + while ( !(len=MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, + mb, mblen, wc, wclen )) ) + { + int r = GetLastError(); + if ( r == ERROR_INSUFFICIENT_BUFFER ) { + if ( wc != wc_auto ) { + qWarning("Size changed in MultiByteToWideChar"); + break; + } else { + wclen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, + mb, mblen, 0, 0 ); + wc = new WCHAR[wclen]; + // and try again... + } + } else { + // Fail. + qWarning("MultiByteToWideChar cannot convert multibyte text"); + break; + } + } + if ( len <= 0 ) + return TQString::null; + TQString s( (TQChar*)wc, len - 1 ); // len - 1: we don't want terminator + if ( wc != wc_auto ) + delete [] wc; + return s; +} + +#endif // Q_OS_WIN32 |