From 87d29563e3ccdeb7fea0197e262e667ef323ff9c Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 7 Jul 2024 14:56:09 +0900 Subject: Rename utility class nt* related files to equivalent tq* Signed-off-by: Michele Calgaro --- src/tools/ntqasciicache.h | 125 -- src/tools/ntqasciidict.h | 123 -- src/tools/ntqbitarray.h | 169 -- src/tools/ntqcache.h | 121 -- src/tools/ntqcstring.h | 382 ---- src/tools/ntqdeepcopy.h | 80 - src/tools/ntqdict.h | 123 -- src/tools/ntqintcache.h | 124 -- src/tools/ntqintdict.h | 119 -- src/tools/ntqiodevice.h | 2 +- src/tools/ntqmemarray.h | 117 -- src/tools/ntqregexp.h | 120 -- src/tools/qbitarray.cpp | 665 ------- src/tools/qcstring.cpp | 2539 -------------------------- src/tools/qdeepcopy.cpp | 168 -- src/tools/qdir.cpp | 10 +- src/tools/qdir_p.h | 2 +- src/tools/qdir_unix.cpp | 2 +- src/tools/qfileinfo.cpp | 2 +- src/tools/qgcache.cpp | 2 +- src/tools/qglobal.cpp | 2 +- src/tools/qgpluginmanager_p.h | 2 +- src/tools/qregexp.cpp | 3996 ----------------------------------------- src/tools/qsettings.cpp | 2 +- src/tools/qt_tools.pri | 30 +- src/tools/qwinexport.cpp | 12 +- src/tools/tqasciicache.h | 125 ++ src/tools/tqasciidict.h | 123 ++ src/tools/tqbitarray.cpp | 665 +++++++ src/tools/tqbitarray.h | 169 ++ src/tools/tqcache.h | 121 ++ src/tools/tqcstring.cpp | 2539 ++++++++++++++++++++++++++ src/tools/tqcstring.h | 382 ++++ src/tools/tqdatetime.cpp | 2 +- src/tools/tqdeepcopy.cpp | 168 ++ src/tools/tqdeepcopy.h | 80 + src/tools/tqdict.h | 123 ++ src/tools/tqintcache.h | 124 ++ src/tools/tqintdict.h | 119 ++ src/tools/tqmemarray.h | 117 ++ src/tools/tqmutexpool_p.h | 2 +- src/tools/tqregexp.cpp | 3996 +++++++++++++++++++++++++++++++++++++++++ src/tools/tqregexp.h | 120 ++ src/tools/tqstring.cpp | 6 +- src/tools/tqstring.h | 2 +- src/tools/tqstringlist.cpp | 4 +- src/tools/tqtextstream.cpp | 2 +- 47 files changed, 9013 insertions(+), 9015 deletions(-) delete mode 100644 src/tools/ntqasciicache.h delete mode 100644 src/tools/ntqasciidict.h delete mode 100644 src/tools/ntqbitarray.h delete mode 100644 src/tools/ntqcache.h delete mode 100644 src/tools/ntqcstring.h delete mode 100644 src/tools/ntqdeepcopy.h delete mode 100644 src/tools/ntqdict.h delete mode 100644 src/tools/ntqintcache.h delete mode 100644 src/tools/ntqintdict.h delete mode 100644 src/tools/ntqmemarray.h delete mode 100644 src/tools/ntqregexp.h delete mode 100644 src/tools/qbitarray.cpp delete mode 100644 src/tools/qcstring.cpp delete mode 100644 src/tools/qdeepcopy.cpp delete mode 100644 src/tools/qregexp.cpp create mode 100644 src/tools/tqasciicache.h create mode 100644 src/tools/tqasciidict.h create mode 100644 src/tools/tqbitarray.cpp create mode 100644 src/tools/tqbitarray.h create mode 100644 src/tools/tqcache.h create mode 100644 src/tools/tqcstring.cpp create mode 100644 src/tools/tqcstring.h create mode 100644 src/tools/tqdeepcopy.cpp create mode 100644 src/tools/tqdeepcopy.h create mode 100644 src/tools/tqdict.h create mode 100644 src/tools/tqintcache.h create mode 100644 src/tools/tqintdict.h create mode 100644 src/tools/tqmemarray.h create mode 100644 src/tools/tqregexp.cpp create mode 100644 src/tools/tqregexp.h (limited to 'src/tools') diff --git a/src/tools/ntqasciicache.h b/src/tools/ntqasciicache.h deleted file mode 100644 index 7323635c6..000000000 --- a/src/tools/ntqasciicache.h +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -** -** Definition of TQAsciiCache template/macro class -** -** Created : 950209 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQASCIICACHE_H -#define TQASCIICACHE_H - -#ifndef QT_H -#include "ntqgcache.h" -#endif // QT_H - - -template -class TQAsciiCache -#ifdef Q_QDOC - : public TQPtrCollection -#else - : public TQGCache -#endif -{ -public: - TQAsciiCache( const TQAsciiCache &c ) : TQGCache(c) {} - TQAsciiCache( int maxCost=100, int size=17, bool caseSensitive=TRUE, - bool copyKeys=TRUE ) - : TQGCache( maxCost, size, AsciiKey, caseSensitive, copyKeys ) {} - ~TQAsciiCache() { clear(); } - TQAsciiCache &operator=( const TQAsciiCache &c ) - { return (TQAsciiCache&)TQGCache::operator=(c); } - int maxCost() const { return TQGCache::maxCost(); } - int totalCost() const { return TQGCache::totalCost(); } - void setMaxCost( int m ) { TQGCache::setMaxCost(m); } - uint count() const { return TQGCache::count(); } - uint size() const { return TQGCache::size(); } - bool isEmpty() const { return TQGCache::count() == 0; } - void clear() { TQGCache::clear(); } - bool insert( const char *k, const type *d, int c=1, int p=0 ) - { return TQGCache::insert_other(k,(Item)d,c,p);} - bool remove( const char *k ) - { return TQGCache::remove_other(k); } - type *take( const char *k ) - { return (type *)TQGCache::take_other(k); } - type *find( const char *k, bool ref=TRUE ) const - { return (type *)TQGCache::find_other(k,ref);} - type *operator[]( const char *k ) const - { return (type *)TQGCache::find_other(k);} - void statistics() const { TQGCache::statistics(); } -private: - void deleteItem( Item d ); -}; - -#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) -template<> inline void TQAsciiCache::deleteItem( TQPtrCollection::Item ) -{ -} -#endif - -template inline void TQAsciiCache::deleteItem( TQPtrCollection::Item d ) -{ - if ( del_item ) delete (type *)d; -} - - -template -class TQAsciiCacheIterator : public TQGCacheIterator -{ -public: - TQAsciiCacheIterator( const TQAsciiCache &c ):TQGCacheIterator((TQGCache &)c) {} - TQAsciiCacheIterator( const TQAsciiCacheIterator &ci) - : TQGCacheIterator( (TQGCacheIterator &)ci ) {} - TQAsciiCacheIterator &operator=(const TQAsciiCacheIterator&ci) - { return ( TQAsciiCacheIterator&)TQGCacheIterator::operator=( ci ); } - uint count() const { return TQGCacheIterator::count(); } - bool isEmpty() const { return TQGCacheIterator::count() == 0; } - bool atFirst() const { return TQGCacheIterator::atFirst(); } - bool atLast() const { return TQGCacheIterator::atLast(); } - type *toFirst() { return (type *)TQGCacheIterator::toFirst(); } - type *toLast() { return (type *)TQGCacheIterator::toLast(); } - operator type *() const { return (type *)TQGCacheIterator::get(); } - type *current() const { return (type *)TQGCacheIterator::get(); } - const char *currentKey() const { return TQGCacheIterator::getKeyAscii(); } - type *operator()() { return (type *)TQGCacheIterator::operator()();} - type *operator++() { return (type *)TQGCacheIterator::operator++(); } - type *operator+=(uint j) { return (type *)TQGCacheIterator::operator+=(j);} - type *operator--() { return (type *)TQGCacheIterator::operator--(); } - type *operator-=(uint j) { return (type *)TQGCacheIterator::operator-=(j);} -}; - - -#endif // TQASCIICACHE_H diff --git a/src/tools/ntqasciidict.h b/src/tools/ntqasciidict.h deleted file mode 100644 index ef09bc025..000000000 --- a/src/tools/ntqasciidict.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Definition of TQAsciiDict template class -** -** Created : 920821 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQASCIIDICT_H -#define TQASCIIDICT_H - -#ifndef QT_H -#include "ntqgdict.h" -#endif // QT_H - -template -class TQAsciiDict -#ifdef Q_QDOC - : public TQPtrCollection -#else - : public TQGDict -#endif -{ -public: - TQAsciiDict(int size=17, bool caseSensitive=TRUE, bool copyKeys=TRUE ) - : TQGDict(size,AsciiKey,caseSensitive,copyKeys) {} - TQAsciiDict( const TQAsciiDict &d ) : TQGDict(d) {} - ~TQAsciiDict() { clear(); } - TQAsciiDict &operator=(const TQAsciiDict &d) - { return (TQAsciiDict&)TQGDict::operator=(d); } - uint count() const { return TQGDict::count(); } - uint size() const { return TQGDict::size(); } - bool isEmpty() const { return TQGDict::count() == 0; } - - void insert( const char *k, const type *d ) - { TQGDict::look_ascii(k,(Item)d,1); } - void replace( const char *k, const type *d ) - { TQGDict::look_ascii(k,(Item)d,2); } - bool remove( const char *k ) { return TQGDict::remove_ascii(k); } - type *take( const char *k ) { return (type *)TQGDict::take_ascii(k); } - type *find( const char *k ) const - { return (type *)((TQGDict*)this)->TQGDict::look_ascii(k,0,0); } - type *operator[]( const char *k ) const - { return (type *)((TQGDict*)this)->TQGDict::look_ascii(k,0,0); } - - void clear() { TQGDict::clear(); } - void resize( uint n ) { TQGDict::resize(n); } - void statistics() const { TQGDict::statistics(); } - -#ifdef Q_QDOC -protected: - virtual TQDataStream& read( TQDataStream &, TQPtrCollection::Item & ); - virtual TQDataStream& write( TQDataStream &, TQPtrCollection::Item ) const; -#endif - -private: - void deleteItem( Item d ); -}; - -#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) -template<> inline void TQAsciiDict::deleteItem( TQPtrCollection::Item ) -{ -} -#endif - -template inline void TQAsciiDict::deleteItem( TQPtrCollection::Item d ) -{ - if ( del_item ) delete (type *)d; -} - -template -class TQAsciiDictIterator : public TQGDictIterator -{ -public: - TQAsciiDictIterator(const TQAsciiDict &d) - : TQGDictIterator((TQGDict &)d) {} - ~TQAsciiDictIterator() {} - uint count() const { return dict->count(); } - bool isEmpty() const { return dict->count() == 0; } - type *toFirst() { return (type *)TQGDictIterator::toFirst(); } - operator type *() const { return (type *)TQGDictIterator::get(); } - type *current() const { return (type *)TQGDictIterator::get(); } - const char *currentKey() const { return TQGDictIterator::getKeyAscii(); } - type *operator()() { return (type *)TQGDictIterator::operator()(); } - type *operator++() { return (type *)TQGDictIterator::operator++(); } - type *operator+=(uint j) { return (type *)TQGDictIterator::operator+=(j);} -}; - -#define Q_DEFINED_QASCIIDICT -#include "ntqwinexport.h" -#endif // TQASCIIDICT_H diff --git a/src/tools/ntqbitarray.h b/src/tools/ntqbitarray.h deleted file mode 100644 index 65b2cdbe7..000000000 --- a/src/tools/ntqbitarray.h +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Definition of TQBitArray class -** -** Created : 940118 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQBITARRAY_H -#define TQBITARRAY_H - -#ifndef QT_H -#include "tqstring.h" -#endif // QT_H - - -/***************************************************************************** - TQBitVal class; a context class for TQBitArray::operator[] - *****************************************************************************/ - -class TQBitArray; - -class TQ_EXPORT TQBitVal -{ -private: - TQBitArray *array; - uint index; -public: - TQBitVal( TQBitArray *a, uint i ) : array(a), index(i) {} - operator int(); - TQBitVal &operator=( const TQBitVal &v ); - TQBitVal &operator=( bool v ); -}; - - -/***************************************************************************** - TQBitArray class - *****************************************************************************/ - -class TQ_EXPORT TQBitArray : public TQByteArray -{ -public: - TQBitArray(); - TQBitArray( uint size ); - TQBitArray( const TQBitArray &a ) : TQByteArray( a ) {} - - TQBitArray &operator=( const TQBitArray & ); - - uint size() const; - bool resize( uint size ); - - bool fill( bool v, int size = -1 ); - - void detach(); - TQBitArray copy() const; - - bool testBit( uint index ) const; - void setBit( uint index ); - void setBit( uint index, bool value ); - void clearBit( uint index ); - bool toggleBit( uint index ); - - bool at( uint index ) const; - TQBitVal operator[]( int index ); - bool operator[]( int index ) const; - - TQBitArray &operator&=( const TQBitArray & ); - TQBitArray &operator|=( const TQBitArray & ); - TQBitArray &operator^=( const TQBitArray & ); - TQBitArray operator~() const; - -protected: - struct bitarr_data : public TQGArray::array_data { - uint nbits; - }; - array_data *newData() { return new bitarr_data; } - void deleteData( array_data *d ) { delete (bitarr_data*)d; } -private: - void pad0(); -}; - - -inline TQBitArray &TQBitArray::operator=( const TQBitArray &a ) -{ return (TQBitArray&)assign( a ); } - -inline uint TQBitArray::size() const -{ return ((bitarr_data*)sharedBlock())->nbits; } - -inline void TQBitArray::setBit( uint index, bool value ) -{ if ( value ) setBit(index); else clearBit(index); } - -inline bool TQBitArray::at( uint index ) const -{ return testBit(index); } - -inline TQBitVal TQBitArray::operator[]( int index ) -{ return TQBitVal( (TQBitArray*)this, index ); } - -inline bool TQBitArray::operator[]( int index ) const -{ return testBit( index ); } - - -/***************************************************************************** - Misc. TQBitArray operator functions - *****************************************************************************/ - -TQ_EXPORT TQBitArray operator&( const TQBitArray &, const TQBitArray & ); -TQ_EXPORT TQBitArray operator|( const TQBitArray &, const TQBitArray & ); -TQ_EXPORT TQBitArray operator^( const TQBitArray &, const TQBitArray & ); - - -inline TQBitVal::operator int() -{ - return array->testBit( index ); -} - -inline TQBitVal &TQBitVal::operator=( const TQBitVal &v ) -{ - array->setBit( index, v.array->testBit(v.index) ); - return *this; -} - -inline TQBitVal &TQBitVal::operator=( bool v ) -{ - array->setBit( index, v ); - return *this; -} - - -/***************************************************************************** - TQBitArray stream functions - *****************************************************************************/ -#ifndef TQT_NO_DATASTREAM -TQ_EXPORT TQDataStream &operator<<( TQDataStream &, const TQBitArray & ); -TQ_EXPORT TQDataStream &operator>>( TQDataStream &, TQBitArray & ); -#endif - -#endif // TQBITARRAY_H diff --git a/src/tools/ntqcache.h b/src/tools/ntqcache.h deleted file mode 100644 index 9d747e346..000000000 --- a/src/tools/ntqcache.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Definition of TQCache template class -** -** Created : 950209 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQCACHE_H -#define TQCACHE_H - -#ifndef QT_H -#include "ntqgcache.h" -#endif // QT_H - -template -class TQCache -#ifdef Q_QDOC - : public TQPtrCollection -#else - : public TQGCache -#endif -{ -public: - TQCache( const TQCache &c ) : TQGCache(c) {} - TQCache( int maxCost=100, int size=17, bool caseSensitive=TRUE ) - : TQGCache( maxCost, size, StringKey, caseSensitive, FALSE ) {} - ~TQCache() { clear(); } - TQCache &operator=( const TQCache &c ) - { return (TQCache&)TQGCache::operator=(c); } - int maxCost() const { return TQGCache::maxCost(); } - int totalCost() const { return TQGCache::totalCost(); } - void setMaxCost( int m ) { TQGCache::setMaxCost(m); } - uint count() const { return TQGCache::count(); } - uint size() const { return TQGCache::size(); } - bool isEmpty() const { return TQGCache::count() == 0; } - void clear() { TQGCache::clear(); } - bool insert( const TQString &k, const type *d, int c=1, int p=0 ) - { return TQGCache::insert_string(k,(Item)d,c,p);} - bool remove( const TQString &k ) - { return TQGCache::remove_string(k); } - type *take( const TQString &k ) - { return (type *)TQGCache::take_string(k); } - type *find( const TQString &k, bool ref=TRUE ) const - { return (type *)TQGCache::find_string(k,ref);} - type *operator[]( const TQString &k ) const - { return (type *)TQGCache::find_string(k);} - void statistics() const { TQGCache::statistics(); } -private: - void deleteItem( Item d ); -}; - -#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) -template<> inline void TQCache::deleteItem( TQPtrCollection::Item ) -{ -} -#endif - -template inline void TQCache::deleteItem( TQPtrCollection::Item d ) -{ - if ( del_item ) delete (type *)d; -} - -template -class TQCacheIterator : public TQGCacheIterator -{ -public: - TQCacheIterator( const TQCache &c ):TQGCacheIterator((TQGCache &)c) {} - TQCacheIterator( const TQCacheIterator &ci) - : TQGCacheIterator( (TQGCacheIterator &)ci ) {} - TQCacheIterator &operator=(const TQCacheIterator&ci) - { return ( TQCacheIterator&)TQGCacheIterator::operator=( ci ); } - uint count() const { return TQGCacheIterator::count(); } - bool isEmpty() const { return TQGCacheIterator::count() == 0; } - bool atFirst() const { return TQGCacheIterator::atFirst(); } - bool atLast() const { return TQGCacheIterator::atLast(); } - type *toFirst() { return (type *)TQGCacheIterator::toFirst(); } - type *toLast() { return (type *)TQGCacheIterator::toLast(); } - operator type *() const { return (type *)TQGCacheIterator::get(); } - type *current() const { return (type *)TQGCacheIterator::get(); } - TQString currentKey() const{ return TQGCacheIterator::getKeyString(); } - type *operator()() { return (type *)TQGCacheIterator::operator()();} - type *operator++() { return (type *)TQGCacheIterator::operator++(); } - type *operator+=(uint j) { return (type *)TQGCacheIterator::operator+=(j);} - type *operator--() { return (type *)TQGCacheIterator::operator--(); } - type *operator-=(uint j) { return (type *)TQGCacheIterator::operator-=(j);} -}; - -#endif // TQCACHE_H diff --git a/src/tools/ntqcstring.h b/src/tools/ntqcstring.h deleted file mode 100644 index e0054bf3a..000000000 --- a/src/tools/ntqcstring.h +++ /dev/null @@ -1,382 +0,0 @@ -/**************************************************************************** -** -** Definition of the extended char array operations, -** and TQByteArray and TQCString classes -** -** Created : 920609 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQCSTRING_H -#define TQCSTRING_H - -#ifndef QT_H -#include "ntqmemarray.h" -#endif // QT_H - -#include - - -/***************************************************************************** - Safe and portable C string functions; extensions to standard string.h - *****************************************************************************/ - -TQ_EXPORT void *tqmemmove( void *dst, const void *src, uint len ); - -TQ_EXPORT char *tqstrdup( const char * ); - -TQ_EXPORT inline uint tqstrlen( const char *str ) -{ return str ? (uint)strlen(str) : 0u; } - -TQ_EXPORT inline char *qstrcpy( char *dst, const char *src ) -{ return src ? strcpy(dst, src) : 0; } - -TQ_EXPORT char *tqstrncpy( char *dst, const char *src, uint len ); - -TQ_EXPORT inline int qstrcmp( const char *str1, const char *str2 ) -{ - return ( str1 && str2 ) ? strcmp( str1, str2 ) - : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); -} - -TQ_EXPORT inline int tqstrncmp( const char *str1, const char *str2, uint len ) -{ - return ( str1 && str2 ) ? strncmp( str1, str2, len ) - : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); -} - -TQ_EXPORT int tqstricmp( const char *, const char * ); - -TQ_EXPORT int tqstrnicmp( const char *, const char *, uint len ); - - -// tqChecksum: Internet checksum - -TQ_EXPORT TQ_UINT16 tqChecksum( const char *s, uint len ); - -/***************************************************************************** - TQByteArray class - *****************************************************************************/ - -#if defined(Q_QDOC) -/* - We want qdoc to document TQByteArray as a real class that inherits - TQMemArray and that is inherited by TQBitArray. -*/ -class TQByteArray : public TQMemArray -{ -public: - TQByteArray(); - TQByteArray( int size ); -}; -#else -typedef TQMemArray TQByteArray; -#endif - -#ifndef TQT_NO_COMPRESS -TQ_EXPORT TQByteArray tqCompress( const uchar* data, int nbytes ); -TQ_EXPORT TQByteArray tqUncompress( const uchar* data, int nbytes ); -TQ_EXPORT inline TQByteArray tqCompress( const TQByteArray& data) -{ return tqCompress( (const uchar*)data.data(), data.size() ); } -TQ_EXPORT inline TQByteArray tqUncompress( const TQByteArray& data ) -{ return tqUncompress( (const uchar*)data.data(), data.size() ); } -#endif - -/***************************************************************************** - TQByteArray stream functions - *****************************************************************************/ -#ifndef TQT_NO_DATASTREAM -TQ_EXPORT TQDataStream &operator<<( TQDataStream &, const TQByteArray & ); -TQ_EXPORT TQDataStream &operator>>( TQDataStream &, TQByteArray & ); -#endif - -/***************************************************************************** - TQCString class - *****************************************************************************/ - -class TQRegExp; - -class TQ_EXPORT TQCString : public TQByteArray // C string class -{ -public: - TQCString() {} // make null string - TQCString( int size ); // allocate size incl. \0 - TQCString( const TQCString &s ) : TQByteArray( s ) {} - TQCString( const char *str ); // deep copy - TQCString( const char *str, uint maxlen ); // deep copy, max length - ~TQCString(); - - TQCString &operator=( const TQCString &s );// shallow copy - TQCString &operator=( const char *str ); // deep copy - - bool isNull() const; - bool isEmpty() const; - uint length() const; - bool resize( uint newlen ); - bool truncate( uint pos ); - bool fill( char c, int len = -1 ); - - TQCString copy() const; - - TQCString &sprintf( const char *format, ... ) -#if defined(Q_CC_GNU) && !defined(__INSURE__) - __attribute__ ((format (printf, 2, 3))) -#endif - ; - - int find( char c, int index=0, bool cs=TRUE ) const; - int find( const char *str, int index=0, bool cs=TRUE ) const; -#ifndef TQT_NO_REGEXP - int find( const TQRegExp &, int index=0 ) const; -#endif - int findRev( char c, int index=-1, bool cs=TRUE) const; - int findRev( const char *str, int index=-1, bool cs=TRUE) const; -#ifndef TQT_NO_REGEXP_CAPTURE - int findRev( const TQRegExp &, int index=-1 ) const; -#endif - int contains( char c, bool cs=TRUE ) const; - int contains( const char *str, bool cs=TRUE ) const; -#ifndef TQT_NO_REGEXP - int contains( const TQRegExp & ) const; -#endif - TQCString left( uint len ) const; - TQCString right( uint len ) const; - TQCString mid( uint index, uint len=0xffffffff) const; - - TQCString leftJustify( uint width, char fill=' ', bool trunc=FALSE)const; - TQCString rightJustify( uint width, char fill=' ',bool trunc=FALSE)const; - - TQCString lower() const; - TQCString upper() const; - - TQCString stripWhiteSpace() const; - TQCString simplifyWhiteSpace() const; - - TQCString &insert( uint index, const char * ); - TQCString &insert( uint index, char ); - TQCString &append( const char * ); - TQCString &prepend( const char * ); - TQCString &remove( uint index, uint len ); - TQCString &replace( uint index, uint len, const char * ); -#ifndef TQT_NO_REGEXP - TQCString &replace( const TQRegExp &, const char * ); -#endif - TQCString &replace( char c, const char *after ); - TQCString &replace( const char *, const char * ); - TQCString &replace( char, char ); - - short toShort( bool *ok=0 ) const; - ushort toUShort( bool *ok=0 ) const; - int toInt( bool *ok=0 ) const; - uint toUInt( bool *ok=0 ) const; - long toLong( bool *ok=0 ) const; - ulong toULong( bool *ok=0 ) const; - float toFloat( bool *ok=0 ) const; - double toDouble( bool *ok=0 ) const; - - TQCString &setStr( const char *s ); - TQCString &setNum( short ); - TQCString &setNum( ushort ); - TQCString &setNum( int ); - TQCString &setNum( uint ); - TQCString &setNum( long ); - TQCString &setNum( ulong ); - TQCString &setNum( float, char f='g', int prec=6 ); - TQCString &setNum( double, char f='g', int prec=6 ); - - bool setExpand( uint index, char c ); - - operator const char *() const; - TQCString &operator+=( const char *str ); - TQCString &operator+=( char c ); -private: - int find( const char *str, int index, bool cs, uint l ) const; -}; - - -/***************************************************************************** - TQCString stream functions - *****************************************************************************/ -#ifndef TQT_NO_DATASTREAM -TQ_EXPORT TQDataStream &operator<<( TQDataStream &, const TQCString & ); -TQ_EXPORT TQDataStream &operator>>( TQDataStream &, TQCString & ); -#endif - -/***************************************************************************** - TQCString inline functions - *****************************************************************************/ - -inline TQCString &TQCString::operator=( const TQCString &s ) -{ return (TQCString&)assign( s ); } - -inline TQCString &TQCString::operator=( const char *str ) -{ return (TQCString&)duplicate( str, tqstrlen(str)+1 ); } - -inline bool TQCString::isNull() const -{ return data() == 0; } - -inline bool TQCString::isEmpty() const -{ return data() == 0 || *data() == '\0'; } - -inline uint TQCString::length() const -{ return tqstrlen( data() ); } - -inline bool TQCString::truncate( uint pos ) -{ return resize(pos+1); } - -inline TQCString TQCString::copy() const -{ return TQCString( data() ); } - -inline TQCString &TQCString::prepend( const char *s ) -{ return insert(0,s); } - -inline TQCString &TQCString::append( const char *s ) -{ return operator+=(s); } - -inline TQCString &TQCString::setNum( short n ) -{ return setNum((long)n); } - -inline TQCString &TQCString::setNum( ushort n ) -{ return setNum((ulong)n); } - -inline TQCString &TQCString::setNum( int n ) -{ return setNum((long)n); } - -inline TQCString &TQCString::setNum( uint n ) -{ return setNum((ulong)n); } - -inline TQCString &TQCString::setNum( float n, char f, int prec ) -{ return setNum((double)n,f,prec); } - -inline TQCString::operator const char *() const -{ return (const char *)data(); } - - -/***************************************************************************** - TQCString non-member operators - *****************************************************************************/ - -TQ_EXPORT inline bool operator==( const TQCString &s1, const TQCString &s2 ) -{ return qstrcmp( s1.data(), s2.data() ) == 0; } - -TQ_EXPORT inline bool operator==( const TQCString &s1, const char *s2 ) -{ return qstrcmp( s1.data(), s2 ) == 0; } - -TQ_EXPORT inline bool operator==( const char *s1, const TQCString &s2 ) -{ return qstrcmp( s1, s2.data() ) == 0; } - -TQ_EXPORT inline bool operator!=( const TQCString &s1, const TQCString &s2 ) -{ return qstrcmp( s1.data(), s2.data() ) != 0; } - -TQ_EXPORT inline bool operator!=( const TQCString &s1, const char *s2 ) -{ return qstrcmp( s1.data(), s2 ) != 0; } - -TQ_EXPORT inline bool operator!=( const char *s1, const TQCString &s2 ) -{ return qstrcmp( s1, s2.data() ) != 0; } - -TQ_EXPORT inline bool operator<( const TQCString &s1, const TQCString& s2 ) -{ return qstrcmp( s1.data(), s2.data() ) < 0; } - -TQ_EXPORT inline bool operator<( const TQCString &s1, const char *s2 ) -{ return qstrcmp( s1.data(), s2 ) < 0; } - -TQ_EXPORT inline bool operator<( const char *s1, const TQCString &s2 ) -{ return qstrcmp( s1, s2.data() ) < 0; } - -TQ_EXPORT inline bool operator<=( const TQCString &s1, const TQCString &s2 ) -{ return qstrcmp( s1.data(), s2.data() ) <= 0; } - -TQ_EXPORT inline bool operator<=( const TQCString &s1, const char *s2 ) -{ return qstrcmp( s1.data(), s2 ) <= 0; } - -TQ_EXPORT inline bool operator<=( const char *s1, const TQCString &s2 ) -{ return qstrcmp( s1, s2.data() ) <= 0; } - -TQ_EXPORT inline bool operator>( const TQCString &s1, const TQCString &s2 ) -{ return qstrcmp( s1.data(), s2.data() ) > 0; } - -TQ_EXPORT inline bool operator>( const TQCString &s1, const char *s2 ) -{ return qstrcmp( s1.data(), s2 ) > 0; } - -TQ_EXPORT inline bool operator>( const char *s1, const TQCString &s2 ) -{ return qstrcmp( s1, s2.data() ) > 0; } - -TQ_EXPORT inline bool operator>=( const TQCString &s1, const TQCString& s2 ) -{ return qstrcmp( s1.data(), s2.data() ) >= 0; } - -TQ_EXPORT inline bool operator>=( const TQCString &s1, const char *s2 ) -{ return qstrcmp( s1.data(), s2 ) >= 0; } - -TQ_EXPORT inline bool operator>=( const char *s1, const TQCString &s2 ) -{ return qstrcmp( s1, s2.data() ) >= 0; } - -TQ_EXPORT inline const TQCString operator+( const TQCString &s1, - const TQCString &s2 ) -{ - TQCString tmp( s1.data() ); - tmp += s2; - return tmp; -} - -TQ_EXPORT inline const TQCString operator+( const TQCString &s1, const char *s2 ) -{ - TQCString tmp( s1.data() ); - tmp += s2; - return tmp; -} - -TQ_EXPORT inline const TQCString operator+( const char *s1, const TQCString &s2 ) -{ - TQCString tmp( s1 ); - tmp += s2; - return tmp; -} - -TQ_EXPORT inline const TQCString operator+( const TQCString &s1, char c2 ) -{ - TQCString tmp( s1.data() ); - tmp += c2; - return tmp; -} - -TQ_EXPORT inline const TQCString operator+( char c1, const TQCString &s2 ) -{ - TQCString tmp; - tmp += c1; - tmp += s2; - return tmp; -} -#include "ntqwinexport.h" -#endif // TQCSTRING_H diff --git a/src/tools/ntqdeepcopy.h b/src/tools/ntqdeepcopy.h deleted file mode 100644 index abe1fc8f1..000000000 --- a/src/tools/ntqdeepcopy.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Definition of TQDeepCopy class -** -** Created : 20020613 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQDEEPCOPY_H -#define TQDEEPCOPY_H - -#ifndef QT_H -# include "ntqglobal.h" -#endif // QT_H - -template -class TQDeepCopy -{ -public: - inline TQDeepCopy() - { - } - - inline TQDeepCopy( const T &t ) - : deepcopy( t ) - { - deepcopy.detach(); - } - - inline TQDeepCopy &operator=( const T &t ) - { - deepcopy = t; - deepcopy.detach(); - return *this; - } - - inline operator T () - { - T tmp = deepcopy; - tmp.detach(); - return tmp; - } - -private: - T deepcopy; -}; - -#endif // TQDEEPCOPY_H diff --git a/src/tools/ntqdict.h b/src/tools/ntqdict.h deleted file mode 100644 index d363538d0..000000000 --- a/src/tools/ntqdict.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Definition of TQDict template class -** -** Created : 920821 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQDICT_H -#define TQDICT_H - -#ifndef QT_H -#include "ntqgdict.h" -#endif // QT_H - -template -class TQDict -#ifdef Q_QDOC - : public TQPtrCollection -#else - : public TQGDict -#endif -{ -public: - TQDict( int size = 17, bool caseSensitive = TRUE ) - : TQGDict( size, StringKey, caseSensitive, FALSE ) { } - TQDict( const TQDict &d ) : TQGDict( d ) { } - ~TQDict() { clear(); } - TQDict &operator=(const TQDict &d) - { return (TQDict&)TQGDict::operator=(d); } - uint count() const { return TQGDict::count(); } - uint size() const { return TQGDict::size(); } - bool isEmpty() const { return TQGDict::count() == 0; } - - void insert( const TQString &k, const type *d ) - { TQGDict::look_string(k,(Item)d,1); } - void replace( const TQString &k, const type *d ) - { TQGDict::look_string(k,(Item)d,2); } - bool remove( const TQString &k ) { return TQGDict::remove_string(k); } - type *take( const TQString &k ) { return (type *)TQGDict::take_string(k); } - type *find( const TQString &k ) const - { return (type *)((TQGDict*)this)->TQGDict::look_string(k,0,0); } - type *operator[]( const TQString &k ) const - { return (type *)((TQGDict*)this)->TQGDict::look_string(k,0,0); } - - void clear() { TQGDict::clear(); } - void resize( uint n ) { TQGDict::resize(n); } - void statistics() const { TQGDict::statistics(); } - -#ifdef Q_QDOC -protected: - virtual TQDataStream& read( TQDataStream &, TQPtrCollection::Item & ); - virtual TQDataStream& write( TQDataStream &, TQPtrCollection::Item ) const; -#endif - -private: - void deleteItem( Item d ); -}; - -#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) -template<> inline void TQDict::deleteItem( Item ) -{ -} -#endif - -template inline void TQDict::deleteItem( TQPtrCollection::Item d ) -{ - if ( del_item ) delete (type *)d; -} - -template -class TQDictIterator : public TQGDictIterator -{ -public: - TQDictIterator(const TQDict &d) : TQGDictIterator((TQGDict &)d) { } - ~TQDictIterator() {} - uint count() const { return dict->count(); } - bool isEmpty() const { return dict->count() == 0; } - type *toFirst() { return (type *)TQGDictIterator::toFirst(); } - operator type *() const { return (type *)TQGDictIterator::get(); } - type *operator*() { return (type *)TQGDictIterator::get(); } - type *current() const { return (type *)TQGDictIterator::get(); } - TQString currentKey() const{ return TQGDictIterator::getKeyString(); } - type *operator()() { return (type *)TQGDictIterator::operator()(); } - type *operator++() { return (type *)TQGDictIterator::operator++(); } - type *operator+=(uint j) { return (type *)TQGDictIterator::operator+=(j); } -}; - -#define Q_DEFINED_QDICT -#include "ntqwinexport.h" -#endif // TQDICT_H diff --git a/src/tools/ntqintcache.h b/src/tools/ntqintcache.h deleted file mode 100644 index 116618058..000000000 --- a/src/tools/ntqintcache.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Definition of TQIntCache template class -** -** Created : 950209 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQINTCACHE_H -#define TQINTCACHE_H - -#ifndef QT_H -#include "ntqgcache.h" -#endif // QT_H - - -template -class TQIntCache -#ifdef Q_QDOC - : public TQPtrCollection -#else - : public TQGCache -#endif -{ -public: - TQIntCache( const TQIntCache &c ) : TQGCache(c) {} - TQIntCache( int maxCost=100, int size=17 ) - : TQGCache( maxCost, size, IntKey, FALSE, FALSE ) {} - ~TQIntCache() { clear(); } - TQIntCache &operator=( const TQIntCache &c ) - { return (TQIntCache&)TQGCache::operator=(c); } - int maxCost() const { return TQGCache::maxCost(); } - int totalCost() const { return TQGCache::totalCost(); } - void setMaxCost( int m) { TQGCache::setMaxCost(m); } - uint count() const { return TQGCache::count(); } - uint size() const { return TQGCache::size(); } - bool isEmpty() const { return TQGCache::count() == 0; } - bool insert( long k, const type *d, int c=1, int p=0 ) - { return TQGCache::insert_other((const char*)k,(Item)d,c,p); } - bool remove( long k ) - { return TQGCache::remove_other((const char*)k); } - type *take( long k ) - { return (type *)TQGCache::take_other((const char*)k);} - void clear() { TQGCache::clear(); } - type *find( long k, bool ref=TRUE ) const - { return (type *)TQGCache::find_other( (const char*)k,ref);} - type *operator[]( long k ) const - { return (type *)TQGCache::find_other( (const char*)k); } - void statistics() const { TQGCache::statistics(); } -private: - void deleteItem( Item d ); -}; - -#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) -template<> inline void TQIntCache::deleteItem( TQPtrCollection::Item ) -{ -} -#endif - -template inline void TQIntCache::deleteItem( TQPtrCollection::Item d ) -{ - if ( del_item ) delete (type *)d; -} - -template -class TQIntCacheIterator : public TQGCacheIterator -{ -public: - TQIntCacheIterator( const TQIntCache &c ) - : TQGCacheIterator( (TQGCache &)c ) {} - TQIntCacheIterator( const TQIntCacheIterator &ci ) - : TQGCacheIterator((TQGCacheIterator &)ci) {} - TQIntCacheIterator &operator=( const TQIntCacheIterator&ci ) - { return ( TQIntCacheIterator&)TQGCacheIterator::operator=( ci );} - uint count() const { return TQGCacheIterator::count(); } - bool isEmpty() const { return TQGCacheIterator::count() == 0; } - bool atFirst() const { return TQGCacheIterator::atFirst(); } - bool atLast() const { return TQGCacheIterator::atLast(); } - type *toFirst() { return (type *)TQGCacheIterator::toFirst(); } - type *toLast() { return (type *)TQGCacheIterator::toLast(); } - operator type *() const { return (type *)TQGCacheIterator::get(); } - type *current() const { return (type *)TQGCacheIterator::get(); } - long currentKey() const { return (long)TQGCacheIterator::getKeyInt();} - type *operator()() { return (type *)TQGCacheIterator::operator()();} - type *operator++() { return (type *)TQGCacheIterator::operator++(); } - type *operator+=(uint j) { return (type *)TQGCacheIterator::operator+=(j);} - type *operator--() { return (type *)TQGCacheIterator::operator--(); } - type *operator-=(uint j) { return (type *)TQGCacheIterator::operator-=(j);} -}; - - -#endif // TQINTCACHE_H diff --git a/src/tools/ntqintdict.h b/src/tools/ntqintdict.h deleted file mode 100644 index 162625855..000000000 --- a/src/tools/ntqintdict.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Definition of TQIntDict template class -** -** Created : 940624 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQINTDICT_H -#define TQINTDICT_H - -#ifndef QT_H -#include "ntqgdict.h" -#endif // QT_H - -template -class TQIntDict -#ifdef Q_QDOC - : public TQPtrCollection -#else - : public TQGDict -#endif -{ -public: - TQIntDict(int size=17) : TQGDict(size,IntKey,0,0) {} - TQIntDict( const TQIntDict &d ) : TQGDict(d) {} - ~TQIntDict() { clear(); } - TQIntDict &operator=(const TQIntDict &d) - { return (TQIntDict&)TQGDict::operator=(d); } - uint count() const { return TQGDict::count(); } - uint size() const { return TQGDict::size(); } - bool isEmpty() const { return TQGDict::count() == 0; } - void insert( long k, const type *d ) - { TQGDict::look_int(k,(Item)d,1); } - void replace( long k, const type *d ) - { TQGDict::look_int(k,(Item)d,2); } - bool remove( long k ) { return TQGDict::remove_int(k); } - type *take( long k ) { return (type*)TQGDict::take_int(k); } - type *find( long k ) const - { return (type *)((TQGDict*)this)->TQGDict::look_int(k,0,0); } - type *operator[]( long k ) const - { return (type *)((TQGDict*)this)->TQGDict::look_int(k,0,0); } - void clear() { TQGDict::clear(); } - void resize( uint n ) { TQGDict::resize(n); } - void statistics() const { TQGDict::statistics(); } - -#ifdef Q_QDOC -protected: - virtual TQDataStream& read( TQDataStream &, TQPtrCollection::Item & ); - virtual TQDataStream& write( TQDataStream &, TQPtrCollection::Item ) const; -#endif - -private: - void deleteItem( Item d ); -}; - -#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) -template<> inline void TQIntDict::deleteItem( TQPtrCollection::Item ) -{ -} -#endif - -template inline void TQIntDict::deleteItem( TQPtrCollection::Item d ) -{ - if ( del_item ) delete (type*)d; -} - -template -class TQIntDictIterator : public TQGDictIterator -{ -public: - TQIntDictIterator(const TQIntDict &d) :TQGDictIterator((TQGDict &)d) {} - ~TQIntDictIterator() {} - uint count() const { return dict->count(); } - bool isEmpty() const { return dict->count() == 0; } - type *toFirst() { return (type *)TQGDictIterator::toFirst(); } - operator type *() const { return (type *)TQGDictIterator::get(); } - type *current() const { return (type *)TQGDictIterator::get(); } - long currentKey() const { return TQGDictIterator::getKeyInt(); } - type *operator()() { return (type *)TQGDictIterator::operator()(); } - type *operator++() { return (type *)TQGDictIterator::operator++(); } - type *operator+=(uint j) { return (type *)TQGDictIterator::operator+=(j);} -}; - -#define Q_DEFINED_QINTDICT -#include "ntqwinexport.h" -#endif // TQINTDICT_H diff --git a/src/tools/ntqiodevice.h b/src/tools/ntqiodevice.h index c9001bc15..712288d8e 100644 --- a/src/tools/ntqiodevice.h +++ b/src/tools/ntqiodevice.h @@ -43,7 +43,7 @@ #ifndef QT_H #include "ntqglobal.h" -#include "ntqcstring.h" +#include "tqcstring.h" #endif // QT_H diff --git a/src/tools/ntqmemarray.h b/src/tools/ntqmemarray.h deleted file mode 100644 index 8a07bf9a9..000000000 --- a/src/tools/ntqmemarray.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Definition of TQMemArray template/macro class -** -** Created : 930906 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQMEMARRAY_H -#define TQMEMARRAY_H - -#ifndef QT_H -#include "ntqgarray.h" -#endif // QT_H - - -template -class TQMemArray : public TQGArray -{ -public: - typedef type* Iterator; - typedef const type* ConstIterator; - typedef type ValueType; - -protected: - TQMemArray( int, int ) : TQGArray( 0, 0 ) {} - -public: - TQMemArray() {} - TQMemArray( int size ) : TQGArray(size*sizeof(type)) {} // ### 4.0 Q_EXPLICIT - TQMemArray( const TQMemArray &a ) : TQGArray(a) {} - ~TQMemArray() {} - TQMemArray &operator=(const TQMemArray &a) - { return (TQMemArray&)TQGArray::assign(a); } - type *data() const { return (type *)TQGArray::data(); } - uint nrefs() const { return TQGArray::nrefs(); } - uint size() const { return TQGArray::size()/sizeof(type); } - uint count() const { return size(); } - bool isEmpty() const { return TQGArray::size() == 0; } - bool isNull() const { return TQGArray::data() == 0; } - bool resize( uint size ) { return TQGArray::resize(size*sizeof(type)); } - bool resize( uint size, Optimization optim ) { return TQGArray::resize(size*sizeof(type), optim); } - bool truncate( uint pos ) { return TQGArray::resize(pos*sizeof(type)); } - bool fill( const type &d, int size = -1 ) - { return TQGArray::fill((char*)&d,size,sizeof(type) ); } - void detach() { TQGArray::detach(); } - TQMemArray copy() const - { TQMemArray tmp; return tmp.duplicate(*this); } - TQMemArray& assign( const TQMemArray& a ) - { return (TQMemArray&)TQGArray::assign(a); } - TQMemArray& assign( const type *a, uint n ) - { return (TQMemArray&)TQGArray::assign((char*)a,n*sizeof(type)); } - TQMemArray& duplicate( const TQMemArray& a ) - { return (TQMemArray&)TQGArray::duplicate(a); } - TQMemArray& duplicate( const type *a, uint n ) - { return (TQMemArray&)TQGArray::duplicate((char*)a,n*sizeof(type)); } - TQMemArray& setRawData( const type *a, uint n ) - { return (TQMemArray&)TQGArray::setRawData((char*)a, - n*sizeof(type)); } - void resetRawData( const type *a, uint n ) - { TQGArray::resetRawData((char*)a,n*sizeof(type)); } - int find( const type &d, uint i=0 ) const - { return TQGArray::find((char*)&d,i,sizeof(type)); } - int contains( const type &d ) const - { return TQGArray::contains((char*)&d,sizeof(type)); } - void sort() { TQGArray::sort(sizeof(type)); } - int bsearch( const type &d ) const - { return TQGArray::bsearch((const char*)&d,sizeof(type)); } - // ### TQt 4.0: maybe provide uint overload as work-around for MSVC bug - type& operator[]( int i ) const - { return (type &)(*(type *)TQGArray::at(i*sizeof(type))); } - type& at( uint i ) const - { return (type &)(*(type *)TQGArray::at(i*sizeof(type))); } - operator const type*() const { return (const type *)TQGArray::data(); } - bool operator==( const TQMemArray &a ) const { return isEqual(a); } - bool operator!=( const TQMemArray &a ) const { return !isEqual(a); } - Iterator begin() { return data(); } - Iterator end() { return data() + size(); } - ConstIterator begin() const { return data(); } - ConstIterator end() const { return data() + size(); } -}; - -#define Q_DEFINED_QMEMARRAY -#include "ntqwinexport.h" -#endif diff --git a/src/tools/ntqregexp.h b/src/tools/ntqregexp.h deleted file mode 100644 index d8aca02c0..000000000 --- a/src/tools/ntqregexp.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Definition of TQRegExp class -** -** Created : 950126 -** -** 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 requirements 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. -** -**********************************************************************/ - -#ifndef TQREGEXP_H -#define TQREGEXP_H - -#ifndef QT_H -#include "tqstringlist.h" -#endif // QT_H - -#ifndef TQT_NO_REGEXP -class TQRegExpEngine; -struct TQRegExpPrivate; - -class TQ_EXPORT TQRegExp -{ -public: - enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; - - TQRegExp(); - TQRegExp( const TQString& pattern, bool caseSensitive = TRUE, - bool wildcard = FALSE ); - TQRegExp( const TQRegExp& rx ); - ~TQRegExp(); - TQRegExp& operator=( const TQRegExp& rx ); - - bool operator==( const TQRegExp& rx ) const; - bool operator!=( const TQRegExp& rx ) const { return !operator==( rx ); } - - bool isEmpty() const; - bool isValid() const; - TQString pattern() const; - void setPattern( const TQString& pattern ); - bool caseSensitive() const; - void setCaseSensitive( bool sensitive ); -#ifndef TQT_NO_REGEXP_WILDCARD - bool wildcard() const; - void setWildcard( bool wildcard ); -#endif - bool minimal() const; - void setMinimal( bool minimal ); - - bool exactMatch( const TQString& str ) const; -#ifndef TQT_NO_COMPAT - int match( const TQString& str, int index = 0, int *len = 0, - bool indexIsStart = TRUE ) const; -#endif - -#if defined(Q_QDOC) - int search( const TQString& str, int offset = 0, - CaretMode caretMode = CaretAtZero ) const; - int searchRev( const TQString& str, int offset = -1, - CaretMode caretMode = CaretAtZero ) const; -#else - // ### TQt 4.0: reduce these four to two functions - int search( const TQString& str, int offset = 0 ) const; - int search( const TQString& str, int offset, CaretMode caretMode ) const; - int searchRev( const TQString& str, int offset = -1 ) const; - int searchRev( const TQString& str, int offset, CaretMode caretMode ) const; -#endif - int matchedLength() const; -#ifndef TQT_NO_REGEXP_CAPTURE - int numCaptures() const; - TQStringList capturedTexts(); - TQString cap( int nth = 0 ); - int pos( int nth = 0 ); - TQString errorString(); -#endif - - static TQString escape( const TQString& str ); - -private: - void prepareEngine() const; - void prepareEngineForMatch( const TQString& str ) const; - void invalidateEngine(); - - static int caretIndex( int offset, CaretMode caretMode ); - - TQRegExpEngine *eng; - TQRegExpPrivate *priv; -}; -#endif // TQT_NO_REGEXP -#endif // TQREGEXP_H diff --git a/src/tools/qbitarray.cpp b/src/tools/qbitarray.cpp deleted file mode 100644 index c850546e9..000000000 --- a/src/tools/qbitarray.cpp +++ /dev/null @@ -1,665 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQBitArray class -** -** Created : 940118 -** -** 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 requirements 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. -** -**********************************************************************/ - -#include "ntqbitarray.h" -#include "ntqdatastream.h" - -#define SHBLOCK ((bitarr_data*)(sharedBlock())) - - -/*! - \class TQBitVal ntqbitarray.h - \reentrant - \brief The TQBitVal class is an internal class, used with TQBitArray. - - \ingroup collection - - The TQBitVal is required by the indexing [] operator on bit arrays. - It is not for use in any other context. -*/ - -/*! - \fn TQBitVal::TQBitVal (TQBitArray* a, uint i) - - Constructs a reference to element \a i in the TQBitArray \a a. - This is what TQBitArray::operator[] constructs its return value - with. -*/ - -/*! - \fn TQBitVal::operator int() - - Returns the value referenced by the TQBitVal. -*/ - -/*! - \fn TQBitVal& TQBitVal::operator= (const TQBitVal& v) - - Sets the value referenced by the TQBitVal to that referenced by - TQBitVal \a v. -*/ - -/*! - \overload TQBitVal& TQBitVal::operator= (bool v) - - Sets the value referenced by the TQBitVal to \a v. -*/ - - -/*! - \class TQBitArray ntqbitarray.h - \reentrant - \brief The TQBitArray class provides an array of bits. - - \ingroup collection - \ingroup tools - \ingroup shared - - Because TQBitArray is a TQMemArray, it uses explicit \link - shclass.html sharing\endlink with a reference count. - - A TQBitArray is a special byte array that can access individual - bits and perform bit-operations (AND, OR, XOR and NOT) on entire - arrays or bits. - - Bits can be manipulated by the setBit() and clearBit() functions, - but it is also possible to use the indexing [] operator to test - and set individual bits. The [] operator is a little slower than - setBit() and clearBit() because some tricks are required to - implement single-bit assignments. - - Example: - \code - TQBitArray a(3); - a.setBit( 0 ); - a.clearBit( 1 ); - a.setBit( 2 ); // a = [1 0 1] - - TQBitArray b(3); - b[0] = 1; - b[1] = 1; - b[2] = 0; // b = [1 1 0] - - TQBitArray c; - c = ~a & b; // c = [0 1 0] - \endcode - - When a TQBitArray is constructed the bits are uninitialized. Use - fill() to set all the bits to 0 or 1. The array can be resized - with resize() and copied with copy(). Bits can be set with - setBit() and cleared with clearBit(). Bits can be toggled with - toggleBit(). A bit's value can be obtained with testBit() and with - at(). - - TQBitArray supports the \& (AND), | (OR), ^ (XOR) and ~ (NOT) - operators. -*/ - -/*! \class TQBitArray::bitarr_data - \brief The TQBitArray::bitarr_data class is internal. - \internal -*/ - - -/*! - Constructs an empty bit array. -*/ - -TQBitArray::TQBitArray() : TQByteArray( 0, 0 ) -{ - bitarr_data *x = new bitarr_data; - TQ_CHECK_PTR( x ); - x->nbits = 0; - setSharedBlock( x ); -} - -/*! - Constructs a bit array of \a size bits. The bits are uninitialized. - - \sa fill() -*/ - -TQBitArray::TQBitArray( uint size ) : TQByteArray( 0, 0 ) -{ - bitarr_data *x = new bitarr_data; - TQ_CHECK_PTR( x ); - x->nbits = 0; - setSharedBlock( x ); - resize( size ); -} - -/*! - \fn TQBitArray::TQBitArray( const TQBitArray &a ) - - Constructs a shallow copy of \a a. -*/ - -/*! - \fn TQBitArray &TQBitArray::operator=( const TQBitArray &a ) - - Assigns a shallow copy of \a a to this bit array and returns a - reference to this array. -*/ - - -/*! - Pad last byte with 0-bits. -*/ -void TQBitArray::pad0() -{ - uint sz = size(); - if ( sz && sz%8 ) - *(data()+sz/8) &= (1 << (sz%8)) - 1; -} - - -/*! - \fn uint TQBitArray::size() const - - Returns the bit array's size (number of bits). - - \sa resize() -*/ - -/*! - Resizes the bit array to \a size bits and returns TRUE if the bit - array could be resized; otherwise returns FALSE. The array becomes - a null array if \a size == 0. - - If the array is expanded, the new bits are set to 0. - - \sa size() -*/ - -bool TQBitArray::resize( uint size ) -{ - uint s = this->size(); - if ( !TQByteArray::resize( (size+7)/8 ) ) - return FALSE; // cannot resize - SHBLOCK->nbits = size; - if ( size != 0 ) { // not null array - int ds = (int)(size+7)/8 - (int)(s+7)/8;// number of bytes difference - if ( ds > 0 ) // expanding array - memset( data() + (s+7)/8, 0, ds ); // reset new data - } - return TRUE; -} - - -/*! - Fills the bit array with \a v (1's if \a v is TRUE, or 0's if \a v - is FALSE). - - fill() resizes the bit array to \a size bits if \a size is - nonnegative. - - Returns FALSE if a nonnegative \e size was specified and the bit - array could not be resized; otherwise returns TRUE. - - \sa resize() -*/ - -bool TQBitArray::fill( bool v, int size ) -{ - if ( size >= 0 ) { // resize first - if ( !resize( size ) ) - return FALSE; // cannot resize - } else { - size = this->size(); - } - if ( size > 0 ) - memset( data(), v ? 0xff : 0, (size + 7) / 8 ); - if ( v ) - pad0(); - return TRUE; -} - - -/*! - Detaches from shared bit array data and makes sure that this bit - array is the only one referring to the data. - - If multiple bit arrays share common data, this bit array - dereferences the data and gets a copy of the data. Nothing happens - if there is only a single reference. - - \sa copy() -*/ - -void TQBitArray::detach() -{ - int nbits = SHBLOCK->nbits; - this->duplicate( *this ); - SHBLOCK->nbits = nbits; -} - -/*! - Returns a deep copy of the bit array. - - \sa detach() -*/ - -TQBitArray TQBitArray::copy() const -{ - TQBitArray tmp; - tmp.duplicate( *this ); - ((bitarr_data*)(tmp.sharedBlock()))->nbits = SHBLOCK->nbits; - return tmp; -} - - -/*! - Returns TRUE if the bit at position \a index is set, i.e. is 1; - otherwise returns FALSE. - - \sa setBit(), clearBit() -*/ - -bool TQBitArray::testBit( uint index ) const -{ -#if defined(QT_CHECK_RANGE) - if ( index >= size() ) { - tqWarning( "TQBitArray::testBit: Index %d out of range", index ); - return FALSE; - } -#endif - return (*(data()+(index>>3)) & (1 << (index & 7))) != 0; -} - -/*! - \overload - - Sets the bit at position \a index to 1. - - \sa clearBit() toggleBit() -*/ - -void TQBitArray::setBit( uint index ) -{ -#if defined(QT_CHECK_RANGE) - if ( index >= size() ) { - tqWarning( "TQBitArray::setBit: Index %d out of range", index ); - return; - } -#endif - *(data()+(index>>3)) |= (1 << (index & 7)); -} - -/*! - \fn void TQBitArray::setBit( uint index, bool value ) - - Sets the bit at position \a index to \a value. - - Equivalent to: - \code - if ( value ) - setBit( index ); - else - clearBit( index ); - \endcode - - \sa clearBit() toggleBit() -*/ - -/*! - Clears the bit at position \a index, i.e. sets it to 0. - - \sa setBit(), toggleBit() -*/ - -void TQBitArray::clearBit( uint index ) -{ -#if defined(QT_CHECK_RANGE) - if ( index >= size() ) { - tqWarning( "TQBitArray::clearBit: Index %d out of range", index ); - return; - } -#endif - *(data()+(index>>3)) &= ~(1 << (index & 7)); -} - -/*! - Toggles the bit at position \a index. - - If the previous value was 0, the new value will be 1. If the - previous value was 1, the new value will be 0. - - \sa setBit(), clearBit() -*/ - -bool TQBitArray::toggleBit( uint index ) -{ -#if defined(QT_CHECK_RANGE) - if ( index >= size() ) { - tqWarning( "TQBitArray::toggleBit: Index %d out of range", index ); - return FALSE; - } -#endif - uchar *p = (uchar *)data() + (index>>3); - uchar b = (1 << (index & 7)); // bit position - uchar c = *p & b; // read bit - *p ^= b; // toggle bit - return c; -} - - -/*! - \fn bool TQBitArray::at( uint index ) const - - Returns the value (0 or 1) of the bit at position \a index. - - \sa operator[]() -*/ - -/*! - \fn TQBitVal TQBitArray::operator[]( int index ) - - Implements the [] operator for bit arrays. - - The returned TQBitVal is a context object. It makes it possible to - get and set a single bit value by its \a index position. - - Example: - \code - TQBitArray a( 3 ); - a[0] = 0; - a[1] = 1; - a[2] = a[0] ^ a[1]; - \endcode - - The functions testBit(), setBit() and clearBit() are faster. - - \sa at() -*/ - -/*! - \overload bool TQBitArray::operator[]( int index ) const - - Implements the [] operator for constant bit arrays. -*/ - - -/*! - Performs the AND operation between all bits in this bit array and - \a a. Returns a reference to this bit array. - - The result has the length of the longest of the two bit arrays, - with any missing bits (i.e. if one array is shorter than the - other), taken to be 0. - \code - TQBitArray a( 3 ), b( 2 ); - a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] - b[0] = 1; b[1] = 0; // b = [1 0] - a &= b; // a = [1 0 0] - \endcode - - \sa operator|=(), operator^=(), operator~() -*/ - -TQBitArray &TQBitArray::operator&=( const TQBitArray &a ) -{ - resize( TQMAX(size(), a.size()) ); - uchar *a1 = (uchar *)data(); - uchar *a2 = (uchar *)a.data(); - int n = TQMIN( TQByteArray::size(), a.TQByteArray::size() ); - int p = TQMAX( TQByteArray::size(), a.TQByteArray::size() ) - n; - while ( n-- > 0 ) - *a1++ &= *a2++; - while ( p-- > 0 ) - *a1++ = 0; - return *this; -} - -/*! - Performs the OR operation between all bits in this bit array and - \a a. Returns a reference to this bit array. - - The result has the length of the longest of the two bit arrays, - with any missing bits (i.e. if one array is shorter than the - other), taken to be 0. - \code - TQBitArray a( 3 ), b( 2 ); - a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] - b[0] = 1; b[1] = 0; // b = [1 0] - a |= b; // a = [1 0 1] - \endcode - - \sa operator&=(), operator^=(), operator~() -*/ - -TQBitArray &TQBitArray::operator|=( const TQBitArray &a ) -{ - resize( TQMAX(size(), a.size()) ); - uchar *a1 = (uchar *)data(); - uchar *a2 = (uchar *)a.data(); - int n = TQMIN( TQByteArray::size(), a.TQByteArray::size() ); - while ( n-- > 0 ) - *a1++ |= *a2++; - return *this; -} - -/*! - Performs the XOR operation between all bits in this bit array and - \a a. Returns a reference to this bit array. - - The result has the length of the longest of the two bit arrays, - with any missing bits (i.e. if one array is shorter than the - other), taken to be 0. - \code - TQBitArray a( 3 ), b( 2 ); - a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] - b[0] = 1; b[1] = 0; // b = [1 0] - a ^= b; // a = [0 0 1] - \endcode - - \sa operator&=(), operator|=(), operator~() -*/ - -TQBitArray &TQBitArray::operator^=( const TQBitArray &a ) -{ - resize( TQMAX(size(), a.size()) ); - uchar *a1 = (uchar *)data(); - uchar *a2 = (uchar *)a.data(); - int n = TQMIN( TQByteArray::size(), a.TQByteArray::size() ); - while ( n-- > 0 ) - *a1++ ^= *a2++; - return *this; -} - -/*! - Returns a bit array that contains the inverted bits of this bit array. - - Example: - \code - TQBitArray a( 3 ), b; - a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] - b = ~a; // b = [0 1 0] - \endcode -*/ - -TQBitArray TQBitArray::operator~() const -{ - TQBitArray a( size() ); - uchar *a1 = (uchar *)data(); - uchar *a2 = (uchar *)a.data(); - int n = TQByteArray::size(); - while ( n-- ) - *a2++ = ~*a1++; - a.pad0(); - return a; -} - - -/*! - \relates TQBitArray - - Returns the AND result between the bit arrays \a a1 and \a a2. - - The result has the length of the longest of the two bit arrays, - with any missing bits (i.e. if one array is shorter than the - other), taken to be 0. - - \sa TQBitArray::operator&=() -*/ - -TQBitArray operator&( const TQBitArray &a1, const TQBitArray &a2 ) -{ - TQBitArray tmp = a1.copy(); - tmp &= a2; - return tmp; -} - -/*! - \relates TQBitArray - - Returns the OR result between the bit arrays \a a1 and \a a2. - - The result has the length of the longest of the two bit arrays, - with any missing bits (i.e. if one array is shorter than the - other), taken to be 0. - - \sa TQBitArray::operator|=() -*/ - -TQBitArray operator|( const TQBitArray &a1, const TQBitArray &a2 ) -{ - TQBitArray tmp = a1.copy(); - tmp |= a2; - return tmp; -} - -/*! - \relates TQBitArray - - Returns the XOR result between the bit arrays \a a1 and \a a2. - - The result has the length of the longest of the two bit arrays, - with any missing bits (i.e. if one array is shorter than the - other), taken to be 0. - - \sa TQBitArray::operator^() -*/ - -TQBitArray operator^( const TQBitArray &a1, const TQBitArray &a2 ) -{ - TQBitArray tmp = a1.copy(); - tmp ^= a2; - return tmp; -} - - -/* \enum TQGArray::array_data - - \warning This will be renamed in the next major release of TQt. Until - then it is undocumented and we recommend against its use. - - \internal - - ### 3.0 rename ### - ### 3.0 move it to TQGArray? ### -*/ - - -/*! - \fn TQBitArray::array_data * TQBitArray::newData() - - \internal - - Returns data specific to TQBitArray that extends what TQGArray provides. - TQPtrCollection mechanism for allowing extra/different data. -*/ - - -/*! - \fn void TQBitArray::deleteData ( array_data * d ) - - \internal - - Deletes data specific to TQBitArray that extended what TQGArray provided. - - TQPtrCollection mechanism for allowing extra/different data. -*/ - - -/***************************************************************************** - TQBitArray stream functions - *****************************************************************************/ - -/*! - \relates TQBitArray - - Writes bit array \a a to stream \a s. - - \sa \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ -#ifndef TQT_NO_DATASTREAM -TQDataStream &operator<<( TQDataStream &s, const TQBitArray &a ) -{ - TQ_UINT32 len = a.size(); - s << len; // write size of array - if ( len > 0 ) // write data - s.writeRawBytes( a.data(), a.TQByteArray::size() ); - return s; -} - -/*! - \relates TQBitArray - - Reads a bit array into \a a from stream \a s. - - \sa \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ - -TQDataStream &operator>>( TQDataStream &s, TQBitArray &a ) -{ - TQ_UINT32 len; - s >> len; // read size of array - if ( !a.resize( (uint)len ) ) { // resize array -#if defined(QT_CHECK_NULL) - tqWarning( "TQDataStream: Not enough memory to read TQBitArray" ); -#endif - len = 0; - } - if ( len > 0 ) // read data - s.readRawBytes( a.data(), a.TQByteArray::size() ); - return s; -} - -#endif // TQT_NO_DATASTREAM diff --git a/src/tools/qcstring.cpp b/src/tools/qcstring.cpp deleted file mode 100644 index d35b06e3e..000000000 --- a/src/tools/qcstring.cpp +++ /dev/null @@ -1,2539 +0,0 @@ -/**************************************************************************** -** -** Implementation of extended char array operations, and TQByteArray and -** TQCString classes -** -** 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 requirements 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. -** -**********************************************************************/ - -#include "tqstring.h" -#include "ntqregexp.h" -#include "ntqdatastream.h" - -#ifdef TQT_THREAD_SUPPORT -# include -#endif // TQT_THREAD_SUPPORT - -#include -#include -#include -#include -#include -#ifndef TQT_NO_COMPRESS -#include "../3rdparty/zlib/zlib.h" -#endif - -/***************************************************************************** - Safe and portable C string functions; extensions to standard string.h - *****************************************************************************/ - -/*! - \relates TQCString - - This function is normally part of the C library. TQt implements - memmove() for platforms that do not provide it. - - memmove() copies \a len bytes from \a src into \a dst. The data - is copied correctly even if \a src and \a dst overlap. -*/ - -void *tqmemmove( void *dst, const void *src, uint len ) -{ - char *d; - char *s; - if ( dst > src ) { - d = (char *)dst + len - 1; - s = (char *)src + len - 1; - while ( len-- ) - *d-- = *s--; - } else if ( dst < src ) { - d = (char *)dst; - s = (char *)src; - while ( len-- ) - *d++ = *s++; - } - return dst; -} - - -/*! - \relates TQCString - - Returns a duplicate string. - - Allocates space for a copy of \a src, copies it, and returns a - pointer to the copy. If \a src is 0, it immediately returns 0. - - The returned string must be deleted using \c delete[]. -*/ - -char *tqstrdup( const char *src ) -{ - if ( !src ) - return 0; - char *dst = new char[strlen(src)+1]; - TQ_CHECK_PTR( dst ); - return strcpy( dst, src ); -} - -/*! - \fn char *qstrcpy( char *dst, const char *src ) - - \relates TQCString - - A safe strcpy() function. - - Copies all characters up to and including the '\0' from \a src - into \a dst and returns a pointer to \a dst. -*/ - -/*! - \relates TQCString - - A safe strncpy() function. - - Copies at most \a len bytes from \a src (stopping at \a len or the - terminating '\0' whichever comes first) into \a dst and returns a - pointer to \a dst. Guarantees that \a dst is '\0'-terminated. If - \a src or \a dst is 0, returns 0 immediately. - - \sa qstrcpy() -*/ - -char *tqstrncpy( char *dst, const char *src, uint len ) -{ - if ( !src || !dst ) - return 0; - strncpy( dst, src, len ); - if ( len > 0 ) - dst[len-1] = '\0'; - return dst; -} - -/*! - \fn uint tqstrlen( const char *str ); - - \relates TQCString - - A safe strlen function. - - Returns the number of characters that precede the terminating '\0'. - or 0 if \a str is 0. -*/ - -/*! - \fn int qstrcmp( const char *str1, const char *str2 ); - - \relates TQCString - - A safe strcmp() function. - - Compares \a str1 and \a str2. Returns a negative value if \a str1 - is less than \a str2, 0 if \a str1 is equal to \a str2 or a - positive value if \a str1 is greater than \a str2. - - Special case I: Returns 0 if \a str1 and \a str2 are both 0. - - Special case II: Returns a random nonzero value if \a str1 is 0 - or \a str2 is 0 (but not both). - - \sa tqstrncmp() tqstricmp() tqstrnicmp() - \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \fn int tqstrncmp( const char *str1, const char *str2, uint len ); - - \relates TQCString - - A safe strncmp() function. - - Compares at most \a len bytes of \a str1 and \a str2. - - Returns a negative value if \a str1 is less than \a str2, 0 if \a - str1 is equal to \a str2 or a positive value if \a str1 is greater - than \a str2. - - Special case I: Returns 0 if \a str1 and \a str2 are both 0. - - Special case II: Returns a random nonzero value if \a str1 is 0 - or \a str2 is 0 (but not both). - - \sa qstrcmp(), tqstricmp(), tqstrnicmp() - \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \relates TQCString - - A safe stricmp() function. - - Compares \a str1 and \a str2 ignoring the case. - - Returns a negative value if \a str1 is less than \a str2, 0 if \a - str1 is equal to \a str2 or a positive value if \a str1 is greater - than \a str2. - - Special case I: Returns 0 if \a str1 and \a str2 are both 0. - - Special case II: Returns a random nonzero value if \a str1 is 0 - or \a str2 is 0 (but not both). - - \sa qstrcmp(), tqstrncmp(), tqstrnicmp() - \link #asciinotion Note on character comparisons \endlink -*/ - -int tqstricmp( const char *str1, const char *str2 ) -{ - const uchar *s1 = (const uchar *)str1; - const uchar *s2 = (const uchar *)str2; - int res; - uchar c; - if ( !s1 || !s2 ) - return s1 ? 1 : ( s2 ? -1 : 0 ); - for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ ) - if ( !c ) // strings are equal - break; - return res; -} - -/*! - \relates TQCString - - A safe strnicmp() function. - - Compares at most \a len bytes of \a str1 and \a str2 ignoring the case. - - Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 - is equal to \a str2 or a positive value if \a str1 is greater than \a - str2. - - Special case I: Returns 0 if \a str1 and \a str2 are both 0. - - Special case II: Returns a random nonzero value if \a str1 is 0 - or \a str2 is 0 (but not both). - - \sa qstrcmp(), tqstrncmp() tqstricmp() - \link #asciinotion Note on character comparisons \endlink -*/ - -int tqstrnicmp( const char *str1, const char *str2, uint len ) -{ - const uchar *s1 = (const uchar *)str1; - const uchar *s2 = (const uchar *)str2; - int res; - uchar c; - if ( !s1 || !s2 ) - return s1 ? 1 : ( s2 ? -1 : 0 ); - for ( ; len--; s1++, s2++ ) { - if ( (res = (c=tolower(*s1)) - tolower(*s2)) ) - return res; - if ( !c ) // strings are equal - break; - } - return 0; -} - - -static TQ_UINT16 crc_tbl[16]; -static bool crc_tbl_init = FALSE; - -static void createCRC16Table() // build CRC16 lookup table -{ - uint i; - uint j; - uint v0, v1, v2, v3; - for ( i = 0; i < 16; i++ ) { - v0 = i & 1; - v1 = ( i >> 1 ) & 1; - v2 = ( i >> 2 ) & 1; - v3 = ( i >> 3 ) & 1; - j = 0; -#undef SET_BIT -#define SET_BIT(x, b, v) (x) |= (v) << (b) - SET_BIT( j, 0, v0 ); - SET_BIT( j, 7, v0 ); - SET_BIT( j, 12, v0 ); - SET_BIT( j, 1, v1 ); - SET_BIT( j, 8, v1 ); - SET_BIT( j, 13, v1 ); - SET_BIT( j, 2, v2 ); - SET_BIT( j, 9, v2 ); - SET_BIT( j, 14, v2 ); - SET_BIT( j, 3, v3 ); - SET_BIT( j, 10, v3 ); - SET_BIT( j, 15, v3 ); - crc_tbl[i] = j; - } -} - -/*! - \relates TQMemArray - - Returns the CRC-16 checksum of \a len bytes starting at \a data. - - The checksum is independent of the byte order (endianness). -*/ - -TQ_UINT16 tqChecksum( const char *data, uint len ) -{ - if ( !crc_tbl_init ) { // create lookup table - -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &crc_tbl_init ) : 0 ); -#endif // TQT_THREAD_SUPPORT - - if ( !crc_tbl_init ) { - createCRC16Table(); - crc_tbl_init = TRUE; - } - } - TQ_UINT16 crc = 0xffff; - uchar c; - uchar *p = (uchar *)data; - while ( len-- ) { - c = *p++; - crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; - c >>= 4; - crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; - } - return ~crc & 0xffff; -} - -/*! - \fn TQByteArray tqCompress( const TQByteArray& data ) - - \relates TQByteArray - - Compresses the array \a data and returns the compressed byte - array using zlib. - - \sa tqUncompress() -*/ - -/*! - \relates TQByteArray - - \overload - - Compresses the array \a data which is \a nbytes long and returns the - compressed byte array. -*/ - -#ifndef TQT_NO_COMPRESS -TQByteArray tqCompress( const uchar* data, int nbytes ) -{ - if ( nbytes == 0 ) { - TQByteArray tmp( 4 ); - tmp.fill( 0 ); - return tmp; - } - if ( !data ) { -#if defined(QT_CHECK_RANGE) - tqWarning( "qCompress: data is NULL." ); -#endif - return TQByteArray(); - } - - ulong len = nbytes + nbytes / 100 + 13; - TQByteArray bazip; - int res; - do { - bazip.resize( len + 4 ); - res = ::compress( (uchar*)bazip.data()+4, &len, (uchar*)data, nbytes ); - - switch ( res ) { - case Z_OK: - bazip.resize( len + 4 ); - bazip[0] = ( nbytes & 0xff000000 ) >> 24; - bazip[1] = ( nbytes & 0x00ff0000 ) >> 16; - bazip[2] = ( nbytes & 0x0000ff00 ) >> 8; - bazip[3] = ( nbytes & 0x000000ff ); - break; - case Z_MEM_ERROR: -#if defined(QT_CHECK_RANGE) - tqWarning( "qCompress: Z_MEM_ERROR: Not enough memory." ); -#endif - bazip.resize( 0 ); - break; - case Z_BUF_ERROR: - len *= 2; - break; - } - } while ( res == Z_BUF_ERROR ); - - return bazip; -} -#endif - -/*! - \fn TQByteArray tqUncompress( const TQByteArray& data ) - - \relates TQByteArray - - Uncompresses the array \a data and returns the uncompressed byte - array. - - Returns an empty TQByteArray if the input data was corrupt. - \omit - ADD THE FOLLOWING FOR TQt 4.0 - This function will uncompress data compressed with tqCompress() - from this and any earlier TQt version, back to TQt 3.1 when this - feature was added. - \endomit - - \sa tqCompress() -*/ - -/*! - \relates TQByteArray - - \overload - - Uncompresses the array \a data which is \a nbytes long and returns - the uncompressed byte array. -*/ - -#ifndef TQT_NO_COMPRESS -TQByteArray tqUncompress( const uchar* data, int nbytes ) -{ - if ( !data ) { -#if defined(QT_CHECK_RANGE) - tqWarning( "qUncompress: data is NULL." ); -#endif - return TQByteArray(); - } - if ( nbytes <= 4 ) { -#if defined(QT_CHECK_RANGE) - if ( nbytes < 4 || ( data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0 ) ) - tqWarning( "qUncompress: Input data is corrupted." ); -#endif - return TQByteArray(); - } - ulong expectedSize = ( data[0] << 24 ) | ( data[1] << 16 ) | ( data[2] << 8 ) | data[3]; - ulong len = TQMAX( expectedSize, 1 ); - TQByteArray baunzip; - int res; - do { - if ( baunzip.resize( len ) ) { - res = ::uncompress( (uchar*)baunzip.data(), &len, - (uchar*)data+4, nbytes-4 ); - } else { - res = Z_MEM_ERROR; - } - - switch ( res ) { - case Z_OK: - if ( len != baunzip.size() ) - baunzip.resize( len ); - break; - case Z_MEM_ERROR: -#if defined(QT_CHECK_RANGE) - tqWarning( "qUncompress: Z_MEM_ERROR: Not enough memory." ); -#endif - break; - case Z_BUF_ERROR: - len *= 2; - break; - case Z_DATA_ERROR: -#if defined(QT_CHECK_RANGE) - tqWarning( "qUncompress: Z_DATA_ERROR: Input data is corrupted." ); -#endif - break; - } - } while ( res == Z_BUF_ERROR ); - - if ( res != Z_OK ) - baunzip = TQByteArray(); - - return baunzip; -} -#endif - -/***************************************************************************** - TQByteArray documentation - *****************************************************************************/ - -/*! - \class TQByteArray - \reentrant - \brief The TQByteArray class provides an array of bytes. - - \ingroup collection - \ingroup tools - - The TQByteArray class provides an explicitly shared array of bytes. - It is useful for manipulating memory areas with custom data. - TQByteArray is implemented as a TQMemArray\. See the \l - TQMemArray documentation for further information. -*/ - -/*! - \fn TQByteArray::TQByteArray() - - Constructs an empty TQByteArray. -*/ - -/*! - \fn TQByteArray::TQByteArray( int size ) - - Constructs a TQByteArray of size \a size. -*/ - -/***************************************************************************** - TQByteArray stream functions - *****************************************************************************/ - -/*! - \relates TQMemArray - - Writes byte array \a a to the stream \a s and returns a reference - to the stream. - - \sa \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ -#ifndef TQT_NO_DATASTREAM - -TQDataStream &operator<<( TQDataStream &s, const TQByteArray &a ) -{ - return s.writeBytes( a.data(), a.size() ); -} - -/*! - \relates TQMemArray - - Reads a byte array into \a a from the stream \a s and returns a - reference to the stream. - - \sa \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ - -TQDataStream &operator>>( TQDataStream &s, TQByteArray &a ) -{ - TQ_UINT32 len; - s >> len; // read size of array - if ( len == 0 || s.eof() ) { // end of file reached - a.resize( 0 ); - return s; - } - if ( !a.resize( (uint)len ) ) { // resize array -#if defined(QT_CHECK_NULL) - tqWarning( "TQDataStream: Not enough memory to read TQByteArray" ); -#endif - len = 0; - } - if ( len > 0 ) // not null array - s.readRawBytes( a.data(), (uint)len ); - return s; -} - -#endif //TQT_NO_DATASTREAM - -/***************************************************************************** - TQCString member functions - *****************************************************************************/ - -/*! - \class TQCString ntqcstring.h - \reentrant - \brief The TQCString class provides an abstraction of the classic C - zero-terminated char array (char *). - - \ingroup text - \ingroup collection - \ingroup tools - \ingroup shared - - TQCString inherits TQByteArray, which is defined as - TQMemArray\. Since TQCString is a TQMemArray, it uses \link - shclass.html explicit sharing\endlink with a reference count. - - TQCString tries to behave like a more convenient \c{const char *}. - The price of doing this is that some algorithms will perform - badly. For example, append() is O(length()) since it scans for a - null terminator. Although you might use TQCString for text that is - never exposed to the user, for most purposes, and especially for - user-visible text, you should use TQString. TQString provides - implicit sharing, Unicode and other internationalization support, - and is well optimized. - - Note that for the TQCString methods that take a \c{const char *} - parameter the \c{const char *} must either be 0 (null) or not-null - and '\0' (NUL byte) terminated; otherwise the results are - undefined. - - A TQCString that has not been assigned to anything is \e null, i.e. - both the length and the data pointer is 0. A TQCString that - references the empty string ("", a single '\0' char) is \e empty. - Both null and empty TQCStrings are legal parameters to the methods. - Assigning \c{const char *} 0 to TQCString produces a null TQCString. - - The length() function returns the length of the string; resize() - resizes the string and truncate() truncates the string. A string - can be filled with a character using fill(). Strings can be left - or right padded with characters using leftJustify() and - rightJustify(). Characters, strings and regular expressions can be - searched for using find() and findRev(), and counted using - contains(). - - Strings and characters can be inserted with insert() and appended - with append(). A string can be prepended with prepend(). - Characters can be removed from the string with remove() and - replaced with replace(). - - Portions of a string can be extracted using left(), right() and - mid(). Whitespace can be removed using stripWhiteSpace() and - simplifyWhiteSpace(). Strings can be converted to uppercase or - lowercase with upper() and lower() respectively. - - Strings that contain numbers can be converted to numbers with - toShort(), toInt(), toLong(), toULong(), toFloat() and toDouble(). - Numbers can be converted to strings with setNum(). - - Many operators are overloaded to work with TQCStrings. TQCString - also supports some more obscure functions, e.g. sprintf(), - setStr() and setExpand(). - - \target asciinotion - \sidebar Note on Character Comparisons - - In TQCString the notion of uppercase and lowercase and of which - character is greater than or less than another character is locale - dependent. This affects functions which support a case insensitive - option or which compare or lowercase or uppercase their arguments. - Case insensitive operations and comparisons will be accurate if - both strings contain only ASCII characters. (If \c $LC_CTYPE is - set, most Unix systems do "the right thing".) Functions that this - affects include contains(), find(), findRev(), \l operator<(), \l - operator<=(), \l operator>(), \l operator>=(), lower() and - upper(). - - This issue does not apply to \l{TQString}s since they represent - characters using Unicode. - \endsidebar - - Performance note: The TQCString methods for TQRegExp searching are - implemented by converting the TQCString to a TQString and performing - the search on that. This implies a deep copy of the TQCString data. - If you are going to perform many TQRegExp searches on a large - TQCString, you will get better performance by converting the - TQCString to a TQString yourself, and then searching in the TQString. -*/ - -/*! - \fn TQCString::TQCString() - - Constructs a null string. - - \sa isNull() -*/ - -/*! - \fn TQCString::TQCString( const TQCString &s ) - - Constructs a shallow copy \a s. - - \sa assign() -*/ - -/*! - Constructs a string with room for \a size characters, including - the '\0'-terminator. Makes a null string if \a size == 0. - - If \a size \> 0, then the first and last characters in the string - are initialized to '\0'. All other characters are uninitialized. - - \sa resize(), isNull() -*/ - -TQCString::TQCString( int size ) - : TQByteArray( size ) -{ - if ( size > 0 ) { - *data() = '\0'; // set terminator - *(data()+(size-1)) = '\0'; - } -} - -/*! - Constructs a string that is a deep copy of \a str. - - If \a str is 0 a null string is created. - - \sa isNull() -*/ - -TQCString::TQCString( const char *str ) -{ - duplicate( str, tqstrlen(str) + 1 ); -} - - -/*! - Constructs a string that is a deep copy of \a str. The copy will - be at most \a maxsize bytes long including the '\0'-terminator. - - Example: - \code - TQCString str( "helloworld", 6 ); // assigns "hello" to str - \endcode - - If \a str contains a 0 byte within the first \a maxsize bytes, the - resulting TQCString will be terminated by this 0. If \a str is 0 a - null string is created. - - \sa isNull() -*/ - -TQCString::TQCString( const char *str, uint maxsize ) -{ - if ( str == 0 ) - return; - uint len; // index of first '\0' - for ( len = 0; len < maxsize - 1; len++ ) { - if ( str[len] == '\0' ) - break; - } - TQByteArray::resize( len + 1 ); - memcpy( data(), str, len ); - data()[len] = 0; -} - -/*! - \reimp -*/ - -TQCString::~TQCString() -{ -} - -/*! - \fn TQCString &TQCString::operator=( const TQCString &s ) - - Assigns a shallow copy of \a s to this string and returns a - reference to this string. -*/ - -/*! - \overload TQCString &TQCString::operator=( const char *str ) - - Assigns a deep copy of \a str to this string and returns a - reference to this string. - - If \a str is 0 a null string is created. - - \sa isNull() -*/ - -/*! - \fn bool TQCString::isNull() const - - Returns TRUE if the string is null, i.e. if data() == 0; otherwise - returns FALSE. A null string is also an empty string. - - Example: - \code - TQCString a; // a.data() == 0, a.size() == 0, a.length() == 0 - TQCString b == ""; // b.data() == "", b.size() == 1, b.length() == 0 - a.isNull(); // TRUE because a.data() == 0 - a.isEmpty(); // TRUE because a.length() == 0 - b.isNull(); // FALSE because b.data() == "" - b.isEmpty(); // TRUE because b.length() == 0 - \endcode - - \sa isEmpty(), length(), size() -*/ - -/*! - \fn bool TQCString::isEmpty() const - - Returns TRUE if the string is empty, i.e. if length() == 0; - otherwise returns FALSE. An empty string is not always a null - string. - - See example in isNull(). - - \sa isNull(), length(), size() -*/ - -/*! - \fn uint TQCString::length() const - - Returns the length of the string, excluding the '\0'-terminator. - Equivalent to calling \c strlen(data()). - - Null strings and empty strings have zero length. - - \sa size(), isNull(), isEmpty() -*/ - -/*! - \fn bool TQCString::truncate( uint pos ) - - Truncates the string at position \a pos. - - Equivalent to calling \c resize(pos+1). - - Example: - \code - TQCString s = "truncate this string"; - s.truncate( 5 ); // s == "trunc" - \endcode - - \sa resize() -*/ - -/*! - Extends or shrinks the string to \a len bytes, including the - '\0'-terminator. - - A '\0'-terminator is set at position \c{len - 1} unless - \c{len == 0}. - - Example: - \code - TQCString s = "resize this string"; - s.resize( 7 ); // s == "resize" - \endcode - - \sa truncate() -*/ - -bool TQCString::resize( uint len ) -{ - detach(); - uint wasNull = isNull(); - if ( !TQByteArray::resize(len) ) - return FALSE; - if ( len ) - data()[len - 1] = '\0'; - if ( len > 0 && wasNull ) - data()[0] = '\0'; - return TRUE; -} - - -/*! - Implemented as a call to the native vsprintf() (see the manual for - your C library). - - If the string is shorter than 256 characters, this sprintf() calls - resize(256) to decrease the chance of memory corruption. The - string is resized back to its actual length before sprintf() - returns. - - Example: - \code - TQCString s; - s.sprintf( "%d - %s", 1, "first" ); // result < 256 chars - - TQCString big( 25000 ); // very long string - big.sprintf( "%d - %s", 2, longString ); // result < 25000 chars - \endcode - - \warning All vsprintf() implementations will write past the end of - the target string (*this) if the \a format specification and - arguments happen to be longer than the target string, and some - will also fail if the target string is longer than some arbitrary - implementation limit. - - Giving user-supplied arguments to sprintf() is risky: Sooner or - later someone will paste a huge line into your application. -*/ - -TQCString &TQCString::sprintf( const char *format, ... ) -{ - detach(); - va_list ap; - va_start( ap, format ); - if ( size() < 256 ) - TQByteArray::resize( 256 ); // make string big enough -#ifdef QT_VSNPRINTF - QT_VSNPRINTF( data(), size(), format, ap ); -#else - vsprintf( data(), format, ap ); -#endif - resize( tqstrlen(data()) + 1 ); // truncate - va_end( ap ); - return *this; -} - - -/*! - Fills the string with \a len bytes of character \a c, followed by - a '\0'-terminator. - - If \a len is negative, then the current string length is used. - - Returns FALSE is \a len is nonnegative and there is not enough - memory to resize the string; otherwise returns TRUE. -*/ - -bool TQCString::fill( char c, int len ) -{ - detach(); - if ( len < 0 ) - len = length(); - if ( !TQByteArray::fill(c,len+1) ) - return FALSE; - *(data()+len) = '\0'; - return TRUE; -} - - -/*! - \fn TQCString TQCString::copy() const - - Returns a deep copy of this string. - - \sa detach() -*/ - - -/*! - Finds the first occurrence of the character \a c, starting at - position \a index. - - The search is case sensitive if \a cs is TRUE, or case insensitive - if \a cs is FALSE. - - Returns the position of \a c, or -1 if \a c could not be found. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -int TQCString::find( char c, int index, bool cs ) const -{ - if ( (uint)index >= size() ) // index outside string - return -1; - const char *d; - if ( cs ) { // case sensitive - d = strchr( data()+index, c ); - } else { - d = data()+index; - c = tolower( (uchar) c ); - while ( *d && tolower((uchar) *d) != c ) - d++; - if ( !*d && c ) // not found - d = 0; - } - return d ? (int)(d - data()) : -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. - - The search is case sensitive if \a cs is TRUE, or case insensitive - if \a cs is FALSE. - - Returns the position of \a str, or -1 if \a str could not be - found. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -int TQCString::find( const char *str, int index, bool cs ) const -{ - return find( str, index, cs, length() ); -} - -int TQCString::find( const char *str, int index, bool cs, uint l ) const -{ - if ( (uint)index >= size() ) - return -1; - if ( !str ) - return -1; - if ( !*str ) - return index; - const uint sl = tqstrlen( str ); - if ( sl + index > l ) - return -1; - - if ( sl == 1 ) - return find( *str, index, cs ); - - /* - See TQString::find() for details. - */ - const char* needle = str; - const char* haystack = data() + index; - const char* end = data() + (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] ); - hashHaystack = ((hashHaystack<<1) + haystack[i] ); - } - hashHaystack -= *(haystack+sl_minus_1); - - while ( haystack <= end ) { - hashHaystack += *(haystack+sl_minus_1); - if ( hashHaystack == hashNeedle && *needle == *haystack - && tqstrncmp( needle, haystack, sl ) == 0 ) - return haystack - data(); - - REHASH( *haystack ); - ++haystack; - } - } else { - for ( i = 0; i < sl; ++i ) { - hashNeedle = ((hashNeedle<<1) + - tolower( needle[i] ) ); - hashHaystack = ((hashHaystack<<1) + - tolower( haystack[i] ) ); - } - hashHaystack -= tolower(*(haystack+sl_minus_1)); - - while ( haystack <= end ) { - hashHaystack += tolower(*(haystack+sl_minus_1)); - if ( hashHaystack == hashNeedle - && tqstrnicmp( needle, haystack, sl ) == 0 ) - return haystack - data(); - - REHASH( tolower(*haystack) ); - ++haystack; - } - } - return -1; -} - - -/*! - Finds the first occurrence of the character \a c, starting at - position \a index and searching backwards. - - The search is case sensitive if \a cs is TRUE, or case insensitive - if \a cs is FALSE. - - Returns the position of \a c, or -1 if \a c could not be found. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -int TQCString::findRev( char c, int index, bool cs ) const -{ - const char *b = data(); - const char *d; - if ( index < 0 ) - index = length(); - if ( (uint)index >= size() ) - return -1; - d = b + index; - if ( cs ) { - while ( d >= b && *d != c ) - d--; - } else { - c = tolower( (uchar) c ); - while ( d >= b && tolower((uchar) *d) != c ) - d--; - } - return d >= b ? (int)(d - b) : -1; -} - -/*! - \overload - - Finds the first occurrence of the string \a str, starting at - position \a index and searching backwards. - - The search is case sensitive if \a cs is TRUE, or case insensitive - if \a cs is FALSE. - - Returns the position of \a str, or -1 if \a str could not be - found. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -int TQCString::findRev( const char *str, int index, bool cs ) const -{ - /* - See TQString::find() for explanations. - */ - const uint sl = tqstrlen( str ); - const uint l = length(); - int delta = l-sl; - if ( index < 0 ) - index = delta; - if ( index < 0 || index > (int)l ) - return -1; - if ( index > delta ) - index = delta; - - if ( sl == 1 ) - return findRev( *str, index, cs ); - - const char* needle = str; - const char* haystack = data() + index; - const char* end = data(); - const uint sl_minus_1 = sl-1; - const char* n = needle+sl_minus_1; - const char* h = haystack+sl_minus_1; - uint hashNeedle = 0, hashHaystack = 0, i; - - if ( cs ) { - for ( i = 0; i < sl; ++i ) { - hashNeedle = ((hashNeedle<<1) + *(n-i) ); - hashHaystack = ((hashHaystack<<1) + *(h-i) ); - } - hashHaystack -= *haystack; - while ( haystack >= end ) { - hashHaystack += *haystack; - if ( hashHaystack == hashNeedle && tqstrncmp( needle, haystack, sl ) == 0 ) - return haystack-data(); - --haystack; - REHASH( *(haystack+sl) ); - } - } else { - for ( i = 0; i < sl; ++i ) { - hashNeedle = ((hashNeedle<<1) + tolower( *(n-i) ) ); - hashHaystack = ((hashHaystack<<1) + tolower( *(h-i) ) ); - } - hashHaystack -= tolower(*haystack); - while ( haystack >= end ) { - hashHaystack += tolower(*haystack); - if ( hashHaystack == hashNeedle && tqstrnicmp( needle, haystack, sl ) == 0 ) - return haystack-data(); - --haystack; - REHASH( tolower(*(haystack+sl)) ); - } - } - return -1; -} - - -/*! - Returns the number of times the character \a c occurs in the - string. - - The match is case sensitive if \a cs is TRUE, or case insensitive - if \a cs if FALSE. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -int TQCString::contains( char c, bool cs ) const -{ - int count = 0; - char *d = data(); - if ( !d ) - return 0; - if ( cs ) { // case sensitive - while ( *d ) - if ( *d++ == c ) - count++; - } else { // case insensitive - c = tolower( (uchar) c ); - while ( *d ) { - if ( tolower((uchar) *d) == c ) - count++; - d++; - } - } - return count; -} - -/*! - \overload - - Returns the number of times \a str occurs in the string. - - The match is case sensitive if \a cs is TRUE, or case insensitive - if \a cs if FALSE. - - This function counts overlapping substrings, for example, "banana" - contains two occurrences of "ana". - - \sa findRev() - \link #asciinotion Note on character comparisons \endlink -*/ - -int TQCString::contains( const char *str, bool cs ) const -{ - int count = 0; - int i = -1; - uint l = length(); - // use find for the faster hashing algorithm - while ( ( i = find ( str, i+1, cs, l ) ) != -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. - - Example: - \code - TQCString s = "Pineapple"; - TQCString t = s.left( 4 ); // t == "Pine" - \endcode - - \sa right(), mid() -*/ -TQCString TQCString::left( uint len ) const -{ - if ( isEmpty() ) { - TQCString empty; - return empty; - } else if ( len >= size() ) { - TQCString same( data() ); - return same; - } else { - TQCString s( len+1 ); - strncpy( s.data(), data(), len ); - *(s.data()+len) = '\0'; - return s; - } -} - -/*! - Returns a substring that contains the \a len rightmost characters - of the string. - - The whole string is returned if \a len exceeds the length of the - string. - - Example: - \code - TQCString s = "Pineapple"; - TQCString t = s.right( 5 ); // t == "apple" - \endcode - - \sa left(), mid() -*/ - -TQCString TQCString::right( uint len ) const -{ - if ( isEmpty() ) { - TQCString empty; - return empty; - } else { - uint l = length(); - if ( len > l ) - len = l; - char *p = data() + (l - len); - return TQCString( p ); - } -} - -/*! - Returns a substring that contains at most \a len characters from - this string, starting at position \a index. - - Returns a null string if the string is empty or if \a index is out - of range. Returns the whole string from \a index if \a index+len - exceeds the length of the string. - - Example: - \code - TQCString s = "Two pineapples"; - TQCString t = s.mid( 4, 3 ); // t == "pin" - \endcode - - \sa left(), right() -*/ - -TQCString TQCString::mid( uint index, uint len ) const -{ - uint slen = tqstrlen( data() ); - if ( isEmpty() || index >= slen ) { - TQCString empty; - return empty; - } else { - if ( len > slen-index ) - len = slen - index; - char *p = data()+index; - TQCString s( len+1 ); - strncpy( s.data(), p, len ); - *(s.data()+len) = '\0'; - return s; - } -} - -/*! - Returns a string of length \a width (plus one for the terminating - '\0') that contains this string padded with the \a fill character. - - If the length of the string exceeds \a width and \a truncate is - FALSE (the default), then the returned string is a copy of the - string. If the length of the string exceeds \a width and \a - truncate is TRUE, then the returned string is a left(\a width). - - Example: - \code - TQCString s("apple"); - TQCString t = s.leftJustify(8, '.'); // t == "apple..." - \endcode - - \sa rightJustify() -*/ - -TQCString TQCString::leftJustify( uint width, char fill, bool truncate ) const -{ - TQCString result; - int len = tqstrlen(data()); - int padlen = width - len; - if ( padlen > 0 ) { - result.TQByteArray::resize( len+padlen+1 ); - memcpy( result.data(), data(), len ); - memset( result.data()+len, fill, padlen ); - result[len+padlen] = '\0'; - } else { - if ( truncate ) - result = left( width ); - else - result = copy(); - } - return result; -} - -/*! - Returns a string of length \a width (plus one for the terminating - '\0') that contains zero or more of the \a fill character followed - by this string. - - If the length of the string exceeds \a width and \a truncate is - FALSE (the default), then the returned string is a copy of the - string. If the length of the string exceeds \a width and \a - truncate is TRUE, then the returned string is a left(\a width). - - Example: - \code - TQCString s("pie"); - TQCString t = s.rightJustify(8, '.'); // t == ".....pie" - \endcode - - \sa leftJustify() -*/ - -TQCString TQCString::rightJustify( uint width, char fill, bool truncate ) const -{ - TQCString result; - int len = tqstrlen(data()); - int padlen = width - len; - if ( padlen > 0 ) { - result.TQByteArray::resize( len+padlen+1 ); - memset( result.data(), fill, padlen ); - memcpy( result.data()+padlen, data(), len ); - result[len+padlen] = '\0'; - } else { - if ( truncate ) - result = left( width ); - else - result = copy(); - } - return result; -} - -/*! - Returns a new string that is a copy of this string converted to lower - case. - - Example: - \code - TQCString s("Credit"); - TQCString t = s.lower(); // t == "credit" - \endcode - - \sa upper() - \link #asciinotion Note on character comparisons \endlink -*/ - -TQCString TQCString::lower() const -{ - TQCString s( data() ); - char *p = s.data(); - if ( p ) { - while ( *p ) { - *p = tolower( (uchar) *p ); - p++; - } - } - return s; -} - -/*! - Returns a new string that is a copy of this string converted to upper case. - - Example: - \code - TQCString s( "Debit" ); - TQCString t = s.upper(); // t == "DEBIT" - \endcode - - \sa lower() - \link #asciinotion Note on character comparisons \endlink -*/ - -TQCString TQCString::upper() const -{ - TQCString s( data() ); - char *p = s.data(); - if ( p ) { - while ( *p ) { - *p = toupper(*p); - p++; - } - } - return s; -} - - -/*! - Returns a new string that has white space removed from the start - and the end. - - White space means the decimal ASCII codes 9, 10, 11, 12, 13 and - 32. - - Example: - \code - TQCString s = " space "; - TQCString t = s.stripWhiteSpace(); // t == "space" - \endcode - - \sa simplifyWhiteSpace() -*/ - -TQCString TQCString::stripWhiteSpace() const -{ - if ( isEmpty() ) // nothing to do - return copy(); - - char *s = data(); - TQCString result = s; - int reslen = result.length(); - if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) ) - return result; // returns a copy - - s = result.data(); - int start = 0; - int end = reslen - 1; - while ( isspace((uchar) s[start]) ) // skip white space from start - start++; - if ( s[start] == '\0' ) { // only white space - result.resize( 1 ); - return result; - } - while ( end && isspace((uchar) s[end]) ) // skip white space from end - end--; - end -= start - 1; - memmove( result.data(), &s[start], end ); - result.resize( end + 1 ); - return result; -} - - -/*! - Returns a new string that has white space removed from the start - and the end, plus any sequence of internal white space replaced - with a single space (ASCII 32). - - White space means the decimal ASCII codes 9, 10, 11, 12, 13 and - 32. - - \code - TQCString s = " lots\t of\nwhite space "; - TQCString t = s.simplifyWhiteSpace(); // t == "lots of white space" - \endcode - - \sa stripWhiteSpace() -*/ - -TQCString TQCString::simplifyWhiteSpace() const -{ - if ( isEmpty() ) // nothing to do - return copy(); - TQCString result( size() ); - char *from = data(); - char *to = result.data(); - char *first = to; - for ( ;; ) { - while ( isspace((uchar) *from) ) - from++; - while ( *from && !isspace((uchar) *from) ) - *to++ = *from++; - if ( *from ) - *to++ = 0x20; // ' ' - else - break; - } - if ( to > first && *(to-1) == 0x20 ) - to--; - *to = '\0'; - result.resize( (int)(to - result.data()) + 1 ); - return result; -} - - -/*! - \overload - - Inserts string \a s into the string at position \a index. - - If \a index is beyond the end of the string, the string is - padded with spaces (ASCII 32) to length \a index and then \a s - is appended. - - \code - TQCString s = "I like fish"; - s.insert( 2, "don't "); // s == "I don't like fish" - - s = "x"; // index 01234 - s.insert( 3, "yz" ); // s == "x yz" - \endcode -*/ - -TQCString &TQCString::insert( uint index, const char *s ) -{ - int len = tqstrlen(s); - if ( len == 0 ) - return *this; - uint olen = length(); - int nlen = olen + len; - if ( index >= olen ) { // insert after end of string - detach(); - if ( TQByteArray::resize(nlen+index-olen+1, TQByteArray::SpeedOptim ) ) { - memset( data()+olen, ' ', index-olen ); - memcpy( data()+index, s, len+1 ); - } - } else { - detach(); - if ( TQByteArray::resize(nlen+1, TQByteArray::SpeedOptim ) ) { // normal insert - memmove( data()+index+len, data()+index, olen-index+1 ); - memcpy( data()+index, s, len ); - } - } - return *this; -} - -/*! - Inserts character \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 - padded with spaces (ASCII 32) to length \a index and then \a c - is appended. - - Example: - \code - TQCString s = "Yes"; - s.insert( 3, '!'); // s == "Yes!" - \endcode - - \sa remove(), replace() -*/ - -TQCString &TQCString::insert( uint index, char c ) // insert char -{ - char buf[2]; - buf[0] = c; - buf[1] = '\0'; - return insert( index, buf ); -} - -/*! - \fn TQCString &TQCString::prepend( const char *s ) - - Prepend \a s to the string. Equivalent to insert(0, s). - - \sa insert() -*/ - -/*! - Removes \a len characters from the string, starting at position \a - index, and returns a reference to the string. - - If \a index is out of range, nothing happens. If \a index is - valid, but \a index + \a len is larger than the length of the - string, the string is truncated at position \a index. - - \code - TQCString s = "Montreal"; - s.remove( 1, 4 ); // s == "Meal" - \endcode - - \sa insert(), replace() -*/ - -TQCString &TQCString::remove( uint index, uint len ) -{ - uint olen = length(); - if ( index + len >= olen ) { // range problems - if ( index < olen ) { // index ok - detach(); - resize( index+1 ); - } - } else if ( len != 0 ) { - detach(); - memmove( data()+index, data()+index+len, olen-index-len+1 ); - TQByteArray::resize(olen-len+1, TQByteArray::SpeedOptim ); - } - return *this; -} - -/*! - Replaces \a len characters from the string, starting at position - \a index, with \a str, and returns a reference to the string. - - If \a index is out of range, nothing is removed and \a str is - appended at the end of the string. If \a index is valid, but \a - index + \a len is larger than the length of the string, \a str - replaces the rest of the string from position \a index. - - \code - TQCString s = "Say yes!"; - s.replace( 4, 3, "NO" ); // s == "Say NO!" - \endcode - - \sa insert(), remove() -*/ - -TQCString &TQCString::replace( uint index, uint len, const char *str ) -{ - remove( index, len ); - insert( index, str ); - return *this; -} - - -/*! \overload - - Replaces every occurrence of the character \a c in the string - with \a after. Returns a reference to the string. - - Example: - \code - TQCString s = "a,b,c"; - s.replace( ',', " or " ); - // s == "a or b or c" - \endcode -*/ -TQCString &TQCString::replace( char c, const char *after ) -{ - char str[2]; - str[0] = c; - str[1] = '\0'; - return replace( str, after ); -} - -/*! \overload - - Replaces every occurrence of the string \a before in the string - with the string \a after. Returns a reference to the string. - - Example: - \code - TQCString s = "Greek is Greek"; - s.replace( "Greek", "English" ); - // s == "English is English" - \endcode -*/ - -TQCString &TQCString::replace( const char *before, const char *after ) -{ - if ( before == after || isNull() ) - return *this; - - detach(); - - int index = 0; - const int bl = before ? int(strlen( before )) : 0; - const int al = after ? int(strlen( after )) : 0; - char *d = data(); - uint len = length(); - - if ( bl == al ) { - if ( bl ) { - while( (index = find( before, index, TRUE, len ) ) != -1 ) { - memcpy( d+index, after, al ); - index += bl; - } - } - } else if ( al < bl ) { - uint to = 0; - uint movestart = 0; - uint num = 0; - while( (index = find( before, index, TRUE, len ) ) != -1 ) { - if ( num ) { - int msize = index - movestart; - if ( msize > 0 ) { - memmove( d + to, d + movestart, msize ); - to += msize; - } - } else { - to = index; - } - if ( al ) { - memcpy( d + to, after, al ); - to += al; - } - index += bl; - movestart = index; - num++; - } - if ( num ) { - int msize = len - movestart; - if ( msize > 0 ) - memmove( d + to, d + movestart, msize ); - resize( len - num*(bl-al) + 1 ); - } - } 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 = find(before, index, TRUE, len); - 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 = len + adjust; - int moveend = len; - if ( newlen > len ) { - resize( newlen + 1 ); - len = newlen; - } - d = data(); - - while( pos ) { - pos--; - int movestart = indices[pos] + bl; - int insertstart = indices[pos] + pos*(al-bl); - int moveto = insertstart + al; - memmove( d + moveto, d + movestart, (moveend - movestart) ); - if ( after ) - memcpy( d + insertstart, after, al ); - moveend = movestart - bl; - } - } - } - return *this; -} - -/*! \overload - - Replaces every occurrence of \a c1 with the char \a c2. - Returns a reference to the string. -*/ -TQCString &TQCString::replace( char c1, char c2 ) -{ - detach(); - uint i = 0; - char *d = data(); - uint len = length(); - while ( i < len ) { - if ( d[i] == c1 ) - d[i] = c2; - i++; - } - return *this; -} - - -#ifndef TQT_NO_REGEXP_CAPTURE -/*! - \overload - - Finds the first occurrence of the regular expression \a rx, - starting at position \a index. - - Returns the position of the next match, or -1 if \a rx was not - found. - - \warning If you want to apply this function repeatedly to the same - string it is more efficient to convert the string to a TQString and - apply the function to that. -*/ - -int TQCString::find( const TQRegExp& rx, int index ) const -{ - TQString d = TQString::fromAscii( data() ); - return d.find( rx, index ); -} - -/*! - \overload - - Finds the first occurrence of the regular expression \a rx, - starting at position \a index and searching backwards. - - Returns the position of the next match (backwards), or -1 if \a rx - was not found. - - \warning If you want to apply this function repeatedly to the same - string it is more efficient to convert the string to a TQString and - apply the function to that. -*/ - -int TQCString::findRev( const TQRegExp& rx, int index ) const -{ - TQString d = TQString::fromAscii( data() ); - return d.findRev( rx, index ); -} - -/*! - \overload - - Counts the number of overlapping occurrences of \a rx in the string. - - Example: - \code - TQString s = "banana and panama"; - TQRegExp r = TQRegExp( "a[nm]a", TRUE, FALSE ); - s.contains( r ); // 4 matches - \endcode - - \sa find(), findRev() - - \warning If you want to apply this function repeatedly to the same - string it is more efficient to convert the string to a TQString and - apply the function to that. -*/ - -int TQCString::contains( const TQRegExp &rx ) const -{ - TQString d = TQString::fromAscii( data() ); - return d.contains( rx ); -} - - -/*! - \overload - - Replaces every occurrence of \a rx in the string with \a str. - Returns a reference to the string. - - Example: - \code - TQString s = "banana"; - s.replace( TQRegExp("a.*a"), "" ); // becomes "b" - - s = "banana"; - s.replace( TQRegExp("^[bn]a"), "X" ); // becomes "Xnana" - - s = "banana"; - s.replace( TQRegExp("^[bn]a"), "" ); // becomes "nana" - \endcode - - \warning If you want to apply this function repeatedly to the same - string it is more efficient to convert the string to a TQString and - apply the function to that. -*/ - -TQCString &TQCString::replace( const TQRegExp &rx, const char *str ) -{ - TQString d = TQString::fromAscii( data() ); - TQString r = TQString::fromAscii( str ); - d.replace( rx, r ); - setStr( d.ascii() ); - return *this; -} -#endif //TQT_NO_REGEXP - -/*! - Returns the string converted to a \c long value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, or if it has trailing garbage; otherwise \a *ok is set to - TRUE. -*/ - -long TQCString::toLong( bool *ok ) const -{ - char *p = data(); - long val=0; - const long max_mult = LONG_MAX / 10; - bool is_ok = FALSE; - int neg = 0; - if ( !p ) - goto bye; - while ( isspace((uchar) *p) ) // skip leading space - p++; - if ( *p == '-' ) { - p++; - neg = 1; - } else if ( *p == '+' ) { - p++; - } - if ( !isdigit((uchar) *p) ) - goto bye; - while ( isdigit((uchar) *p) ) { - if ( val > max_mult || (val == max_mult && (*p-'0') > 7+neg) ) - goto bye; - val = 10*val + (*p++ - '0'); - } - if ( neg ) - val = -val; - while ( isspace((uchar) *p) ) // skip trailing space - p++; - if ( *p == '\0' ) - is_ok = TRUE; -bye: - if ( ok ) - *ok = is_ok; - return is_ok ? val : 0; -} - -/*! - Returns the string converted to an \c{unsigned long} value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, or if it has trailing garbage; otherwise \a *ok is set to - TRUE. -*/ - -ulong TQCString::toULong( bool *ok ) const -{ - char *p = data(); - ulong val=0; - const ulong max_mult = ULONG_MAX / 10; - bool is_ok = FALSE; - if ( !p ) - goto bye; - while ( isspace((uchar) *p) ) // skip leading space - p++; - if ( *p == '+' ) - p++; - if ( !isdigit((uchar) *p) ) - goto bye; - while ( isdigit((uchar) *p) ) { - if ( val > max_mult || (val == max_mult && (*p-'0') > 5) ) - goto bye; - val = 10*val + (*p++ - '0'); - } - while ( isspace((uchar) *p) ) // skip trailing space - p++; - if ( *p == '\0' ) - is_ok = TRUE; -bye: - if ( ok ) - *ok = is_ok; - return is_ok ? val : 0; -} - -/*! - Returns the string converted to a \c{short} value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, is out of range, or if it has trailing garbage; otherwise - \a *ok is set to TRUE. -*/ - -short TQCString::toShort( bool *ok ) const -{ - long v = toLong( ok ); - 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} value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, is out of range, or if it has trailing garbage; otherwise - \a *ok is set to TRUE. -*/ - -ushort TQCString::toUShort( bool *ok ) const -{ - ulong v = toULong( ok ); - if ( v > USHRT_MAX ) { - if ( ok ) - *ok = FALSE; - v = 0; - } - return (ushort)v; -} - - -/*! - Returns the string converted to a \c{int} value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, or if it has trailing garbage; otherwise \a *ok is set to - TRUE. -*/ - -int TQCString::toInt( bool *ok ) const -{ - long v = toLong( ok ); - 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} value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, or if it has trailing garbage; otherwise \a *ok is set to - TRUE. -*/ - -uint TQCString::toUInt( bool *ok ) const -{ - ulong v = toULong( ok ); - 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: \a *ok is set to FALSE if the string is not a - number, or if it has trailing garbage; otherwise \a *ok is set to - TRUE. -*/ - -double TQCString::toDouble( bool *ok ) const -{ - char *end; - double val = strtod( data() ? data() : "", &end ); - if ( ok ) - *ok = ( data() && *data() && ( end == 0 || *end == '\0' ) ); - return val; -} - -/*! - Returns the string converted to a \c{float} value. - - If \a ok is not 0: \a *ok is set to FALSE if the string is not a - number, or if it has trailing garbage; otherwise \a *ok is set to - TRUE. -*/ - -float TQCString::toFloat( bool *ok ) const -{ - return (float)toDouble( ok ); -} - - -/*! - Makes a deep copy of \a str. Returns a reference to the string. -*/ - -TQCString &TQCString::setStr( const char *str ) -{ - detach(); - if ( str ) // valid string - store( str, tqstrlen(str)+1 ); - else // empty - resize( 0 ); - return *this; -} - -/*! - \overload - - Sets the string to the string representation of the number \a n - and returns a reference to the string. -*/ - -TQCString &TQCString::setNum( long n ) -{ - detach(); - char buf[20]; - char *p = &buf[19]; - bool neg; - if ( n < 0 ) { - neg = TRUE; - n = -n; - } else { - neg = FALSE; - } - *p = '\0'; - do { - *--p = ((int)(n%10)) + '0'; - n /= 10; - } while ( n ); - if ( neg ) - *--p = '-'; - store( p, tqstrlen(p)+1 ); - return *this; -} - -/*! - \overload - - Sets the string to the string representation of the number \a n - and returns a reference to the string. -*/ - -TQCString &TQCString::setNum( ulong n ) -{ - detach(); - char buf[20]; - char *p = &buf[19]; - *p = '\0'; - do { - *--p = ((int)(n%10)) + '0'; - n /= 10; - } while ( n ); - store( p, tqstrlen(p)+1 ); - return *this; -} - -/*! - \overload TQCString &TQCString::setNum( int n ) - - Sets the string to the string representation of the number \a n - and returns a reference to the string. -*/ - -/*! - \overload TQCString &TQCString::setNum( uint n ) - - Sets the string to the string representation of the number \a n - and returns a reference to the string. -*/ - -/*! - \overload TQCString &TQCString::setNum( short n ) - - Sets the string to the string representation of the number \a n - and returns a reference to the string. -*/ - -/*! - \overload TQCString &TQCString::setNum( ushort n ) - - Sets the string to the string representation of the number \a n - and returns a reference to the string. -*/ - -/*! - Sets the string to the string representation of the number \a n - and returns a reference to the string. - - The format of the string representation is specified by the format - character \a f, and the precision (number of digits after the - decimal point) is specified with \a prec. - - The valid formats for \a f are 'e', 'E', 'f', 'g' and 'G'. The - formats are the same as for sprintf(); they are explained in \l - TQString::arg(). -*/ - -TQCString &TQCString::setNum( double n, char f, int prec ) -{ -#if defined(QT_CHECK_RANGE) - if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') ) - tqWarning( "TQCString::setNum: Invalid format char '%c'", f ); -#endif - char format[20]; - char *fs = format; // generate format string - *fs++ = '%'; // "%.l" - if ( prec > 99 ) - prec = 99; - *fs++ = '.'; - if ( prec >= 10 ) { - *fs++ = prec / 10 + '0'; - *fs++ = prec % 10 + '0'; - } else { - *fs++ = prec + '0'; - } - *fs++ = 'l'; - *fs++ = f; - *fs = '\0'; - return sprintf( format, n ); -} - -/*! \overload TQCString &TQCString::setNum( float n, char f, int prec ) */ - - -/*! - Sets the character at position \a index to \a c and expands the - string if necessary, padding with spaces. - - Returns FALSE if \a index was out of range and the string could - not be expanded; otherwise returns TRUE. -*/ - -bool TQCString::setExpand( uint index, char c ) -{ - detach(); - uint oldlen = length(); - if ( index >= oldlen ) { - if ( !TQByteArray::resize( index+2 ) ) // no memory - return FALSE; - if ( index > oldlen ) - memset( data() + oldlen, ' ', index - oldlen ); - *(data() + index+1) = '\0'; // terminate padded string - } - *(data() + index) = c; - return TRUE; -} - - -/*! - \fn TQCString::operator const char *() const - - Returns the string data. -*/ - - -/*! - \fn TQCString& TQCString::append( const char *str ) - - Appends string \a str to the string and returns a reference to the - string. Equivalent to operator+=(). -*/ - -/*! - Appends string \a str to the string and returns a reference to the string. -*/ - -TQCString& TQCString::operator+=( const char *str ) -{ - if ( !str ) - return *this; // nothing to append - detach(); - uint len1 = length(); - uint len2 = tqstrlen(str); - if ( !TQByteArray::resize( len1 + len2 + 1, TQByteArray::SpeedOptim ) ) - return *this; // no memory - memcpy( data() + len1, str, len2 + 1 ); - return *this; -} - -/*! - \overload - - Appends character \a c to the string and returns a reference to the string. -*/ - -TQCString &TQCString::operator+=( char c ) -{ - detach(); - uint len = length(); - if ( !TQByteArray::resize( len + 2, TQByteArray::SpeedOptim ) ) - return *this; // no memory - *(data() + len) = c; - *(data() + len+1) = '\0'; - return *this; -} - - -/***************************************************************************** - TQCString stream functions - *****************************************************************************/ -#ifndef TQT_NO_DATASTREAM -/*! - \relates TQCString - - Writes string \a str to the stream \a s. - - \sa \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ -TQDataStream &operator<<( TQDataStream &s, const TQCString &str ) -{ - return s.writeBytes( str.data(), str.size() ); -} - -/*! - \relates TQCString - - Reads a string into \a str from the stream \a s. - - \sa \link datastreamformat.html Format of the TQDataStream operators \endlink -*/ - -TQDataStream &operator>>( TQDataStream &s, TQCString &str ) -{ - str.detach(); - TQ_UINT32 len; - s >> len; // read size of string - if ( len == 0 || s.eof() ) { // end of file reached - str.resize( 0 ); - return s; - } - if ( !str.TQByteArray::resize( (uint)len )) {// resize string -#if defined(QT_CHECK_NULL) - tqWarning( "TQDataStream: Not enough memory to read TQCString" ); -#endif - len = 0; - } - if ( len > 0 ) // not null array - s.readRawBytes( str.data(), (uint)len ); - return s; -} -#endif //TQT_NO_DATASTREAM - -/***************************************************************************** - Documentation for related functions - *****************************************************************************/ - -/*! - \fn bool operator==( const TQCString &s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) == 0. -*/ - -/*! - \overload bool operator==( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) == 0. -*/ - -/*! - \overload bool operator==( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) == 0. -*/ - -/*! - \fn bool operator!=( const TQCString &s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) != 0. -*/ - -/*! - \overload bool operator!=( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) != 0. -*/ - -/*! - \overload bool operator!=( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) != 0. -*/ - -/*! - \fn bool operator<( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \< 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \overload bool operator<( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \< 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \fn bool operator<=( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is less than or equal to \a s2; otherwise - returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \<= 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \overload bool operator<=( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is less than or equal to \a s2; otherwise - returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \<= 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \fn bool operator>( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \> 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \overload bool operator>( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \> 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \fn bool operator>=( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise - returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \>= 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \overload bool operator>=( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise - returns FALSE. - - Equivalent to qstrcmp(\a s1, \a s2) \>= 0. - - \sa \link #asciinotion Note on character comparisons \endlink -*/ - -/*! - \fn const TQCString operator+( const TQCString &s1, const TQCString &s2 ) - - \relates TQCString - - Returns a string which consists of the concatenation of \a s1 and - \a s2. -*/ - -/*! - \overload const TQCString operator+( const TQCString &s1, const char *s2 ) - - \relates TQCString - - Returns a string which consists of the concatenation of \a s1 and \a s2. -*/ - -/*! - \overload const TQCString operator+( const char *s1, const TQCString &s2 ) - - \relates TQCString - - Returns a string which consists of the concatenation of \a s1 and \a s2. -*/ - -/*! - \overload const TQCString operator+( const TQCString &s, char c ) - - \relates TQCString - - Returns a string which consists of the concatenation of \a s and \a c. -*/ - -/*! - \overload const TQCString operator+( char c, const TQCString &s ) - - \relates TQCString - - Returns a string which consists of the concatenation of \a c and \a s. -*/ diff --git a/src/tools/qdeepcopy.cpp b/src/tools/qdeepcopy.cpp deleted file mode 100644 index ea23fa639..000000000 --- a/src/tools/qdeepcopy.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQDeepCopy class -** -** Created : 20020613 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the kernel 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 requirements 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. -** -**********************************************************************/ - -#include "ntqdeepcopy.h" - -/*! - \class TQDeepCopy ntqdeepcopy.h - \brief The TQDeepCopy class is a template class which ensures that - implicitly shared and explicitly shared classes reference unique - data. - - \reentrant - - \ingroup tools - \ingroup shared - - Normally, shared copies reference the same data to optimize memory - use and for maximum speed. In the example below, \c s1, \c s2, \c - s3, \c s4 and \c s5 share data. - - \code - // all 5 strings share the same data - TQString s1 = "abcd"; - TQString s2 = s1; - TQString s3 = s2; - TQString s4 = s3; - TQString s5 = s2; - \endcode - - TQDeepCopy can be used several ways to ensure that an object - references unique, unshared data. In the example below, \c s1, \c - s2 and \c s5 share data, while neither \c s3 nor \c s4 share data. - \code - // s1, s2 and s5 share the same data, neither s3 nor s4 are shared - TQString s1 = "abcd"; - TQString s2 = s1; - TQDeepCopy s3 = s2; // s3 is a deep copy of s2 - TQString s4 = s3; // s4 is a deep copy of s3 - TQString s5 = s2; - \endcode - - In the example below, \c s1, \c s2 and \c s5 share data, and \c s3 - and \c s4 share data. - \code - // s1, s2 and s5 share the same data, s3 and s4 share the same data - TQString s1 = "abcd"; - TQString s2 = s1; - TQString s3 = TQDeepCopy( s2 ); // s3 is a deep copy of s2 - TQString s4 = s3; // s4 is a shallow copy of s3 - TQString s5 = s2; - \endcode - - TQDeepCopy can also provide safety in multithreaded applications - that use shared classes. In the example below, the variable \c - global_string is used safely since the data contained in \c - global_string is always a deep copy. This ensures that all threads - get a unique copy of the data, and that any assignments to \c - global_string will result in a deep copy. - - \code - TQDeepCopy global_string; // global string data - TQMutex global_mutex; // mutex to protext global_string - - ... - - void setGlobalString( const TQString &str ) - { - global_mutex.lock(); - global_string = str; // global_string is a deep copy of str - global_mutex.unlock(); - } - - ... - - void MyThread::run() - { - global_mutex.lock(); - TQString str = global_string; // str is a deep copy of global_string - global_mutex.unlock(); - - // process the string data - ... - - // update global_string - setGlobalString( str ); - } - \endcode - - \warning It is the application developer's responsibility to - protect the object shared across multiple threads. - - The examples above use TQString, which is an implicitly shared - class. The behavior of TQDeepCopy is the same when using explicitly - shared classes like TQByteArray. - - Currently, TQDeepCopy works with the following classes: - \list - \i TQMemArray (including subclasses like TQByteArray and TQCString) - \i TQMap - \i TQString - \i TQValueList (including subclasses like TQStringList and TQValueStack) - \i TQValueVector - \endlist - - \sa \link threads.html Thread Support in TQt \endlink -*/ - -/*! - \fn TQDeepCopy::TQDeepCopy() - - Constructs an empty instance of type \e T. -*/ - -/*! - \fn TQDeepCopy::TQDeepCopy( const T &t ) - - Constructs a deep copy of \a t. -*/ - -/*! - \fn TQDeepCopy& TQDeepCopy::operator=( const T &t ) - - Assigns a deep copy of \a t. -*/ - -/*! - \fn TQDeepCopy::operator T () - - Returns a deep copy of the encapsulated data. -*/ - diff --git a/src/tools/qdir.cpp b/src/tools/qdir.cpp index 1a2f654f5..4ca6be4aa 100644 --- a/src/tools/qdir.cpp +++ b/src/tools/qdir.cpp @@ -44,9 +44,9 @@ #ifndef TQT_NO_DIR #include #include "ntqfileinfo.h" -#include "ntqregexp.h" +#include "tqregexp.h" #include "tqstringlist.h" -#include "ntqdeepcopy.h" +#include "tqdeepcopy.h" #include #if defined(Q_FS_FAT) && !defined(Q_OS_UNIX) @@ -561,7 +561,7 @@ bool TQDir::cdUp() nameFilter. The \a nameFilter is a wildcard (globbing) filter that understands - "*" and "?" wildcards. (See \link ntqregexp.html#wildcard-matching + "*" and "?" wildcards. (See \link tqregexp.html#wildcard-matching TQRegExp wildcard matching\endlink.) You may specify several filter entries all separated by a single space " " or by a semi-colon ";". @@ -1198,7 +1198,7 @@ bool qt_matchFilterList( const TQValueList& filters, Returns TRUE if the \a fileName matches any of the wildcard (glob) patterns in the list of \a filters; otherwise returns FALSE. - (See \link ntqregexp.html#wildcard-matching TQRegExp wildcard + (See \link tqregexp.html#wildcard-matching TQRegExp wildcard matching.\endlink) \sa TQRegExp::match() */ @@ -1220,7 +1220,7 @@ bool TQDir::match( const TQStringList &filters, const TQString &fileName ) pattern \a filter; otherwise returns FALSE. The \a filter may contain multiple patterns separated by spaces or semicolons. - (See \link ntqregexp.html#wildcard-matching TQRegExp wildcard + (See \link tqregexp.html#wildcard-matching TQRegExp wildcard matching.\endlink) \sa TQRegExp::match() */ diff --git a/src/tools/qdir_p.h b/src/tools/qdir_p.h index 91138abb5..a0309648b 100644 --- a/src/tools/qdir_p.h +++ b/src/tools/qdir_p.h @@ -55,7 +55,7 @@ // #ifndef QT_H -#include "ntqregexp.h" +#include "tqregexp.h" #include "tqvaluelist.h" #endif // QT_H diff --git a/src/tools/qdir_unix.cpp b/src/tools/qdir_unix.cpp index 8019d7b16..e4418f8e6 100644 --- a/src/tools/qdir_unix.cpp +++ b/src/tools/qdir_unix.cpp @@ -45,7 +45,7 @@ #include "qdir_p.h" #include "ntqfileinfo.h" -#include "ntqregexp.h" +#include "tqregexp.h" #include "tqstringlist.h" #ifdef TQT_THREAD_SUPPORT diff --git a/src/tools/qfileinfo.cpp b/src/tools/qfileinfo.cpp index f5e85119b..60a39346a 100644 --- a/src/tools/qfileinfo.cpp +++ b/src/tools/qfileinfo.cpp @@ -44,7 +44,7 @@ #include "tqdatetime.h" #include "ntqdir.h" #include "qfiledefs_p.h" -#include "ntqdeepcopy.h" +#include "tqdeepcopy.h" #if defined(QT_LARGEFILE_SUPPORT) #include #endif diff --git a/src/tools/qgcache.cpp b/src/tools/qgcache.cpp index 452128890..95f75534e 100644 --- a/src/tools/qgcache.cpp +++ b/src/tools/qgcache.cpp @@ -40,7 +40,7 @@ #include "ntqgcache.h" #include "tqptrlist.h" -#include "ntqdict.h" +#include "tqdict.h" #include "tqstring.h" /*! diff --git a/src/tools/qglobal.cpp b/src/tools/qglobal.cpp index 910580f7a..ff5fd5c74 100644 --- a/src/tools/qglobal.cpp +++ b/src/tools/qglobal.cpp @@ -40,7 +40,7 @@ #include "qplatformdefs.h" -#include "ntqasciidict.h" +#include "tqasciidict.h" #include #include #include diff --git a/src/tools/qgpluginmanager_p.h b/src/tools/qgpluginmanager_p.h index 982970131..069b7e27a 100644 --- a/src/tools/qgpluginmanager_p.h +++ b/src/tools/qgpluginmanager_p.h @@ -40,7 +40,7 @@ #define TQGPLUGINMANAGER_P_H #ifndef QT_H -#include "ntqdict.h" +#include "tqdict.h" #include "ntqlibrary.h" #include "ntquuid.h" #include "tqstringlist.h" diff --git a/src/tools/qregexp.cpp b/src/tools/qregexp.cpp deleted file mode 100644 index e6447cdf1..000000000 --- a/src/tools/qregexp.cpp +++ /dev/null @@ -1,3996 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQRegExp class -** -** Created : 950126 -** -** 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 requirements 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. -** -**********************************************************************/ - -#include "ntqregexp.h" - -#ifndef TQT_NO_REGEXP - -#include "ntqmemarray.h" -#include "ntqbitarray.h" -#include "ntqcache.h" -#include "ntqcleanuphandler.h" -#include "ntqintdict.h" -#include "tqmap.h" -#include "tqptrvector.h" -#include "tqstring.h" -#include "ntqtl.h" - -#ifdef TQT_THREAD_SUPPORT -#include "tqthreadstorage.h" -#include -#endif // TQT_THREAD_SUPPORT - -#undef TQT_TRANSLATE_NOOP -#define TQT_TRANSLATE_NOOP( context, sourceText ) sourceText - -#include - -// error strings for the regexp parser -#define RXERR_OK TQT_TRANSLATE_NOOP( "TQRegExp", "no error occurred" ) -#define RXERR_DISABLED TQT_TRANSLATE_NOOP( "TQRegExp", "disabled feature used" ) -#define RXERR_CHARCLASS TQT_TRANSLATE_NOOP( "TQRegExp", "bad char class syntax" ) -#define RXERR_LOOKAHEAD TQT_TRANSLATE_NOOP( "TQRegExp", "bad lookahead syntax" ) -#define RXERR_REPETITION TQT_TRANSLATE_NOOP( "TQRegExp", "bad repetition syntax" ) -#define RXERR_OCTAL TQT_TRANSLATE_NOOP( "TQRegExp", "invalid octal value" ) -#define RXERR_LEFTDELIM TQT_TRANSLATE_NOOP( "TQRegExp", "missing left delim" ) -#define RXERR_END TQT_TRANSLATE_NOOP( "TQRegExp", "unexpected end" ) -#define RXERR_LIMIT TQT_TRANSLATE_NOOP( "TQRegExp", "met internal limit" ) - -/* - WARNING! Be sure to read qregexp.tex before modifying this file. -*/ - -/*! - \class TQRegExp ntqregexp.h - \reentrant - \brief The TQRegExp class provides pattern matching using regular expressions. - - \ingroup tools - \ingroup misc - \ingroup shared - \mainclass - \keyword regular expression - - Regular expressions, or "regexps", provide a way to find patterns - within text. This is useful in many contexts, for example: - - \table - \row \i Validation - \i A regexp can be used to check whether a piece of text - meets some criteria, e.g. is an integer or contains no - whitespace. - \row \i Searching - \i Regexps provide a much more powerful means of searching - text than simple string matching does. For example we can - create a regexp which says "find one of the words 'mail', - 'letter' or 'correspondence' but not any of the words - 'email', 'mailman' 'mailer', 'letterbox' etc." - \row \i Search and Replace - \i A regexp can be used to replace a pattern with a piece of - text, for example replace all occurrences of '&' with - '\&' except where the '&' is already followed by 'amp;'. - \row \i String Splitting - \i A regexp can be used to identify where a string should be - split into its component fields, e.g. splitting tab-delimited - strings. - \endtable - - We present a very brief introduction to regexps, a description of - TQt's regexp language, some code examples, and finally the function - documentation itself. TQRegExp is modeled on Perl's regexp - language, and also fully supports Unicode. TQRegExp can also be - used in the weaker 'wildcard' (globbing) mode which works in a - similar way to command shells. A good text on regexps is \e - {Mastering Regular Expressions: Powerful Techniques for Perl and - Other Tools} by Jeffrey E. Friedl, ISBN 1565922573. - - Experienced regexp users may prefer to skip the introduction and - go directly to the relevant information. - - In case of multi-threaded programming, note that TQRegExp depends on - TQThreadStorage internally. For that reason, TQRegExp should only be - used with threads started with TQThread, i.e. not with threads - started with platform-specific APIs. - - \tableofcontents - - \section1 Introduction - - Regexps are built up from expressions, quantifiers, and assertions. - The simplest form of expression is simply a character, e.g. - x or 5. An expression can also be a set of - characters. For example, [ABCD], will match an A or - a B or a C or a D. As a shorthand we could - write this as [A-D]. If we want to match any of the - captital letters in the English alphabet we can write - [A-Z]. A quantifier tells the regexp engine how many - occurrences of the expression we want, e.g. x{1,1} means - match an x which occurs at least once and at most once. - We'll look at assertions and more complex expressions later. - - Note that in general regexps cannot be used to check for balanced - brackets or tags. For example if you want to match an opening html - \c and its closing \c you can only use a regexp if you - know that these tags are not nested; the html fragment, \c{bold - bolder} will not match as expected. If you know the - maximum level of nesting it is possible to create a regexp that - will match correctly, but for an unknown level of nesting, regexps - will fail. - - We'll start by writing a regexp to match integers in the range 0 - to 99. We will require at least one digit so we will start with - [0-9]{1,1} which means match a digit exactly once. This - regexp alone will match integers in the range 0 to 9. To match one - or two digits we can increase the maximum number of occurrences so - the regexp becomes [0-9]{1,2} meaning match a digit at - least once and at most twice. However, this regexp as it stands - will not match correctly. This regexp will match one or two digits - \e within a string. To ensure that we match against the whole - string we must use the anchor assertions. We need ^ (caret) - which when it is the first character in the regexp means that the - regexp must match from the beginning of the string. And we also - need $ (dollar) which when it is the last character in the - regexp means that the regexp must match until the end of the - string. So now our regexp is ^[0-9]{1,2}$. Note that - assertions, such as ^ and $, do not match any - characters. - - If you've seen regexps elsewhere they may have looked different from - the ones above. This is because some sets of characters and some - quantifiers are so common that they have special symbols to - represent them. [0-9] can be replaced with the symbol - \d. The quantifier to match exactly one occurrence, - {1,1}, can be replaced with the expression itself. This means - that x{1,1} is exactly the same as x alone. So our 0 - to 99 matcher could be written ^\d{1,2}$. Another way of - writing it would be ^\d\d{0,1}$, i.e. from the start of the - string match a digit followed by zero or one digits. In practice - most people would write it ^\d\d?$. The ? is a - shorthand for the quantifier {0,1}, i.e. a minimum of no - occurrences a maximum of one occurrence. This is used to make an - expression optional. The regexp ^\d\d?$ means "from the - beginning of the string match one digit followed by zero or one - digits and then the end of the string". - - Our second example is matching the words 'mail', 'letter' or - 'correspondence' but without matching 'email', 'mailman', - 'mailer', 'letterbox' etc. We'll start by just matching 'mail'. In - full the regexp is, m{1,1}a{1,1}i{1,1}l{1,1}, but since - each expression itself is automatically quantified by {1,1} - we can simply write this as mail; an 'm' followed by an 'a' - followed by an 'i' followed by an 'l'. The symbol '|' (bar) is - used for \e alternation, so our regexp now becomes - mail|letter|correspondence which means match 'mail' \e or - 'letter' \e or 'correspondence'. Whilst this regexp will find the - words we want it will also find words we don't want such as - 'email'. We will start by putting our regexp in parentheses, - (mail|letter|correspondence). Parentheses have two effects, - firstly they group expressions together and secondly they identify - parts of the regexp that we wish to \link #capturing-text capture - \endlink. Our regexp still matches any of the three words but now - they are grouped together as a unit. This is useful for building - up more complex regexps. It is also useful because it allows us to - examine which of the words actually matched. We need to use - another assertion, this time \b "word boundary": - \b(mail|letter|correspondence)\b. This regexp means "match - a word boundary followed by the expression in parentheses followed - by another word boundary". The \b assertion matches at a \e - position in the regexp not a \e character in the regexp. A word - boundary is any non-word character such as a space a newline or - the beginning or end of the string. - - For our third example we want to replace ampersands with the HTML - entity '\&'. The regexp to match is simple: \&, i.e. - match one ampersand. Unfortunately this will mess up our text if - some of the ampersands have already been turned into HTML - entities. So what we really want to say is replace an ampersand - providing it is not followed by 'amp;'. For this we need the - negative lookahead assertion and our regexp becomes: - \&(?!amp;). The negative lookahead assertion is introduced - with '(?!' and finishes at the ')'. It means that the text it - contains, 'amp;' in our example, must \e not follow the expression - that preceeds it. - - Regexps provide a rich language that can be used in a variety of - ways. For example suppose we want to count all the occurrences of - 'Eric' and 'Eirik' in a string. Two valid regexps to match these - are \\b(Eric|Eirik)\\b and \\bEi?ri[ck]\\b. We need - the word boundary '\b' so we don't get 'Ericsson' etc. The second - regexp actually matches more than we want, 'Eric', 'Erik', 'Eiric' - and 'Eirik'. - - We will implement some the examples above in the - \link #code-examples code examples \endlink section. - - \target characters-and-abbreviations-for-sets-of-characters - \section1 Characters and Abbreviations for Sets of Characters - - \table - \header \i Element \i Meaning - \row \i c - \i Any character represents itself unless it has a special - regexp meaning. Thus c matches the character \e c. - \row \i \\c - \i A character that follows a backslash matches the character - itself except where mentioned below. For example if you - wished to match a literal caret at the beginning of a string - you would write \^. - \row \i \\a - \i This matches the ASCII bell character (BEL, 0x07). - \row \i \\f - \i This matches the ASCII form feed character (FF, 0x0C). - \row \i \\n - \i This matches the ASCII line feed character (LF, 0x0A, Unix newline). - \row \i \\r - \i This matches the ASCII carriage return character (CR, 0x0D). - \row \i \\t - \i This matches the ASCII horizontal tab character (HT, 0x09). - \row \i \\v - \i This matches the ASCII vertical tab character (VT, 0x0B). - \row \i \\xhhhh - \i This matches the Unicode character corresponding to the - hexadecimal number hhhh (between 0x0000 and 0xFFFF). \0ooo - (i.e., \zero ooo) matches the ASCII/Latin-1 character - corresponding to the octal number ooo (between 0 and 0377). - \row \i . (dot) - \i This matches any character (including newline). - \row \i \\d - \i This matches a digit (TQChar::isDigit()). - \row \i \\D - \i This matches a non-digit. - \row \i \\s - \i This matches a whitespace (TQChar::isSpace()). - \row \i \\S - \i This matches a non-whitespace. - \row \i \\w - \i This matches a word character (TQChar::isLetterOrNumber() or '_'). - \row \i \\W - \i This matches a non-word character. - \row \i \\n - \i The n-th \link #capturing-text backreference \endlink, - e.g. \1, \2, etc. - \endtable - - \e {Note that the C++ compiler transforms backslashes in strings - so to include a \\ in a regexp you will need to enter it - twice, i.e. \\\\.} - - \target sets-of-characters - \section1 Sets of Characters - - Square brackets are used to match any character in the set of - characters contained within the square brackets. All the character - set abbreviations described above can be used within square - brackets. Apart from the character set abbreviations and the - following two exceptions no characters have special meanings in - square brackets. - - \table - \row \i ^ - \i The caret negates the character set if it occurs as the - first character, i.e. immediately after the opening square - bracket. For example, [abc] matches 'a' or 'b' or 'c', - but [^abc] matches anything \e except 'a' or 'b' or - 'c'. - \row \i - - \i The dash is used to indicate a range of characters, for - example [W-Z] matches 'W' or 'X' or 'Y' or 'Z'. - \endtable - - Using the predefined character set abbreviations is more portable - than using character ranges across platforms and languages. For - example, [0-9] matches a digit in Western alphabets but - \d matches a digit in \e any alphabet. - - Note that in most regexp literature sets of characters are called - "character classes". - - \target quantifiers - \section1 Quantifiers - - By default an expression is automatically quantified by - {1,1}, i.e. it should occur exactly once. In the following - list \e {E} stands for any expression. An expression is a - character or an abbreviation for a set of characters or a set of - characters in square brackets or any parenthesised expression. - - \table - \row \i \e {E}? - \i Matches zero or one occurrence of \e E. This quantifier - means "the previous expression is optional" since it will - match whether or not the expression occurs in the string. It - is the same as \e {E}{0,1}. For example dents? - will match 'dent' and 'dents'. - - \row \i \e {E}+ - \i Matches one or more occurrences of \e E. This is the same - as \e {E}{1,MAXINT}. For example, 0+ will match - '0', '00', '000', etc. - - \row \i \e {E}* - \i Matches zero or more occurrences of \e E. This is the same - as \e {E}{0,MAXINT}. The * quantifier is often - used by a mistake. Since it matches \e zero or more - occurrences it will match no occurrences at all. For example - if we want to match strings that end in whitespace and use - the regexp \s*$ we would get a match on every string. - This is because we have said find zero or more whitespace - followed by the end of string, so even strings that don't end - in whitespace will match. The regexp we want in this case is - \s+$ to match strings that have at least one - whitespace at the end. - - \row \i \e {E}{n} - \i Matches exactly \e n occurrences of the expression. This - is the same as repeating the expression \e n times. For - example, x{5} is the same as xxxxx. It is also - the same as \e {E}{n,n}, e.g. x{5,5}. - - \row \i \e {E}{n,} - \i Matches at least \e n occurrences of the expression. This - is the same as \e {E}{n,MAXINT}. - - \row \i \e {E}{,m} - \i Matches at most \e m occurrences of the expression. This - is the same as \e {E}{0,m}. - - \row \i \e {E}{n,m} - \i Matches at least \e n occurrences of the expression and at - most \e m occurrences of the expression. - \endtable - - (MAXINT is implementation dependent but will not be smaller than - 1024.) - - If we wish to apply a quantifier to more than just the preceding - character we can use parentheses to group characters together in - an expression. For example, tag+ matches a 't' followed by - an 'a' followed by at least one 'g', whereas (tag)+ matches - at least one occurrence of 'tag'. - - Note that quantifiers are "greedy". They will match as much text - as they can. For example, 0+ will match as many zeros as it - can from the first zero it finds, e.g. '2.0005'. - Quantifiers can be made non-greedy, see setMinimal(). - - \target capturing-text - \section1 Capturing Text - - Parentheses allow us to group elements together so that we can - quantify and capture them. For example if we have the expression - mail|letter|correspondence that matches a string we know - that \e one of the words matched but not which one. Using - parentheses allows us to "capture" whatever is matched within - their bounds, so if we used (mail|letter|correspondence) - and matched this regexp against the string "I sent you some email" - we can use the cap() or capturedTexts() functions to extract the - matched characters, in this case 'mail'. - - We can use captured text within the regexp itself. To refer to the - captured text we use \e backreferences which are indexed from 1, - the same as for cap(). For example we could search for duplicate - words in a string using \b(\w+)\W+\1\b which means match a - word boundary followed by one or more word characters followed by - one or more non-word characters followed by the same text as the - first parenthesised expression followed by a word boundary. - - If we want to use parentheses purely for grouping and not for - capturing we can use the non-capturing syntax, e.g. - (?:green|blue). Non-capturing parentheses begin '(?:' and - end ')'. In this example we match either 'green' or 'blue' but we - do not capture the match so we only know whether or not we matched - but not which color we actually found. Using non-capturing - parentheses is more efficient than using capturing parentheses - since the regexp engine has to do less book-keeping. - - Both capturing and non-capturing parentheses may be nested. - - \target assertions - \section1 Assertions - - Assertions make some statement about the text at the point where - they occur in the regexp but they do not match any characters. In - the following list \e {E} stands for any expression. - - \table - \row \i ^ - \i The caret signifies the beginning of the string. If you - wish to match a literal \c{^} you must escape it by - writing \^. For example, ^#include will only - match strings which \e begin with the characters '#include'. - (When the caret is the first character of a character set it - has a special meaning, see \link #sets-of-characters Sets of - Characters \endlink.) - - \row \i $ - \i The dollar signifies the end of the string. For example - \d\s*$ will match strings which end with a digit - optionally followed by whitespace. If you wish to match a - literal \c{$} you must escape it by writing - \$. - - \row \i \\b - \i A word boundary. For example the regexp - \\bOK\\b means match immediately after a word - boundary (e.g. start of string or whitespace) the letter 'O' - then the letter 'K' immediately before another word boundary - (e.g. end of string or whitespace). But note that the - assertion does not actually match any whitespace so if we - write (\\bOK\\b) and we have a match it will only - contain 'OK' even if the string is "Its OK now". - - \row \i \\B - \i A non-word boundary. This assertion is true wherever - \\b is false. For example if we searched for - \\Bon\\B in "Left on" the match would fail (space - and end of string aren't non-word boundaries), but it would - match in "tonne". - - \row \i (?=\e E) - \i Positive lookahead. This assertion is true if the - expression matches at this point in the regexp. For example, - const(?=\\s+char) matches 'const' whenever it is - followed by 'char', as in 'static const char *'. - (Compare with const\\s+char, which matches 'static - const char *'.) - - \row \i (?!\e E) - \i Negative lookahead. This assertion is true if the - expression does not match at this point in the regexp. For - example, const(?!\\s+char) matches 'const' \e except - when it is followed by 'char'. - \endtable - - \target wildcard-matching - \section1 Wildcard Matching (globbing) - - Most command shells such as \e bash or \e cmd.exe support "file - globbing", the ability to identify a group of files by using - wildcards. The setWildcard() function is used to switch between - regexp and wildcard mode. Wildcard matching is much simpler than - full regexps and has only four features: - - \table - \row \i c - \i Any character represents itself apart from those mentioned - below. Thus c matches the character \e c. - \row \i ? - \i This matches any single character. It is the same as - . in full regexps. - \row \i * - \i This matches zero or more of any characters. It is the - same as .* in full regexps. - \row \i [...] - \i Sets of characters can be represented in square brackets, - similar to full regexps. Within the character class, like - outside, backslash has no special meaning. - \endtable - - For example if we are in wildcard mode and have strings which - contain filenames we could identify HTML files with *.html. - This will match zero or more characters followed by a dot followed - by 'h', 't', 'm' and 'l'. - - \target perl-users - \section1 Notes for Perl Users - - Most of the character class abbreviations supported by Perl are - supported by TQRegExp, see \link - #characters-and-abbreviations-for-sets-of-characters characters - and abbreviations for sets of characters \endlink. - - In TQRegExp, apart from within character classes, \c{^} always - signifies the start of the string, so carets must always be - escaped unless used for that purpose. In Perl the meaning of caret - varies automagically depending on where it occurs so escaping it - is rarely necessary. The same applies to \c{$} which in - TQRegExp always signifies the end of the string. - - TQRegExp's quantifiers are the same as Perl's greedy quantifiers. - Non-greedy matching cannot be applied to individual quantifiers, - but can be applied to all the quantifiers in the pattern. For - example, to match the Perl regexp ro+?m requires: - \code - TQRegExp rx( "ro+m" ); - rx.setMinimal( TRUE ); - \endcode - - The equivalent of Perl's \c{/i} option is - setCaseSensitive(FALSE). - - Perl's \c{/g} option can be emulated using a \link - #cap_in_a_loop loop \endlink. - - In TQRegExp . matches any character, therefore all TQRegExp - regexps have the equivalent of Perl's \c{/s} option. TQRegExp - does not have an equivalent to Perl's \c{/m} option, but this - can be emulated in various ways for example by splitting the input - into lines or by looping with a regexp that searches for newlines. - - Because TQRegExp is string oriented there are no \A, \Z or \z - assertions. The \G assertion is not supported but can be emulated - in a loop. - - Perl's $& is cap(0) or capturedTexts()[0]. There are no TQRegExp - equivalents for $`, $' or $+. Perl's capturing variables, $1, $2, - ... correspond to cap(1) or capturedTexts()[1], cap(2) or - capturedTexts()[2], etc. - - To substitute a pattern use TQString::replace(). - - Perl's extended \c{/x} syntax is not supported, nor are - directives, e.g. (?i), or regexp comments, e.g. (?#comment). On - the other hand, C++'s rules for literal strings can be used to - achieve the same: - \code - TQRegExp mark( "\\b" // word boundary - "[Mm]ark" // the word we want to match - ); - \endcode - - Both zero-width positive and zero-width negative lookahead - assertions (?=pattern) and (?!pattern) are supported with the same - syntax as Perl. Perl's lookbehind assertions, "independent" - subexpressions and conditional expressions are not supported. - - Non-capturing parentheses are also supported, with the same - (?:pattern) syntax. - - See TQStringList::split() and TQStringList::join() for equivalents - to Perl's split and join functions. - - Note: because C++ transforms \\'s they must be written \e twice in - code, e.g. \\b must be written \\\\b. - - \target code-examples - \section1 Code Examples - - \code - TQRegExp rx( "^\\d\\d?$" ); // match integers 0 to 99 - rx.search( "123" ); // returns -1 (no match) - rx.search( "-6" ); // returns -1 (no match) - rx.search( "6" ); // returns 0 (matched as position 0) - \endcode - - The third string matches '6'. This is a simple validation - regexp for integers in the range 0 to 99. - - \code - TQRegExp rx( "^\\S+$" ); // match strings without whitespace - rx.search( "Hello world" ); // returns -1 (no match) - rx.search( "This_is-OK" ); // returns 0 (matched at position 0) - \endcode - - The second string matches 'This_is-OK'. We've used the - character set abbreviation '\S' (non-whitespace) and the anchors - to match strings which contain no whitespace. - - In the following example we match strings containing 'mail' or - 'letter' or 'correspondence' but only match whole words i.e. not - 'email' - - \code - TQRegExp rx( "\\b(mail|letter|correspondence)\\b" ); - rx.search( "I sent you an email" ); // returns -1 (no match) - rx.search( "Please write the letter" ); // returns 17 - \endcode - - The second string matches "Please write the letter". The - word 'letter' is also captured (because of the parentheses). We - can see what text we've captured like this: - - \code - TQString captured = rx.cap( 1 ); // captured == "letter" - \endcode - - This will capture the text from the first set of capturing - parentheses (counting capturing left parentheses from left to - right). The parentheses are counted from 1 since cap( 0 ) is the - whole matched regexp (equivalent to '&' in most regexp engines). - - \code - TQRegExp rx( "&(?!amp;)" ); // match ampersands but not & - TQString line1 = "This & that"; - line1.replace( rx, "&" ); - // line1 == "This & that" - TQString line2 = "His & hers & theirs"; - line2.replace( rx, "&" ); - // line2 == "His & hers & theirs" - \endcode - - Here we've passed the TQRegExp to TQString's replace() function to - replace the matched text with new text. - - \code - TQString str = "One Eric another Eirik, and an Ericsson." - " How many Eiriks, Eric?"; - TQRegExp rx( "\\b(Eric|Eirik)\\b" ); // match Eric or Eirik - int pos = 0; // where we are in the string - int count = 0; // how many Eric and Eirik's we've counted - while ( pos >= 0 ) { - pos = rx.search( str, pos ); - if ( pos >= 0 ) { - pos++; // move along in str - count++; // count our Eric or Eirik - } - } - \endcode - - We've used the search() function to repeatedly match the regexp in - the string. Note that instead of moving forward by one character - at a time \c pos++ we could have written \c {pos += - rx.matchedLength()} to skip over the already matched string. The - count will equal 3, matching 'One Eric another - Eirik, and an Ericsson. How many Eiriks, Eric?'; it - doesn't match 'Ericsson' or 'Eiriks' because they are not bounded - by non-word boundaries. - - One common use of regexps is to split lines of delimited data into - their component fields. - - \code - str = "Trolltech AS\twww.trolltech.com\tNorway"; - TQString company, web, country; - rx.setPattern( "^([^\t]+)\t([^\t]+)\t([^\t]+)$" ); - if ( rx.search( str ) != -1 ) { - company = rx.cap( 1 ); - web = rx.cap( 2 ); - country = rx.cap( 3 ); - } - \endcode - - In this example our input lines have the format company name, web - address and country. Unfortunately the regexp is rather long and - not very versatile -- the code will break if we add any more - fields. A simpler and better solution is to look for the - separator, '\t' in this case, and take the surrounding text. The - TQStringList split() function can take a separator string or regexp - as an argument and split a string accordingly. - - \code - TQStringList field = TQStringList::split( "\t", str ); - \endcode - - Here field[0] is the company, field[1] the web address and so on. - - To imitate the matching of a shell we can use wildcard mode. - - \code - TQRegExp rx( "*.html" ); // invalid regexp: * doesn't quantify anything - rx.setWildcard( TRUE ); // now it's a valid wildcard regexp - rx.exactMatch( "index.html" ); // returns TRUE - rx.exactMatch( "default.htm" ); // returns FALSE - rx.exactMatch( "readme.txt" ); // returns FALSE - \endcode - - Wildcard matching can be convenient because of its simplicity, but - any wildcard regexp can be defined using full regexps, e.g. - .*\.html$. Notice that we can't match both \c .html and \c - .htm files with a wildcard unless we use *.htm* which will - also match 'test.html.bak'. A full regexp gives us the precision - we need, .*\\.html?$. - - TQRegExp can match case insensitively using setCaseSensitive(), and - can use non-greedy matching, see setMinimal(). By default TQRegExp - uses full regexps but this can be changed with setWildcard(). - Searching can be forward with search() or backward with - searchRev(). Captured text can be accessed using capturedTexts() - which returns a string list of all captured strings, or using - cap() which returns the captured string for the given index. The - pos() function takes a match index and returns the position in the - string where the match was made (or -1 if there was no match). - - \sa TQRegExpValidator TQString TQStringList - - \target member-function-documentation -*/ - -const int NumBadChars = 64; -#define BadChar( ch ) ( (ch).unicode() % NumBadChars ) - -const int NoOccurrence = INT_MAX; -const int EmptyCapture = INT_MAX; -const int InftyLen = INT_MAX; -const int InftyRep = 1025; -const int EOS = -1; - -static bool isWord( TQChar ch ) -{ - return ch.isLetterOrNumber() || ch == TQChar( '_' ); -} - -/* - Merges two TQMemArrays of ints and puts the result into the first - one. -*/ -static void mergeInto( TQMemArray *a, const TQMemArray& b ) -{ - int asize = a->size(); - int bsize = b.size(); - if ( asize == 0 ) { - *a = b.copy(); -#ifndef TQT_NO_REGEXP_OPTIM - } else if ( bsize == 1 && (*a)[asize - 1] < b[0] ) { - a->resize( asize + 1 ); - (*a)[asize] = b[0]; -#endif - } else if ( bsize >= 1 ) { - int csize = asize + bsize; - TQMemArray c( csize ); - int i = 0, j = 0, k = 0; - while ( i < asize ) { - if ( j < bsize ) { - if ( (*a)[i] == b[j] ) { - i++; - csize--; - } else if ( (*a)[i] < b[j] ) { - c[k++] = (*a)[i++]; - } else { - c[k++] = b[j++]; - } - } else { - memcpy( c.data() + k, (*a).data() + i, - (asize - i) * sizeof(int) ); - break; - } - } - c.resize( csize ); - if ( j < bsize ) - memcpy( c.data() + k, b.data() + j, (bsize - j) * sizeof(int) ); - *a = c; - } -} - -/* - Merges two disjoint TQMaps of (int, int) pairs and puts the result - into the first one. -*/ -static void mergeInto( TQMap *a, const TQMap& b ) -{ - TQMap::ConstIterator it; - for ( it = b.begin(); it != b.end(); ++it ) - a->insert( it.key(), *it ); -} - -/* - Returns the value associated to key k in TQMap m of (int, int) - pairs, or 0 if no such value is explicitly present. -*/ -static int at( const TQMap& m, int k ) -{ - TQMap::ConstIterator it = m.find( k ); - if ( it == m.end() ) - return 0; - else - return *it; -} - -#ifndef TQT_NO_REGEXP_WILDCARD -/* - Translates a wildcard pattern to an equivalent regular expression - pattern (e.g., *.cpp to .*\.cpp). -*/ -static TQString wc2rx( const TQString& wc_str ) -{ - int wclen = wc_str.length(); - TQString rx = TQString::fromLatin1( "" ); - int i = 0; - const TQChar *wc = wc_str.unicode(); - while ( i < wclen ) { - TQChar c = wc[i++]; - switch ( c.unicode() ) { - case '*': - rx += TQString::fromLatin1( ".*" ); - break; - case '?': - rx += TQChar( '.' ); - break; - case '$': - case '(': - case ')': - case '+': - case '.': - case '\\': - case '^': - case '{': - case '|': - case '}': - rx += TQChar( '\\' ); - rx += c; - break; - case '[': - rx += c; - if ( wc[i] == TQChar('^') ) - rx += wc[i++]; - if ( i < wclen ) { - if ( rx[i] == ']' ) - rx += wc[i++]; - while ( i < wclen && wc[i] != TQChar(']') ) { - if ( wc[i] == '\\' ) - rx += TQChar( '\\' ); - rx += wc[i++]; - } - } - break; - default: - rx += c; - } - } - return rx; -} -#endif - -/* - The class TQRegExpEngine encapsulates a modified nondeterministic - finite automaton (NFA). -*/ -class TQRegExpEngine : public TQShared -{ -public: -#ifndef TQT_NO_REGEXP_CCLASS - /* - The class CharClass represents a set of characters, such as can - be found in regular expressions (e.g., [a-z] denotes the set - {a, b, ..., z}). - */ - class CharClass - { - public: - CharClass(); - CharClass( const CharClass& cc ) { operator=( cc ); } - - CharClass& operator=( const CharClass& cc ); - - void clear(); - bool negative() const { return n; } - void setNegative( bool negative ); - void addCategories( int cats ); - void addRange( ushort from, ushort to ); - void addSingleton( ushort ch ) { addRange( ch, ch ); } - - bool in( TQChar ch ) const; -#ifndef TQT_NO_REGEXP_OPTIM - const TQMemArray& firstOccurrence() const { return occ1; } -#endif - -#if defined(QT_DEBUG) - void dump() const; -#endif - - private: - /* - The struct Range represents a range of characters (e.g., - [0-9] denotes range 48 to 57). - */ - struct Range - { - ushort from; // 48 - ushort to; // 57 - }; - - int c; // character classes - TQMemArray r; // character ranges - bool n; // negative? -#ifndef TQT_NO_REGEXP_OPTIM - TQMemArray occ1; // first-occurrence array -#endif - }; -#else - struct CharClass - { - int dummy; - -#ifndef TQT_NO_REGEXP_OPTIM - CharClass() { occ1.fill( 0, NumBadChars ); } - - const TQMemArray& firstOccurrence() const { return occ1; } - TQMemArray occ1; -#endif - }; -#endif - - TQRegExpEngine( bool caseSensitive ) { setup( caseSensitive ); } - TQRegExpEngine( const TQString& rx, bool caseSensitive ); -#ifndef TQT_NO_REGEXP_OPTIM - ~TQRegExpEngine(); -#endif - - bool isValid() const { return valid; } - bool caseSensitive() const { return cs; } - const TQString& errorString() const { return yyError; } - int numCaptures() const { return officialncap; } - void match( const TQString& str, int pos, bool minimal, bool oneTest, - int caretIndex, TQMemArray& captured ); - int partialMatchLength() const { return mmOneTestMatchedLen; } - - int createState( TQChar ch ); - int createState( const CharClass& cc ); -#ifndef TQT_NO_REGEXP_BACKREF - int createState( int bref ); -#endif - - void addCatTransitions( const TQMemArray& from, - const TQMemArray& to ); -#ifndef TQT_NO_REGEXP_CAPTURE - void addPlusTransitions( const TQMemArray& from, - const TQMemArray& to, int atom ); -#endif - -#ifndef TQT_NO_REGEXP_ANCHOR_ALT - int anchorAlternation( int a, int b ); - int anchorConcatenation( int a, int b ); -#else - int anchorAlternation( int a, int b ) { return a & b; } - int anchorConcatenation( int a, int b ) { return a | b; } -#endif - void addAnchors( int from, int to, int a ); - -#ifndef TQT_NO_REGEXP_OPTIM - void heuristicallyChooseHeuristic(); -#endif - -#if defined(QT_DEBUG) - void dump() const; -#endif - -private: - enum { CharClassBit = 0x10000, BackRefBit = 0x20000 }; - - /* - The struct State represents one state in a modified NFA. The - input characters matched are stored in the state instead of on - the transitions, something possible for an automaton - constructed from a regular expression. - */ - struct State - { -#ifndef TQT_NO_REGEXP_CAPTURE - int atom; // which atom does this state belong to? -#endif - int match; // what does it match? (see CharClassBit and BackRefBit) - TQMemArray outs; // out-transitions - TQMap *reenter; // atoms reentered when transiting out - TQMap *anchors; // anchors met when transiting out - -#ifndef TQT_NO_REGEXP_CAPTURE - State( int a, int m ) - : atom( a ), match( m ), reenter( 0 ), anchors( 0 ) { } -#else - State( int m ) - : match( m ), reenter( 0 ), anchors( 0 ) { } -#endif - ~State() { delete reenter; delete anchors; } - }; - -#ifndef TQT_NO_REGEXP_LOOKAHEAD - /* - The struct Lookahead represents a lookahead a la Perl (e.g., - (?=foo) and (?!bar)). - */ - struct Lookahead - { - TQRegExpEngine *eng; // NFA representing the embedded regular expression - bool neg; // negative lookahead? - - Lookahead( TQRegExpEngine *eng0, bool neg0 ) - : eng( eng0 ), neg( neg0 ) { } - ~Lookahead() { delete eng; } - }; -#endif - -#ifndef TQT_NO_REGEXP_CAPTURE - /* - The struct Atom represents one node in the hierarchy of regular - expression atoms. - */ - struct Atom - { - int parent; // index of parent in array of atoms - int capture; // index of capture, from 1 to ncap - }; -#endif - -#ifndef TQT_NO_REGEXP_ANCHOR_ALT - /* - The struct AnchorAlternation represents a pair of anchors with - OR semantics. - */ - struct AnchorAlternation - { - int a; // this anchor... - int b; // ...or this one - }; -#endif - - enum { InitialState = 0, FinalState = 1 }; - void setup( bool caseSensitive ); - int setupState( int match ); - - /* - Let's hope that 13 lookaheads and 14 back-references are - enough. - */ - enum { MaxLookaheads = 13, MaxBackRefs = 14 }; - enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, - Anchor_Word = 0x00000004, Anchor_NonWord = 0x00000008, - Anchor_FirstLookahead = 0x00000010, - Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads, - Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1, - Anchor_Alternation = Anchor_BackRef1Empty << MaxBackRefs, - - Anchor_LookaheadMask = ( Anchor_FirstLookahead - 1 ) ^ - ( (Anchor_FirstLookahead << MaxLookaheads) - 1 ) }; -#ifndef TQT_NO_REGEXP_CAPTURE - int startAtom( bool capture ); - void finishAtom( int atom ) { cf = f[atom].parent; } -#endif - -#ifndef TQT_NO_REGEXP_LOOKAHEAD - int addLookahead( TQRegExpEngine *eng, bool negative ); -#endif - -#ifndef TQT_NO_REGEXP_CAPTURE - bool isBetterCapture( const int *begin1, const int *end1, const int *begin2, - const int *end2 ); -#endif - bool testAnchor( int i, int a, const int *capBegin ); - -#ifndef TQT_NO_REGEXP_OPTIM - bool goodStringMatch(); - bool badCharMatch(); -#else - bool bruteMatch(); -#endif - bool matchHere(); - - TQPtrVector s; // array of states - int ns; // number of states -#ifndef TQT_NO_REGEXP_CAPTURE - TQMemArray f; // atom hierarchy - int nf; // number of atoms - int cf; // current atom -#endif - int officialncap; // number of captures, seen from the outside - int ncap; // number of captures, seen from the inside -#ifndef TQT_NO_REGEXP_CCLASS - TQPtrVector cl; // array of character classes -#endif -#ifndef TQT_NO_REGEXP_LOOKAHEAD - TQPtrVector ahead; // array of lookaheads -#endif -#ifndef TQT_NO_REGEXP_ANCHOR_ALT - TQMemArray aa; // array of (a, b) pairs of anchors -#endif -#ifndef TQT_NO_REGEXP_OPTIM - bool caretAnchored; // does the regexp start with ^? - bool trivial; // is the good-string all that needs to match? -#endif - bool valid; // is the regular expression valid? - bool cs; // case sensitive? -#ifndef TQT_NO_REGEXP_BACKREF - int nbrefs; // number of back-references -#endif - -#ifndef TQT_NO_REGEXP_OPTIM - bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch - - int goodEarlyStart; // the index where goodStr can first occur in a match - int goodLateStart; // the index where goodStr can last occur in a match - TQString goodStr; // the string that any match has to contain - - int minl; // the minimum length of a match - TQMemArray occ1; // first-occurrence array -#endif - - /* - The class Box is an abstraction for a regular expression - fragment. It can also be seen as one node in the syntax tree of - a regular expression with synthetized attributes. - - Its interface is ugly for performance reasons. - */ - class Box - { - public: - Box( TQRegExpEngine *engine ); - Box( const Box& b ) { operator=( b ); } - - Box& operator=( const Box& b ); - - void clear() { operator=( Box(eng) ); } - void set( TQChar ch ); - void set( const CharClass& cc ); -#ifndef TQT_NO_REGEXP_BACKREF - void set( int bref ); -#endif - - void cat( const Box& b ); - void orx( const Box& b ); - void plus( int atom ); - void opt(); - void catAnchor( int a ); -#ifndef TQT_NO_REGEXP_OPTIM - void setupHeuristics(); -#endif - -#if defined(QT_DEBUG) - void dump() const; -#endif - - private: - void addAnchorsToEngine( const Box& to ) const; - - TQRegExpEngine *eng; // the automaton under construction - TQMemArray ls; // the left states (firstpos) - TQMemArray rs; // the right states (lastpos) - TQMap lanchors; // the left anchors - TQMap ranchors; // the right anchors - int skipanchors; // the anchors to match if the box is skipped - -#ifndef TQT_NO_REGEXP_OPTIM - int earlyStart; // the index where str can first occur - int lateStart; // the index where str can last occur - TQString str; // a string that has to occur in any match - TQString leftStr; // a string occurring at the left of this box - TQString rightStr; // a string occurring at the right of this box - int maxl; // the maximum length of this box (possibly InftyLen) -#endif - - int minl; // the minimum length of this box -#ifndef TQT_NO_REGEXP_OPTIM - TQMemArray occ1; // first-occurrence array -#endif - }; - friend class Box; - - /* - This is the lexical analyzer for regular expressions. - */ - enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen, - Tok_PosLookahead, Tok_NegLookahead, Tok_RightParen, Tok_CharClass, - Tok_Caret, Tok_Quantifier, Tok_Bar, Tok_Word, Tok_NonWord, - Tok_Char = 0x10000, Tok_BackRef = 0x20000 }; - int getChar(); - int getEscape(); -#ifndef TQT_NO_REGEXP_INTERVAL - int getRep( int def ); -#endif -#ifndef TQT_NO_REGEXP_LOOKAHEAD - void skipChars( int n ); -#endif - void error( const char *msg ); - void startTokenizer( const TQChar *rx, int len ); - int getToken(); - - const TQChar *yyIn; // a pointer to the input regular expression pattern - int yyPos0; // the position of yyTok in the input pattern - int yyPos; // the position of the next character to read - int yyLen; // the length of yyIn - int yyCh; // the last character read - CharClass *yyCharClass; // attribute for Tok_CharClass tokens - int yyMinRep; // attribute for Tok_Quantifier - int yyMaxRep; // ditto - TQString yyError; // syntax error or overflow during parsing? - - /* - This is the syntactic analyzer for regular expressions. - */ - int parse( const TQChar *rx, int len ); - void parseAtom( Box *box ); - void parseFactor( Box *box ); - void parseTerm( Box *box ); - void parseExpression( Box *box ); - - int yyTok; // the last token read - bool yyMayCapture; // set this to FALSE to disable capturing - - /* - This is the engine state during matching. - */ - const TQString *mmStr; // a pointer to the input TQString - const TQChar *mmIn; // a pointer to the input string data - int mmPos; // the current position in the string - int mmCaretPos; - int mmLen; // the length of the input string - bool mmMinimal; // minimal matching? - TQMemArray mmBigArray; // big TQMemArray array - int *mmInNextStack; // is state is mmNextStack? - int *mmCurStack; // stack of current states - int *mmNextStack; // stack of next states - int *mmCurCapBegin; // start of current states' captures - int *mmNextCapBegin; // start of next states' captures - int *mmCurCapEnd; // end of current states' captures - int *mmNextCapEnd; // end of next states' captures - int *mmTempCapBegin; // start of temporary captures - int *mmTempCapEnd; // end of temporary captures - int *mmCapBegin; // start of captures for a next state - int *mmCapEnd; // end of captures for a next state - int *mmSlideTab; // bump-along slide table for bad-character heuristic - int mmSlideTabSize; // size of slide table -#ifndef TQT_NO_REGEXP_BACKREF - TQIntDict mmSleeping; // dictionary of back-reference sleepers -#endif - int mmMatchLen; // length of match - int mmOneTestMatchedLen; // length of partial match -}; - -TQRegExpEngine::TQRegExpEngine( const TQString& rx, bool caseSensitive ) -#ifndef TQT_NO_REGEXP_BACKREF - : mmSleeping( 101 ) -#endif -{ - setup( caseSensitive ); - valid = ( parse(rx.unicode(), rx.length()) == (int) rx.length() ); - if ( !valid ) { -#ifndef TQT_NO_REGEXP_OPTIM - trivial = FALSE; -#endif - error( RXERR_LEFTDELIM ); - } -} - -#ifndef TQT_NO_REGEXP_OPTIM -TQRegExpEngine::~TQRegExpEngine() -{ -} -#endif - -/* - Tries to match in str and returns an array of (begin, length) pairs - for captured text. If there is no match, all pairs are (-1, -1). -*/ -void TQRegExpEngine::match( const TQString& str, int pos, bool minimal, - bool oneTest, int caretIndex, - TQMemArray& captured ) -{ - bool matched = FALSE; - -#ifndef TQT_NO_REGEXP_OPTIM - if ( trivial && !oneTest ) { - mmPos = str.find( goodStr, pos, cs ); - mmMatchLen = goodStr.length(); - matched = ( mmPos != -1 ); - } else -#endif - { - mmStr = &str; - mmIn = str.unicode(); - if ( mmIn == 0 ) - mmIn = &TQChar::null; - mmPos = pos; - mmCaretPos = caretIndex; - mmLen = str.length(); - mmMinimal = minimal; - mmMatchLen = 0; - mmOneTestMatchedLen = 0; - - if ( valid && mmPos >= 0 && mmPos <= mmLen ) { -#ifndef TQT_NO_REGEXP_OPTIM - if ( oneTest ) { - matched = matchHere(); - } else { - if ( mmPos <= mmLen - minl ) { - if ( caretAnchored ) { - matched = matchHere(); - } else if ( useGoodStringHeuristic ) { - matched = goodStringMatch(); - } else { - matched = badCharMatch(); - } - } - } -#else - matched = oneTest ? matchHere() : bruteMatch(); -#endif - } - } - - int capturedSize = 2 + 2 * officialncap; - captured.detach(); - captured.resize( capturedSize ); - if ( matched ) { - captured[0] = mmPos; - captured[1] = mmMatchLen; - for ( int j = 0; j < officialncap; j++ ) { - int len = mmCapEnd[j] - mmCapBegin[j]; - captured[2 + 2 * j] = len > 0 ? mmPos + mmCapBegin[j] : 0; - captured[2 + 2 * j + 1] = len; - } - } else { - // we rely on 2's complement here - memset( captured.data(), -1, capturedSize * sizeof(int) ); - } -} - -/* - The three following functions add one state to the automaton and - return the number of the state. -*/ - -int TQRegExpEngine::createState( TQChar ch ) -{ - return setupState( ch.unicode() ); -} - -int TQRegExpEngine::createState( const CharClass& cc ) -{ -#ifndef TQT_NO_REGEXP_CCLASS - int n = cl.size(); - cl.resize( n + 1 ); - cl.insert( n, new CharClass(cc) ); - return setupState( CharClassBit | n ); -#else - Q_UNUSED( cc ); - return setupState( CharClassBit ); -#endif -} - -#ifndef TQT_NO_REGEXP_BACKREF -int TQRegExpEngine::createState( int bref ) -{ - if ( bref > nbrefs ) { - nbrefs = bref; - if ( nbrefs > MaxBackRefs ) { - error( RXERR_LIMIT ); - return 0; - } - } - return setupState( BackRefBit | bref ); -} -#endif - -/* - The two following functions add a transition between all pairs of - states (i, j) where i is fond in from, and j is found in to. - - Cat-transitions are distinguished from plus-transitions for - capturing. -*/ - -void TQRegExpEngine::addCatTransitions( const TQMemArray& from, - const TQMemArray& to ) -{ - for ( int i = 0; i < (int) from.size(); i++ ) { - State *st = s[from[i]]; - mergeInto( &st->outs, to ); - } -} - -#ifndef TQT_NO_REGEXP_CAPTURE -void TQRegExpEngine::addPlusTransitions( const TQMemArray& from, - const TQMemArray& to, int atom ) -{ - for ( int i = 0; i < (int) from.size(); i++ ) { - State *st = s[from[i]]; - TQMemArray oldOuts = st->outs.copy(); - mergeInto( &st->outs, to ); - if ( f[atom].capture >= 0 ) { - if ( st->reenter == 0 ) - st->reenter = new TQMap; - for ( int j = 0; j < (int) to.size(); j++ ) { - if ( !st->reenter->contains(to[j]) && - oldOuts.bsearch(to[j]) < 0 ) - st->reenter->insert( to[j], atom ); - } - } - } -} -#endif - -#ifndef TQT_NO_REGEXP_ANCHOR_ALT -/* - Returns an anchor that means a OR b. -*/ -int TQRegExpEngine::anchorAlternation( int a, int b ) -{ - if ( ((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0 ) - return a & b; - - int n = aa.size(); -#ifndef TQT_NO_REGEXP_OPTIM - if ( n > 0 && aa[n - 1].a == a && aa[n - 1].b == b ) - return Anchor_Alternation | ( n - 1 ); -#endif - - aa.resize( n + 1 ); - aa[n].a = a; - aa[n].b = b; - return Anchor_Alternation | n; -} - -/* - Returns an anchor that means a AND b. -*/ -int TQRegExpEngine::anchorConcatenation( int a, int b ) -{ - if ( ((a | b) & Anchor_Alternation) == 0 ) - return a | b; - if ( (b & Anchor_Alternation) != 0 ) - tqSwap( a, b ); - - int aprime = anchorConcatenation( aa[a ^ Anchor_Alternation].a, b ); - int bprime = anchorConcatenation( aa[a ^ Anchor_Alternation].b, b ); - return anchorAlternation( aprime, bprime ); -} -#endif - -/* - Adds anchor a on a transition caracterised by its from state and - its to state. -*/ -void TQRegExpEngine::addAnchors( int from, int to, int a ) -{ - State *st = s[from]; - if ( st->anchors == 0 ) - st->anchors = new TQMap; - if ( st->anchors->contains(to) ) - a = anchorAlternation( (*st->anchors)[to], a ); - st->anchors->insert( to, a ); -} - -#ifndef TQT_NO_REGEXP_OPTIM -/* - This function chooses between the good-string and the bad-character - heuristics. It computes two scores and chooses the heuristic with - the highest score. - - Here are some common-sense constraints on the scores that should be - respected if the formulas are ever modified: (1) If goodStr is - empty, the good-string heuristic scores 0. (2) If the regular - expression is trivial, the good-string heuristic should be used. - (3) If the search is case insensitive, the good-string heuristic - should be used, unless it scores 0. (Case insensitivity turns all - entries of occ1 to 0.) (4) If (goodLateStart - goodEarlyStart) is - big, the good-string heuristic should score less. -*/ -void TQRegExpEngine::heuristicallyChooseHeuristic() -{ - if ( minl == 0 ) { - useGoodStringHeuristic = FALSE; - } else if ( trivial ) { - useGoodStringHeuristic = TRUE; - } else { - /* - Magic formula: The good string has to constitute a good - proportion of the minimum-length string, and appear at a - more-or-less known index. - */ - int goodStringScore = ( 64 * goodStr.length() / minl ) - - ( goodLateStart - goodEarlyStart ); - /* - Less magic formula: We pick some characters at random, and - check whether they are good or bad. - */ - int badCharScore = 0; - int step = TQMAX( 1, NumBadChars / 32 ); - for ( int i = 1; i < NumBadChars; i += step ) { - if ( occ1[i] == NoOccurrence ) - badCharScore += minl; - else - badCharScore += occ1[i]; - } - badCharScore /= minl; - useGoodStringHeuristic = ( goodStringScore > badCharScore ); - } -} -#endif - -#if defined(QT_DEBUG) -void TQRegExpEngine::dump() const -{ - int i, j; - tqDebug( "Case %ssensitive engine", cs ? "" : "in" ); - tqDebug( " States" ); - for ( i = 0; i < ns; i++ ) { - tqDebug( " %d%s", i, - i == InitialState ? " (initial)" : - i == FinalState ? " (final)" : "" ); -#ifndef TQT_NO_REGEXP_CAPTURE - tqDebug( " in atom %d", s[i]->atom ); -#endif - int m = s[i]->match; - if ( (m & CharClassBit) != 0 ) { - tqDebug( " match character class %d", m ^ CharClassBit ); -#ifndef TQT_NO_REGEXP_CCLASS - cl[m ^ CharClassBit]->dump(); -#else - tqDebug( " negative character class" ); -#endif - } else if ( (m & BackRefBit) != 0 ) { - tqDebug( " match back-reference %d", m ^ BackRefBit ); - } else if ( m >= 0x20 && m <= 0x7e ) { - tqDebug( " match 0x%.4x (%c)", m, m ); - } else { - tqDebug( " match 0x%.4x", m ); - } - for ( j = 0; j < (int) s[i]->outs.size(); j++ ) { - int next = s[i]->outs[j]; - tqDebug( " -> %d", next ); - if ( s[i]->reenter != 0 && s[i]->reenter->contains(next) ) - tqDebug( " [reenter %d]", (*s[i]->reenter)[next] ); - if ( s[i]->anchors != 0 && at(*s[i]->anchors, next) != 0 ) - tqDebug( " [anchors 0x%.8x]", (*s[i]->anchors)[next] ); - } - } -#ifndef TQT_NO_REGEXP_CAPTURE - if ( nf > 0 ) { - tqDebug( " Atom Parent Capture" ); - for ( i = 0; i < nf; i++ ) - tqDebug( " %6d %6d %6d", i, f[i].parent, f[i].capture ); - } -#endif -#ifndef TQT_NO_REGEXP_ANCHOR_ALT - for ( i = 0; i < (int) aa.size(); i++ ) - tqDebug( " Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, - aa[i].b ); -#endif -} -#endif - -void TQRegExpEngine::setup( bool caseSensitive ) -{ - s.setAutoDelete( TRUE ); - s.resize( 32 ); - ns = 0; -#ifndef TQT_NO_REGEXP_CAPTURE - f.resize( 32 ); - nf = 0; - cf = -1; -#endif - officialncap = 0; - ncap = 0; -#ifndef TQT_NO_REGEXP_CCLASS - cl.setAutoDelete( TRUE ); -#endif -#ifndef TQT_NO_REGEXP_LOOKAHEAD - ahead.setAutoDelete( TRUE ); -#endif -#ifndef TQT_NO_REGEXP_OPTIM - caretAnchored = TRUE; - trivial = TRUE; -#endif - valid = FALSE; - cs = caseSensitive; -#ifndef TQT_NO_REGEXP_BACKREF - nbrefs = 0; -#endif -#ifndef TQT_NO_REGEXP_OPTIM - useGoodStringHeuristic = TRUE; - minl = 0; - occ1.fill( 0, NumBadChars ); -#endif -} - -int TQRegExpEngine::setupState( int match ) -{ - if ( (ns & (ns + 1)) == 0 && ns + 1 >= (int) s.size() ) - s.resize( (ns + 1) << 1 ); -#ifndef TQT_NO_REGEXP_CAPTURE - s.insert( ns, new State(cf, match) ); -#else - s.insert( ns, new State(match) ); -#endif - return ns++; -} - -#ifndef TQT_NO_REGEXP_CAPTURE -/* - Functions startAtom() and finishAtom() should be called to delimit - atoms. When a state is created, it is assigned to the current atom. - The information is later used for capturing. -*/ -int TQRegExpEngine::startAtom( bool capture ) -{ - if ( (nf & (nf + 1)) == 0 && nf + 1 >= (int) f.size() ) - f.resize( (nf + 1) << 1 ); - f[nf].parent = cf; - cf = nf++; - f[cf].capture = capture ? ncap++ : -1; - return cf; -} -#endif - -#ifndef TQT_NO_REGEXP_LOOKAHEAD -/* - Creates a lookahead anchor. -*/ -int TQRegExpEngine::addLookahead( TQRegExpEngine *eng, bool negative ) -{ - int n = ahead.size(); - if ( n == MaxLookaheads ) { - error( RXERR_LIMIT ); - return 0; - } - ahead.resize( n + 1 ); - ahead.insert( n, new Lookahead(eng, negative) ); - return Anchor_FirstLookahead << n; -} -#endif - -#ifndef TQT_NO_REGEXP_CAPTURE -/* - We want the longest leftmost captures. -*/ -bool TQRegExpEngine::isBetterCapture( const int *begin1, const int *end1, - const int *begin2, const int *end2 ) -{ - for ( int i = 0; i < ncap; i++ ) { - int delta = begin2[i] - begin1[i]; // it has to start early... - if ( delta == 0 ) - delta = end1[i] - end2[i]; // ...and end late (like a party) - - if ( delta != 0 ) - return delta > 0; - } - return FALSE; -} -#endif - -/* - Returns TRUE if anchor a matches at position mmPos + i in the input - string, otherwise FALSE. -*/ -bool TQRegExpEngine::testAnchor( int i, int a, const int *capBegin ) -{ - int j; - -#ifndef TQT_NO_REGEXP_ANCHOR_ALT - if ( (a & Anchor_Alternation) != 0 ) { - return testAnchor( i, aa[a ^ Anchor_Alternation].a, capBegin ) || - testAnchor( i, aa[a ^ Anchor_Alternation].b, capBegin ); - } -#endif - - if ( (a & Anchor_Caret) != 0 ) { - if ( mmPos + i != mmCaretPos ) - return FALSE; - } - if ( (a & Anchor_Dollar) != 0 ) { - if ( mmPos + i != mmLen ) - return FALSE; - } -#ifndef TQT_NO_REGEXP_ESCAPE - if ( (a & (Anchor_Word | Anchor_NonWord)) != 0 ) { - bool before = FALSE; - bool after = FALSE; - if ( mmPos + i != 0 ) - before = isWord( mmIn[mmPos + i - 1] ); - if ( mmPos + i != mmLen ) - after = isWord( mmIn[mmPos + i] ); - if ( (a & Anchor_Word) != 0 && (before == after) ) - return FALSE; - if ( (a & Anchor_NonWord) != 0 && (before != after) ) - return FALSE; - } -#endif -#ifndef TQT_NO_REGEXP_LOOKAHEAD - if ( (a & Anchor_LookaheadMask) != 0 ) { - TQConstString cstr = TQConstString( (TQChar *) mmIn + mmPos + i, - mmLen - mmPos - i ); - for ( j = 0; j < (int) ahead.size(); j++ ) { - if ( (a & (Anchor_FirstLookahead << j)) != 0 ) { - TQMemArray captured; - ahead[j]->eng->match( cstr.string(), 0, TRUE, TRUE, - mmCaretPos - mmPos - i, captured ); - if ( (captured[0] == 0) == ahead[j]->neg ) - return FALSE; - } - } - } -#endif -#ifndef TQT_NO_REGEXP_CAPTURE -#ifndef TQT_NO_REGEXP_BACKREF - for ( j = 0; j < nbrefs; j++ ) { - if ( (a & (Anchor_BackRef1Empty << j)) != 0 ) { - if ( capBegin[j] != EmptyCapture ) - return FALSE; - } - } -#endif -#endif - return TRUE; -} - -#ifndef TQT_NO_REGEXP_OPTIM -/* - The three following functions are what Jeffrey Friedl would call - transmissions (or bump-alongs). Using one or the other should make - no difference except in performance. -*/ - -bool TQRegExpEngine::goodStringMatch() -{ - int k = mmPos + goodEarlyStart; - while ( (k = mmStr->find(goodStr, k, cs)) != -1 ) { - int from = k - goodLateStart; - int to = k - goodEarlyStart; - if ( from > mmPos ) - mmPos = from; - - while ( mmPos <= to ) { - if ( matchHere() ) - return TRUE; - mmPos++; - } - k++; - } - return FALSE; -} - -bool TQRegExpEngine::badCharMatch() -{ - int slideHead = 0; - int slideNext = 0; - int i; - int lastPos = mmLen - minl; - memset( mmSlideTab, 0, mmSlideTabSize * sizeof(int) ); - - /* - Set up the slide table, used for the bad-character heuristic, - using the table of first occurrence of each character. - */ - for ( i = 0; i < minl; i++ ) { - int sk = occ1[BadChar(mmIn[mmPos + i])]; - if ( sk == NoOccurrence ) - sk = i + 1; - if ( sk > 0 ) { - int k = i + 1 - sk; - if ( k < 0 ) { - sk = i + 1; - k = 0; - } - if ( sk > mmSlideTab[k] ) - mmSlideTab[k] = sk; - } - } - - if ( mmPos > lastPos ) - return FALSE; - - for ( ;; ) { - if ( ++slideNext >= mmSlideTabSize ) - slideNext = 0; - if ( mmSlideTab[slideHead] > 0 ) { - if ( mmSlideTab[slideHead] - 1 > mmSlideTab[slideNext] ) - mmSlideTab[slideNext] = mmSlideTab[slideHead] - 1; - mmSlideTab[slideHead] = 0; - } else { - if ( matchHere() ) - return TRUE; - } - - if ( mmPos == lastPos ) - break; - - /* - Update the slide table. This code has much in common with - the initialization code. - */ - int sk = occ1[BadChar(mmIn[mmPos + minl])]; - if ( sk == NoOccurrence ) { - mmSlideTab[slideNext] = minl; - } else if ( sk > 0 ) { - int k = slideNext + minl - sk; - if ( k >= mmSlideTabSize ) - k -= mmSlideTabSize; - if ( sk > mmSlideTab[k] ) - mmSlideTab[k] = sk; - } - slideHead = slideNext; - mmPos++; - } - return FALSE; -} -#else -bool TQRegExpEngine::bruteMatch() -{ - while ( mmPos <= mmLen ) { - if ( matchHere() ) - return TRUE; - mmPos++; - } - return FALSE; -} -#endif - -/* - Here's the core of the engine. It tries to do a match here and now. -*/ -bool TQRegExpEngine::matchHere() -{ - int ncur = 1, nnext = 0; - int i = 0, j, k, m; - bool stop = FALSE; - - mmMatchLen = -1; - mmOneTestMatchedLen = -1; - mmCurStack[0] = InitialState; - -#ifndef TQT_NO_REGEXP_CAPTURE - if ( ncap > 0 ) { - for ( j = 0; j < ncap; j++ ) { - mmCurCapBegin[j] = EmptyCapture; - mmCurCapEnd[j] = EmptyCapture; - } - } -#endif - -#ifndef TQT_NO_REGEXP_BACKREF - int *zzZ = 0; - - while ( (ncur > 0 || !mmSleeping.isEmpty()) && i <= mmLen - mmPos && - !stop ) -#else - while ( ncur > 0 && i <= mmLen - mmPos && !stop ) -#endif - { - int ch = ( i < mmLen - mmPos ) ? mmIn[mmPos + i].unicode() : 0; - for ( j = 0; j < ncur; j++ ) { - int cur = mmCurStack[j]; - State *scur = s[cur]; - TQMemArray& outs = scur->outs; - for ( k = 0; k < (int) outs.size(); k++ ) { - int next = outs[k]; - State *snext = s[next]; - bool in = TRUE; -#ifndef TQT_NO_REGEXP_BACKREF - int needSomeSleep = 0; -#endif - - /* - First, check if the anchors are anchored properly. - */ - if ( scur->anchors != 0 ) { - int a = at( *scur->anchors, next ); - if ( a != 0 && !testAnchor(i, a, mmCurCapBegin + j * ncap) ) - in = FALSE; - } - /* - If indeed they are, check if the input character is - correct for this transition. - */ - if ( in ) { - m = snext->match; - if ( (m & (CharClassBit | BackRefBit)) == 0 ) { - if ( cs ) - in = ( m == ch ); - else - in = ( TQChar(m).lower() == TQChar(ch).lower() ); - } else if ( next == FinalState ) { - mmMatchLen = i; - stop = mmMinimal; - in = TRUE; - } else if ( (m & CharClassBit) != 0 ) { -#ifndef TQT_NO_REGEXP_CCLASS - const CharClass *cc = cl[m ^ CharClassBit]; - if ( cs ) - in = cc->in( ch ); - else if ( cc->negative() ) - in = cc->in( TQChar(ch).lower() ) && - cc->in( TQChar(ch).upper() ); - else - in = cc->in( TQChar(ch).lower() ) || - cc->in( TQChar(ch).upper() ); -#endif -#ifndef TQT_NO_REGEXP_BACKREF - } else { /* ( (m & BackRefBit) != 0 ) */ - int bref = m ^ BackRefBit; - int ell = j * ncap + ( bref - 1 ); - - in = bref <= ncap && mmCurCapBegin[ell] != EmptyCapture; - if ( in ) { - if ( cs ) - in = ( mmIn[mmPos + mmCurCapBegin[ell]] - == TQChar(ch) ); - else - in = ( mmIn[mmPos + mmCurCapBegin[ell]].lower() - == TQChar(ch).lower() ); - } - - if ( in ) { - int delta; - if ( mmCurCapEnd[ell] == EmptyCapture ) - delta = i - mmCurCapBegin[ell]; - else - delta = mmCurCapEnd[ell] - mmCurCapBegin[ell]; - - in = ( delta <= mmLen - (mmPos + i) ); - if ( in && delta > 1 ) { - int n = 1; - if ( cs ) { - while ( n < delta ) { - if ( mmIn[mmPos + - mmCurCapBegin[ell] + n] != - mmIn[mmPos + i + n] ) - break; - n++; - } - } else { - while ( n < delta ) { - TQChar a = mmIn[mmPos + - mmCurCapBegin[ell] + n]; - TQChar b = mmIn[mmPos + i + n]; - if ( a.lower() != b.lower() ) - break; - n++; - } - } - in = ( n == delta ); - if ( in ) - needSomeSleep = delta - 1; - } - } -#endif - } - } - - /* - We must now update our data structures. - */ - if ( in ) { -#ifndef TQT_NO_REGEXP_CAPTURE - int *capBegin, *capEnd; -#endif - /* - If the next state was not encountered yet, all - is fine. - */ - if ( (m = mmInNextStack[next]) == -1 ) { - m = nnext++; - mmNextStack[m] = next; - mmInNextStack[next] = m; -#ifndef TQT_NO_REGEXP_CAPTURE - capBegin = mmNextCapBegin + m * ncap; - capEnd = mmNextCapEnd + m * ncap; - - /* - Otherwise, we'll first maintain captures in - temporary arrays, and decide at the end whether - it's best to keep the previous capture zones or - the new ones. - */ - } else { - capBegin = mmTempCapBegin; - capEnd = mmTempCapEnd; -#endif - } - -#ifndef TQT_NO_REGEXP_CAPTURE - /* - Updating the capture zones is much of a task. - */ - if ( ncap > 0 ) { - memcpy( capBegin, mmCurCapBegin + j * ncap, - ncap * sizeof(int) ); - memcpy( capEnd, mmCurCapEnd + j * ncap, - ncap * sizeof(int) ); - int c = scur->atom, n = snext->atom; - int p = -1, q = -1; - int cap; - - /* - Lemma 1. For any x in the range [0..nf), we - have f[x].parent < x. - - Proof. By looking at startAtom(), it is - clear that cf < nf holds all the time, and - thus that f[nf].parent < nf. - */ - - /* - If we are reentering an atom, we empty all - capture zones inside it. - */ - if ( scur->reenter != 0 && - (q = at(*scur->reenter, next)) != 0 ) { - TQBitArray b; - b.fill( FALSE, nf ); - b.setBit( q, TRUE ); - for ( int ell = q + 1; ell < nf; ell++ ) { - if ( b.testBit(f[ell].parent) ) { - b.setBit( ell, TRUE ); - cap = f[ell].capture; - if ( cap >= 0 ) { - capBegin[cap] = EmptyCapture; - capEnd[cap] = EmptyCapture; - } - } - } - p = f[q].parent; - - /* - Otherwise, close the capture zones we are - leaving. We are leaving f[c].capture, - f[f[c].parent].capture, - f[f[f[c].parent].parent].capture, ..., - until f[x].capture, with x such that - f[x].parent is the youngest common ancestor - for c and n. - - We go up along c's and n's ancestry until - we find x. - */ - } else { - p = c; - q = n; - while ( p != q ) { - if ( p > q ) { - cap = f[p].capture; - if ( cap >= 0 ) { - if ( capBegin[cap] == i ) { - capBegin[cap] = EmptyCapture; - capEnd[cap] = EmptyCapture; - } else { - capEnd[cap] = i; - } - } - p = f[p].parent; - } else { - q = f[q].parent; - } - } - } - - /* - In any case, we now open the capture zones - we are entering. We work upwards from n - until we reach p (the parent of the atom we - reenter or the youngest common ancestor). - */ - while ( n > p ) { - cap = f[n].capture; - if ( cap >= 0 ) { - capBegin[cap] = i; - capEnd[cap] = EmptyCapture; - } - n = f[n].parent; - } - /* - If the next state was already in - mmNextStack, we must choose carefully which - capture zones we want to keep. - */ - if ( capBegin == mmTempCapBegin && - isBetterCapture(capBegin, capEnd, - mmNextCapBegin + m * ncap, - mmNextCapEnd + m * ncap) ) { - memcpy( mmNextCapBegin + m * ncap, capBegin, - ncap * sizeof(int) ); - memcpy( mmNextCapEnd + m * ncap, capEnd, - ncap * sizeof(int) ); - } - } -#ifndef TQT_NO_REGEXP_BACKREF - /* - We are done with updating the capture zones. - It's now time to put the next state to sleep, - if it needs to, and to remove it from - mmNextStack. - */ - if ( needSomeSleep > 0 ) { - zzZ = new int[1 + 2 * ncap]; - zzZ[0] = next; - if ( ncap > 0 ) { - memcpy( zzZ + 1, capBegin, ncap * sizeof(int) ); - memcpy( zzZ + 1 + ncap, capEnd, - ncap * sizeof(int) ); - } - mmInNextStack[mmNextStack[--nnext]] = -1; - mmSleeping.insert( i + needSomeSleep, zzZ ); - } -#endif -#endif - } - } - } -#ifndef TQT_NO_REGEXP_CAPTURE - /* - If we reached the final state, hurray! Copy the captured - zone. - */ - if ( ncap > 0 && (m = mmInNextStack[FinalState]) != -1 ) { - memcpy( mmCapBegin, mmNextCapBegin + m * ncap, ncap * sizeof(int) ); - memcpy( mmCapEnd, mmNextCapEnd + m * ncap, ncap * sizeof(int) ); - } -#ifndef TQT_NO_REGEXP_BACKREF - /* - It's time to wake up the sleepers. - */ - if ( !mmSleeping.isEmpty() ) { - while ( (zzZ = mmSleeping.take(i)) != 0 ) { - int next = zzZ[0]; - int *capBegin = zzZ + 1; - int *capEnd = zzZ + 1 + ncap; - bool copyOver = TRUE; - - if ( (m = mmInNextStack[zzZ[0]]) == -1 ) { - m = nnext++; - mmNextStack[m] = next; - mmInNextStack[next] = m; - } else { - copyOver = isBetterCapture( mmNextCapBegin + m * ncap, - mmNextCapEnd + m * ncap, - capBegin, capEnd ); - } - if ( copyOver ) { - memcpy( mmNextCapBegin + m * ncap, capBegin, - ncap * sizeof(int) ); - memcpy( mmNextCapEnd + m * ncap, capEnd, - ncap * sizeof(int) ); - } - delete[] zzZ; - } - } -#endif -#endif - for ( j = 0; j < nnext; j++ ) - mmInNextStack[mmNextStack[j]] = -1; - - // avoid needless iteration that confuses mmOneTestMatchedLen - if ( nnext == 1 && mmNextStack[0] == FinalState -#ifndef TQT_NO_REGEXP_BACKREF - && mmSleeping.isEmpty() -#endif - ) - stop = TRUE; - - tqSwap( mmCurStack, mmNextStack ); -#ifndef TQT_NO_REGEXP_CAPTURE - tqSwap( mmCurCapBegin, mmNextCapBegin ); - tqSwap( mmCurCapEnd, mmNextCapEnd ); -#endif - ncur = nnext; - nnext = 0; - i++; - } - -#ifndef TQT_NO_REGEXP_BACKREF - /* - If minimal matching is enabled, we might have some sleepers - left. - */ - while ( !mmSleeping.isEmpty() ) { - zzZ = mmSleeping.take( *TQIntDictIterator(mmSleeping) ); - delete[] zzZ; - } -#endif - - mmOneTestMatchedLen = i - 1; - return ( mmMatchLen >= 0 ); -} - -#ifndef TQT_NO_REGEXP_CCLASS - -TQRegExpEngine::CharClass::CharClass() - : c( 0 ), n( FALSE ) -{ -#ifndef TQT_NO_REGEXP_OPTIM - occ1.fill( NoOccurrence, NumBadChars ); -#endif -} - -TQRegExpEngine::CharClass& TQRegExpEngine::CharClass::operator=( - const CharClass& cc ) -{ - c = cc.c; - r = cc.r.copy(); - n = cc.n; -#ifndef TQT_NO_REGEXP_OPTIM - occ1 = cc.occ1; -#endif - return *this; -} - -void TQRegExpEngine::CharClass::clear() -{ - c = 0; - r.resize( 0 ); - n = FALSE; -} - -void TQRegExpEngine::CharClass::setNegative( bool negative ) -{ - n = negative; -#ifndef TQT_NO_REGEXP_OPTIM - occ1.fill( 0, NumBadChars ); -#endif -} - -void TQRegExpEngine::CharClass::addCategories( int cats ) -{ - c |= cats; -#ifndef TQT_NO_REGEXP_OPTIM - occ1.fill( 0, NumBadChars ); -#endif -} - -void TQRegExpEngine::CharClass::addRange( ushort from, ushort to ) -{ - if ( from > to ) - tqSwap( from, to ); - int m = r.size(); - r.resize( m + 1 ); - r[m].from = from; - r[m].to = to; - -#ifndef TQT_NO_REGEXP_OPTIM - int i; - - if ( to - from < NumBadChars ) { - occ1.detach(); - if ( from % NumBadChars <= to % NumBadChars ) { - for ( i = from % NumBadChars; i <= to % NumBadChars; i++ ) - occ1[i] = 0; - } else { - for ( i = 0; i <= to % NumBadChars; i++ ) - occ1[i] = 0; - for ( i = from % NumBadChars; i < NumBadChars; i++ ) - occ1[i] = 0; - } - } else { - occ1.fill( 0, NumBadChars ); - } -#endif -} - -bool TQRegExpEngine::CharClass::in( TQChar ch ) const -{ -#ifndef TQT_NO_REGEXP_OPTIM - if ( occ1[BadChar(ch)] == NoOccurrence ) - return n; -#endif - - if ( c != 0 && (c & (1 << (int) ch.category())) != 0 ) - return !n; - for ( int i = 0; i < (int) r.size(); i++ ) { - if ( ch.unicode() >= r[i].from && ch.unicode() <= r[i].to ) - return !n; - } - return n; -} - -#if defined(QT_DEBUG) -void TQRegExpEngine::CharClass::dump() const -{ - int i; - tqDebug( " %stive character class", n ? "nega" : "posi" ); -#ifndef TQT_NO_REGEXP_CCLASS - if ( c != 0 ) - tqDebug( " categories 0x%.8x", c ); -#endif - for ( i = 0; i < (int) r.size(); i++ ) - tqDebug( " 0x%.4x through 0x%.4x", r[i].from, r[i].to ); -} -#endif -#endif - -TQRegExpEngine::Box::Box( TQRegExpEngine *engine ) - : eng( engine ), skipanchors( 0 ) -#ifndef TQT_NO_REGEXP_OPTIM - , earlyStart( 0 ), lateStart( 0 ), maxl( 0 ) -#endif -{ -#ifndef TQT_NO_REGEXP_OPTIM - occ1.fill( NoOccurrence, NumBadChars ); -#endif - minl = 0; -} - -TQRegExpEngine::Box& TQRegExpEngine::Box::operator=( const Box& b ) -{ - eng = b.eng; - ls = b.ls; - rs = b.rs; - lanchors = b.lanchors; - ranchors = b.ranchors; - skipanchors = b.skipanchors; -#ifndef TQT_NO_REGEXP_OPTIM - earlyStart = b.earlyStart; - lateStart = b.lateStart; - str = b.str; - leftStr = b.leftStr; - rightStr = b.rightStr; - maxl = b.maxl; - occ1 = b.occ1; -#endif - minl = b.minl; - return *this; -} - -void TQRegExpEngine::Box::set( TQChar ch ) -{ - ls.resize( 1 ); - ls[0] = eng->createState( ch ); - rs = ls; - rs.detach(); -#ifndef TQT_NO_REGEXP_OPTIM - str = ch; - leftStr = ch; - rightStr = ch; - maxl = 1; - occ1.detach(); - occ1[BadChar(ch)] = 0; -#endif - minl = 1; -} - -void TQRegExpEngine::Box::set( const CharClass& cc ) -{ - ls.resize( 1 ); - ls[0] = eng->createState( cc ); - rs = ls; - rs.detach(); -#ifndef TQT_NO_REGEXP_OPTIM - maxl = 1; - occ1 = cc.firstOccurrence(); -#endif - minl = 1; -} - -#ifndef TQT_NO_REGEXP_BACKREF -void TQRegExpEngine::Box::set( int bref ) -{ - ls.resize( 1 ); - ls[0] = eng->createState( bref ); - rs = ls; - rs.detach(); - if ( bref >= 1 && bref <= MaxBackRefs ) - skipanchors = Anchor_BackRef0Empty << bref; -#ifndef TQT_NO_REGEXP_OPTIM - maxl = InftyLen; -#endif - minl = 0; -} -#endif - -void TQRegExpEngine::Box::cat( const Box& b ) -{ - eng->addCatTransitions( rs, b.ls ); - addAnchorsToEngine( b ); - if ( minl == 0 ) { - mergeInto( &lanchors, b.lanchors ); - if ( skipanchors != 0 ) { - for ( int i = 0; i < (int) b.ls.size(); i++ ) { - int a = eng->anchorConcatenation( at(lanchors, b.ls[i]), - skipanchors ); - lanchors.insert( b.ls[i], a ); - } - } - mergeInto( &ls, b.ls ); - } - if ( b.minl == 0 ) { - mergeInto( &ranchors, b.ranchors ); - if ( b.skipanchors != 0 ) { - for ( int i = 0; i < (int) rs.size(); i++ ) { - int a = eng->anchorConcatenation( at(ranchors, rs[i]), - b.skipanchors ); - ranchors.insert( rs[i], a ); - } - } - mergeInto( &rs, b.rs ); - } else { - ranchors = b.ranchors; - rs = b.rs; - } - -#ifndef TQT_NO_REGEXP_OPTIM - if ( maxl != InftyLen ) { - if ( rightStr.length() + b.leftStr.length() > - TQMAX(str.length(), b.str.length()) ) { - earlyStart = minl - rightStr.length(); - lateStart = maxl - rightStr.length(); - str = rightStr + b.leftStr; - } else if ( b.str.length() > str.length() ) { - earlyStart = minl + b.earlyStart; - lateStart = maxl + b.lateStart; - str = b.str; - } - } - - if ( (int) leftStr.length() == maxl ) - leftStr += b.leftStr; - - if ( (int) b.rightStr.length() == b.maxl ) { - rightStr += b.rightStr; - } else { - rightStr = b.rightStr; - } - - if ( maxl == InftyLen || b.maxl == InftyLen ) { - maxl = InftyLen; - } else { - maxl += b.maxl; - } - - occ1.detach(); - for ( int i = 0; i < NumBadChars; i++ ) { - if ( b.occ1[i] != NoOccurrence && minl + b.occ1[i] < occ1[i] ) - occ1[i] = minl + b.occ1[i]; - } -#endif - - minl += b.minl; - if ( minl == 0 ) - skipanchors = eng->anchorConcatenation( skipanchors, b.skipanchors ); - else - skipanchors = 0; -} - -void TQRegExpEngine::Box::orx( const Box& b ) -{ - mergeInto( &ls, b.ls ); - mergeInto( &lanchors, b.lanchors ); - mergeInto( &rs, b.rs ); - mergeInto( &ranchors, b.ranchors ); - - if ( b.minl == 0 ) { - if ( minl == 0 ) - skipanchors = eng->anchorAlternation( skipanchors, b.skipanchors ); - else - skipanchors = b.skipanchors; - } - -#ifndef TQT_NO_REGEXP_OPTIM - occ1.detach(); - for ( int i = 0; i < NumBadChars; i++ ) { - if ( occ1[i] > b.occ1[i] ) - occ1[i] = b.occ1[i]; - } - earlyStart = 0; - lateStart = 0; - str = TQString(); - leftStr = TQString(); - rightStr = TQString(); - if ( b.maxl > maxl ) - maxl = b.maxl; -#endif - if ( b.minl < minl ) - minl = b.minl; -} - -void TQRegExpEngine::Box::plus( int atom ) -{ -#ifndef TQT_NO_REGEXP_CAPTURE - eng->addPlusTransitions( rs, ls, atom ); -#else - Q_UNUSED( atom ); - eng->addCatTransitions( rs, ls ); -#endif - addAnchorsToEngine( *this ); -#ifndef TQT_NO_REGEXP_OPTIM - maxl = InftyLen; -#endif -} - -void TQRegExpEngine::Box::opt() -{ -#ifndef TQT_NO_REGEXP_OPTIM - earlyStart = 0; - lateStart = 0; - str = TQString(); - leftStr = TQString(); - rightStr = TQString(); -#endif - skipanchors = 0; - minl = 0; -} - -void TQRegExpEngine::Box::catAnchor( int a ) -{ - if ( a != 0 ) { - for ( int i = 0; i < (int) rs.size(); i++ ) { - a = eng->anchorConcatenation( at(ranchors, rs[i]), a ); - ranchors.insert( rs[i], a ); - } - if ( minl == 0 ) - skipanchors = eng->anchorConcatenation( skipanchors, a ); - } -} - -#ifndef TQT_NO_REGEXP_OPTIM -void TQRegExpEngine::Box::setupHeuristics() -{ - eng->goodEarlyStart = earlyStart; - eng->goodLateStart = lateStart; - eng->goodStr = eng->cs ? str : str.lower(); - - eng->minl = minl; - if ( eng->cs ) { - /* - A regular expression such as 112|1 has occ1['2'] = 2 and minl = - 1 at this point. An entry of occ1 has to be at most minl or - infinity for the rest of the algorithm to go well. - - We waited until here before normalizing these cases (instead of - doing it in Box::orx()) because sometimes things improve by - themselves. Consider for example (112|1)34. - */ - for ( int i = 0; i < NumBadChars; i++ ) { - if ( occ1[i] != NoOccurrence && occ1[i] >= minl ) - occ1[i] = minl; - } - eng->occ1 = occ1; - } else { - eng->occ1.fill( 0, NumBadChars ); - } - - eng->heuristicallyChooseHeuristic(); -} -#endif - -#if defined(QT_DEBUG) -void TQRegExpEngine::Box::dump() const -{ - int i; - tqDebug( "Box of at least %d character%s", minl, minl == 1 ? "" : "s" ); - tqDebug( " Left states:" ); - for ( i = 0; i < (int) ls.size(); i++ ) { - if ( at(lanchors, ls[i]) == 0 ) - tqDebug( " %d", ls[i] ); - else - tqDebug( " %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]] ); - } - tqDebug( " Right states:" ); - for ( i = 0; i < (int) rs.size(); i++ ) { - if ( at(ranchors, rs[i]) == 0 ) - tqDebug( " %d", rs[i] ); - else - tqDebug( " %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]] ); - } - tqDebug( " Skip anchors: 0x%.8x", skipanchors ); -} -#endif - -void TQRegExpEngine::Box::addAnchorsToEngine( const Box& to ) const -{ - for ( int i = 0; i < (int) to.ls.size(); i++ ) { - for ( int j = 0; j < (int) rs.size(); j++ ) { - int a = eng->anchorConcatenation( at(ranchors, rs[j]), - at(to.lanchors, to.ls[i]) ); - eng->addAnchors( rs[j], to.ls[i], a ); - } - } -} - -int TQRegExpEngine::getChar() -{ - return ( yyPos == yyLen ) ? EOS : yyIn[yyPos++].unicode(); -} - -int TQRegExpEngine::getEscape() -{ -#ifndef TQT_NO_REGEXP_ESCAPE - const char tab[] = "afnrtv"; // no b, as \b means word boundary - const char backTab[] = "\a\f\n\r\t\v"; - ushort low; - int i; -#endif - ushort val; - int prevCh = yyCh; - - if ( prevCh == EOS ) { - error( RXERR_END ); - return Tok_Char | '\\'; - } - yyCh = getChar(); -#ifndef TQT_NO_REGEXP_ESCAPE - if ( (prevCh & ~0xff) == 0 ) { - const char *p = strchr( tab, prevCh ); - if ( p != 0 ) - return Tok_Char | backTab[p - tab]; - } -#endif - - switch ( prevCh ) { -#ifndef TQT_NO_REGEXP_ESCAPE - case '0': - val = 0; - for ( i = 0; i < 3; i++ ) { - if ( yyCh >= '0' && yyCh <= '7' ) - val = ( val << 3 ) | ( yyCh - '0' ); - else - break; - yyCh = getChar(); - } - if ( (val & ~0377) != 0 ) - error( RXERR_OCTAL ); - return Tok_Char | val; -#endif -#ifndef TQT_NO_REGEXP_ESCAPE - case 'B': - return Tok_NonWord; -#endif -#ifndef TQT_NO_REGEXP_CCLASS - case 'D': - // see TQChar::isDigit() - yyCharClass->addCategories( 0x7fffffef ); - return Tok_CharClass; - case 'S': - // see TQChar::isSpace() - yyCharClass->addCategories( 0x7ffff87f ); - yyCharClass->addRange( 0x0000, 0x0008 ); - yyCharClass->addRange( 0x000e, 0x001f ); - yyCharClass->addRange( 0x007f, 0x009f ); - return Tok_CharClass; - case 'W': - // see TQChar::isLetterOrNumber() - yyCharClass->addCategories( 0x7fe07f8f ); - yyCharClass->addRange( 0x203f, 0x2040 ); - yyCharClass->addSingleton( 0x2040 ); - yyCharClass->addSingleton( 0x30fb ); - yyCharClass->addRange( 0xfe33, 0xfe34 ); - yyCharClass->addRange( 0xfe4d, 0xfe4f ); - yyCharClass->addSingleton( 0xff3f ); - yyCharClass->addSingleton( 0xff65 ); - return Tok_CharClass; -#endif -#ifndef TQT_NO_REGEXP_ESCAPE - case 'b': - return Tok_Word; -#endif -#ifndef TQT_NO_REGEXP_CCLASS - case 'd': - // see TQChar::isDigit() - yyCharClass->addCategories( 0x00000010 ); - return Tok_CharClass; - case 's': - // see TQChar::isSpace() - yyCharClass->addCategories( 0x00000380 ); - yyCharClass->addRange( 0x0009, 0x000d ); - return Tok_CharClass; - case 'w': - // see TQChar::isLetterOrNumber() - yyCharClass->addCategories( 0x000f8070 ); - yyCharClass->addSingleton( 0x005f ); // '_' - return Tok_CharClass; -#endif -#ifndef TQT_NO_REGEXP_ESCAPE - case 'x': - val = 0; - for ( i = 0; i < 4; i++ ) { - low = TQChar( yyCh ).lower(); - if ( low >= '0' && low <= '9' ) - val = ( val << 4 ) | ( low - '0' ); - else if ( low >= 'a' && low <= 'f' ) - val = ( val << 4 ) | ( low - 'a' + 10 ); - else - break; - yyCh = getChar(); - } - return Tok_Char | val; -#endif - default: - if ( prevCh >= '1' && prevCh <= '9' ) { -#ifndef TQT_NO_REGEXP_BACKREF - val = prevCh - '0'; - while ( yyCh >= '0' && yyCh <= '9' ) { - val = ( val * 10 ) + ( yyCh - '0' ); - yyCh = getChar(); - } - return Tok_BackRef | val; -#else - error( RXERR_DISABLED ); -#endif - } - return Tok_Char | prevCh; - } -} - -#ifndef TQT_NO_REGEXP_INTERVAL -int TQRegExpEngine::getRep( int def ) -{ - if ( yyCh >= '0' && yyCh <= '9' ) { - int rep = 0; - do { - rep = 10 * rep + yyCh - '0'; - if ( rep >= InftyRep ) { - error( RXERR_REPETITION ); - rep = def; - } - yyCh = getChar(); - } while ( yyCh >= '0' && yyCh <= '9' ); - return rep; - } else { - return def; - } -} -#endif - -#ifndef TQT_NO_REGEXP_LOOKAHEAD -void TQRegExpEngine::skipChars( int n ) -{ - if ( n > 0 ) { - yyPos += n - 1; - yyCh = getChar(); - } -} -#endif - -void TQRegExpEngine::error( const char *msg ) -{ - if ( yyError.isEmpty() ) - yyError = TQString::fromLatin1( msg ); -} - -void TQRegExpEngine::startTokenizer( const TQChar *rx, int len ) -{ - yyIn = rx; - yyPos0 = 0; - yyPos = 0; - yyLen = len; - yyCh = getChar(); - yyCharClass = new CharClass; - yyMinRep = 0; - yyMaxRep = 0; - yyError = TQString(); -} - -int TQRegExpEngine::getToken() -{ -#ifndef TQT_NO_REGEXP_CCLASS - ushort pendingCh = 0; - bool charPending; - bool rangePending; - int tok; -#endif - int prevCh = yyCh; - - yyPos0 = yyPos - 1; -#ifndef TQT_NO_REGEXP_CCLASS - yyCharClass->clear(); -#endif - yyMinRep = 0; - yyMaxRep = 0; - yyCh = getChar(); - - switch ( prevCh ) { - case EOS: - yyPos0 = yyPos; - return Tok_Eos; - case '$': - return Tok_Dollar; - case '(': - if ( yyCh == '?' ) { - prevCh = getChar(); - yyCh = getChar(); - switch ( prevCh ) { -#ifndef TQT_NO_REGEXP_LOOKAHEAD - case '!': - return Tok_NegLookahead; - case '=': - return Tok_PosLookahead; -#endif - case ':': - return Tok_MagicLeftParen; - default: - error( RXERR_LOOKAHEAD ); - return Tok_MagicLeftParen; - } - } else { - return Tok_LeftParen; - } - case ')': - return Tok_RightParen; - case '*': - yyMinRep = 0; - yyMaxRep = InftyRep; - return Tok_Quantifier; - case '+': - yyMinRep = 1; - yyMaxRep = InftyRep; - return Tok_Quantifier; - case '.': -#ifndef TQT_NO_REGEXP_CCLASS - yyCharClass->setNegative( TRUE ); -#endif - return Tok_CharClass; - case '?': - yyMinRep = 0; - yyMaxRep = 1; - return Tok_Quantifier; - case '[': -#ifndef TQT_NO_REGEXP_CCLASS - if ( yyCh == '^' ) { - yyCharClass->setNegative( TRUE ); - yyCh = getChar(); - } - charPending = FALSE; - rangePending = FALSE; - do { - if ( yyCh == '-' && charPending && !rangePending ) { - rangePending = TRUE; - yyCh = getChar(); - } else { - if ( charPending && !rangePending ) { - yyCharClass->addSingleton( pendingCh ); - charPending = FALSE; - } - if ( yyCh == '\\' ) { - yyCh = getChar(); - tok = getEscape(); - if ( tok == Tok_Word ) - tok = '\b'; - } else { - tok = Tok_Char | yyCh; - yyCh = getChar(); - } - if ( tok == Tok_CharClass ) { - if ( rangePending ) { - yyCharClass->addSingleton( '-' ); - yyCharClass->addSingleton( pendingCh ); - charPending = FALSE; - rangePending = FALSE; - } - } else if ( (tok & Tok_Char) != 0 ) { - if ( rangePending ) { - yyCharClass->addRange( pendingCh, tok ^ Tok_Char ); - charPending = FALSE; - rangePending = FALSE; - } else { - pendingCh = tok ^ Tok_Char; - charPending = TRUE; - } - } else { - error( RXERR_CHARCLASS ); - } - } - } while ( yyCh != ']' && yyCh != EOS ); - if ( rangePending ) - yyCharClass->addSingleton( '-' ); - if ( charPending ) - yyCharClass->addSingleton( pendingCh ); - if ( yyCh == EOS ) - error( RXERR_END ); - else - yyCh = getChar(); - return Tok_CharClass; -#else - error( RXERR_END ); - return Tok_Char | '['; -#endif - case '\\': - return getEscape(); - case ']': - error( RXERR_LEFTDELIM ); - return Tok_Char | ']'; - case '^': - return Tok_Caret; - case '{': -#ifndef TQT_NO_REGEXP_INTERVAL - yyMinRep = getRep( 0 ); - yyMaxRep = yyMinRep; - if ( yyCh == ',' ) { - yyCh = getChar(); - yyMaxRep = getRep( InftyRep ); - } - if ( yyMaxRep < yyMinRep ) - tqSwap( yyMinRep, yyMaxRep ); - if ( yyCh != '}' ) - error( RXERR_REPETITION ); - yyCh = getChar(); - return Tok_Quantifier; -#else - error( RXERR_DISABLED ); - return Tok_Char | '{'; -#endif - case '|': - return Tok_Bar; - case '}': - error( RXERR_LEFTDELIM ); - return Tok_Char | '}'; - default: - return Tok_Char | prevCh; - } -} - -int TQRegExpEngine::parse( const TQChar *pattern, int len ) -{ - valid = TRUE; - startTokenizer( pattern, len ); - yyTok = getToken(); -#ifndef TQT_NO_REGEXP_CAPTURE - yyMayCapture = TRUE; -#else - yyMayCapture = FALSE; -#endif - -#ifndef TQT_NO_REGEXP_CAPTURE - int atom = startAtom( FALSE ); -#endif - CharClass anything; - Box box( this ); // create InitialState - box.set( anything ); - Box rightBox( this ); // create FinalState - rightBox.set( anything ); - - Box middleBox( this ); - parseExpression( &middleBox ); -#ifndef TQT_NO_REGEXP_CAPTURE - finishAtom( atom ); -#endif -#ifndef TQT_NO_REGEXP_OPTIM - middleBox.setupHeuristics(); -#endif - box.cat( middleBox ); - box.cat( rightBox ); - delete yyCharClass; - yyCharClass = 0; - - officialncap = ncap; -#ifndef TQT_NO_REGEXP_BACKREF - if ( nbrefs > ncap ) - ncap = nbrefs; -#endif - - /* - We use one TQMemArray for all the big data used a lot in - matchHere() and friends. - */ -#ifndef TQT_NO_REGEXP_OPTIM - mmSlideTabSize = TQMAX( minl + 1, 16 ); -#else - mmSlideTabSize = 0; -#endif - mmBigArray.resize( (3 + 4 * ncap) * ns + 4 * ncap + mmSlideTabSize ); - - mmInNextStack = mmBigArray.data(); - memset( mmInNextStack, -1, ns * sizeof(int) ); - mmCurStack = mmInNextStack + ns; - mmNextStack = mmInNextStack + 2 * ns; - - mmCurCapBegin = mmInNextStack + 3 * ns; - mmNextCapBegin = mmCurCapBegin + ncap * ns; - mmCurCapEnd = mmCurCapBegin + 2 * ncap * ns; - mmNextCapEnd = mmCurCapBegin + 3 * ncap * ns; - - mmTempCapBegin = mmCurCapBegin + 4 * ncap * ns; - mmTempCapEnd = mmTempCapBegin + ncap; - mmCapBegin = mmTempCapBegin + 2 * ncap; - mmCapEnd = mmTempCapBegin + 3 * ncap; - - mmSlideTab = mmTempCapBegin + 4 * ncap; - - if ( !yyError.isEmpty() ) - return -1; - -#ifndef TQT_NO_REGEXP_OPTIM - State *sinit = s[InitialState]; - caretAnchored = ( sinit->anchors != 0 ); - if ( caretAnchored ) { - TQMap& anchors = *sinit->anchors; - TQMap::ConstIterator a; - for ( a = anchors.begin(); a != anchors.end(); ++a ) { - if ( -#ifndef TQT_NO_REGEXP_ANCHOR_ALT - (*a & Anchor_Alternation) != 0 || -#endif - (*a & Anchor_Caret) == 0 ) { - caretAnchored = FALSE; - break; - } - } - } -#endif - return yyPos0; -} - -void TQRegExpEngine::parseAtom( Box *box ) -{ -#ifndef TQT_NO_REGEXP_LOOKAHEAD - TQRegExpEngine *eng = 0; - bool neg; - int len; -#endif - - if ( (yyTok & Tok_Char) != 0 ) { - box->set( TQChar(yyTok ^ Tok_Char) ); - } else { -#ifndef TQT_NO_REGEXP_OPTIM - trivial = FALSE; -#endif - switch ( yyTok ) { - case Tok_Dollar: - box->catAnchor( Anchor_Dollar ); - break; - case Tok_Caret: - box->catAnchor( Anchor_Caret ); - break; -#ifndef TQT_NO_REGEXP_LOOKAHEAD - case Tok_PosLookahead: - case Tok_NegLookahead: - neg = ( yyTok == Tok_NegLookahead ); - eng = new TQRegExpEngine( cs ); - len = eng->parse( yyIn + yyPos - 1, yyLen - yyPos + 1 ); - if ( len >= 0 ) - skipChars( len ); - else - error( RXERR_LOOKAHEAD ); - box->catAnchor( addLookahead(eng, neg) ); - yyTok = getToken(); - if ( yyTok != Tok_RightParen ) - error( RXERR_LOOKAHEAD ); - break; -#endif -#ifndef TQT_NO_REGEXP_ESCAPE - case Tok_Word: - box->catAnchor( Anchor_Word ); - break; - case Tok_NonWord: - box->catAnchor( Anchor_NonWord ); - break; -#endif - case Tok_LeftParen: - case Tok_MagicLeftParen: - yyTok = getToken(); - parseExpression( box ); - if ( yyTok != Tok_RightParen ) - error( RXERR_END ); - break; - case Tok_CharClass: - box->set( *yyCharClass ); - break; - case Tok_Quantifier: - error( RXERR_REPETITION ); - break; - default: -#ifndef TQT_NO_REGEXP_BACKREF - if ( (yyTok & Tok_BackRef) != 0 ) - box->set( yyTok ^ Tok_BackRef ); - else -#endif - error( RXERR_DISABLED ); - } - } - yyTok = getToken(); -} - -void TQRegExpEngine::parseFactor( Box *box ) -{ -#ifndef TQT_NO_REGEXP_CAPTURE - int atom = startAtom( yyMayCapture && yyTok == Tok_LeftParen ); -#else - static const int atom = 0; -#endif - -#ifndef TQT_NO_REGEXP_INTERVAL -#define YYREDO() \ - yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \ - *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok - - const TQChar *in = yyIn; - int pos0 = yyPos0; - int pos = yyPos; - int len = yyLen; - int ch = yyCh; - CharClass charClass; - if ( yyTok == Tok_CharClass ) - charClass = *yyCharClass; - int tok = yyTok; - bool mayCapture = yyMayCapture; -#endif - - parseAtom( box ); -#ifndef TQT_NO_REGEXP_CAPTURE - finishAtom( atom ); -#endif - - if ( yyTok == Tok_Quantifier ) { -#ifndef TQT_NO_REGEXP_OPTIM - trivial = FALSE; -#endif - if ( yyMaxRep == InftyRep ) { - box->plus( atom ); -#ifndef TQT_NO_REGEXP_INTERVAL - } else if ( yyMaxRep == 0 ) { - box->clear(); -#endif - } - if ( yyMinRep == 0 ) - box->opt(); - -#ifndef TQT_NO_REGEXP_INTERVAL - yyMayCapture = FALSE; - int alpha = ( yyMinRep == 0 ) ? 0 : yyMinRep - 1; - int beta = ( yyMaxRep == InftyRep ) ? 0 : yyMaxRep - ( alpha + 1 ); - - Box rightBox( this ); - int i; - - for ( i = 0; i < beta; i++ ) { - YYREDO(); - Box leftBox( this ); - parseAtom( &leftBox ); - leftBox.cat( rightBox ); - leftBox.opt(); - rightBox = leftBox; - } - for ( i = 0; i < alpha; i++ ) { - YYREDO(); - Box leftBox( this ); - parseAtom( &leftBox ); - leftBox.cat( rightBox ); - rightBox = leftBox; - } - rightBox.cat( *box ); - *box = rightBox; -#endif - yyTok = getToken(); -#ifndef TQT_NO_REGEXP_INTERVAL - yyMayCapture = mayCapture; -#endif - } -#undef YYREDO -} - -void TQRegExpEngine::parseTerm( Box *box ) -{ -#ifndef TQT_NO_REGEXP_OPTIM - if ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) - parseFactor( box ); -#endif - while ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) { - Box rightBox( this ); - parseFactor( &rightBox ); - box->cat( rightBox ); - } -} - -void TQRegExpEngine::parseExpression( Box *box ) -{ - parseTerm( box ); - while ( yyTok == Tok_Bar ) { -#ifndef TQT_NO_REGEXP_OPTIM - trivial = FALSE; -#endif - Box rightBox( this ); - yyTok = getToken(); - parseTerm( &rightBox ); - box->orx( rightBox ); - } -} - -/* - The struct TQRegExpPrivate contains the private data of a regular - expression other than the automaton. It makes it possible for many - TQRegExp objects to use the same TQRegExpEngine object with different - TQRegExpPrivate objects. -*/ -struct TQRegExpPrivate -{ - TQString pattern; // regular-expression or wildcard pattern - TQString rxpattern; // regular-expression pattern -#ifndef TQT_NO_REGEXP_WILDCARD - bool wc : 1; // wildcard mode? -#endif - bool min : 1; // minimal matching? (instead of maximal) - bool cs : 1; // case sensitive? -#ifndef TQT_NO_REGEXP_CAPTURE - TQString t; // last string passed to TQRegExp::search() or searchRev() - TQStringList capturedCache; // what TQRegExp::capturedTexts() returned last -#endif - TQMemArray captured; // what TQRegExpEngine::search() returned last - - TQRegExpPrivate() { captured.fill( -1, 2 ); } -}; - -#ifndef TQT_NO_REGEXP_OPTIM -static TQSingleCleanupHandler > cleanup_cache; -# ifndef TQT_THREAD_SUPPORT -static TQCache *engineCache = 0; -# endif // TQT_THREAD_SUPPORT -#endif // TQT_NO_REGEXP_OPTIM - -static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern, - bool caseSensitive, bool deref ) -{ -# ifdef TQT_THREAD_SUPPORT - static TQThreadStorage *> engineCaches; - TQCache *engineCache = 0; - TQThreadInstance *currentThread = TQThreadInstance::current(); - if (currentThread) - engineCache = engineCaches.localData(); -#endif // TQT_THREAD_SUPPORT - - if ( !deref ) { -#ifndef TQT_NO_REGEXP_OPTIM -# ifdef TQT_THREAD_SUPPORT - if ( currentThread ) -# endif - { - if ( engineCache != 0 ) { - eng = engineCache->take( pattern ); - if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { - delete eng; - } else { - eng->ref(); - return; - } - } - } -#endif // TQT_NO_REGEXP_OPTIM - eng = new TQRegExpEngine( pattern, caseSensitive ); - return; - } - - if ( eng->deref() ) { -#ifndef TQT_NO_REGEXP_OPTIM -# ifdef TQT_THREAD_SUPPORT - if ( currentThread ) -# endif - { - if ( engineCache == 0 ) { - engineCache = new TQCache; - engineCache->setAutoDelete( TRUE ); -# ifdef TQT_THREAD_SUPPORT - engineCaches.setLocalData(engineCache); -# else - cleanup_cache.set( &engineCache ); -# endif // !TQT_THREAD_SUPPORT - } - if ( !pattern.isNull() && - engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) - return; - } -#else - Q_UNUSED( pattern ); -#endif // TQT_NO_REGEXP_OPTIM - delete eng; - eng = 0; - } -} - -/*! - \enum TQRegExp::CaretMode - - The CaretMode enum defines the different meanings of the caret - (^) in a regular expression. The possible values are: - - \value CaretAtZero - The caret corresponds to index 0 in the searched string. - - \value CaretAtOffset - The caret corresponds to the start offset of the search. - - \value CaretWontMatch - The caret never matches. -*/ - -/*! - Constructs an empty regexp. - - \sa isValid() errorString() -*/ -TQRegExp::TQRegExp() - : eng( 0 ) -{ - priv = new TQRegExpPrivate; -#ifndef TQT_NO_REGEXP_WILDCARD - priv->wc = FALSE; -#endif - priv->min = FALSE; - priv->cs = TRUE; -} - -/*! - Constructs a regular expression object for the given \a pattern - string. The pattern must be given using wildcard notation if \a - wildcard is TRUE (default is FALSE). The pattern is case - sensitive, unless \a caseSensitive is FALSE. Matching is greedy - (maximal), but can be changed by calling setMinimal(). - - \sa setPattern() setCaseSensitive() setWildcard() setMinimal() -*/ -TQRegExp::TQRegExp( const TQString& pattern, bool caseSensitive, bool wildcard ) - : eng( 0 ) -{ - priv = new TQRegExpPrivate; - priv->pattern = pattern; -#ifndef TQT_NO_REGEXP_WILDCARD - priv->wc = wildcard; -#endif - priv->min = FALSE; - priv->cs = caseSensitive; -} - -/*! - Constructs a regular expression as a copy of \a rx. - - \sa operator=() -*/ -TQRegExp::TQRegExp( const TQRegExp& rx ) - : eng( 0 ) -{ - priv = new TQRegExpPrivate; - operator=( rx ); -} - -/*! - Destroys the regular expression and cleans up its internal data. -*/ -TQRegExp::~TQRegExp() -{ - invalidateEngine(); - delete priv; -} - -/*! - Copies the regular expression \a rx and returns a reference to the - copy. The case sensitivity, wildcard and minimal matching options - are also copied. -*/ -TQRegExp& TQRegExp::operator=( const TQRegExp& rx ) -{ - TQRegExpEngine *otherEng = rx.eng; - if ( otherEng != 0 ) - otherEng->ref(); - invalidateEngine(); - eng = otherEng; - priv->pattern = rx.priv->pattern; - priv->rxpattern = rx.priv->rxpattern; -#ifndef TQT_NO_REGEXP_WILDCARD - priv->wc = rx.priv->wc; -#endif - priv->min = rx.priv->min; - priv->cs = rx.priv->cs; -#ifndef TQT_NO_REGEXP_CAPTURE - priv->t = rx.priv->t; - priv->capturedCache = rx.priv->capturedCache; -#endif - priv->captured = rx.priv->captured; - return *this; -} - -/*! - Returns TRUE if this regular expression is equal to \a rx; - otherwise returns FALSE. - - Two TQRegExp objects are equal if they have the same pattern - strings and the same settings for case sensitivity, wildcard and - minimal matching. -*/ -bool TQRegExp::operator==( const TQRegExp& rx ) const -{ - return priv->pattern == rx.priv->pattern && -#ifndef TQT_NO_REGEXP_WILDCARD - priv->wc == rx.priv->wc && -#endif - priv->min == rx.priv->min && - priv->cs == rx.priv->cs; -} - -/*! - \fn bool TQRegExp::operator!=( const TQRegExp& rx ) const - - Returns TRUE if this regular expression is not equal to \a rx; - otherwise returns FALSE. - - \sa operator==() -*/ - -/*! - Returns TRUE if the pattern string is empty; otherwise returns - FALSE. - - If you call exactMatch() with an empty pattern on an empty string - it will return TRUE; otherwise it returns FALSE since it operates - over the whole string. If you call search() with an empty pattern - on \e any string it will return the start offset (0 by default) - because the empty pattern matches the 'emptiness' at the start of - the string. In this case the length of the match returned by - matchedLength() will be 0. - - See TQString::isEmpty(). -*/ - -bool TQRegExp::isEmpty() const -{ - return priv->pattern.isEmpty(); -} - -/*! - Returns TRUE if the regular expression is valid; otherwise returns - FALSE. An invalid regular expression never matches. - - The pattern [a-z is an example of an invalid pattern, since - it lacks a closing square bracket. - - Note that the validity of a regexp may also depend on the setting - of the wildcard flag, for example *.html is a valid - wildcard regexp but an invalid full regexp. - - \sa errorString() -*/ -bool TQRegExp::isValid() const -{ - if ( priv->pattern.isEmpty() ) { - return TRUE; - } else { - prepareEngine(); - return eng->isValid(); - } -} - -/*! - Returns the pattern string of the regular expression. The pattern - has either regular expression syntax or wildcard syntax, depending - on wildcard(). - - \sa setPattern() -*/ -TQString TQRegExp::pattern() const -{ - return priv->pattern; -} - -/*! - Sets the pattern string to \a pattern. The case sensitivity, - wildcard and minimal matching options are not changed. - - \sa pattern() -*/ -void TQRegExp::setPattern( const TQString& pattern ) -{ - if ( priv->pattern != pattern ) { - priv->pattern = pattern; - invalidateEngine(); - } -} - -/*! - Returns TRUE if case sensitivity is enabled; otherwise returns - FALSE. The default is TRUE. - - \sa setCaseSensitive() -*/ -bool TQRegExp::caseSensitive() const -{ - return priv->cs; -} - -/*! - Sets case sensitive matching to \a sensitive. - - If \a sensitive is TRUE, \\.txt$ matches \c{readme.txt} but - not \c{README.TXT}. - - \sa caseSensitive() -*/ -void TQRegExp::setCaseSensitive( bool sensitive ) -{ - if ( sensitive != priv->cs ) { - priv->cs = sensitive; - invalidateEngine(); - } -} - -#ifndef TQT_NO_REGEXP_WILDCARD -/*! - Returns TRUE if wildcard mode is enabled; otherwise returns FALSE. - The default is FALSE. - - \sa setWildcard() -*/ -bool TQRegExp::wildcard() const -{ - return priv->wc; -} - -/*! - Sets the wildcard mode for the regular expression. The default is - FALSE. - - Setting \a wildcard to TRUE enables simple shell-like wildcard - matching. (See \link #wildcard-matching wildcard matching - (globbing) \endlink.) - - For example, r*.txt matches the string \c{readme.txt} in - wildcard mode, but does not match \c{readme}. - - \sa wildcard() -*/ -void TQRegExp::setWildcard( bool wildcard ) -{ - if ( wildcard != priv->wc ) { - priv->wc = wildcard; - invalidateEngine(); - } -} -#endif - -/*! - Returns TRUE if minimal (non-greedy) matching is enabled; - otherwise returns FALSE. - - \sa setMinimal() -*/ -bool TQRegExp::minimal() const -{ - return priv->min; -} - -/*! - Enables or disables minimal matching. If \a minimal is FALSE, - matching is greedy (maximal) which is the default. - - For example, suppose we have the input string "We must be - \bold\, very \bold\!" and the pattern - \.*\. With the default greedy (maximal) matching, - the match is "We must be \bold\, very - \bold\!". But with minimal (non-greedy) matching the - first match is: "We must be \bold\, very - \bold\!" and the second match is "We must be \bold\, - very \bold\!". In practice we might use the pattern - \[^\<]+\ instead, although this will still fail for - nested tags. - - \sa minimal() -*/ -void TQRegExp::setMinimal( bool minimal ) -{ - priv->min = minimal; -} - -/*! - Returns TRUE if \a str is matched exactly by this regular - expression; otherwise returns FALSE. You can determine how much of - the string was matched by calling matchedLength(). - - For a given regexp string, R, exactMatch("R") is the equivalent of - search("^R$") since exactMatch() effectively encloses the regexp - in the start of string and end of string anchors, except that it - sets matchedLength() differently. - - For example, if the regular expression is blue, then - exactMatch() returns TRUE only for input \c blue. For inputs \c - bluebell, \c blutak and \c lightblue, exactMatch() returns FALSE - and matchedLength() will return 4, 3 and 0 respectively. - - Although const, this function sets matchedLength(), - capturedTexts() and pos(). - - \sa search() searchRev() TQRegExpValidator -*/ -bool TQRegExp::exactMatch( const TQString& str ) const -{ - prepareEngineForMatch( str ); - eng->match( str, 0, priv->min, TRUE, 0, priv->captured ); - if ( priv->captured[1] == (int) str.length() ) { - return TRUE; - } else { - priv->captured[0] = 0; - priv->captured[1] = eng->partialMatchLength(); - return FALSE; - } -} - -#ifndef TQT_NO_COMPAT -/*! \obsolete - - Attempts to match in \a str, starting from position \a index. - Returns the position of the match, or -1 if there was no match. - - The length of the match is stored in \a *len, unless \a len is a - null pointer. - - If \a indexIsStart is TRUE (the default), the position \a index in - the string will match the start of string anchor, ^, in the - regexp, if present. Otherwise, position 0 in \a str will match. - - Use search() and matchedLength() instead of this function. - - \sa TQString::mid() TQConstString -*/ -int TQRegExp::match( const TQString& str, int index, int *len, - bool indexIsStart ) const -{ - int pos = search( str, index, indexIsStart ? CaretAtOffset : CaretAtZero ); - if ( len != 0 ) - *len = matchedLength(); - return pos; -} -#endif // TQT_NO_COMPAT - -int TQRegExp::search( const TQString& str, int offset ) const -{ - return search( str, offset, CaretAtZero ); -} - -/*! - Attempts to find a match in \a str from position \a offset (0 by - default). If \a offset is -1, the search starts at the last - character; if -2, at the next to last character; etc. - - Returns the position of the first match, or -1 if there was no - match. - - The \a caretMode parameter can be used to instruct whether ^ - should match at index 0 or at \a offset. - - You might prefer to use TQString::find(), TQString::contains() or - even TQStringList::grep(). To replace matches use - TQString::replace(). - - Example: - \code - TQString str = "offsets: 1.23 .50 71.00 6.00"; - TQRegExp rx( "\\d*\\.\\d+" ); // primitive floating point matching - int count = 0; - int pos = 0; - while ( (pos = rx.search(str, pos)) != -1 ) { - count++; - pos += rx.matchedLength(); - } - // pos will be 9, 14, 18 and finally 24; count will end up as 4 - \endcode - - Although const, this function sets matchedLength(), - capturedTexts() and pos(). - - \sa searchRev() exactMatch() -*/ - -int TQRegExp::search( const TQString& str, int offset, CaretMode caretMode ) const -{ - prepareEngineForMatch( str ); - if ( offset < 0 ) - offset += str.length(); - eng->match( str, offset, priv->min, FALSE, caretIndex(offset, caretMode), - priv->captured ); - return priv->captured[0]; -} - - -int TQRegExp::searchRev( const TQString& str, int offset ) const -{ - return searchRev( str, offset, CaretAtZero ); -} - -/*! - Attempts to find a match backwards in \a str from position \a - offset. If \a offset is -1 (the default), the search starts at the - last character; if -2, at the next to last character; etc. - - Returns the position of the first match, or -1 if there was no - match. - - The \a caretMode parameter can be used to instruct whether ^ - should match at index 0 or at \a offset. - - Although const, this function sets matchedLength(), - capturedTexts() and pos(). - - \warning Searching backwards is much slower than searching - forwards. - - \sa search() exactMatch() -*/ - -int TQRegExp::searchRev( const TQString& str, int offset, - CaretMode caretMode ) const -{ - prepareEngineForMatch( str ); - if ( offset < 0 ) - offset += str.length(); - if ( offset < 0 || offset > (int) str.length() ) { - priv->captured.detach(); - priv->captured.fill( -1 ); - return -1; - } - - while ( offset >= 0 ) { - eng->match( str, offset, priv->min, TRUE, caretIndex(offset, caretMode), - priv->captured ); - if ( priv->captured[0] == offset ) - return offset; - offset--; - } - return -1; -} - -/*! - Returns the length of the last matched string, or -1 if there was - no match. - - \sa exactMatch() search() searchRev() -*/ -int TQRegExp::matchedLength() const -{ - return priv->captured[1]; -} - -#ifndef TQT_NO_REGEXP_CAPTURE -/*! - Returns the number of captures contained in the regular expression. - */ -int TQRegExp::numCaptures() const -{ - prepareEngine(); - return eng->numCaptures(); -} - -/*! - Returns a list of the captured text strings. - - The first string in the list is the entire matched string. Each - subsequent list element contains a string that matched a - (capturing) subexpression of the regexp. - - For example: - \code - TQRegExp rx( "(\\d+)(\\s*)(cm|inch(es)?)" ); - int pos = rx.search( "Length: 36 inches" ); - TQStringList list = rx.capturedTexts(); - // list is now ( "36 inches", "36", " ", "inches", "es" ) - \endcode - - The above example also captures elements that may be present but - which we have no interest in. This problem can be solved by using - non-capturing parentheses: - - \code - TQRegExp rx( "(\\d+)(?:\\s*)(cm|inch(?:es)?)" ); - int pos = rx.search( "Length: 36 inches" ); - TQStringList list = rx.capturedTexts(); - // list is now ( "36 inches", "36", "inches" ) - \endcode - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = rx.capturedTexts(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - - Some regexps can match an indeterminate number of times. For - example if the input string is "Offsets: 12 14 99 231 7" and the - regexp, \c{rx}, is (\\d+)+, we would hope to get a list of - all the numbers matched. However, after calling - \c{rx.search(str)}, capturedTexts() will return the list ( "12", - "12" ), i.e. the entire match was "12" and the first subexpression - matched was "12". The correct approach is to use cap() in a \link - #cap_in_a_loop loop \endlink. - - The order of elements in the string list is as follows. The first - element is the entire matching string. Each subsequent element - corresponds to the next capturing open left parentheses. Thus - capturedTexts()[1] is the text of the first capturing parentheses, - capturedTexts()[2] is the text of the second and so on - (corresponding to $1, $2, etc., in some other regexp languages). - - \sa cap() pos() exactMatch() search() searchRev() -*/ -TQStringList TQRegExp::capturedTexts() -{ - if ( priv->capturedCache.isEmpty() ) { - for ( int i = 0; i < (int) priv->captured.size(); i += 2 ) { - TQString m; - if ( priv->captured[i + 1] == 0 ) - m = TQString::fromLatin1( "" ); - else if ( priv->captured[i] >= 0 ) - m = priv->t.mid( priv->captured[i], - priv->captured[i + 1] ); - priv->capturedCache.append( m ); - } - priv->t = TQString::null; - } - return priv->capturedCache; -} - -/*! - Returns the text captured by the \a nth subexpression. The entire - match has index 0 and the parenthesized subexpressions have - indices starting from 1 (excluding non-capturing parentheses). - - \code - TQRegExp rxlen( "(\\d+)(?:\\s*)(cm|inch)" ); - int pos = rxlen.search( "Length: 189cm" ); - if ( pos > -1 ) { - TQString value = rxlen.cap( 1 ); // "189" - TQString unit = rxlen.cap( 2 ); // "cm" - // ... - } - \endcode - - The order of elements matched by cap() is as follows. The first - element, cap(0), is the entire matching string. Each subsequent - element corresponds to the next capturing open left parentheses. - Thus cap(1) is the text of the first capturing parentheses, cap(2) - is the text of the second, and so on. - - \target cap_in_a_loop - Some patterns may lead to a number of matches which cannot be - determined in advance, for example: - - \code - TQRegExp rx( "(\\d+)" ); - str = "Offsets: 12 14 99 231 7"; - TQStringList list; - pos = 0; - while ( pos >= 0 ) { - pos = rx.search( str, pos ); - if ( pos > -1 ) { - list += rx.cap( 1 ); - pos += rx.matchedLength(); - } - } - // list contains "12", "14", "99", "231", "7" - \endcode - - \sa capturedTexts() pos() exactMatch() search() searchRev() -*/ -TQString TQRegExp::cap( int nth ) -{ - if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) { - return TQString::null; - } else { - return capturedTexts()[nth]; - } -} - -/*! - Returns the position of the \a nth captured text in the searched - string. If \a nth is 0 (the default), pos() returns the position - of the whole match. - - Example: - \code - TQRegExp rx( "/([a-z]+)/([a-z]+)" ); - rx.search( "Output /dev/null" ); // returns 7 (position of /dev/null) - rx.pos( 0 ); // returns 7 (position of /dev/null) - rx.pos( 1 ); // returns 8 (position of dev) - rx.pos( 2 ); // returns 12 (position of null) - \endcode - - For zero-length matches, pos() always returns -1. (For example, if - cap(4) would return an empty string, pos(4) returns -1.) This is - due to an implementation tradeoff. - - \sa capturedTexts() exactMatch() search() searchRev() -*/ -int TQRegExp::pos( int nth ) -{ - if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) - return -1; - else - return priv->captured[2 * nth]; -} - -/*! - Returns a text string that explains why a regexp pattern is - invalid the case being; otherwise returns "no error occurred". - - \sa isValid() -*/ -TQString TQRegExp::errorString() -{ - if ( isValid() ) { - return TQString( RXERR_OK ); - } else { - return eng->errorString(); - } -} -#endif - -/*! - Returns the string \a str with every regexp special character - escaped with a backslash. The special characters are $, (, ), *, +, - ., ?, [, \, ], ^, {, | and }. - - Example: - \code - s1 = TQRegExp::escape( "bingo" ); // s1 == "bingo" - s2 = TQRegExp::escape( "f(x)" ); // s2 == "f\\(x\\)" - \endcode - - This function is useful to construct regexp patterns dynamically: - - \code - TQRegExp rx( "(" + TQRegExp::escape(name) + - "|" + TQRegExp::escape(alias) + ")" ); - \endcode -*/ -TQString TQRegExp::escape( const TQString& str ) -{ - static const char meta[] = "$()*+.?[\\]^{|}"; - TQString quoted = str; - int i = 0; - - while ( i < (int) quoted.length() ) { - if ( strchr(meta, quoted[i].latin1()) != 0 ) - quoted.insert( i++, "\\" ); - i++; - } - return quoted; -} - -void TQRegExp::prepareEngine() const -{ - if ( eng == 0 ) { -#ifndef TQT_NO_REGEXP_WILDCARD - if ( priv->wc ) - priv->rxpattern = wc2rx( priv->pattern ); - else -#endif - priv->rxpattern = priv->pattern.isNull() ? TQString::fromLatin1( "" ) - : priv->pattern; - TQRegExp *that = (TQRegExp *) this; - // that->eng = newEngine( priv->rxpattern, priv->cs ); - regexpEngine( that->eng, priv->rxpattern, priv->cs, FALSE ); - priv->captured.detach(); - priv->captured.fill( -1, 2 + 2 * eng->numCaptures() ); - } -} - -void TQRegExp::prepareEngineForMatch( const TQString& str ) const -{ - prepareEngine(); -#ifndef TQT_NO_REGEXP_CAPTURE - priv->t = str; - priv->capturedCache.clear(); -#else - Q_UNUSED( str ); -#endif -} - -void TQRegExp::invalidateEngine() -{ - if ( eng != 0 ) { - regexpEngine( eng, priv->rxpattern, priv->cs, TRUE ); - priv->rxpattern = TQString(); - eng = 0; - } -} - -int TQRegExp::caretIndex( int offset, CaretMode caretMode ) -{ - if ( caretMode == CaretAtZero ) { - return 0; - } else if ( caretMode == CaretAtOffset ) { - return offset; - } else { // CaretWontMatch - return -1; - } -} - -#endif // TQT_NO_REGEXP diff --git a/src/tools/qsettings.cpp b/src/tools/qsettings.cpp index 250e5623d..e76fc6ca7 100644 --- a/src/tools/qsettings.cpp +++ b/src/tools/qsettings.cpp @@ -62,7 +62,7 @@ static inline int qt_open( const char *pathname, int flags, mode_t mode ) #include "ntqfileinfo.h" #include "tqmap.h" #include "tqtextstream.h" -#include "ntqregexp.h" +#include "tqregexp.h" #include #ifndef NO_ERRNO_H #include diff --git a/src/tools/qt_tools.pri b/src/tools/qt_tools.pri index d52bbd339..dc9fa2753 100644 --- a/src/tools/qt_tools.pri +++ b/src/tools/qt_tools.pri @@ -2,20 +2,20 @@ tools { TOOLS_P = tools - HEADERS += $$TOOLS_H/ntqmemarray.h \ - $$TOOLS_H/ntqasciicache.h \ - $$TOOLS_H/ntqasciidict.h \ - $$TOOLS_H/ntqbitarray.h \ + HEADERS += $$TOOLS_H/tqmemarray.h \ + $$TOOLS_H/tqasciicache.h \ + $$TOOLS_H/tqasciidict.h \ + $$TOOLS_H/tqbitarray.h \ $$TOOLS_H/ntqbuffer.h \ - $$TOOLS_H/ntqcache.h \ + $$TOOLS_H/tqcache.h \ $$TOOLS_H/ntqcleanuphandler.h \ $$TOOLS_P/qcomponentfactory_p.h \ $$TOOLS_P/qcomlibrary_p.h \ - $$TOOLS_H/ntqcstring.h \ + $$TOOLS_H/tqcstring.h \ $$TOOLS_H/ntqdatastream.h \ $$TOOLS_H/tqdatetime.h \ - $$TOOLS_H/ntqdeepcopy.h \ - $$TOOLS_H/ntqdict.h \ + $$TOOLS_H/tqdeepcopy.h \ + $$TOOLS_H/tqdict.h \ $$TOOLS_H/ntqdir.h \ $$TOOLS_P/qdir_p.h \ $$TOOLS_H/ntqfile.h \ @@ -29,8 +29,8 @@ tools { $$TOOLS_H/ntqglobal.h \ $$TOOLS_P/qgpluginmanager_p.h \ $$TOOLS_H/ntqgvector.h \ - $$TOOLS_H/ntqintcache.h \ - $$TOOLS_H/ntqintdict.h \ + $$TOOLS_H/tqintcache.h \ + $$TOOLS_H/tqintdict.h \ $$TOOLS_H/ntqiodevice.h \ $$TOOLS_H/ntqlibrary.h \ $$TOOLS_P/qlibrary_p.h \ @@ -45,7 +45,7 @@ tools { $$TOOLS_H/tqptrcollection.h \ $$TOOLS_H/tqptrdict.h \ $$TOOLS_H/tqptrqueue.h \ - $$TOOLS_H/ntqregexp.h \ + $$TOOLS_H/tqregexp.h \ $$TOOLS_H/tqsemaphore.h \ $$TOOLS_H/ntqsettings.h \ $$TOOLS_P/qsettings_p.h \ @@ -106,14 +106,14 @@ tools { } unix:SOURCES += $$TOOLS_CPP/qlibrary_unix.cpp - SOURCES += $$TOOLS_CPP/qbitarray.cpp \ + SOURCES += $$TOOLS_CPP/tqbitarray.cpp \ $$TOOLS_CPP/qbuffer.cpp \ $$TOOLS_CPP/qcomponentfactory.cpp \ $$TOOLS_CPP/qcomlibrary.cpp \ - $$TOOLS_CPP/qcstring.cpp \ + $$TOOLS_CPP/tqcstring.cpp \ $$TOOLS_CPP/qdatastream.cpp \ $$TOOLS_CPP/tqdatetime.cpp \ - $$TOOLS_CPP/qdeepcopy.cpp \ + $$TOOLS_CPP/tqdeepcopy.cpp \ $$TOOLS_CPP/qdir.cpp \ $$TOOLS_CPP/qfile.cpp \ $$TOOLS_CPP/qfileinfo.cpp \ @@ -130,7 +130,7 @@ tools { $$TOOLS_CPP/tqmap.cpp \ $$TOOLS_CPP/tqmutexpool.cpp \ $$TOOLS_CPP/tqptrcollection.cpp \ - $$TOOLS_CPP/qregexp.cpp \ + $$TOOLS_CPP/tqregexp.cpp \ $$TOOLS_CPP/tqstring.cpp \ $$TOOLS_CPP/tqsemaphore.cpp \ $$TOOLS_CPP/qsettings.cpp \ diff --git a/src/tools/qwinexport.cpp b/src/tools/qwinexport.cpp index 8bd5fd0f4..cb5ce9c17 100644 --- a/src/tools/qwinexport.cpp +++ b/src/tools/qwinexport.cpp @@ -13,15 +13,13 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include #include -#include +#include #include #include #include diff --git a/src/tools/tqasciicache.h b/src/tools/tqasciicache.h new file mode 100644 index 000000000..7323635c6 --- /dev/null +++ b/src/tools/tqasciicache.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Definition of TQAsciiCache template/macro class +** +** Created : 950209 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQASCIICACHE_H +#define TQASCIICACHE_H + +#ifndef QT_H +#include "ntqgcache.h" +#endif // QT_H + + +template +class TQAsciiCache +#ifdef Q_QDOC + : public TQPtrCollection +#else + : public TQGCache +#endif +{ +public: + TQAsciiCache( const TQAsciiCache &c ) : TQGCache(c) {} + TQAsciiCache( int maxCost=100, int size=17, bool caseSensitive=TRUE, + bool copyKeys=TRUE ) + : TQGCache( maxCost, size, AsciiKey, caseSensitive, copyKeys ) {} + ~TQAsciiCache() { clear(); } + TQAsciiCache &operator=( const TQAsciiCache &c ) + { return (TQAsciiCache&)TQGCache::operator=(c); } + int maxCost() const { return TQGCache::maxCost(); } + int totalCost() const { return TQGCache::totalCost(); } + void setMaxCost( int m ) { TQGCache::setMaxCost(m); } + uint count() const { return TQGCache::count(); } + uint size() const { return TQGCache::size(); } + bool isEmpty() const { return TQGCache::count() == 0; } + void clear() { TQGCache::clear(); } + bool insert( const char *k, const type *d, int c=1, int p=0 ) + { return TQGCache::insert_other(k,(Item)d,c,p);} + bool remove( const char *k ) + { return TQGCache::remove_other(k); } + type *take( const char *k ) + { return (type *)TQGCache::take_other(k); } + type *find( const char *k, bool ref=TRUE ) const + { return (type *)TQGCache::find_other(k,ref);} + type *operator[]( const char *k ) const + { return (type *)TQGCache::find_other(k);} + void statistics() const { TQGCache::statistics(); } +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void TQAsciiCache::deleteItem( TQPtrCollection::Item ) +{ +} +#endif + +template inline void TQAsciiCache::deleteItem( TQPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + + +template +class TQAsciiCacheIterator : public TQGCacheIterator +{ +public: + TQAsciiCacheIterator( const TQAsciiCache &c ):TQGCacheIterator((TQGCache &)c) {} + TQAsciiCacheIterator( const TQAsciiCacheIterator &ci) + : TQGCacheIterator( (TQGCacheIterator &)ci ) {} + TQAsciiCacheIterator &operator=(const TQAsciiCacheIterator&ci) + { return ( TQAsciiCacheIterator&)TQGCacheIterator::operator=( ci ); } + uint count() const { return TQGCacheIterator::count(); } + bool isEmpty() const { return TQGCacheIterator::count() == 0; } + bool atFirst() const { return TQGCacheIterator::atFirst(); } + bool atLast() const { return TQGCacheIterator::atLast(); } + type *toFirst() { return (type *)TQGCacheIterator::toFirst(); } + type *toLast() { return (type *)TQGCacheIterator::toLast(); } + operator type *() const { return (type *)TQGCacheIterator::get(); } + type *current() const { return (type *)TQGCacheIterator::get(); } + const char *currentKey() const { return TQGCacheIterator::getKeyAscii(); } + type *operator()() { return (type *)TQGCacheIterator::operator()();} + type *operator++() { return (type *)TQGCacheIterator::operator++(); } + type *operator+=(uint j) { return (type *)TQGCacheIterator::operator+=(j);} + type *operator--() { return (type *)TQGCacheIterator::operator--(); } + type *operator-=(uint j) { return (type *)TQGCacheIterator::operator-=(j);} +}; + + +#endif // TQASCIICACHE_H diff --git a/src/tools/tqasciidict.h b/src/tools/tqasciidict.h new file mode 100644 index 000000000..ef09bc025 --- /dev/null +++ b/src/tools/tqasciidict.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Definition of TQAsciiDict template class +** +** Created : 920821 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQASCIIDICT_H +#define TQASCIIDICT_H + +#ifndef QT_H +#include "ntqgdict.h" +#endif // QT_H + +template +class TQAsciiDict +#ifdef Q_QDOC + : public TQPtrCollection +#else + : public TQGDict +#endif +{ +public: + TQAsciiDict(int size=17, bool caseSensitive=TRUE, bool copyKeys=TRUE ) + : TQGDict(size,AsciiKey,caseSensitive,copyKeys) {} + TQAsciiDict( const TQAsciiDict &d ) : TQGDict(d) {} + ~TQAsciiDict() { clear(); } + TQAsciiDict &operator=(const TQAsciiDict &d) + { return (TQAsciiDict&)TQGDict::operator=(d); } + uint count() const { return TQGDict::count(); } + uint size() const { return TQGDict::size(); } + bool isEmpty() const { return TQGDict::count() == 0; } + + void insert( const char *k, const type *d ) + { TQGDict::look_ascii(k,(Item)d,1); } + void replace( const char *k, const type *d ) + { TQGDict::look_ascii(k,(Item)d,2); } + bool remove( const char *k ) { return TQGDict::remove_ascii(k); } + type *take( const char *k ) { return (type *)TQGDict::take_ascii(k); } + type *find( const char *k ) const + { return (type *)((TQGDict*)this)->TQGDict::look_ascii(k,0,0); } + type *operator[]( const char *k ) const + { return (type *)((TQGDict*)this)->TQGDict::look_ascii(k,0,0); } + + void clear() { TQGDict::clear(); } + void resize( uint n ) { TQGDict::resize(n); } + void statistics() const { TQGDict::statistics(); } + +#ifdef Q_QDOC +protected: + virtual TQDataStream& read( TQDataStream &, TQPtrCollection::Item & ); + virtual TQDataStream& write( TQDataStream &, TQPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void TQAsciiDict::deleteItem( TQPtrCollection::Item ) +{ +} +#endif + +template inline void TQAsciiDict::deleteItem( TQPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template +class TQAsciiDictIterator : public TQGDictIterator +{ +public: + TQAsciiDictIterator(const TQAsciiDict &d) + : TQGDictIterator((TQGDict &)d) {} + ~TQAsciiDictIterator() {} + uint count() const { return dict->count(); } + bool isEmpty() const { return dict->count() == 0; } + type *toFirst() { return (type *)TQGDictIterator::toFirst(); } + operator type *() const { return (type *)TQGDictIterator::get(); } + type *current() const { return (type *)TQGDictIterator::get(); } + const char *currentKey() const { return TQGDictIterator::getKeyAscii(); } + type *operator()() { return (type *)TQGDictIterator::operator()(); } + type *operator++() { return (type *)TQGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)TQGDictIterator::operator+=(j);} +}; + +#define Q_DEFINED_QASCIIDICT +#include "ntqwinexport.h" +#endif // TQASCIIDICT_H diff --git a/src/tools/tqbitarray.cpp b/src/tools/tqbitarray.cpp new file mode 100644 index 000000000..283a99406 --- /dev/null +++ b/src/tools/tqbitarray.cpp @@ -0,0 +1,665 @@ +/**************************************************************************** +** +** Implementation of TQBitArray class +** +** Created : 940118 +** +** 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 requirements 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. +** +**********************************************************************/ + +#include "tqbitarray.h" +#include "ntqdatastream.h" + +#define SHBLOCK ((bitarr_data*)(sharedBlock())) + + +/*! + \class TQBitVal tqbitarray.h + \reentrant + \brief The TQBitVal class is an internal class, used with TQBitArray. + + \ingroup collection + + The TQBitVal is required by the indexing [] operator on bit arrays. + It is not for use in any other context. +*/ + +/*! + \fn TQBitVal::TQBitVal (TQBitArray* a, uint i) + + Constructs a reference to element \a i in the TQBitArray \a a. + This is what TQBitArray::operator[] constructs its return value + with. +*/ + +/*! + \fn TQBitVal::operator int() + + Returns the value referenced by the TQBitVal. +*/ + +/*! + \fn TQBitVal& TQBitVal::operator= (const TQBitVal& v) + + Sets the value referenced by the TQBitVal to that referenced by + TQBitVal \a v. +*/ + +/*! + \overload TQBitVal& TQBitVal::operator= (bool v) + + Sets the value referenced by the TQBitVal to \a v. +*/ + + +/*! + \class TQBitArray tqbitarray.h + \reentrant + \brief The TQBitArray class provides an array of bits. + + \ingroup collection + \ingroup tools + \ingroup shared + + Because TQBitArray is a TQMemArray, it uses explicit \link + shclass.html sharing\endlink with a reference count. + + A TQBitArray is a special byte array that can access individual + bits and perform bit-operations (AND, OR, XOR and NOT) on entire + arrays or bits. + + Bits can be manipulated by the setBit() and clearBit() functions, + but it is also possible to use the indexing [] operator to test + and set individual bits. The [] operator is a little slower than + setBit() and clearBit() because some tricks are required to + implement single-bit assignments. + + Example: + \code + TQBitArray a(3); + a.setBit( 0 ); + a.clearBit( 1 ); + a.setBit( 2 ); // a = [1 0 1] + + TQBitArray b(3); + b[0] = 1; + b[1] = 1; + b[2] = 0; // b = [1 1 0] + + TQBitArray c; + c = ~a & b; // c = [0 1 0] + \endcode + + When a TQBitArray is constructed the bits are uninitialized. Use + fill() to set all the bits to 0 or 1. The array can be resized + with resize() and copied with copy(). Bits can be set with + setBit() and cleared with clearBit(). Bits can be toggled with + toggleBit(). A bit's value can be obtained with testBit() and with + at(). + + TQBitArray supports the \& (AND), | (OR), ^ (XOR) and ~ (NOT) + operators. +*/ + +/*! \class TQBitArray::bitarr_data + \brief The TQBitArray::bitarr_data class is internal. + \internal +*/ + + +/*! + Constructs an empty bit array. +*/ + +TQBitArray::TQBitArray() : TQByteArray( 0, 0 ) +{ + bitarr_data *x = new bitarr_data; + TQ_CHECK_PTR( x ); + x->nbits = 0; + setSharedBlock( x ); +} + +/*! + Constructs a bit array of \a size bits. The bits are uninitialized. + + \sa fill() +*/ + +TQBitArray::TQBitArray( uint size ) : TQByteArray( 0, 0 ) +{ + bitarr_data *x = new bitarr_data; + TQ_CHECK_PTR( x ); + x->nbits = 0; + setSharedBlock( x ); + resize( size ); +} + +/*! + \fn TQBitArray::TQBitArray( const TQBitArray &a ) + + Constructs a shallow copy of \a a. +*/ + +/*! + \fn TQBitArray &TQBitArray::operator=( const TQBitArray &a ) + + Assigns a shallow copy of \a a to this bit array and returns a + reference to this array. +*/ + + +/*! + Pad last byte with 0-bits. +*/ +void TQBitArray::pad0() +{ + uint sz = size(); + if ( sz && sz%8 ) + *(data()+sz/8) &= (1 << (sz%8)) - 1; +} + + +/*! + \fn uint TQBitArray::size() const + + Returns the bit array's size (number of bits). + + \sa resize() +*/ + +/*! + Resizes the bit array to \a size bits and returns TRUE if the bit + array could be resized; otherwise returns FALSE. The array becomes + a null array if \a size == 0. + + If the array is expanded, the new bits are set to 0. + + \sa size() +*/ + +bool TQBitArray::resize( uint size ) +{ + uint s = this->size(); + if ( !TQByteArray::resize( (size+7)/8 ) ) + return FALSE; // cannot resize + SHBLOCK->nbits = size; + if ( size != 0 ) { // not null array + int ds = (int)(size+7)/8 - (int)(s+7)/8;// number of bytes difference + if ( ds > 0 ) // expanding array + memset( data() + (s+7)/8, 0, ds ); // reset new data + } + return TRUE; +} + + +/*! + Fills the bit array with \a v (1's if \a v is TRUE, or 0's if \a v + is FALSE). + + fill() resizes the bit array to \a size bits if \a size is + nonnegative. + + Returns FALSE if a nonnegative \e size was specified and the bit + array could not be resized; otherwise returns TRUE. + + \sa resize() +*/ + +bool TQBitArray::fill( bool v, int size ) +{ + if ( size >= 0 ) { // resize first + if ( !resize( size ) ) + return FALSE; // cannot resize + } else { + size = this->size(); + } + if ( size > 0 ) + memset( data(), v ? 0xff : 0, (size + 7) / 8 ); + if ( v ) + pad0(); + return TRUE; +} + + +/*! + Detaches from shared bit array data and makes sure that this bit + array is the only one referring to the data. + + If multiple bit arrays share common data, this bit array + dereferences the data and gets a copy of the data. Nothing happens + if there is only a single reference. + + \sa copy() +*/ + +void TQBitArray::detach() +{ + int nbits = SHBLOCK->nbits; + this->duplicate( *this ); + SHBLOCK->nbits = nbits; +} + +/*! + Returns a deep copy of the bit array. + + \sa detach() +*/ + +TQBitArray TQBitArray::copy() const +{ + TQBitArray tmp; + tmp.duplicate( *this ); + ((bitarr_data*)(tmp.sharedBlock()))->nbits = SHBLOCK->nbits; + return tmp; +} + + +/*! + Returns TRUE if the bit at position \a index is set, i.e. is 1; + otherwise returns FALSE. + + \sa setBit(), clearBit() +*/ + +bool TQBitArray::testBit( uint index ) const +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + tqWarning( "TQBitArray::testBit: Index %d out of range", index ); + return FALSE; + } +#endif + return (*(data()+(index>>3)) & (1 << (index & 7))) != 0; +} + +/*! + \overload + + Sets the bit at position \a index to 1. + + \sa clearBit() toggleBit() +*/ + +void TQBitArray::setBit( uint index ) +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + tqWarning( "TQBitArray::setBit: Index %d out of range", index ); + return; + } +#endif + *(data()+(index>>3)) |= (1 << (index & 7)); +} + +/*! + \fn void TQBitArray::setBit( uint index, bool value ) + + Sets the bit at position \a index to \a value. + + Equivalent to: + \code + if ( value ) + setBit( index ); + else + clearBit( index ); + \endcode + + \sa clearBit() toggleBit() +*/ + +/*! + Clears the bit at position \a index, i.e. sets it to 0. + + \sa setBit(), toggleBit() +*/ + +void TQBitArray::clearBit( uint index ) +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + tqWarning( "TQBitArray::clearBit: Index %d out of range", index ); + return; + } +#endif + *(data()+(index>>3)) &= ~(1 << (index & 7)); +} + +/*! + Toggles the bit at position \a index. + + If the previous value was 0, the new value will be 1. If the + previous value was 1, the new value will be 0. + + \sa setBit(), clearBit() +*/ + +bool TQBitArray::toggleBit( uint index ) +{ +#if defined(QT_CHECK_RANGE) + if ( index >= size() ) { + tqWarning( "TQBitArray::toggleBit: Index %d out of range", index ); + return FALSE; + } +#endif + uchar *p = (uchar *)data() + (index>>3); + uchar b = (1 << (index & 7)); // bit position + uchar c = *p & b; // read bit + *p ^= b; // toggle bit + return c; +} + + +/*! + \fn bool TQBitArray::at( uint index ) const + + Returns the value (0 or 1) of the bit at position \a index. + + \sa operator[]() +*/ + +/*! + \fn TQBitVal TQBitArray::operator[]( int index ) + + Implements the [] operator for bit arrays. + + The returned TQBitVal is a context object. It makes it possible to + get and set a single bit value by its \a index position. + + Example: + \code + TQBitArray a( 3 ); + a[0] = 0; + a[1] = 1; + a[2] = a[0] ^ a[1]; + \endcode + + The functions testBit(), setBit() and clearBit() are faster. + + \sa at() +*/ + +/*! + \overload bool TQBitArray::operator[]( int index ) const + + Implements the [] operator for constant bit arrays. +*/ + + +/*! + Performs the AND operation between all bits in this bit array and + \a a. Returns a reference to this bit array. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + \code + TQBitArray a( 3 ), b( 2 ); + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b[0] = 1; b[1] = 0; // b = [1 0] + a &= b; // a = [1 0 0] + \endcode + + \sa operator|=(), operator^=(), operator~() +*/ + +TQBitArray &TQBitArray::operator&=( const TQBitArray &a ) +{ + resize( TQMAX(size(), a.size()) ); + uchar *a1 = (uchar *)data(); + uchar *a2 = (uchar *)a.data(); + int n = TQMIN( TQByteArray::size(), a.TQByteArray::size() ); + int p = TQMAX( TQByteArray::size(), a.TQByteArray::size() ) - n; + while ( n-- > 0 ) + *a1++ &= *a2++; + while ( p-- > 0 ) + *a1++ = 0; + return *this; +} + +/*! + Performs the OR operation between all bits in this bit array and + \a a. Returns a reference to this bit array. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + \code + TQBitArray a( 3 ), b( 2 ); + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b[0] = 1; b[1] = 0; // b = [1 0] + a |= b; // a = [1 0 1] + \endcode + + \sa operator&=(), operator^=(), operator~() +*/ + +TQBitArray &TQBitArray::operator|=( const TQBitArray &a ) +{ + resize( TQMAX(size(), a.size()) ); + uchar *a1 = (uchar *)data(); + uchar *a2 = (uchar *)a.data(); + int n = TQMIN( TQByteArray::size(), a.TQByteArray::size() ); + while ( n-- > 0 ) + *a1++ |= *a2++; + return *this; +} + +/*! + Performs the XOR operation between all bits in this bit array and + \a a. Returns a reference to this bit array. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + \code + TQBitArray a( 3 ), b( 2 ); + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b[0] = 1; b[1] = 0; // b = [1 0] + a ^= b; // a = [0 0 1] + \endcode + + \sa operator&=(), operator|=(), operator~() +*/ + +TQBitArray &TQBitArray::operator^=( const TQBitArray &a ) +{ + resize( TQMAX(size(), a.size()) ); + uchar *a1 = (uchar *)data(); + uchar *a2 = (uchar *)a.data(); + int n = TQMIN( TQByteArray::size(), a.TQByteArray::size() ); + while ( n-- > 0 ) + *a1++ ^= *a2++; + return *this; +} + +/*! + Returns a bit array that contains the inverted bits of this bit array. + + Example: + \code + TQBitArray a( 3 ), b; + a[0] = 1; a[1] = 0; a[2] = 1; // a = [1 0 1] + b = ~a; // b = [0 1 0] + \endcode +*/ + +TQBitArray TQBitArray::operator~() const +{ + TQBitArray a( size() ); + uchar *a1 = (uchar *)data(); + uchar *a2 = (uchar *)a.data(); + int n = TQByteArray::size(); + while ( n-- ) + *a2++ = ~*a1++; + a.pad0(); + return a; +} + + +/*! + \relates TQBitArray + + Returns the AND result between the bit arrays \a a1 and \a a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + + \sa TQBitArray::operator&=() +*/ + +TQBitArray operator&( const TQBitArray &a1, const TQBitArray &a2 ) +{ + TQBitArray tmp = a1.copy(); + tmp &= a2; + return tmp; +} + +/*! + \relates TQBitArray + + Returns the OR result between the bit arrays \a a1 and \a a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + + \sa TQBitArray::operator|=() +*/ + +TQBitArray operator|( const TQBitArray &a1, const TQBitArray &a2 ) +{ + TQBitArray tmp = a1.copy(); + tmp |= a2; + return tmp; +} + +/*! + \relates TQBitArray + + Returns the XOR result between the bit arrays \a a1 and \a a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (i.e. if one array is shorter than the + other), taken to be 0. + + \sa TQBitArray::operator^() +*/ + +TQBitArray operator^( const TQBitArray &a1, const TQBitArray &a2 ) +{ + TQBitArray tmp = a1.copy(); + tmp ^= a2; + return tmp; +} + + +/* \enum TQGArray::array_data + + \warning This will be renamed in the next major release of TQt. Until + then it is undocumented and we recommend against its use. + + \internal + + ### 3.0 rename ### + ### 3.0 move it to TQGArray? ### +*/ + + +/*! + \fn TQBitArray::array_data * TQBitArray::newData() + + \internal + + Returns data specific to TQBitArray that extends what TQGArray provides. + TQPtrCollection mechanism for allowing extra/different data. +*/ + + +/*! + \fn void TQBitArray::deleteData ( array_data * d ) + + \internal + + Deletes data specific to TQBitArray that extended what TQGArray provided. + + TQPtrCollection mechanism for allowing extra/different data. +*/ + + +/***************************************************************************** + TQBitArray stream functions + *****************************************************************************/ + +/*! + \relates TQBitArray + + Writes bit array \a a to stream \a s. + + \sa \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ +#ifndef TQT_NO_DATASTREAM +TQDataStream &operator<<( TQDataStream &s, const TQBitArray &a ) +{ + TQ_UINT32 len = a.size(); + s << len; // write size of array + if ( len > 0 ) // write data + s.writeRawBytes( a.data(), a.TQByteArray::size() ); + return s; +} + +/*! + \relates TQBitArray + + Reads a bit array into \a a from stream \a s. + + \sa \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ + +TQDataStream &operator>>( TQDataStream &s, TQBitArray &a ) +{ + TQ_UINT32 len; + s >> len; // read size of array + if ( !a.resize( (uint)len ) ) { // resize array +#if defined(QT_CHECK_NULL) + tqWarning( "TQDataStream: Not enough memory to read TQBitArray" ); +#endif + len = 0; + } + if ( len > 0 ) // read data + s.readRawBytes( a.data(), a.TQByteArray::size() ); + return s; +} + +#endif // TQT_NO_DATASTREAM diff --git a/src/tools/tqbitarray.h b/src/tools/tqbitarray.h new file mode 100644 index 000000000..65b2cdbe7 --- /dev/null +++ b/src/tools/tqbitarray.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Definition of TQBitArray class +** +** Created : 940118 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQBITARRAY_H +#define TQBITARRAY_H + +#ifndef QT_H +#include "tqstring.h" +#endif // QT_H + + +/***************************************************************************** + TQBitVal class; a context class for TQBitArray::operator[] + *****************************************************************************/ + +class TQBitArray; + +class TQ_EXPORT TQBitVal +{ +private: + TQBitArray *array; + uint index; +public: + TQBitVal( TQBitArray *a, uint i ) : array(a), index(i) {} + operator int(); + TQBitVal &operator=( const TQBitVal &v ); + TQBitVal &operator=( bool v ); +}; + + +/***************************************************************************** + TQBitArray class + *****************************************************************************/ + +class TQ_EXPORT TQBitArray : public TQByteArray +{ +public: + TQBitArray(); + TQBitArray( uint size ); + TQBitArray( const TQBitArray &a ) : TQByteArray( a ) {} + + TQBitArray &operator=( const TQBitArray & ); + + uint size() const; + bool resize( uint size ); + + bool fill( bool v, int size = -1 ); + + void detach(); + TQBitArray copy() const; + + bool testBit( uint index ) const; + void setBit( uint index ); + void setBit( uint index, bool value ); + void clearBit( uint index ); + bool toggleBit( uint index ); + + bool at( uint index ) const; + TQBitVal operator[]( int index ); + bool operator[]( int index ) const; + + TQBitArray &operator&=( const TQBitArray & ); + TQBitArray &operator|=( const TQBitArray & ); + TQBitArray &operator^=( const TQBitArray & ); + TQBitArray operator~() const; + +protected: + struct bitarr_data : public TQGArray::array_data { + uint nbits; + }; + array_data *newData() { return new bitarr_data; } + void deleteData( array_data *d ) { delete (bitarr_data*)d; } +private: + void pad0(); +}; + + +inline TQBitArray &TQBitArray::operator=( const TQBitArray &a ) +{ return (TQBitArray&)assign( a ); } + +inline uint TQBitArray::size() const +{ return ((bitarr_data*)sharedBlock())->nbits; } + +inline void TQBitArray::setBit( uint index, bool value ) +{ if ( value ) setBit(index); else clearBit(index); } + +inline bool TQBitArray::at( uint index ) const +{ return testBit(index); } + +inline TQBitVal TQBitArray::operator[]( int index ) +{ return TQBitVal( (TQBitArray*)this, index ); } + +inline bool TQBitArray::operator[]( int index ) const +{ return testBit( index ); } + + +/***************************************************************************** + Misc. TQBitArray operator functions + *****************************************************************************/ + +TQ_EXPORT TQBitArray operator&( const TQBitArray &, const TQBitArray & ); +TQ_EXPORT TQBitArray operator|( const TQBitArray &, const TQBitArray & ); +TQ_EXPORT TQBitArray operator^( const TQBitArray &, const TQBitArray & ); + + +inline TQBitVal::operator int() +{ + return array->testBit( index ); +} + +inline TQBitVal &TQBitVal::operator=( const TQBitVal &v ) +{ + array->setBit( index, v.array->testBit(v.index) ); + return *this; +} + +inline TQBitVal &TQBitVal::operator=( bool v ) +{ + array->setBit( index, v ); + return *this; +} + + +/***************************************************************************** + TQBitArray stream functions + *****************************************************************************/ +#ifndef TQT_NO_DATASTREAM +TQ_EXPORT TQDataStream &operator<<( TQDataStream &, const TQBitArray & ); +TQ_EXPORT TQDataStream &operator>>( TQDataStream &, TQBitArray & ); +#endif + +#endif // TQBITARRAY_H diff --git a/src/tools/tqcache.h b/src/tools/tqcache.h new file mode 100644 index 000000000..9d747e346 --- /dev/null +++ b/src/tools/tqcache.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Definition of TQCache template class +** +** Created : 950209 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQCACHE_H +#define TQCACHE_H + +#ifndef QT_H +#include "ntqgcache.h" +#endif // QT_H + +template +class TQCache +#ifdef Q_QDOC + : public TQPtrCollection +#else + : public TQGCache +#endif +{ +public: + TQCache( const TQCache &c ) : TQGCache(c) {} + TQCache( int maxCost=100, int size=17, bool caseSensitive=TRUE ) + : TQGCache( maxCost, size, StringKey, caseSensitive, FALSE ) {} + ~TQCache() { clear(); } + TQCache &operator=( const TQCache &c ) + { return (TQCache&)TQGCache::operator=(c); } + int maxCost() const { return TQGCache::maxCost(); } + int totalCost() const { return TQGCache::totalCost(); } + void setMaxCost( int m ) { TQGCache::setMaxCost(m); } + uint count() const { return TQGCache::count(); } + uint size() const { return TQGCache::size(); } + bool isEmpty() const { return TQGCache::count() == 0; } + void clear() { TQGCache::clear(); } + bool insert( const TQString &k, const type *d, int c=1, int p=0 ) + { return TQGCache::insert_string(k,(Item)d,c,p);} + bool remove( const TQString &k ) + { return TQGCache::remove_string(k); } + type *take( const TQString &k ) + { return (type *)TQGCache::take_string(k); } + type *find( const TQString &k, bool ref=TRUE ) const + { return (type *)TQGCache::find_string(k,ref);} + type *operator[]( const TQString &k ) const + { return (type *)TQGCache::find_string(k);} + void statistics() const { TQGCache::statistics(); } +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void TQCache::deleteItem( TQPtrCollection::Item ) +{ +} +#endif + +template inline void TQCache::deleteItem( TQPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template +class TQCacheIterator : public TQGCacheIterator +{ +public: + TQCacheIterator( const TQCache &c ):TQGCacheIterator((TQGCache &)c) {} + TQCacheIterator( const TQCacheIterator &ci) + : TQGCacheIterator( (TQGCacheIterator &)ci ) {} + TQCacheIterator &operator=(const TQCacheIterator&ci) + { return ( TQCacheIterator&)TQGCacheIterator::operator=( ci ); } + uint count() const { return TQGCacheIterator::count(); } + bool isEmpty() const { return TQGCacheIterator::count() == 0; } + bool atFirst() const { return TQGCacheIterator::atFirst(); } + bool atLast() const { return TQGCacheIterator::atLast(); } + type *toFirst() { return (type *)TQGCacheIterator::toFirst(); } + type *toLast() { return (type *)TQGCacheIterator::toLast(); } + operator type *() const { return (type *)TQGCacheIterator::get(); } + type *current() const { return (type *)TQGCacheIterator::get(); } + TQString currentKey() const{ return TQGCacheIterator::getKeyString(); } + type *operator()() { return (type *)TQGCacheIterator::operator()();} + type *operator++() { return (type *)TQGCacheIterator::operator++(); } + type *operator+=(uint j) { return (type *)TQGCacheIterator::operator+=(j);} + type *operator--() { return (type *)TQGCacheIterator::operator--(); } + type *operator-=(uint j) { return (type *)TQGCacheIterator::operator-=(j);} +}; + +#endif // TQCACHE_H diff --git a/src/tools/tqcstring.cpp b/src/tools/tqcstring.cpp new file mode 100644 index 000000000..d4af46412 --- /dev/null +++ b/src/tools/tqcstring.cpp @@ -0,0 +1,2539 @@ +/**************************************************************************** +** +** Implementation of extended char array operations, and TQByteArray and +** TQCString classes +** +** 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 requirements 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. +** +**********************************************************************/ + +#include "tqstring.h" +#include "tqregexp.h" +#include "ntqdatastream.h" + +#ifdef TQT_THREAD_SUPPORT +# include +#endif // TQT_THREAD_SUPPORT + +#include +#include +#include +#include +#include +#ifndef TQT_NO_COMPRESS +#include "../3rdparty/zlib/zlib.h" +#endif + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +/*! + \relates TQCString + + This function is normally part of the C library. TQt implements + memmove() for platforms that do not provide it. + + memmove() copies \a len bytes from \a src into \a dst. The data + is copied correctly even if \a src and \a dst overlap. +*/ + +void *tqmemmove( void *dst, const void *src, uint len ) +{ + char *d; + char *s; + if ( dst > src ) { + d = (char *)dst + len - 1; + s = (char *)src + len - 1; + while ( len-- ) + *d-- = *s--; + } else if ( dst < src ) { + d = (char *)dst; + s = (char *)src; + while ( len-- ) + *d++ = *s++; + } + return dst; +} + + +/*! + \relates TQCString + + Returns a duplicate string. + + Allocates space for a copy of \a src, copies it, and returns a + pointer to the copy. If \a src is 0, it immediately returns 0. + + The returned string must be deleted using \c delete[]. +*/ + +char *tqstrdup( const char *src ) +{ + if ( !src ) + return 0; + char *dst = new char[strlen(src)+1]; + TQ_CHECK_PTR( dst ); + return strcpy( dst, src ); +} + +/*! + \fn char *qstrcpy( char *dst, const char *src ) + + \relates TQCString + + A safe strcpy() function. + + Copies all characters up to and including the '\0' from \a src + into \a dst and returns a pointer to \a dst. +*/ + +/*! + \relates TQCString + + A safe strncpy() function. + + Copies at most \a len bytes from \a src (stopping at \a len or the + terminating '\0' whichever comes first) into \a dst and returns a + pointer to \a dst. Guarantees that \a dst is '\0'-terminated. If + \a src or \a dst is 0, returns 0 immediately. + + \sa qstrcpy() +*/ + +char *tqstrncpy( char *dst, const char *src, uint len ) +{ + if ( !src || !dst ) + return 0; + strncpy( dst, src, len ); + if ( len > 0 ) + dst[len-1] = '\0'; + return dst; +} + +/*! + \fn uint tqstrlen( const char *str ); + + \relates TQCString + + A safe strlen function. + + Returns the number of characters that precede the terminating '\0'. + or 0 if \a str is 0. +*/ + +/*! + \fn int qstrcmp( const char *str1, const char *str2 ); + + \relates TQCString + + A safe strcmp() function. + + Compares \a str1 and \a str2. Returns a negative value if \a str1 + is less than \a str2, 0 if \a str1 is equal to \a str2 or a + positive value if \a str1 is greater than \a str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa tqstrncmp() tqstricmp() tqstrnicmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn int tqstrncmp( const char *str1, const char *str2, uint len ); + + \relates TQCString + + A safe strncmp() function. + + Compares at most \a len bytes of \a str1 and \a str2. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a + str1 is equal to \a str2 or a positive value if \a str1 is greater + than \a str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), tqstricmp(), tqstrnicmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \relates TQCString + + A safe stricmp() function. + + Compares \a str1 and \a str2 ignoring the case. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a + str1 is equal to \a str2 or a positive value if \a str1 is greater + than \a str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), tqstrncmp(), tqstrnicmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +int tqstricmp( const char *str1, const char *str2 ) +{ + const uchar *s1 = (const uchar *)str1; + const uchar *s2 = (const uchar *)str2; + int res; + uchar c; + if ( !s1 || !s2 ) + return s1 ? 1 : ( s2 ? -1 : 0 ); + for ( ; !(res = (c=tolower(*s1)) - tolower(*s2)); s1++, s2++ ) + if ( !c ) // strings are equal + break; + return res; +} + +/*! + \relates TQCString + + A safe strnicmp() function. + + Compares at most \a len bytes of \a str1 and \a str2 ignoring the case. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 + is equal to \a str2 or a positive value if \a str1 is greater than \a + str2. + + Special case I: Returns 0 if \a str1 and \a str2 are both 0. + + Special case II: Returns a random nonzero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), tqstrncmp() tqstricmp() + \link #asciinotion Note on character comparisons \endlink +*/ + +int tqstrnicmp( const char *str1, const char *str2, uint len ) +{ + const uchar *s1 = (const uchar *)str1; + const uchar *s2 = (const uchar *)str2; + int res; + uchar c; + if ( !s1 || !s2 ) + return s1 ? 1 : ( s2 ? -1 : 0 ); + for ( ; len--; s1++, s2++ ) { + if ( (res = (c=tolower(*s1)) - tolower(*s2)) ) + return res; + if ( !c ) // strings are equal + break; + } + return 0; +} + + +static TQ_UINT16 crc_tbl[16]; +static bool crc_tbl_init = FALSE; + +static void createCRC16Table() // build CRC16 lookup table +{ + uint i; + uint j; + uint v0, v1, v2, v3; + for ( i = 0; i < 16; i++ ) { + v0 = i & 1; + v1 = ( i >> 1 ) & 1; + v2 = ( i >> 2 ) & 1; + v3 = ( i >> 3 ) & 1; + j = 0; +#undef SET_BIT +#define SET_BIT(x, b, v) (x) |= (v) << (b) + SET_BIT( j, 0, v0 ); + SET_BIT( j, 7, v0 ); + SET_BIT( j, 12, v0 ); + SET_BIT( j, 1, v1 ); + SET_BIT( j, 8, v1 ); + SET_BIT( j, 13, v1 ); + SET_BIT( j, 2, v2 ); + SET_BIT( j, 9, v2 ); + SET_BIT( j, 14, v2 ); + SET_BIT( j, 3, v3 ); + SET_BIT( j, 10, v3 ); + SET_BIT( j, 15, v3 ); + crc_tbl[i] = j; + } +} + +/*! + \relates TQMemArray + + Returns the CRC-16 checksum of \a len bytes starting at \a data. + + The checksum is independent of the byte order (endianness). +*/ + +TQ_UINT16 tqChecksum( const char *data, uint len ) +{ + if ( !crc_tbl_init ) { // create lookup table + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &crc_tbl_init ) : 0 ); +#endif // TQT_THREAD_SUPPORT + + if ( !crc_tbl_init ) { + createCRC16Table(); + crc_tbl_init = TRUE; + } + } + TQ_UINT16 crc = 0xffff; + uchar c; + uchar *p = (uchar *)data; + while ( len-- ) { + c = *p++; + crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; + c >>= 4; + crc = ( (crc >> 4) & 0x0fff ) ^ crc_tbl[((crc ^ c) & 15)]; + } + return ~crc & 0xffff; +} + +/*! + \fn TQByteArray tqCompress( const TQByteArray& data ) + + \relates TQByteArray + + Compresses the array \a data and returns the compressed byte + array using zlib. + + \sa tqUncompress() +*/ + +/*! + \relates TQByteArray + + \overload + + Compresses the array \a data which is \a nbytes long and returns the + compressed byte array. +*/ + +#ifndef TQT_NO_COMPRESS +TQByteArray tqCompress( const uchar* data, int nbytes ) +{ + if ( nbytes == 0 ) { + TQByteArray tmp( 4 ); + tmp.fill( 0 ); + return tmp; + } + if ( !data ) { +#if defined(QT_CHECK_RANGE) + tqWarning( "qCompress: data is NULL." ); +#endif + return TQByteArray(); + } + + ulong len = nbytes + nbytes / 100 + 13; + TQByteArray bazip; + int res; + do { + bazip.resize( len + 4 ); + res = ::compress( (uchar*)bazip.data()+4, &len, (uchar*)data, nbytes ); + + switch ( res ) { + case Z_OK: + bazip.resize( len + 4 ); + bazip[0] = ( nbytes & 0xff000000 ) >> 24; + bazip[1] = ( nbytes & 0x00ff0000 ) >> 16; + bazip[2] = ( nbytes & 0x0000ff00 ) >> 8; + bazip[3] = ( nbytes & 0x000000ff ); + break; + case Z_MEM_ERROR: +#if defined(QT_CHECK_RANGE) + tqWarning( "qCompress: Z_MEM_ERROR: Not enough memory." ); +#endif + bazip.resize( 0 ); + break; + case Z_BUF_ERROR: + len *= 2; + break; + } + } while ( res == Z_BUF_ERROR ); + + return bazip; +} +#endif + +/*! + \fn TQByteArray tqUncompress( const TQByteArray& data ) + + \relates TQByteArray + + Uncompresses the array \a data and returns the uncompressed byte + array. + + Returns an empty TQByteArray if the input data was corrupt. + \omit + ADD THE FOLLOWING FOR TQt 4.0 + This function will uncompress data compressed with tqCompress() + from this and any earlier TQt version, back to TQt 3.1 when this + feature was added. + \endomit + + \sa tqCompress() +*/ + +/*! + \relates TQByteArray + + \overload + + Uncompresses the array \a data which is \a nbytes long and returns + the uncompressed byte array. +*/ + +#ifndef TQT_NO_COMPRESS +TQByteArray tqUncompress( const uchar* data, int nbytes ) +{ + if ( !data ) { +#if defined(QT_CHECK_RANGE) + tqWarning( "qUncompress: data is NULL." ); +#endif + return TQByteArray(); + } + if ( nbytes <= 4 ) { +#if defined(QT_CHECK_RANGE) + if ( nbytes < 4 || ( data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0 ) ) + tqWarning( "qUncompress: Input data is corrupted." ); +#endif + return TQByteArray(); + } + ulong expectedSize = ( data[0] << 24 ) | ( data[1] << 16 ) | ( data[2] << 8 ) | data[3]; + ulong len = TQMAX( expectedSize, 1 ); + TQByteArray baunzip; + int res; + do { + if ( baunzip.resize( len ) ) { + res = ::uncompress( (uchar*)baunzip.data(), &len, + (uchar*)data+4, nbytes-4 ); + } else { + res = Z_MEM_ERROR; + } + + switch ( res ) { + case Z_OK: + if ( len != baunzip.size() ) + baunzip.resize( len ); + break; + case Z_MEM_ERROR: +#if defined(QT_CHECK_RANGE) + tqWarning( "qUncompress: Z_MEM_ERROR: Not enough memory." ); +#endif + break; + case Z_BUF_ERROR: + len *= 2; + break; + case Z_DATA_ERROR: +#if defined(QT_CHECK_RANGE) + tqWarning( "qUncompress: Z_DATA_ERROR: Input data is corrupted." ); +#endif + break; + } + } while ( res == Z_BUF_ERROR ); + + if ( res != Z_OK ) + baunzip = TQByteArray(); + + return baunzip; +} +#endif + +/***************************************************************************** + TQByteArray documentation + *****************************************************************************/ + +/*! + \class TQByteArray + \reentrant + \brief The TQByteArray class provides an array of bytes. + + \ingroup collection + \ingroup tools + + The TQByteArray class provides an explicitly shared array of bytes. + It is useful for manipulating memory areas with custom data. + TQByteArray is implemented as a TQMemArray\. See the \l + TQMemArray documentation for further information. +*/ + +/*! + \fn TQByteArray::TQByteArray() + + Constructs an empty TQByteArray. +*/ + +/*! + \fn TQByteArray::TQByteArray( int size ) + + Constructs a TQByteArray of size \a size. +*/ + +/***************************************************************************** + TQByteArray stream functions + *****************************************************************************/ + +/*! + \relates TQMemArray + + Writes byte array \a a to the stream \a s and returns a reference + to the stream. + + \sa \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ +#ifndef TQT_NO_DATASTREAM + +TQDataStream &operator<<( TQDataStream &s, const TQByteArray &a ) +{ + return s.writeBytes( a.data(), a.size() ); +} + +/*! + \relates TQMemArray + + Reads a byte array into \a a from the stream \a s and returns a + reference to the stream. + + \sa \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ + +TQDataStream &operator>>( TQDataStream &s, TQByteArray &a ) +{ + TQ_UINT32 len; + s >> len; // read size of array + if ( len == 0 || s.eof() ) { // end of file reached + a.resize( 0 ); + return s; + } + if ( !a.resize( (uint)len ) ) { // resize array +#if defined(QT_CHECK_NULL) + tqWarning( "TQDataStream: Not enough memory to read TQByteArray" ); +#endif + len = 0; + } + if ( len > 0 ) // not null array + s.readRawBytes( a.data(), (uint)len ); + return s; +} + +#endif //TQT_NO_DATASTREAM + +/***************************************************************************** + TQCString member functions + *****************************************************************************/ + +/*! + \class TQCString tqcstring.h + \reentrant + \brief The TQCString class provides an abstraction of the classic C + zero-terminated char array (char *). + + \ingroup text + \ingroup collection + \ingroup tools + \ingroup shared + + TQCString inherits TQByteArray, which is defined as + TQMemArray\. Since TQCString is a TQMemArray, it uses \link + shclass.html explicit sharing\endlink with a reference count. + + TQCString tries to behave like a more convenient \c{const char *}. + The price of doing this is that some algorithms will perform + badly. For example, append() is O(length()) since it scans for a + null terminator. Although you might use TQCString for text that is + never exposed to the user, for most purposes, and especially for + user-visible text, you should use TQString. TQString provides + implicit sharing, Unicode and other internationalization support, + and is well optimized. + + Note that for the TQCString methods that take a \c{const char *} + parameter the \c{const char *} must either be 0 (null) or not-null + and '\0' (NUL byte) terminated; otherwise the results are + undefined. + + A TQCString that has not been assigned to anything is \e null, i.e. + both the length and the data pointer is 0. A TQCString that + references the empty string ("", a single '\0' char) is \e empty. + Both null and empty TQCStrings are legal parameters to the methods. + Assigning \c{const char *} 0 to TQCString produces a null TQCString. + + The length() function returns the length of the string; resize() + resizes the string and truncate() truncates the string. A string + can be filled with a character using fill(). Strings can be left + or right padded with characters using leftJustify() and + rightJustify(). Characters, strings and regular expressions can be + searched for using find() and findRev(), and counted using + contains(). + + Strings and characters can be inserted with insert() and appended + with append(). A string can be prepended with prepend(). + Characters can be removed from the string with remove() and + replaced with replace(). + + Portions of a string can be extracted using left(), right() and + mid(). Whitespace can be removed using stripWhiteSpace() and + simplifyWhiteSpace(). Strings can be converted to uppercase or + lowercase with upper() and lower() respectively. + + Strings that contain numbers can be converted to numbers with + toShort(), toInt(), toLong(), toULong(), toFloat() and toDouble(). + Numbers can be converted to strings with setNum(). + + Many operators are overloaded to work with TQCStrings. TQCString + also supports some more obscure functions, e.g. sprintf(), + setStr() and setExpand(). + + \target asciinotion + \sidebar Note on Character Comparisons + + In TQCString the notion of uppercase and lowercase and of which + character is greater than or less than another character is locale + dependent. This affects functions which support a case insensitive + option or which compare or lowercase or uppercase their arguments. + Case insensitive operations and comparisons will be accurate if + both strings contain only ASCII characters. (If \c $LC_CTYPE is + set, most Unix systems do "the right thing".) Functions that this + affects include contains(), find(), findRev(), \l operator<(), \l + operator<=(), \l operator>(), \l operator>=(), lower() and + upper(). + + This issue does not apply to \l{TQString}s since they represent + characters using Unicode. + \endsidebar + + Performance note: The TQCString methods for TQRegExp searching are + implemented by converting the TQCString to a TQString and performing + the search on that. This implies a deep copy of the TQCString data. + If you are going to perform many TQRegExp searches on a large + TQCString, you will get better performance by converting the + TQCString to a TQString yourself, and then searching in the TQString. +*/ + +/*! + \fn TQCString::TQCString() + + Constructs a null string. + + \sa isNull() +*/ + +/*! + \fn TQCString::TQCString( const TQCString &s ) + + Constructs a shallow copy \a s. + + \sa assign() +*/ + +/*! + Constructs a string with room for \a size characters, including + the '\0'-terminator. Makes a null string if \a size == 0. + + If \a size \> 0, then the first and last characters in the string + are initialized to '\0'. All other characters are uninitialized. + + \sa resize(), isNull() +*/ + +TQCString::TQCString( int size ) + : TQByteArray( size ) +{ + if ( size > 0 ) { + *data() = '\0'; // set terminator + *(data()+(size-1)) = '\0'; + } +} + +/*! + Constructs a string that is a deep copy of \a str. + + If \a str is 0 a null string is created. + + \sa isNull() +*/ + +TQCString::TQCString( const char *str ) +{ + duplicate( str, tqstrlen(str) + 1 ); +} + + +/*! + Constructs a string that is a deep copy of \a str. The copy will + be at most \a maxsize bytes long including the '\0'-terminator. + + Example: + \code + TQCString str( "helloworld", 6 ); // assigns "hello" to str + \endcode + + If \a str contains a 0 byte within the first \a maxsize bytes, the + resulting TQCString will be terminated by this 0. If \a str is 0 a + null string is created. + + \sa isNull() +*/ + +TQCString::TQCString( const char *str, uint maxsize ) +{ + if ( str == 0 ) + return; + uint len; // index of first '\0' + for ( len = 0; len < maxsize - 1; len++ ) { + if ( str[len] == '\0' ) + break; + } + TQByteArray::resize( len + 1 ); + memcpy( data(), str, len ); + data()[len] = 0; +} + +/*! + \reimp +*/ + +TQCString::~TQCString() +{ +} + +/*! + \fn TQCString &TQCString::operator=( const TQCString &s ) + + Assigns a shallow copy of \a s to this string and returns a + reference to this string. +*/ + +/*! + \overload TQCString &TQCString::operator=( const char *str ) + + Assigns a deep copy of \a str to this string and returns a + reference to this string. + + If \a str is 0 a null string is created. + + \sa isNull() +*/ + +/*! + \fn bool TQCString::isNull() const + + Returns TRUE if the string is null, i.e. if data() == 0; otherwise + returns FALSE. A null string is also an empty string. + + Example: + \code + TQCString a; // a.data() == 0, a.size() == 0, a.length() == 0 + TQCString b == ""; // b.data() == "", b.size() == 1, b.length() == 0 + a.isNull(); // TRUE because a.data() == 0 + a.isEmpty(); // TRUE because a.length() == 0 + b.isNull(); // FALSE because b.data() == "" + b.isEmpty(); // TRUE because b.length() == 0 + \endcode + + \sa isEmpty(), length(), size() +*/ + +/*! + \fn bool TQCString::isEmpty() const + + Returns TRUE if the string is empty, i.e. if length() == 0; + otherwise returns FALSE. An empty string is not always a null + string. + + See example in isNull(). + + \sa isNull(), length(), size() +*/ + +/*! + \fn uint TQCString::length() const + + Returns the length of the string, excluding the '\0'-terminator. + Equivalent to calling \c strlen(data()). + + Null strings and empty strings have zero length. + + \sa size(), isNull(), isEmpty() +*/ + +/*! + \fn bool TQCString::truncate( uint pos ) + + Truncates the string at position \a pos. + + Equivalent to calling \c resize(pos+1). + + Example: + \code + TQCString s = "truncate this string"; + s.truncate( 5 ); // s == "trunc" + \endcode + + \sa resize() +*/ + +/*! + Extends or shrinks the string to \a len bytes, including the + '\0'-terminator. + + A '\0'-terminator is set at position \c{len - 1} unless + \c{len == 0}. + + Example: + \code + TQCString s = "resize this string"; + s.resize( 7 ); // s == "resize" + \endcode + + \sa truncate() +*/ + +bool TQCString::resize( uint len ) +{ + detach(); + uint wasNull = isNull(); + if ( !TQByteArray::resize(len) ) + return FALSE; + if ( len ) + data()[len - 1] = '\0'; + if ( len > 0 && wasNull ) + data()[0] = '\0'; + return TRUE; +} + + +/*! + Implemented as a call to the native vsprintf() (see the manual for + your C library). + + If the string is shorter than 256 characters, this sprintf() calls + resize(256) to decrease the chance of memory corruption. The + string is resized back to its actual length before sprintf() + returns. + + Example: + \code + TQCString s; + s.sprintf( "%d - %s", 1, "first" ); // result < 256 chars + + TQCString big( 25000 ); // very long string + big.sprintf( "%d - %s", 2, longString ); // result < 25000 chars + \endcode + + \warning All vsprintf() implementations will write past the end of + the target string (*this) if the \a format specification and + arguments happen to be longer than the target string, and some + will also fail if the target string is longer than some arbitrary + implementation limit. + + Giving user-supplied arguments to sprintf() is risky: Sooner or + later someone will paste a huge line into your application. +*/ + +TQCString &TQCString::sprintf( const char *format, ... ) +{ + detach(); + va_list ap; + va_start( ap, format ); + if ( size() < 256 ) + TQByteArray::resize( 256 ); // make string big enough +#ifdef QT_VSNPRINTF + QT_VSNPRINTF( data(), size(), format, ap ); +#else + vsprintf( data(), format, ap ); +#endif + resize( tqstrlen(data()) + 1 ); // truncate + va_end( ap ); + return *this; +} + + +/*! + Fills the string with \a len bytes of character \a c, followed by + a '\0'-terminator. + + If \a len is negative, then the current string length is used. + + Returns FALSE is \a len is nonnegative and there is not enough + memory to resize the string; otherwise returns TRUE. +*/ + +bool TQCString::fill( char c, int len ) +{ + detach(); + if ( len < 0 ) + len = length(); + if ( !TQByteArray::fill(c,len+1) ) + return FALSE; + *(data()+len) = '\0'; + return TRUE; +} + + +/*! + \fn TQCString TQCString::copy() const + + Returns a deep copy of this string. + + \sa detach() +*/ + + +/*! + Finds the first occurrence of the character \a c, starting at + position \a index. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a c, or -1 if \a c could not be found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int TQCString::find( char c, int index, bool cs ) const +{ + if ( (uint)index >= size() ) // index outside string + return -1; + const char *d; + if ( cs ) { // case sensitive + d = strchr( data()+index, c ); + } else { + d = data()+index; + c = tolower( (uchar) c ); + while ( *d && tolower((uchar) *d) != c ) + d++; + if ( !*d && c ) // not found + d = 0; + } + return d ? (int)(d - data()) : -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. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a str, or -1 if \a str could not be + found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int TQCString::find( const char *str, int index, bool cs ) const +{ + return find( str, index, cs, length() ); +} + +int TQCString::find( const char *str, int index, bool cs, uint l ) const +{ + if ( (uint)index >= size() ) + return -1; + if ( !str ) + return -1; + if ( !*str ) + return index; + const uint sl = tqstrlen( str ); + if ( sl + index > l ) + return -1; + + if ( sl == 1 ) + return find( *str, index, cs ); + + /* + See TQString::find() for details. + */ + const char* needle = str; + const char* haystack = data() + index; + const char* end = data() + (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] ); + hashHaystack = ((hashHaystack<<1) + haystack[i] ); + } + hashHaystack -= *(haystack+sl_minus_1); + + while ( haystack <= end ) { + hashHaystack += *(haystack+sl_minus_1); + if ( hashHaystack == hashNeedle && *needle == *haystack + && tqstrncmp( needle, haystack, sl ) == 0 ) + return haystack - data(); + + REHASH( *haystack ); + ++haystack; + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + + tolower( needle[i] ) ); + hashHaystack = ((hashHaystack<<1) + + tolower( haystack[i] ) ); + } + hashHaystack -= tolower(*(haystack+sl_minus_1)); + + while ( haystack <= end ) { + hashHaystack += tolower(*(haystack+sl_minus_1)); + if ( hashHaystack == hashNeedle + && tqstrnicmp( needle, haystack, sl ) == 0 ) + return haystack - data(); + + REHASH( tolower(*haystack) ); + ++haystack; + } + } + return -1; +} + + +/*! + Finds the first occurrence of the character \a c, starting at + position \a index and searching backwards. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a c, or -1 if \a c could not be found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int TQCString::findRev( char c, int index, bool cs ) const +{ + const char *b = data(); + const char *d; + if ( index < 0 ) + index = length(); + if ( (uint)index >= size() ) + return -1; + d = b + index; + if ( cs ) { + while ( d >= b && *d != c ) + d--; + } else { + c = tolower( (uchar) c ); + while ( d >= b && tolower((uchar) *d) != c ) + d--; + } + return d >= b ? (int)(d - b) : -1; +} + +/*! + \overload + + Finds the first occurrence of the string \a str, starting at + position \a index and searching backwards. + + The search is case sensitive if \a cs is TRUE, or case insensitive + if \a cs is FALSE. + + Returns the position of \a str, or -1 if \a str could not be + found. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int TQCString::findRev( const char *str, int index, bool cs ) const +{ + /* + See TQString::find() for explanations. + */ + const uint sl = tqstrlen( str ); + const uint l = length(); + int delta = l-sl; + if ( index < 0 ) + index = delta; + if ( index < 0 || index > (int)l ) + return -1; + if ( index > delta ) + index = delta; + + if ( sl == 1 ) + return findRev( *str, index, cs ); + + const char* needle = str; + const char* haystack = data() + index; + const char* end = data(); + const uint sl_minus_1 = sl-1; + const char* n = needle+sl_minus_1; + const char* h = haystack+sl_minus_1; + uint hashNeedle = 0, hashHaystack = 0, i; + + if ( cs ) { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + *(n-i) ); + hashHaystack = ((hashHaystack<<1) + *(h-i) ); + } + hashHaystack -= *haystack; + while ( haystack >= end ) { + hashHaystack += *haystack; + if ( hashHaystack == hashNeedle && tqstrncmp( needle, haystack, sl ) == 0 ) + return haystack-data(); + --haystack; + REHASH( *(haystack+sl) ); + } + } else { + for ( i = 0; i < sl; ++i ) { + hashNeedle = ((hashNeedle<<1) + tolower( *(n-i) ) ); + hashHaystack = ((hashHaystack<<1) + tolower( *(h-i) ) ); + } + hashHaystack -= tolower(*haystack); + while ( haystack >= end ) { + hashHaystack += tolower(*haystack); + if ( hashHaystack == hashNeedle && tqstrnicmp( needle, haystack, sl ) == 0 ) + return haystack-data(); + --haystack; + REHASH( tolower(*(haystack+sl)) ); + } + } + return -1; +} + + +/*! + Returns the number of times the character \a c occurs in the + string. + + The match is case sensitive if \a cs is TRUE, or case insensitive + if \a cs if FALSE. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +int TQCString::contains( char c, bool cs ) const +{ + int count = 0; + char *d = data(); + if ( !d ) + return 0; + if ( cs ) { // case sensitive + while ( *d ) + if ( *d++ == c ) + count++; + } else { // case insensitive + c = tolower( (uchar) c ); + while ( *d ) { + if ( tolower((uchar) *d) == c ) + count++; + d++; + } + } + return count; +} + +/*! + \overload + + Returns the number of times \a str occurs in the string. + + The match is case sensitive if \a cs is TRUE, or case insensitive + if \a cs if FALSE. + + This function counts overlapping substrings, for example, "banana" + contains two occurrences of "ana". + + \sa findRev() + \link #asciinotion Note on character comparisons \endlink +*/ + +int TQCString::contains( const char *str, bool cs ) const +{ + int count = 0; + int i = -1; + uint l = length(); + // use find for the faster hashing algorithm + while ( ( i = find ( str, i+1, cs, l ) ) != -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. + + Example: + \code + TQCString s = "Pineapple"; + TQCString t = s.left( 4 ); // t == "Pine" + \endcode + + \sa right(), mid() +*/ +TQCString TQCString::left( uint len ) const +{ + if ( isEmpty() ) { + TQCString empty; + return empty; + } else if ( len >= size() ) { + TQCString same( data() ); + return same; + } else { + TQCString s( len+1 ); + strncpy( s.data(), data(), len ); + *(s.data()+len) = '\0'; + return s; + } +} + +/*! + Returns a substring that contains the \a len rightmost characters + of the string. + + The whole string is returned if \a len exceeds the length of the + string. + + Example: + \code + TQCString s = "Pineapple"; + TQCString t = s.right( 5 ); // t == "apple" + \endcode + + \sa left(), mid() +*/ + +TQCString TQCString::right( uint len ) const +{ + if ( isEmpty() ) { + TQCString empty; + return empty; + } else { + uint l = length(); + if ( len > l ) + len = l; + char *p = data() + (l - len); + return TQCString( p ); + } +} + +/*! + Returns a substring that contains at most \a len characters from + this string, starting at position \a index. + + Returns a null string if the string is empty or if \a index is out + of range. Returns the whole string from \a index if \a index+len + exceeds the length of the string. + + Example: + \code + TQCString s = "Two pineapples"; + TQCString t = s.mid( 4, 3 ); // t == "pin" + \endcode + + \sa left(), right() +*/ + +TQCString TQCString::mid( uint index, uint len ) const +{ + uint slen = tqstrlen( data() ); + if ( isEmpty() || index >= slen ) { + TQCString empty; + return empty; + } else { + if ( len > slen-index ) + len = slen - index; + char *p = data()+index; + TQCString s( len+1 ); + strncpy( s.data(), p, len ); + *(s.data()+len) = '\0'; + return s; + } +} + +/*! + Returns a string of length \a width (plus one for the terminating + '\0') that contains this string padded with the \a fill character. + + If the length of the string exceeds \a width and \a truncate is + FALSE (the default), then the returned string is a copy of the + string. If the length of the string exceeds \a width and \a + truncate is TRUE, then the returned string is a left(\a width). + + Example: + \code + TQCString s("apple"); + TQCString t = s.leftJustify(8, '.'); // t == "apple..." + \endcode + + \sa rightJustify() +*/ + +TQCString TQCString::leftJustify( uint width, char fill, bool truncate ) const +{ + TQCString result; + int len = tqstrlen(data()); + int padlen = width - len; + if ( padlen > 0 ) { + result.TQByteArray::resize( len+padlen+1 ); + memcpy( result.data(), data(), len ); + memset( result.data()+len, fill, padlen ); + result[len+padlen] = '\0'; + } else { + if ( truncate ) + result = left( width ); + else + result = copy(); + } + return result; +} + +/*! + Returns a string of length \a width (plus one for the terminating + '\0') that contains zero or more of the \a fill character followed + by this string. + + If the length of the string exceeds \a width and \a truncate is + FALSE (the default), then the returned string is a copy of the + string. If the length of the string exceeds \a width and \a + truncate is TRUE, then the returned string is a left(\a width). + + Example: + \code + TQCString s("pie"); + TQCString t = s.rightJustify(8, '.'); // t == ".....pie" + \endcode + + \sa leftJustify() +*/ + +TQCString TQCString::rightJustify( uint width, char fill, bool truncate ) const +{ + TQCString result; + int len = tqstrlen(data()); + int padlen = width - len; + if ( padlen > 0 ) { + result.TQByteArray::resize( len+padlen+1 ); + memset( result.data(), fill, padlen ); + memcpy( result.data()+padlen, data(), len ); + result[len+padlen] = '\0'; + } else { + if ( truncate ) + result = left( width ); + else + result = copy(); + } + return result; +} + +/*! + Returns a new string that is a copy of this string converted to lower + case. + + Example: + \code + TQCString s("Credit"); + TQCString t = s.lower(); // t == "credit" + \endcode + + \sa upper() + \link #asciinotion Note on character comparisons \endlink +*/ + +TQCString TQCString::lower() const +{ + TQCString s( data() ); + char *p = s.data(); + if ( p ) { + while ( *p ) { + *p = tolower( (uchar) *p ); + p++; + } + } + return s; +} + +/*! + Returns a new string that is a copy of this string converted to upper case. + + Example: + \code + TQCString s( "Debit" ); + TQCString t = s.upper(); // t == "DEBIT" + \endcode + + \sa lower() + \link #asciinotion Note on character comparisons \endlink +*/ + +TQCString TQCString::upper() const +{ + TQCString s( data() ); + char *p = s.data(); + if ( p ) { + while ( *p ) { + *p = toupper(*p); + p++; + } + } + return s; +} + + +/*! + Returns a new string that has white space removed from the start + and the end. + + White space means the decimal ASCII codes 9, 10, 11, 12, 13 and + 32. + + Example: + \code + TQCString s = " space "; + TQCString t = s.stripWhiteSpace(); // t == "space" + \endcode + + \sa simplifyWhiteSpace() +*/ + +TQCString TQCString::stripWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return copy(); + + char *s = data(); + TQCString result = s; + int reslen = result.length(); + if ( !isspace((uchar) s[0]) && !isspace((uchar) s[reslen-1]) ) + return result; // returns a copy + + s = result.data(); + int start = 0; + int end = reslen - 1; + while ( isspace((uchar) s[start]) ) // skip white space from start + start++; + if ( s[start] == '\0' ) { // only white space + result.resize( 1 ); + return result; + } + while ( end && isspace((uchar) s[end]) ) // skip white space from end + end--; + end -= start - 1; + memmove( result.data(), &s[start], end ); + result.resize( end + 1 ); + return result; +} + + +/*! + Returns a new string that has white space removed from the start + and the end, plus any sequence of internal white space replaced + with a single space (ASCII 32). + + White space means the decimal ASCII codes 9, 10, 11, 12, 13 and + 32. + + \code + TQCString s = " lots\t of\nwhite space "; + TQCString t = s.simplifyWhiteSpace(); // t == "lots of white space" + \endcode + + \sa stripWhiteSpace() +*/ + +TQCString TQCString::simplifyWhiteSpace() const +{ + if ( isEmpty() ) // nothing to do + return copy(); + TQCString result( size() ); + char *from = data(); + char *to = result.data(); + char *first = to; + for ( ;; ) { + while ( isspace((uchar) *from) ) + from++; + while ( *from && !isspace((uchar) *from) ) + *to++ = *from++; + if ( *from ) + *to++ = 0x20; // ' ' + else + break; + } + if ( to > first && *(to-1) == 0x20 ) + to--; + *to = '\0'; + result.resize( (int)(to - result.data()) + 1 ); + return result; +} + + +/*! + \overload + + Inserts string \a s into the string at position \a index. + + If \a index is beyond the end of the string, the string is + padded with spaces (ASCII 32) to length \a index and then \a s + is appended. + + \code + TQCString s = "I like fish"; + s.insert( 2, "don't "); // s == "I don't like fish" + + s = "x"; // index 01234 + s.insert( 3, "yz" ); // s == "x yz" + \endcode +*/ + +TQCString &TQCString::insert( uint index, const char *s ) +{ + int len = tqstrlen(s); + if ( len == 0 ) + return *this; + uint olen = length(); + int nlen = olen + len; + if ( index >= olen ) { // insert after end of string + detach(); + if ( TQByteArray::resize(nlen+index-olen+1, TQByteArray::SpeedOptim ) ) { + memset( data()+olen, ' ', index-olen ); + memcpy( data()+index, s, len+1 ); + } + } else { + detach(); + if ( TQByteArray::resize(nlen+1, TQByteArray::SpeedOptim ) ) { // normal insert + memmove( data()+index+len, data()+index, olen-index+1 ); + memcpy( data()+index, s, len ); + } + } + return *this; +} + +/*! + Inserts character \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 + padded with spaces (ASCII 32) to length \a index and then \a c + is appended. + + Example: + \code + TQCString s = "Yes"; + s.insert( 3, '!'); // s == "Yes!" + \endcode + + \sa remove(), replace() +*/ + +TQCString &TQCString::insert( uint index, char c ) // insert char +{ + char buf[2]; + buf[0] = c; + buf[1] = '\0'; + return insert( index, buf ); +} + +/*! + \fn TQCString &TQCString::prepend( const char *s ) + + Prepend \a s to the string. Equivalent to insert(0, s). + + \sa insert() +*/ + +/*! + Removes \a len characters from the string, starting at position \a + index, and returns a reference to the string. + + If \a index is out of range, nothing happens. If \a index is + valid, but \a index + \a len is larger than the length of the + string, the string is truncated at position \a index. + + \code + TQCString s = "Montreal"; + s.remove( 1, 4 ); // s == "Meal" + \endcode + + \sa insert(), replace() +*/ + +TQCString &TQCString::remove( uint index, uint len ) +{ + uint olen = length(); + if ( index + len >= olen ) { // range problems + if ( index < olen ) { // index ok + detach(); + resize( index+1 ); + } + } else if ( len != 0 ) { + detach(); + memmove( data()+index, data()+index+len, olen-index-len+1 ); + TQByteArray::resize(olen-len+1, TQByteArray::SpeedOptim ); + } + return *this; +} + +/*! + Replaces \a len characters from the string, starting at position + \a index, with \a str, and returns a reference to the string. + + If \a index is out of range, nothing is removed and \a str is + appended at the end of the string. If \a index is valid, but \a + index + \a len is larger than the length of the string, \a str + replaces the rest of the string from position \a index. + + \code + TQCString s = "Say yes!"; + s.replace( 4, 3, "NO" ); // s == "Say NO!" + \endcode + + \sa insert(), remove() +*/ + +TQCString &TQCString::replace( uint index, uint len, const char *str ) +{ + remove( index, len ); + insert( index, str ); + return *this; +} + + +/*! \overload + + Replaces every occurrence of the character \a c in the string + with \a after. Returns a reference to the string. + + Example: + \code + TQCString s = "a,b,c"; + s.replace( ',', " or " ); + // s == "a or b or c" + \endcode +*/ +TQCString &TQCString::replace( char c, const char *after ) +{ + char str[2]; + str[0] = c; + str[1] = '\0'; + return replace( str, after ); +} + +/*! \overload + + Replaces every occurrence of the string \a before in the string + with the string \a after. Returns a reference to the string. + + Example: + \code + TQCString s = "Greek is Greek"; + s.replace( "Greek", "English" ); + // s == "English is English" + \endcode +*/ + +TQCString &TQCString::replace( const char *before, const char *after ) +{ + if ( before == after || isNull() ) + return *this; + + detach(); + + int index = 0; + const int bl = before ? int(strlen( before )) : 0; + const int al = after ? int(strlen( after )) : 0; + char *d = data(); + uint len = length(); + + if ( bl == al ) { + if ( bl ) { + while( (index = find( before, index, TRUE, len ) ) != -1 ) { + memcpy( d+index, after, al ); + index += bl; + } + } + } else if ( al < bl ) { + uint to = 0; + uint movestart = 0; + uint num = 0; + while( (index = find( before, index, TRUE, len ) ) != -1 ) { + if ( num ) { + int msize = index - movestart; + if ( msize > 0 ) { + memmove( d + to, d + movestart, msize ); + to += msize; + } + } else { + to = index; + } + if ( al ) { + memcpy( d + to, after, al ); + to += al; + } + index += bl; + movestart = index; + num++; + } + if ( num ) { + int msize = len - movestart; + if ( msize > 0 ) + memmove( d + to, d + movestart, msize ); + resize( len - num*(bl-al) + 1 ); + } + } 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 = find(before, index, TRUE, len); + 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 = len + adjust; + int moveend = len; + if ( newlen > len ) { + resize( newlen + 1 ); + len = newlen; + } + d = data(); + + while( pos ) { + pos--; + int movestart = indices[pos] + bl; + int insertstart = indices[pos] + pos*(al-bl); + int moveto = insertstart + al; + memmove( d + moveto, d + movestart, (moveend - movestart) ); + if ( after ) + memcpy( d + insertstart, after, al ); + moveend = movestart - bl; + } + } + } + return *this; +} + +/*! \overload + + Replaces every occurrence of \a c1 with the char \a c2. + Returns a reference to the string. +*/ +TQCString &TQCString::replace( char c1, char c2 ) +{ + detach(); + uint i = 0; + char *d = data(); + uint len = length(); + while ( i < len ) { + if ( d[i] == c1 ) + d[i] = c2; + i++; + } + return *this; +} + + +#ifndef TQT_NO_REGEXP_CAPTURE +/*! + \overload + + Finds the first occurrence of the regular expression \a rx, + starting at position \a index. + + Returns the position of the next match, or -1 if \a rx was not + found. + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a TQString and + apply the function to that. +*/ + +int TQCString::find( const TQRegExp& rx, int index ) const +{ + TQString d = TQString::fromAscii( data() ); + return d.find( rx, index ); +} + +/*! + \overload + + Finds the first occurrence of the regular expression \a rx, + starting at position \a index and searching backwards. + + Returns the position of the next match (backwards), or -1 if \a rx + was not found. + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a TQString and + apply the function to that. +*/ + +int TQCString::findRev( const TQRegExp& rx, int index ) const +{ + TQString d = TQString::fromAscii( data() ); + return d.findRev( rx, index ); +} + +/*! + \overload + + Counts the number of overlapping occurrences of \a rx in the string. + + Example: + \code + TQString s = "banana and panama"; + TQRegExp r = TQRegExp( "a[nm]a", TRUE, FALSE ); + s.contains( r ); // 4 matches + \endcode + + \sa find(), findRev() + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a TQString and + apply the function to that. +*/ + +int TQCString::contains( const TQRegExp &rx ) const +{ + TQString d = TQString::fromAscii( data() ); + return d.contains( rx ); +} + + +/*! + \overload + + Replaces every occurrence of \a rx in the string with \a str. + Returns a reference to the string. + + Example: + \code + TQString s = "banana"; + s.replace( TQRegExp("a.*a"), "" ); // becomes "b" + + s = "banana"; + s.replace( TQRegExp("^[bn]a"), "X" ); // becomes "Xnana" + + s = "banana"; + s.replace( TQRegExp("^[bn]a"), "" ); // becomes "nana" + \endcode + + \warning If you want to apply this function repeatedly to the same + string it is more efficient to convert the string to a TQString and + apply the function to that. +*/ + +TQCString &TQCString::replace( const TQRegExp &rx, const char *str ) +{ + TQString d = TQString::fromAscii( data() ); + TQString r = TQString::fromAscii( str ); + d.replace( rx, r ); + setStr( d.ascii() ); + return *this; +} +#endif //TQT_NO_REGEXP + +/*! + Returns the string converted to a \c long value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +long TQCString::toLong( bool *ok ) const +{ + char *p = data(); + long val=0; + const long max_mult = LONG_MAX / 10; + bool is_ok = FALSE; + int neg = 0; + if ( !p ) + goto bye; + while ( isspace((uchar) *p) ) // skip leading space + p++; + if ( *p == '-' ) { + p++; + neg = 1; + } else if ( *p == '+' ) { + p++; + } + if ( !isdigit((uchar) *p) ) + goto bye; + while ( isdigit((uchar) *p) ) { + if ( val > max_mult || (val == max_mult && (*p-'0') > 7+neg) ) + goto bye; + val = 10*val + (*p++ - '0'); + } + if ( neg ) + val = -val; + while ( isspace((uchar) *p) ) // skip trailing space + p++; + if ( *p == '\0' ) + is_ok = TRUE; +bye: + if ( ok ) + *ok = is_ok; + return is_ok ? val : 0; +} + +/*! + Returns the string converted to an \c{unsigned long} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +ulong TQCString::toULong( bool *ok ) const +{ + char *p = data(); + ulong val=0; + const ulong max_mult = ULONG_MAX / 10; + bool is_ok = FALSE; + if ( !p ) + goto bye; + while ( isspace((uchar) *p) ) // skip leading space + p++; + if ( *p == '+' ) + p++; + if ( !isdigit((uchar) *p) ) + goto bye; + while ( isdigit((uchar) *p) ) { + if ( val > max_mult || (val == max_mult && (*p-'0') > 5) ) + goto bye; + val = 10*val + (*p++ - '0'); + } + while ( isspace((uchar) *p) ) // skip trailing space + p++; + if ( *p == '\0' ) + is_ok = TRUE; +bye: + if ( ok ) + *ok = is_ok; + return is_ok ? val : 0; +} + +/*! + Returns the string converted to a \c{short} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, is out of range, or if it has trailing garbage; otherwise + \a *ok is set to TRUE. +*/ + +short TQCString::toShort( bool *ok ) const +{ + long v = toLong( ok ); + 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} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, is out of range, or if it has trailing garbage; otherwise + \a *ok is set to TRUE. +*/ + +ushort TQCString::toUShort( bool *ok ) const +{ + ulong v = toULong( ok ); + if ( v > USHRT_MAX ) { + if ( ok ) + *ok = FALSE; + v = 0; + } + return (ushort)v; +} + + +/*! + Returns the string converted to a \c{int} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +int TQCString::toInt( bool *ok ) const +{ + long v = toLong( ok ); + 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} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +uint TQCString::toUInt( bool *ok ) const +{ + ulong v = toULong( ok ); + 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: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +double TQCString::toDouble( bool *ok ) const +{ + char *end; + double val = strtod( data() ? data() : "", &end ); + if ( ok ) + *ok = ( data() && *data() && ( end == 0 || *end == '\0' ) ); + return val; +} + +/*! + Returns the string converted to a \c{float} value. + + If \a ok is not 0: \a *ok is set to FALSE if the string is not a + number, or if it has trailing garbage; otherwise \a *ok is set to + TRUE. +*/ + +float TQCString::toFloat( bool *ok ) const +{ + return (float)toDouble( ok ); +} + + +/*! + Makes a deep copy of \a str. Returns a reference to the string. +*/ + +TQCString &TQCString::setStr( const char *str ) +{ + detach(); + if ( str ) // valid string + store( str, tqstrlen(str)+1 ); + else // empty + resize( 0 ); + return *this; +} + +/*! + \overload + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +TQCString &TQCString::setNum( long n ) +{ + detach(); + char buf[20]; + char *p = &buf[19]; + bool neg; + if ( n < 0 ) { + neg = TRUE; + n = -n; + } else { + neg = FALSE; + } + *p = '\0'; + do { + *--p = ((int)(n%10)) + '0'; + n /= 10; + } while ( n ); + if ( neg ) + *--p = '-'; + store( p, tqstrlen(p)+1 ); + return *this; +} + +/*! + \overload + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +TQCString &TQCString::setNum( ulong n ) +{ + detach(); + char buf[20]; + char *p = &buf[19]; + *p = '\0'; + do { + *--p = ((int)(n%10)) + '0'; + n /= 10; + } while ( n ); + store( p, tqstrlen(p)+1 ); + return *this; +} + +/*! + \overload TQCString &TQCString::setNum( int n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + \overload TQCString &TQCString::setNum( uint n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + \overload TQCString &TQCString::setNum( short n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + \overload TQCString &TQCString::setNum( ushort n ) + + Sets the string to the string representation of the number \a n + and returns a reference to the string. +*/ + +/*! + Sets the string to the string representation of the number \a n + and returns a reference to the string. + + The format of the string representation is specified by the format + character \a f, and the precision (number of digits after the + decimal point) is specified with \a prec. + + The valid formats for \a f are 'e', 'E', 'f', 'g' and 'G'. The + formats are the same as for sprintf(); they are explained in \l + TQString::arg(). +*/ + +TQCString &TQCString::setNum( double n, char f, int prec ) +{ +#if defined(QT_CHECK_RANGE) + if ( !(f=='f' || f=='F' || f=='e' || f=='E' || f=='g' || f=='G') ) + tqWarning( "TQCString::setNum: Invalid format char '%c'", f ); +#endif + char format[20]; + char *fs = format; // generate format string + *fs++ = '%'; // "%.l" + if ( prec > 99 ) + prec = 99; + *fs++ = '.'; + if ( prec >= 10 ) { + *fs++ = prec / 10 + '0'; + *fs++ = prec % 10 + '0'; + } else { + *fs++ = prec + '0'; + } + *fs++ = 'l'; + *fs++ = f; + *fs = '\0'; + return sprintf( format, n ); +} + +/*! \overload TQCString &TQCString::setNum( float n, char f, int prec ) */ + + +/*! + Sets the character at position \a index to \a c and expands the + string if necessary, padding with spaces. + + Returns FALSE if \a index was out of range and the string could + not be expanded; otherwise returns TRUE. +*/ + +bool TQCString::setExpand( uint index, char c ) +{ + detach(); + uint oldlen = length(); + if ( index >= oldlen ) { + if ( !TQByteArray::resize( index+2 ) ) // no memory + return FALSE; + if ( index > oldlen ) + memset( data() + oldlen, ' ', index - oldlen ); + *(data() + index+1) = '\0'; // terminate padded string + } + *(data() + index) = c; + return TRUE; +} + + +/*! + \fn TQCString::operator const char *() const + + Returns the string data. +*/ + + +/*! + \fn TQCString& TQCString::append( const char *str ) + + Appends string \a str to the string and returns a reference to the + string. Equivalent to operator+=(). +*/ + +/*! + Appends string \a str to the string and returns a reference to the string. +*/ + +TQCString& TQCString::operator+=( const char *str ) +{ + if ( !str ) + return *this; // nothing to append + detach(); + uint len1 = length(); + uint len2 = tqstrlen(str); + if ( !TQByteArray::resize( len1 + len2 + 1, TQByteArray::SpeedOptim ) ) + return *this; // no memory + memcpy( data() + len1, str, len2 + 1 ); + return *this; +} + +/*! + \overload + + Appends character \a c to the string and returns a reference to the string. +*/ + +TQCString &TQCString::operator+=( char c ) +{ + detach(); + uint len = length(); + if ( !TQByteArray::resize( len + 2, TQByteArray::SpeedOptim ) ) + return *this; // no memory + *(data() + len) = c; + *(data() + len+1) = '\0'; + return *this; +} + + +/***************************************************************************** + TQCString stream functions + *****************************************************************************/ +#ifndef TQT_NO_DATASTREAM +/*! + \relates TQCString + + Writes string \a str to the stream \a s. + + \sa \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ +TQDataStream &operator<<( TQDataStream &s, const TQCString &str ) +{ + return s.writeBytes( str.data(), str.size() ); +} + +/*! + \relates TQCString + + Reads a string into \a str from the stream \a s. + + \sa \link datastreamformat.html Format of the TQDataStream operators \endlink +*/ + +TQDataStream &operator>>( TQDataStream &s, TQCString &str ) +{ + str.detach(); + TQ_UINT32 len; + s >> len; // read size of string + if ( len == 0 || s.eof() ) { // end of file reached + str.resize( 0 ); + return s; + } + if ( !str.TQByteArray::resize( (uint)len )) {// resize string +#if defined(QT_CHECK_NULL) + tqWarning( "TQDataStream: Not enough memory to read TQCString" ); +#endif + len = 0; + } + if ( len > 0 ) // not null array + s.readRawBytes( str.data(), (uint)len ); + return s; +} +#endif //TQT_NO_DATASTREAM + +/***************************************************************************** + Documentation for related functions + *****************************************************************************/ + +/*! + \fn bool operator==( const TQCString &s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) == 0. +*/ + +/*! + \overload bool operator==( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) == 0. +*/ + +/*! + \overload bool operator==( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 and \a s2 are equal; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) == 0. +*/ + +/*! + \fn bool operator!=( const TQCString &s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) != 0. +*/ + +/*! + \overload bool operator!=( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) != 0. +*/ + +/*! + \overload bool operator!=( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 and \a s2 are different; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) != 0. +*/ + +/*! + \fn bool operator<( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \< 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator<( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is less than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \< 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn bool operator<=( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is less than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \<= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator<=( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is less than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \<= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn bool operator>( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \> 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator>( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is greater than \a s2; otherwise returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \> 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn bool operator>=( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \>= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \overload bool operator>=( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns TRUE if \a s1 is greater than or equal to \a s2; otherwise + returns FALSE. + + Equivalent to qstrcmp(\a s1, \a s2) \>= 0. + + \sa \link #asciinotion Note on character comparisons \endlink +*/ + +/*! + \fn const TQCString operator+( const TQCString &s1, const TQCString &s2 ) + + \relates TQCString + + Returns a string which consists of the concatenation of \a s1 and + \a s2. +*/ + +/*! + \overload const TQCString operator+( const TQCString &s1, const char *s2 ) + + \relates TQCString + + Returns a string which consists of the concatenation of \a s1 and \a s2. +*/ + +/*! + \overload const TQCString operator+( const char *s1, const TQCString &s2 ) + + \relates TQCString + + Returns a string which consists of the concatenation of \a s1 and \a s2. +*/ + +/*! + \overload const TQCString operator+( const TQCString &s, char c ) + + \relates TQCString + + Returns a string which consists of the concatenation of \a s and \a c. +*/ + +/*! + \overload const TQCString operator+( char c, const TQCString &s ) + + \relates TQCString + + Returns a string which consists of the concatenation of \a c and \a s. +*/ diff --git a/src/tools/tqcstring.h b/src/tools/tqcstring.h new file mode 100644 index 000000000..3d989ff52 --- /dev/null +++ b/src/tools/tqcstring.h @@ -0,0 +1,382 @@ +/**************************************************************************** +** +** Definition of the extended char array operations, +** and TQByteArray and TQCString classes +** +** Created : 920609 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQCSTRING_H +#define TQCSTRING_H + +#ifndef QT_H +#include "tqmemarray.h" +#endif // QT_H + +#include + + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +TQ_EXPORT void *tqmemmove( void *dst, const void *src, uint len ); + +TQ_EXPORT char *tqstrdup( const char * ); + +TQ_EXPORT inline uint tqstrlen( const char *str ) +{ return str ? (uint)strlen(str) : 0u; } + +TQ_EXPORT inline char *qstrcpy( char *dst, const char *src ) +{ return src ? strcpy(dst, src) : 0; } + +TQ_EXPORT char *tqstrncpy( char *dst, const char *src, uint len ); + +TQ_EXPORT inline int qstrcmp( const char *str1, const char *str2 ) +{ + return ( str1 && str2 ) ? strcmp( str1, str2 ) + : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); +} + +TQ_EXPORT inline int tqstrncmp( const char *str1, const char *str2, uint len ) +{ + return ( str1 && str2 ) ? strncmp( str1, str2, len ) + : ( str1 ? 1 : ( str2 ? -1 : 0 ) ); +} + +TQ_EXPORT int tqstricmp( const char *, const char * ); + +TQ_EXPORT int tqstrnicmp( const char *, const char *, uint len ); + + +// tqChecksum: Internet checksum + +TQ_EXPORT TQ_UINT16 tqChecksum( const char *s, uint len ); + +/***************************************************************************** + TQByteArray class + *****************************************************************************/ + +#if defined(Q_QDOC) +/* + We want qdoc to document TQByteArray as a real class that inherits + TQMemArray and that is inherited by TQBitArray. +*/ +class TQByteArray : public TQMemArray +{ +public: + TQByteArray(); + TQByteArray( int size ); +}; +#else +typedef TQMemArray TQByteArray; +#endif + +#ifndef TQT_NO_COMPRESS +TQ_EXPORT TQByteArray tqCompress( const uchar* data, int nbytes ); +TQ_EXPORT TQByteArray tqUncompress( const uchar* data, int nbytes ); +TQ_EXPORT inline TQByteArray tqCompress( const TQByteArray& data) +{ return tqCompress( (const uchar*)data.data(), data.size() ); } +TQ_EXPORT inline TQByteArray tqUncompress( const TQByteArray& data ) +{ return tqUncompress( (const uchar*)data.data(), data.size() ); } +#endif + +/***************************************************************************** + TQByteArray stream functions + *****************************************************************************/ +#ifndef TQT_NO_DATASTREAM +TQ_EXPORT TQDataStream &operator<<( TQDataStream &, const TQByteArray & ); +TQ_EXPORT TQDataStream &operator>>( TQDataStream &, TQByteArray & ); +#endif + +/***************************************************************************** + TQCString class + *****************************************************************************/ + +class TQRegExp; + +class TQ_EXPORT TQCString : public TQByteArray // C string class +{ +public: + TQCString() {} // make null string + TQCString( int size ); // allocate size incl. \0 + TQCString( const TQCString &s ) : TQByteArray( s ) {} + TQCString( const char *str ); // deep copy + TQCString( const char *str, uint maxlen ); // deep copy, max length + ~TQCString(); + + TQCString &operator=( const TQCString &s );// shallow copy + TQCString &operator=( const char *str ); // deep copy + + bool isNull() const; + bool isEmpty() const; + uint length() const; + bool resize( uint newlen ); + bool truncate( uint pos ); + bool fill( char c, int len = -1 ); + + TQCString copy() const; + + TQCString &sprintf( const char *format, ... ) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + + int find( char c, int index=0, bool cs=TRUE ) const; + int find( const char *str, int index=0, bool cs=TRUE ) const; +#ifndef TQT_NO_REGEXP + int find( const TQRegExp &, int index=0 ) const; +#endif + int findRev( char c, int index=-1, bool cs=TRUE) const; + int findRev( const char *str, int index=-1, bool cs=TRUE) const; +#ifndef TQT_NO_REGEXP_CAPTURE + int findRev( const TQRegExp &, int index=-1 ) const; +#endif + int contains( char c, bool cs=TRUE ) const; + int contains( const char *str, bool cs=TRUE ) const; +#ifndef TQT_NO_REGEXP + int contains( const TQRegExp & ) const; +#endif + TQCString left( uint len ) const; + TQCString right( uint len ) const; + TQCString mid( uint index, uint len=0xffffffff) const; + + TQCString leftJustify( uint width, char fill=' ', bool trunc=FALSE)const; + TQCString rightJustify( uint width, char fill=' ',bool trunc=FALSE)const; + + TQCString lower() const; + TQCString upper() const; + + TQCString stripWhiteSpace() const; + TQCString simplifyWhiteSpace() const; + + TQCString &insert( uint index, const char * ); + TQCString &insert( uint index, char ); + TQCString &append( const char * ); + TQCString &prepend( const char * ); + TQCString &remove( uint index, uint len ); + TQCString &replace( uint index, uint len, const char * ); +#ifndef TQT_NO_REGEXP + TQCString &replace( const TQRegExp &, const char * ); +#endif + TQCString &replace( char c, const char *after ); + TQCString &replace( const char *, const char * ); + TQCString &replace( char, char ); + + short toShort( bool *ok=0 ) const; + ushort toUShort( bool *ok=0 ) const; + int toInt( bool *ok=0 ) const; + uint toUInt( bool *ok=0 ) const; + long toLong( bool *ok=0 ) const; + ulong toULong( bool *ok=0 ) const; + float toFloat( bool *ok=0 ) const; + double toDouble( bool *ok=0 ) const; + + TQCString &setStr( const char *s ); + TQCString &setNum( short ); + TQCString &setNum( ushort ); + TQCString &setNum( int ); + TQCString &setNum( uint ); + TQCString &setNum( long ); + TQCString &setNum( ulong ); + TQCString &setNum( float, char f='g', int prec=6 ); + TQCString &setNum( double, char f='g', int prec=6 ); + + bool setExpand( uint index, char c ); + + operator const char *() const; + TQCString &operator+=( const char *str ); + TQCString &operator+=( char c ); +private: + int find( const char *str, int index, bool cs, uint l ) const; +}; + + +/***************************************************************************** + TQCString stream functions + *****************************************************************************/ +#ifndef TQT_NO_DATASTREAM +TQ_EXPORT TQDataStream &operator<<( TQDataStream &, const TQCString & ); +TQ_EXPORT TQDataStream &operator>>( TQDataStream &, TQCString & ); +#endif + +/***************************************************************************** + TQCString inline functions + *****************************************************************************/ + +inline TQCString &TQCString::operator=( const TQCString &s ) +{ return (TQCString&)assign( s ); } + +inline TQCString &TQCString::operator=( const char *str ) +{ return (TQCString&)duplicate( str, tqstrlen(str)+1 ); } + +inline bool TQCString::isNull() const +{ return data() == 0; } + +inline bool TQCString::isEmpty() const +{ return data() == 0 || *data() == '\0'; } + +inline uint TQCString::length() const +{ return tqstrlen( data() ); } + +inline bool TQCString::truncate( uint pos ) +{ return resize(pos+1); } + +inline TQCString TQCString::copy() const +{ return TQCString( data() ); } + +inline TQCString &TQCString::prepend( const char *s ) +{ return insert(0,s); } + +inline TQCString &TQCString::append( const char *s ) +{ return operator+=(s); } + +inline TQCString &TQCString::setNum( short n ) +{ return setNum((long)n); } + +inline TQCString &TQCString::setNum( ushort n ) +{ return setNum((ulong)n); } + +inline TQCString &TQCString::setNum( int n ) +{ return setNum((long)n); } + +inline TQCString &TQCString::setNum( uint n ) +{ return setNum((ulong)n); } + +inline TQCString &TQCString::setNum( float n, char f, int prec ) +{ return setNum((double)n,f,prec); } + +inline TQCString::operator const char *() const +{ return (const char *)data(); } + + +/***************************************************************************** + TQCString non-member operators + *****************************************************************************/ + +TQ_EXPORT inline bool operator==( const TQCString &s1, const TQCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) == 0; } + +TQ_EXPORT inline bool operator==( const TQCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) == 0; } + +TQ_EXPORT inline bool operator==( const char *s1, const TQCString &s2 ) +{ return qstrcmp( s1, s2.data() ) == 0; } + +TQ_EXPORT inline bool operator!=( const TQCString &s1, const TQCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) != 0; } + +TQ_EXPORT inline bool operator!=( const TQCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) != 0; } + +TQ_EXPORT inline bool operator!=( const char *s1, const TQCString &s2 ) +{ return qstrcmp( s1, s2.data() ) != 0; } + +TQ_EXPORT inline bool operator<( const TQCString &s1, const TQCString& s2 ) +{ return qstrcmp( s1.data(), s2.data() ) < 0; } + +TQ_EXPORT inline bool operator<( const TQCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) < 0; } + +TQ_EXPORT inline bool operator<( const char *s1, const TQCString &s2 ) +{ return qstrcmp( s1, s2.data() ) < 0; } + +TQ_EXPORT inline bool operator<=( const TQCString &s1, const TQCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) <= 0; } + +TQ_EXPORT inline bool operator<=( const TQCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) <= 0; } + +TQ_EXPORT inline bool operator<=( const char *s1, const TQCString &s2 ) +{ return qstrcmp( s1, s2.data() ) <= 0; } + +TQ_EXPORT inline bool operator>( const TQCString &s1, const TQCString &s2 ) +{ return qstrcmp( s1.data(), s2.data() ) > 0; } + +TQ_EXPORT inline bool operator>( const TQCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) > 0; } + +TQ_EXPORT inline bool operator>( const char *s1, const TQCString &s2 ) +{ return qstrcmp( s1, s2.data() ) > 0; } + +TQ_EXPORT inline bool operator>=( const TQCString &s1, const TQCString& s2 ) +{ return qstrcmp( s1.data(), s2.data() ) >= 0; } + +TQ_EXPORT inline bool operator>=( const TQCString &s1, const char *s2 ) +{ return qstrcmp( s1.data(), s2 ) >= 0; } + +TQ_EXPORT inline bool operator>=( const char *s1, const TQCString &s2 ) +{ return qstrcmp( s1, s2.data() ) >= 0; } + +TQ_EXPORT inline const TQCString operator+( const TQCString &s1, + const TQCString &s2 ) +{ + TQCString tmp( s1.data() ); + tmp += s2; + return tmp; +} + +TQ_EXPORT inline const TQCString operator+( const TQCString &s1, const char *s2 ) +{ + TQCString tmp( s1.data() ); + tmp += s2; + return tmp; +} + +TQ_EXPORT inline const TQCString operator+( const char *s1, const TQCString &s2 ) +{ + TQCString tmp( s1 ); + tmp += s2; + return tmp; +} + +TQ_EXPORT inline const TQCString operator+( const TQCString &s1, char c2 ) +{ + TQCString tmp( s1.data() ); + tmp += c2; + return tmp; +} + +TQ_EXPORT inline const TQCString operator+( char c1, const TQCString &s2 ) +{ + TQCString tmp; + tmp += c1; + tmp += s2; + return tmp; +} +#include "ntqwinexport.h" +#endif // TQCSTRING_H diff --git a/src/tools/tqdatetime.cpp b/src/tools/tqdatetime.cpp index d6f212a12..5253fa50e 100644 --- a/src/tools/tqdatetime.cpp +++ b/src/tools/tqdatetime.cpp @@ -42,7 +42,7 @@ #include "tqdatetime.h" #include "ntqdatastream.h" -#include "ntqregexp.h" +#include "tqregexp.h" #include #ifndef Q_OS_TEMP diff --git a/src/tools/tqdeepcopy.cpp b/src/tools/tqdeepcopy.cpp new file mode 100644 index 000000000..28b3741d0 --- /dev/null +++ b/src/tools/tqdeepcopy.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Implementation of TQDeepCopy class +** +** Created : 20020613 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel 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 requirements 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. +** +**********************************************************************/ + +#include "tqdeepcopy.h" + +/*! + \class TQDeepCopy tqdeepcopy.h + \brief The TQDeepCopy class is a template class which ensures that + implicitly shared and explicitly shared classes reference unique + data. + + \reentrant + + \ingroup tools + \ingroup shared + + Normally, shared copies reference the same data to optimize memory + use and for maximum speed. In the example below, \c s1, \c s2, \c + s3, \c s4 and \c s5 share data. + + \code + // all 5 strings share the same data + TQString s1 = "abcd"; + TQString s2 = s1; + TQString s3 = s2; + TQString s4 = s3; + TQString s5 = s2; + \endcode + + TQDeepCopy can be used several ways to ensure that an object + references unique, unshared data. In the example below, \c s1, \c + s2 and \c s5 share data, while neither \c s3 nor \c s4 share data. + \code + // s1, s2 and s5 share the same data, neither s3 nor s4 are shared + TQString s1 = "abcd"; + TQString s2 = s1; + TQDeepCopy s3 = s2; // s3 is a deep copy of s2 + TQString s4 = s3; // s4 is a deep copy of s3 + TQString s5 = s2; + \endcode + + In the example below, \c s1, \c s2 and \c s5 share data, and \c s3 + and \c s4 share data. + \code + // s1, s2 and s5 share the same data, s3 and s4 share the same data + TQString s1 = "abcd"; + TQString s2 = s1; + TQString s3 = TQDeepCopy( s2 ); // s3 is a deep copy of s2 + TQString s4 = s3; // s4 is a shallow copy of s3 + TQString s5 = s2; + \endcode + + TQDeepCopy can also provide safety in multithreaded applications + that use shared classes. In the example below, the variable \c + global_string is used safely since the data contained in \c + global_string is always a deep copy. This ensures that all threads + get a unique copy of the data, and that any assignments to \c + global_string will result in a deep copy. + + \code + TQDeepCopy global_string; // global string data + TQMutex global_mutex; // mutex to protext global_string + + ... + + void setGlobalString( const TQString &str ) + { + global_mutex.lock(); + global_string = str; // global_string is a deep copy of str + global_mutex.unlock(); + } + + ... + + void MyThread::run() + { + global_mutex.lock(); + TQString str = global_string; // str is a deep copy of global_string + global_mutex.unlock(); + + // process the string data + ... + + // update global_string + setGlobalString( str ); + } + \endcode + + \warning It is the application developer's responsibility to + protect the object shared across multiple threads. + + The examples above use TQString, which is an implicitly shared + class. The behavior of TQDeepCopy is the same when using explicitly + shared classes like TQByteArray. + + Currently, TQDeepCopy works with the following classes: + \list + \i TQMemArray (including subclasses like TQByteArray and TQCString) + \i TQMap + \i TQString + \i TQValueList (including subclasses like TQStringList and TQValueStack) + \i TQValueVector + \endlist + + \sa \link threads.html Thread Support in TQt \endlink +*/ + +/*! + \fn TQDeepCopy::TQDeepCopy() + + Constructs an empty instance of type \e T. +*/ + +/*! + \fn TQDeepCopy::TQDeepCopy( const T &t ) + + Constructs a deep copy of \a t. +*/ + +/*! + \fn TQDeepCopy& TQDeepCopy::operator=( const T &t ) + + Assigns a deep copy of \a t. +*/ + +/*! + \fn TQDeepCopy::operator T () + + Returns a deep copy of the encapsulated data. +*/ + diff --git a/src/tools/tqdeepcopy.h b/src/tools/tqdeepcopy.h new file mode 100644 index 000000000..abe1fc8f1 --- /dev/null +++ b/src/tools/tqdeepcopy.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Definition of TQDeepCopy class +** +** Created : 20020613 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the kernel 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQDEEPCOPY_H +#define TQDEEPCOPY_H + +#ifndef QT_H +# include "ntqglobal.h" +#endif // QT_H + +template +class TQDeepCopy +{ +public: + inline TQDeepCopy() + { + } + + inline TQDeepCopy( const T &t ) + : deepcopy( t ) + { + deepcopy.detach(); + } + + inline TQDeepCopy &operator=( const T &t ) + { + deepcopy = t; + deepcopy.detach(); + return *this; + } + + inline operator T () + { + T tmp = deepcopy; + tmp.detach(); + return tmp; + } + +private: + T deepcopy; +}; + +#endif // TQDEEPCOPY_H diff --git a/src/tools/tqdict.h b/src/tools/tqdict.h new file mode 100644 index 000000000..d363538d0 --- /dev/null +++ b/src/tools/tqdict.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Definition of TQDict template class +** +** Created : 920821 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQDICT_H +#define TQDICT_H + +#ifndef QT_H +#include "ntqgdict.h" +#endif // QT_H + +template +class TQDict +#ifdef Q_QDOC + : public TQPtrCollection +#else + : public TQGDict +#endif +{ +public: + TQDict( int size = 17, bool caseSensitive = TRUE ) + : TQGDict( size, StringKey, caseSensitive, FALSE ) { } + TQDict( const TQDict &d ) : TQGDict( d ) { } + ~TQDict() { clear(); } + TQDict &operator=(const TQDict &d) + { return (TQDict&)TQGDict::operator=(d); } + uint count() const { return TQGDict::count(); } + uint size() const { return TQGDict::size(); } + bool isEmpty() const { return TQGDict::count() == 0; } + + void insert( const TQString &k, const type *d ) + { TQGDict::look_string(k,(Item)d,1); } + void replace( const TQString &k, const type *d ) + { TQGDict::look_string(k,(Item)d,2); } + bool remove( const TQString &k ) { return TQGDict::remove_string(k); } + type *take( const TQString &k ) { return (type *)TQGDict::take_string(k); } + type *find( const TQString &k ) const + { return (type *)((TQGDict*)this)->TQGDict::look_string(k,0,0); } + type *operator[]( const TQString &k ) const + { return (type *)((TQGDict*)this)->TQGDict::look_string(k,0,0); } + + void clear() { TQGDict::clear(); } + void resize( uint n ) { TQGDict::resize(n); } + void statistics() const { TQGDict::statistics(); } + +#ifdef Q_QDOC +protected: + virtual TQDataStream& read( TQDataStream &, TQPtrCollection::Item & ); + virtual TQDataStream& write( TQDataStream &, TQPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void TQDict::deleteItem( Item ) +{ +} +#endif + +template inline void TQDict::deleteItem( TQPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template +class TQDictIterator : public TQGDictIterator +{ +public: + TQDictIterator(const TQDict &d) : TQGDictIterator((TQGDict &)d) { } + ~TQDictIterator() {} + uint count() const { return dict->count(); } + bool isEmpty() const { return dict->count() == 0; } + type *toFirst() { return (type *)TQGDictIterator::toFirst(); } + operator type *() const { return (type *)TQGDictIterator::get(); } + type *operator*() { return (type *)TQGDictIterator::get(); } + type *current() const { return (type *)TQGDictIterator::get(); } + TQString currentKey() const{ return TQGDictIterator::getKeyString(); } + type *operator()() { return (type *)TQGDictIterator::operator()(); } + type *operator++() { return (type *)TQGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)TQGDictIterator::operator+=(j); } +}; + +#define Q_DEFINED_QDICT +#include "ntqwinexport.h" +#endif // TQDICT_H diff --git a/src/tools/tqintcache.h b/src/tools/tqintcache.h new file mode 100644 index 000000000..116618058 --- /dev/null +++ b/src/tools/tqintcache.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Definition of TQIntCache template class +** +** Created : 950209 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQINTCACHE_H +#define TQINTCACHE_H + +#ifndef QT_H +#include "ntqgcache.h" +#endif // QT_H + + +template +class TQIntCache +#ifdef Q_QDOC + : public TQPtrCollection +#else + : public TQGCache +#endif +{ +public: + TQIntCache( const TQIntCache &c ) : TQGCache(c) {} + TQIntCache( int maxCost=100, int size=17 ) + : TQGCache( maxCost, size, IntKey, FALSE, FALSE ) {} + ~TQIntCache() { clear(); } + TQIntCache &operator=( const TQIntCache &c ) + { return (TQIntCache&)TQGCache::operator=(c); } + int maxCost() const { return TQGCache::maxCost(); } + int totalCost() const { return TQGCache::totalCost(); } + void setMaxCost( int m) { TQGCache::setMaxCost(m); } + uint count() const { return TQGCache::count(); } + uint size() const { return TQGCache::size(); } + bool isEmpty() const { return TQGCache::count() == 0; } + bool insert( long k, const type *d, int c=1, int p=0 ) + { return TQGCache::insert_other((const char*)k,(Item)d,c,p); } + bool remove( long k ) + { return TQGCache::remove_other((const char*)k); } + type *take( long k ) + { return (type *)TQGCache::take_other((const char*)k);} + void clear() { TQGCache::clear(); } + type *find( long k, bool ref=TRUE ) const + { return (type *)TQGCache::find_other( (const char*)k,ref);} + type *operator[]( long k ) const + { return (type *)TQGCache::find_other( (const char*)k); } + void statistics() const { TQGCache::statistics(); } +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void TQIntCache::deleteItem( TQPtrCollection::Item ) +{ +} +#endif + +template inline void TQIntCache::deleteItem( TQPtrCollection::Item d ) +{ + if ( del_item ) delete (type *)d; +} + +template +class TQIntCacheIterator : public TQGCacheIterator +{ +public: + TQIntCacheIterator( const TQIntCache &c ) + : TQGCacheIterator( (TQGCache &)c ) {} + TQIntCacheIterator( const TQIntCacheIterator &ci ) + : TQGCacheIterator((TQGCacheIterator &)ci) {} + TQIntCacheIterator &operator=( const TQIntCacheIterator&ci ) + { return ( TQIntCacheIterator&)TQGCacheIterator::operator=( ci );} + uint count() const { return TQGCacheIterator::count(); } + bool isEmpty() const { return TQGCacheIterator::count() == 0; } + bool atFirst() const { return TQGCacheIterator::atFirst(); } + bool atLast() const { return TQGCacheIterator::atLast(); } + type *toFirst() { return (type *)TQGCacheIterator::toFirst(); } + type *toLast() { return (type *)TQGCacheIterator::toLast(); } + operator type *() const { return (type *)TQGCacheIterator::get(); } + type *current() const { return (type *)TQGCacheIterator::get(); } + long currentKey() const { return (long)TQGCacheIterator::getKeyInt();} + type *operator()() { return (type *)TQGCacheIterator::operator()();} + type *operator++() { return (type *)TQGCacheIterator::operator++(); } + type *operator+=(uint j) { return (type *)TQGCacheIterator::operator+=(j);} + type *operator--() { return (type *)TQGCacheIterator::operator--(); } + type *operator-=(uint j) { return (type *)TQGCacheIterator::operator-=(j);} +}; + + +#endif // TQINTCACHE_H diff --git a/src/tools/tqintdict.h b/src/tools/tqintdict.h new file mode 100644 index 000000000..162625855 --- /dev/null +++ b/src/tools/tqintdict.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Definition of TQIntDict template class +** +** Created : 940624 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQINTDICT_H +#define TQINTDICT_H + +#ifndef QT_H +#include "ntqgdict.h" +#endif // QT_H + +template +class TQIntDict +#ifdef Q_QDOC + : public TQPtrCollection +#else + : public TQGDict +#endif +{ +public: + TQIntDict(int size=17) : TQGDict(size,IntKey,0,0) {} + TQIntDict( const TQIntDict &d ) : TQGDict(d) {} + ~TQIntDict() { clear(); } + TQIntDict &operator=(const TQIntDict &d) + { return (TQIntDict&)TQGDict::operator=(d); } + uint count() const { return TQGDict::count(); } + uint size() const { return TQGDict::size(); } + bool isEmpty() const { return TQGDict::count() == 0; } + void insert( long k, const type *d ) + { TQGDict::look_int(k,(Item)d,1); } + void replace( long k, const type *d ) + { TQGDict::look_int(k,(Item)d,2); } + bool remove( long k ) { return TQGDict::remove_int(k); } + type *take( long k ) { return (type*)TQGDict::take_int(k); } + type *find( long k ) const + { return (type *)((TQGDict*)this)->TQGDict::look_int(k,0,0); } + type *operator[]( long k ) const + { return (type *)((TQGDict*)this)->TQGDict::look_int(k,0,0); } + void clear() { TQGDict::clear(); } + void resize( uint n ) { TQGDict::resize(n); } + void statistics() const { TQGDict::statistics(); } + +#ifdef Q_QDOC +protected: + virtual TQDataStream& read( TQDataStream &, TQPtrCollection::Item & ); + virtual TQDataStream& write( TQDataStream &, TQPtrCollection::Item ) const; +#endif + +private: + void deleteItem( Item d ); +}; + +#if !defined(Q_BROKEN_TEMPLATE_SPECIALIZATION) +template<> inline void TQIntDict::deleteItem( TQPtrCollection::Item ) +{ +} +#endif + +template inline void TQIntDict::deleteItem( TQPtrCollection::Item d ) +{ + if ( del_item ) delete (type*)d; +} + +template +class TQIntDictIterator : public TQGDictIterator +{ +public: + TQIntDictIterator(const TQIntDict &d) :TQGDictIterator((TQGDict &)d) {} + ~TQIntDictIterator() {} + uint count() const { return dict->count(); } + bool isEmpty() const { return dict->count() == 0; } + type *toFirst() { return (type *)TQGDictIterator::toFirst(); } + operator type *() const { return (type *)TQGDictIterator::get(); } + type *current() const { return (type *)TQGDictIterator::get(); } + long currentKey() const { return TQGDictIterator::getKeyInt(); } + type *operator()() { return (type *)TQGDictIterator::operator()(); } + type *operator++() { return (type *)TQGDictIterator::operator++(); } + type *operator+=(uint j) { return (type *)TQGDictIterator::operator+=(j);} +}; + +#define Q_DEFINED_QINTDICT +#include "ntqwinexport.h" +#endif // TQINTDICT_H diff --git a/src/tools/tqmemarray.h b/src/tools/tqmemarray.h new file mode 100644 index 000000000..8a07bf9a9 --- /dev/null +++ b/src/tools/tqmemarray.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Definition of TQMemArray template/macro class +** +** Created : 930906 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQMEMARRAY_H +#define TQMEMARRAY_H + +#ifndef QT_H +#include "ntqgarray.h" +#endif // QT_H + + +template +class TQMemArray : public TQGArray +{ +public: + typedef type* Iterator; + typedef const type* ConstIterator; + typedef type ValueType; + +protected: + TQMemArray( int, int ) : TQGArray( 0, 0 ) {} + +public: + TQMemArray() {} + TQMemArray( int size ) : TQGArray(size*sizeof(type)) {} // ### 4.0 Q_EXPLICIT + TQMemArray( const TQMemArray &a ) : TQGArray(a) {} + ~TQMemArray() {} + TQMemArray &operator=(const TQMemArray &a) + { return (TQMemArray&)TQGArray::assign(a); } + type *data() const { return (type *)TQGArray::data(); } + uint nrefs() const { return TQGArray::nrefs(); } + uint size() const { return TQGArray::size()/sizeof(type); } + uint count() const { return size(); } + bool isEmpty() const { return TQGArray::size() == 0; } + bool isNull() const { return TQGArray::data() == 0; } + bool resize( uint size ) { return TQGArray::resize(size*sizeof(type)); } + bool resize( uint size, Optimization optim ) { return TQGArray::resize(size*sizeof(type), optim); } + bool truncate( uint pos ) { return TQGArray::resize(pos*sizeof(type)); } + bool fill( const type &d, int size = -1 ) + { return TQGArray::fill((char*)&d,size,sizeof(type) ); } + void detach() { TQGArray::detach(); } + TQMemArray copy() const + { TQMemArray tmp; return tmp.duplicate(*this); } + TQMemArray& assign( const TQMemArray& a ) + { return (TQMemArray&)TQGArray::assign(a); } + TQMemArray& assign( const type *a, uint n ) + { return (TQMemArray&)TQGArray::assign((char*)a,n*sizeof(type)); } + TQMemArray& duplicate( const TQMemArray& a ) + { return (TQMemArray&)TQGArray::duplicate(a); } + TQMemArray& duplicate( const type *a, uint n ) + { return (TQMemArray&)TQGArray::duplicate((char*)a,n*sizeof(type)); } + TQMemArray& setRawData( const type *a, uint n ) + { return (TQMemArray&)TQGArray::setRawData((char*)a, + n*sizeof(type)); } + void resetRawData( const type *a, uint n ) + { TQGArray::resetRawData((char*)a,n*sizeof(type)); } + int find( const type &d, uint i=0 ) const + { return TQGArray::find((char*)&d,i,sizeof(type)); } + int contains( const type &d ) const + { return TQGArray::contains((char*)&d,sizeof(type)); } + void sort() { TQGArray::sort(sizeof(type)); } + int bsearch( const type &d ) const + { return TQGArray::bsearch((const char*)&d,sizeof(type)); } + // ### TQt 4.0: maybe provide uint overload as work-around for MSVC bug + type& operator[]( int i ) const + { return (type &)(*(type *)TQGArray::at(i*sizeof(type))); } + type& at( uint i ) const + { return (type &)(*(type *)TQGArray::at(i*sizeof(type))); } + operator const type*() const { return (const type *)TQGArray::data(); } + bool operator==( const TQMemArray &a ) const { return isEqual(a); } + bool operator!=( const TQMemArray &a ) const { return !isEqual(a); } + Iterator begin() { return data(); } + Iterator end() { return data() + size(); } + ConstIterator begin() const { return data(); } + ConstIterator end() const { return data() + size(); } +}; + +#define Q_DEFINED_QMEMARRAY +#include "ntqwinexport.h" +#endif diff --git a/src/tools/tqmutexpool_p.h b/src/tools/tqmutexpool_p.h index 28a7ac63a..9e388473e 100644 --- a/src/tools/tqmutexpool_p.h +++ b/src/tools/tqmutexpool_p.h @@ -55,7 +55,7 @@ #ifndef QT_H #include "tqmutex.h" -#include "ntqmemarray.h" +#include "tqmemarray.h" #endif // QT_H class TQ_EXPORT TQMutexPool diff --git a/src/tools/tqregexp.cpp b/src/tools/tqregexp.cpp new file mode 100644 index 000000000..19758f95c --- /dev/null +++ b/src/tools/tqregexp.cpp @@ -0,0 +1,3996 @@ +/**************************************************************************** +** +** Implementation of TQRegExp class +** +** Created : 950126 +** +** 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 requirements 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. +** +**********************************************************************/ + +#include "tqregexp.h" + +#ifndef TQT_NO_REGEXP + +#include "tqmemarray.h" +#include "tqbitarray.h" +#include "tqcache.h" +#include "ntqcleanuphandler.h" +#include "tqintdict.h" +#include "tqmap.h" +#include "tqptrvector.h" +#include "tqstring.h" +#include "ntqtl.h" + +#ifdef TQT_THREAD_SUPPORT +#include "tqthreadstorage.h" +#include +#endif // TQT_THREAD_SUPPORT + +#undef TQT_TRANSLATE_NOOP +#define TQT_TRANSLATE_NOOP( context, sourceText ) sourceText + +#include + +// error strings for the regexp parser +#define RXERR_OK TQT_TRANSLATE_NOOP( "TQRegExp", "no error occurred" ) +#define RXERR_DISABLED TQT_TRANSLATE_NOOP( "TQRegExp", "disabled feature used" ) +#define RXERR_CHARCLASS TQT_TRANSLATE_NOOP( "TQRegExp", "bad char class syntax" ) +#define RXERR_LOOKAHEAD TQT_TRANSLATE_NOOP( "TQRegExp", "bad lookahead syntax" ) +#define RXERR_REPETITION TQT_TRANSLATE_NOOP( "TQRegExp", "bad repetition syntax" ) +#define RXERR_OCTAL TQT_TRANSLATE_NOOP( "TQRegExp", "invalid octal value" ) +#define RXERR_LEFTDELIM TQT_TRANSLATE_NOOP( "TQRegExp", "missing left delim" ) +#define RXERR_END TQT_TRANSLATE_NOOP( "TQRegExp", "unexpected end" ) +#define RXERR_LIMIT TQT_TRANSLATE_NOOP( "TQRegExp", "met internal limit" ) + +/* + WARNING! Be sure to read tqregexp.tex before modifying this file. +*/ + +/*! + \class TQRegExp tqregexp.h + \reentrant + \brief The TQRegExp class provides pattern matching using regular expressions. + + \ingroup tools + \ingroup misc + \ingroup shared + \mainclass + \keyword regular expression + + Regular expressions, or "regexps", provide a way to find patterns + within text. This is useful in many contexts, for example: + + \table + \row \i Validation + \i A regexp can be used to check whether a piece of text + meets some criteria, e.g. is an integer or contains no + whitespace. + \row \i Searching + \i Regexps provide a much more powerful means of searching + text than simple string matching does. For example we can + create a regexp which says "find one of the words 'mail', + 'letter' or 'correspondence' but not any of the words + 'email', 'mailman' 'mailer', 'letterbox' etc." + \row \i Search and Replace + \i A regexp can be used to replace a pattern with a piece of + text, for example replace all occurrences of '&' with + '\&' except where the '&' is already followed by 'amp;'. + \row \i String Splitting + \i A regexp can be used to identify where a string should be + split into its component fields, e.g. splitting tab-delimited + strings. + \endtable + + We present a very brief introduction to regexps, a description of + TQt's regexp language, some code examples, and finally the function + documentation itself. TQRegExp is modeled on Perl's regexp + language, and also fully supports Unicode. TQRegExp can also be + used in the weaker 'wildcard' (globbing) mode which works in a + similar way to command shells. A good text on regexps is \e + {Mastering Regular Expressions: Powerful Techniques for Perl and + Other Tools} by Jeffrey E. Friedl, ISBN 1565922573. + + Experienced regexp users may prefer to skip the introduction and + go directly to the relevant information. + + In case of multi-threaded programming, note that TQRegExp depends on + TQThreadStorage internally. For that reason, TQRegExp should only be + used with threads started with TQThread, i.e. not with threads + started with platform-specific APIs. + + \tableofcontents + + \section1 Introduction + + Regexps are built up from expressions, quantifiers, and assertions. + The simplest form of expression is simply a character, e.g. + x or 5. An expression can also be a set of + characters. For example, [ABCD], will match an A or + a B or a C or a D. As a shorthand we could + write this as [A-D]. If we want to match any of the + captital letters in the English alphabet we can write + [A-Z]. A quantifier tells the regexp engine how many + occurrences of the expression we want, e.g. x{1,1} means + match an x which occurs at least once and at most once. + We'll look at assertions and more complex expressions later. + + Note that in general regexps cannot be used to check for balanced + brackets or tags. For example if you want to match an opening html + \c and its closing \c you can only use a regexp if you + know that these tags are not nested; the html fragment, \c{bold + bolder} will not match as expected. If you know the + maximum level of nesting it is possible to create a regexp that + will match correctly, but for an unknown level of nesting, regexps + will fail. + + We'll start by writing a regexp to match integers in the range 0 + to 99. We will require at least one digit so we will start with + [0-9]{1,1} which means match a digit exactly once. This + regexp alone will match integers in the range 0 to 9. To match one + or two digits we can increase the maximum number of occurrences so + the regexp becomes [0-9]{1,2} meaning match a digit at + least once and at most twice. However, this regexp as it stands + will not match correctly. This regexp will match one or two digits + \e within a string. To ensure that we match against the whole + string we must use the anchor assertions. We need ^ (caret) + which when it is the first character in the regexp means that the + regexp must match from the beginning of the string. And we also + need $ (dollar) which when it is the last character in the + regexp means that the regexp must match until the end of the + string. So now our regexp is ^[0-9]{1,2}$. Note that + assertions, such as ^ and $, do not match any + characters. + + If you've seen regexps elsewhere they may have looked different from + the ones above. This is because some sets of characters and some + quantifiers are so common that they have special symbols to + represent them. [0-9] can be replaced with the symbol + \d. The quantifier to match exactly one occurrence, + {1,1}, can be replaced with the expression itself. This means + that x{1,1} is exactly the same as x alone. So our 0 + to 99 matcher could be written ^\d{1,2}$. Another way of + writing it would be ^\d\d{0,1}$, i.e. from the start of the + string match a digit followed by zero or one digits. In practice + most people would write it ^\d\d?$. The ? is a + shorthand for the quantifier {0,1}, i.e. a minimum of no + occurrences a maximum of one occurrence. This is used to make an + expression optional. The regexp ^\d\d?$ means "from the + beginning of the string match one digit followed by zero or one + digits and then the end of the string". + + Our second example is matching the words 'mail', 'letter' or + 'correspondence' but without matching 'email', 'mailman', + 'mailer', 'letterbox' etc. We'll start by just matching 'mail'. In + full the regexp is, m{1,1}a{1,1}i{1,1}l{1,1}, but since + each expression itself is automatically quantified by {1,1} + we can simply write this as mail; an 'm' followed by an 'a' + followed by an 'i' followed by an 'l'. The symbol '|' (bar) is + used for \e alternation, so our regexp now becomes + mail|letter|correspondence which means match 'mail' \e or + 'letter' \e or 'correspondence'. Whilst this regexp will find the + words we want it will also find words we don't want such as + 'email'. We will start by putting our regexp in parentheses, + (mail|letter|correspondence). Parentheses have two effects, + firstly they group expressions together and secondly they identify + parts of the regexp that we wish to \link #capturing-text capture + \endlink. Our regexp still matches any of the three words but now + they are grouped together as a unit. This is useful for building + up more complex regexps. It is also useful because it allows us to + examine which of the words actually matched. We need to use + another assertion, this time \b "word boundary": + \b(mail|letter|correspondence)\b. This regexp means "match + a word boundary followed by the expression in parentheses followed + by another word boundary". The \b assertion matches at a \e + position in the regexp not a \e character in the regexp. A word + boundary is any non-word character such as a space a newline or + the beginning or end of the string. + + For our third example we want to replace ampersands with the HTML + entity '\&'. The regexp to match is simple: \&, i.e. + match one ampersand. Unfortunately this will mess up our text if + some of the ampersands have already been turned into HTML + entities. So what we really want to say is replace an ampersand + providing it is not followed by 'amp;'. For this we need the + negative lookahead assertion and our regexp becomes: + \&(?!amp;). The negative lookahead assertion is introduced + with '(?!' and finishes at the ')'. It means that the text it + contains, 'amp;' in our example, must \e not follow the expression + that preceeds it. + + Regexps provide a rich language that can be used in a variety of + ways. For example suppose we want to count all the occurrences of + 'Eric' and 'Eirik' in a string. Two valid regexps to match these + are \\b(Eric|Eirik)\\b and \\bEi?ri[ck]\\b. We need + the word boundary '\b' so we don't get 'Ericsson' etc. The second + regexp actually matches more than we want, 'Eric', 'Erik', 'Eiric' + and 'Eirik'. + + We will implement some the examples above in the + \link #code-examples code examples \endlink section. + + \target characters-and-abbreviations-for-sets-of-characters + \section1 Characters and Abbreviations for Sets of Characters + + \table + \header \i Element \i Meaning + \row \i c + \i Any character represents itself unless it has a special + regexp meaning. Thus c matches the character \e c. + \row \i \\c + \i A character that follows a backslash matches the character + itself except where mentioned below. For example if you + wished to match a literal caret at the beginning of a string + you would write \^. + \row \i \\a + \i This matches the ASCII bell character (BEL, 0x07). + \row \i \\f + \i This matches the ASCII form feed character (FF, 0x0C). + \row \i \\n + \i This matches the ASCII line feed character (LF, 0x0A, Unix newline). + \row \i \\r + \i This matches the ASCII carriage return character (CR, 0x0D). + \row \i \\t + \i This matches the ASCII horizontal tab character (HT, 0x09). + \row \i \\v + \i This matches the ASCII vertical tab character (VT, 0x0B). + \row \i \\xhhhh + \i This matches the Unicode character corresponding to the + hexadecimal number hhhh (between 0x0000 and 0xFFFF). \0ooo + (i.e., \zero ooo) matches the ASCII/Latin-1 character + corresponding to the octal number ooo (between 0 and 0377). + \row \i . (dot) + \i This matches any character (including newline). + \row \i \\d + \i This matches a digit (TQChar::isDigit()). + \row \i \\D + \i This matches a non-digit. + \row \i \\s + \i This matches a whitespace (TQChar::isSpace()). + \row \i \\S + \i This matches a non-whitespace. + \row \i \\w + \i This matches a word character (TQChar::isLetterOrNumber() or '_'). + \row \i \\W + \i This matches a non-word character. + \row \i \\n + \i The n-th \link #capturing-text backreference \endlink, + e.g. \1, \2, etc. + \endtable + + \e {Note that the C++ compiler transforms backslashes in strings + so to include a \\ in a regexp you will need to enter it + twice, i.e. \\\\.} + + \target sets-of-characters + \section1 Sets of Characters + + Square brackets are used to match any character in the set of + characters contained within the square brackets. All the character + set abbreviations described above can be used within square + brackets. Apart from the character set abbreviations and the + following two exceptions no characters have special meanings in + square brackets. + + \table + \row \i ^ + \i The caret negates the character set if it occurs as the + first character, i.e. immediately after the opening square + bracket. For example, [abc] matches 'a' or 'b' or 'c', + but [^abc] matches anything \e except 'a' or 'b' or + 'c'. + \row \i - + \i The dash is used to indicate a range of characters, for + example [W-Z] matches 'W' or 'X' or 'Y' or 'Z'. + \endtable + + Using the predefined character set abbreviations is more portable + than using character ranges across platforms and languages. For + example, [0-9] matches a digit in Western alphabets but + \d matches a digit in \e any alphabet. + + Note that in most regexp literature sets of characters are called + "character classes". + + \target quantifiers + \section1 Quantifiers + + By default an expression is automatically quantified by + {1,1}, i.e. it should occur exactly once. In the following + list \e {E} stands for any expression. An expression is a + character or an abbreviation for a set of characters or a set of + characters in square brackets or any parenthesised expression. + + \table + \row \i \e {E}? + \i Matches zero or one occurrence of \e E. This quantifier + means "the previous expression is optional" since it will + match whether or not the expression occurs in the string. It + is the same as \e {E}{0,1}. For example dents? + will match 'dent' and 'dents'. + + \row \i \e {E}+ + \i Matches one or more occurrences of \e E. This is the same + as \e {E}{1,MAXINT}. For example, 0+ will match + '0', '00', '000', etc. + + \row \i \e {E}* + \i Matches zero or more occurrences of \e E. This is the same + as \e {E}{0,MAXINT}. The * quantifier is often + used by a mistake. Since it matches \e zero or more + occurrences it will match no occurrences at all. For example + if we want to match strings that end in whitespace and use + the regexp \s*$ we would get a match on every string. + This is because we have said find zero or more whitespace + followed by the end of string, so even strings that don't end + in whitespace will match. The regexp we want in this case is + \s+$ to match strings that have at least one + whitespace at the end. + + \row \i \e {E}{n} + \i Matches exactly \e n occurrences of the expression. This + is the same as repeating the expression \e n times. For + example, x{5} is the same as xxxxx. It is also + the same as \e {E}{n,n}, e.g. x{5,5}. + + \row \i \e {E}{n,} + \i Matches at least \e n occurrences of the expression. This + is the same as \e {E}{n,MAXINT}. + + \row \i \e {E}{,m} + \i Matches at most \e m occurrences of the expression. This + is the same as \e {E}{0,m}. + + \row \i \e {E}{n,m} + \i Matches at least \e n occurrences of the expression and at + most \e m occurrences of the expression. + \endtable + + (MAXINT is implementation dependent but will not be smaller than + 1024.) + + If we wish to apply a quantifier to more than just the preceding + character we can use parentheses to group characters together in + an expression. For example, tag+ matches a 't' followed by + an 'a' followed by at least one 'g', whereas (tag)+ matches + at least one occurrence of 'tag'. + + Note that quantifiers are "greedy". They will match as much text + as they can. For example, 0+ will match as many zeros as it + can from the first zero it finds, e.g. '2.0005'. + Quantifiers can be made non-greedy, see setMinimal(). + + \target capturing-text + \section1 Capturing Text + + Parentheses allow us to group elements together so that we can + quantify and capture them. For example if we have the expression + mail|letter|correspondence that matches a string we know + that \e one of the words matched but not which one. Using + parentheses allows us to "capture" whatever is matched within + their bounds, so if we used (mail|letter|correspondence) + and matched this regexp against the string "I sent you some email" + we can use the cap() or capturedTexts() functions to extract the + matched characters, in this case 'mail'. + + We can use captured text within the regexp itself. To refer to the + captured text we use \e backreferences which are indexed from 1, + the same as for cap(). For example we could search for duplicate + words in a string using \b(\w+)\W+\1\b which means match a + word boundary followed by one or more word characters followed by + one or more non-word characters followed by the same text as the + first parenthesised expression followed by a word boundary. + + If we want to use parentheses purely for grouping and not for + capturing we can use the non-capturing syntax, e.g. + (?:green|blue). Non-capturing parentheses begin '(?:' and + end ')'. In this example we match either 'green' or 'blue' but we + do not capture the match so we only know whether or not we matched + but not which color we actually found. Using non-capturing + parentheses is more efficient than using capturing parentheses + since the regexp engine has to do less book-keeping. + + Both capturing and non-capturing parentheses may be nested. + + \target assertions + \section1 Assertions + + Assertions make some statement about the text at the point where + they occur in the regexp but they do not match any characters. In + the following list \e {E} stands for any expression. + + \table + \row \i ^ + \i The caret signifies the beginning of the string. If you + wish to match a literal \c{^} you must escape it by + writing \^. For example, ^#include will only + match strings which \e begin with the characters '#include'. + (When the caret is the first character of a character set it + has a special meaning, see \link #sets-of-characters Sets of + Characters \endlink.) + + \row \i $ + \i The dollar signifies the end of the string. For example + \d\s*$ will match strings which end with a digit + optionally followed by whitespace. If you wish to match a + literal \c{$} you must escape it by writing + \$. + + \row \i \\b + \i A word boundary. For example the regexp + \\bOK\\b means match immediately after a word + boundary (e.g. start of string or whitespace) the letter 'O' + then the letter 'K' immediately before another word boundary + (e.g. end of string or whitespace). But note that the + assertion does not actually match any whitespace so if we + write (\\bOK\\b) and we have a match it will only + contain 'OK' even if the string is "Its OK now". + + \row \i \\B + \i A non-word boundary. This assertion is true wherever + \\b is false. For example if we searched for + \\Bon\\B in "Left on" the match would fail (space + and end of string aren't non-word boundaries), but it would + match in "tonne". + + \row \i (?=\e E) + \i Positive lookahead. This assertion is true if the + expression matches at this point in the regexp. For example, + const(?=\\s+char) matches 'const' whenever it is + followed by 'char', as in 'static const char *'. + (Compare with const\\s+char, which matches 'static + const char *'.) + + \row \i (?!\e E) + \i Negative lookahead. This assertion is true if the + expression does not match at this point in the regexp. For + example, const(?!\\s+char) matches 'const' \e except + when it is followed by 'char'. + \endtable + + \target wildcard-matching + \section1 Wildcard Matching (globbing) + + Most command shells such as \e bash or \e cmd.exe support "file + globbing", the ability to identify a group of files by using + wildcards. The setWildcard() function is used to switch between + regexp and wildcard mode. Wildcard matching is much simpler than + full regexps and has only four features: + + \table + \row \i c + \i Any character represents itself apart from those mentioned + below. Thus c matches the character \e c. + \row \i ? + \i This matches any single character. It is the same as + . in full regexps. + \row \i * + \i This matches zero or more of any characters. It is the + same as .* in full regexps. + \row \i [...] + \i Sets of characters can be represented in square brackets, + similar to full regexps. Within the character class, like + outside, backslash has no special meaning. + \endtable + + For example if we are in wildcard mode and have strings which + contain filenames we could identify HTML files with *.html. + This will match zero or more characters followed by a dot followed + by 'h', 't', 'm' and 'l'. + + \target perl-users + \section1 Notes for Perl Users + + Most of the character class abbreviations supported by Perl are + supported by TQRegExp, see \link + #characters-and-abbreviations-for-sets-of-characters characters + and abbreviations for sets of characters \endlink. + + In TQRegExp, apart from within character classes, \c{^} always + signifies the start of the string, so carets must always be + escaped unless used for that purpose. In Perl the meaning of caret + varies automagically depending on where it occurs so escaping it + is rarely necessary. The same applies to \c{$} which in + TQRegExp always signifies the end of the string. + + TQRegExp's quantifiers are the same as Perl's greedy quantifiers. + Non-greedy matching cannot be applied to individual quantifiers, + but can be applied to all the quantifiers in the pattern. For + example, to match the Perl regexp ro+?m requires: + \code + TQRegExp rx( "ro+m" ); + rx.setMinimal( TRUE ); + \endcode + + The equivalent of Perl's \c{/i} option is + setCaseSensitive(FALSE). + + Perl's \c{/g} option can be emulated using a \link + #cap_in_a_loop loop \endlink. + + In TQRegExp . matches any character, therefore all TQRegExp + regexps have the equivalent of Perl's \c{/s} option. TQRegExp + does not have an equivalent to Perl's \c{/m} option, but this + can be emulated in various ways for example by splitting the input + into lines or by looping with a regexp that searches for newlines. + + Because TQRegExp is string oriented there are no \A, \Z or \z + assertions. The \G assertion is not supported but can be emulated + in a loop. + + Perl's $& is cap(0) or capturedTexts()[0]. There are no TQRegExp + equivalents for $`, $' or $+. Perl's capturing variables, $1, $2, + ... correspond to cap(1) or capturedTexts()[1], cap(2) or + capturedTexts()[2], etc. + + To substitute a pattern use TQString::replace(). + + Perl's extended \c{/x} syntax is not supported, nor are + directives, e.g. (?i), or regexp comments, e.g. (?#comment). On + the other hand, C++'s rules for literal strings can be used to + achieve the same: + \code + TQRegExp mark( "\\b" // word boundary + "[Mm]ark" // the word we want to match + ); + \endcode + + Both zero-width positive and zero-width negative lookahead + assertions (?=pattern) and (?!pattern) are supported with the same + syntax as Perl. Perl's lookbehind assertions, "independent" + subexpressions and conditional expressions are not supported. + + Non-capturing parentheses are also supported, with the same + (?:pattern) syntax. + + See TQStringList::split() and TQStringList::join() for equivalents + to Perl's split and join functions. + + Note: because C++ transforms \\'s they must be written \e twice in + code, e.g. \\b must be written \\\\b. + + \target code-examples + \section1 Code Examples + + \code + TQRegExp rx( "^\\d\\d?$" ); // match integers 0 to 99 + rx.search( "123" ); // returns -1 (no match) + rx.search( "-6" ); // returns -1 (no match) + rx.search( "6" ); // returns 0 (matched as position 0) + \endcode + + The third string matches '6'. This is a simple validation + regexp for integers in the range 0 to 99. + + \code + TQRegExp rx( "^\\S+$" ); // match strings without whitespace + rx.search( "Hello world" ); // returns -1 (no match) + rx.search( "This_is-OK" ); // returns 0 (matched at position 0) + \endcode + + The second string matches 'This_is-OK'. We've used the + character set abbreviation '\S' (non-whitespace) and the anchors + to match strings which contain no whitespace. + + In the following example we match strings containing 'mail' or + 'letter' or 'correspondence' but only match whole words i.e. not + 'email' + + \code + TQRegExp rx( "\\b(mail|letter|correspondence)\\b" ); + rx.search( "I sent you an email" ); // returns -1 (no match) + rx.search( "Please write the letter" ); // returns 17 + \endcode + + The second string matches "Please write the letter". The + word 'letter' is also captured (because of the parentheses). We + can see what text we've captured like this: + + \code + TQString captured = rx.cap( 1 ); // captured == "letter" + \endcode + + This will capture the text from the first set of capturing + parentheses (counting capturing left parentheses from left to + right). The parentheses are counted from 1 since cap( 0 ) is the + whole matched regexp (equivalent to '&' in most regexp engines). + + \code + TQRegExp rx( "&(?!amp;)" ); // match ampersands but not & + TQString line1 = "This & that"; + line1.replace( rx, "&" ); + // line1 == "This & that" + TQString line2 = "His & hers & theirs"; + line2.replace( rx, "&" ); + // line2 == "His & hers & theirs" + \endcode + + Here we've passed the TQRegExp to TQString's replace() function to + replace the matched text with new text. + + \code + TQString str = "One Eric another Eirik, and an Ericsson." + " How many Eiriks, Eric?"; + TQRegExp rx( "\\b(Eric|Eirik)\\b" ); // match Eric or Eirik + int pos = 0; // where we are in the string + int count = 0; // how many Eric and Eirik's we've counted + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + if ( pos >= 0 ) { + pos++; // move along in str + count++; // count our Eric or Eirik + } + } + \endcode + + We've used the search() function to repeatedly match the regexp in + the string. Note that instead of moving forward by one character + at a time \c pos++ we could have written \c {pos += + rx.matchedLength()} to skip over the already matched string. The + count will equal 3, matching 'One Eric another + Eirik, and an Ericsson. How many Eiriks, Eric?'; it + doesn't match 'Ericsson' or 'Eiriks' because they are not bounded + by non-word boundaries. + + One common use of regexps is to split lines of delimited data into + their component fields. + + \code + str = "Trolltech AS\twww.trolltech.com\tNorway"; + TQString company, web, country; + rx.setPattern( "^([^\t]+)\t([^\t]+)\t([^\t]+)$" ); + if ( rx.search( str ) != -1 ) { + company = rx.cap( 1 ); + web = rx.cap( 2 ); + country = rx.cap( 3 ); + } + \endcode + + In this example our input lines have the format company name, web + address and country. Unfortunately the regexp is rather long and + not very versatile -- the code will break if we add any more + fields. A simpler and better solution is to look for the + separator, '\t' in this case, and take the surrounding text. The + TQStringList split() function can take a separator string or regexp + as an argument and split a string accordingly. + + \code + TQStringList field = TQStringList::split( "\t", str ); + \endcode + + Here field[0] is the company, field[1] the web address and so on. + + To imitate the matching of a shell we can use wildcard mode. + + \code + TQRegExp rx( "*.html" ); // invalid regexp: * doesn't quantify anything + rx.setWildcard( TRUE ); // now it's a valid wildcard regexp + rx.exactMatch( "index.html" ); // returns TRUE + rx.exactMatch( "default.htm" ); // returns FALSE + rx.exactMatch( "readme.txt" ); // returns FALSE + \endcode + + Wildcard matching can be convenient because of its simplicity, but + any wildcard regexp can be defined using full regexps, e.g. + .*\.html$. Notice that we can't match both \c .html and \c + .htm files with a wildcard unless we use *.htm* which will + also match 'test.html.bak'. A full regexp gives us the precision + we need, .*\\.html?$. + + TQRegExp can match case insensitively using setCaseSensitive(), and + can use non-greedy matching, see setMinimal(). By default TQRegExp + uses full regexps but this can be changed with setWildcard(). + Searching can be forward with search() or backward with + searchRev(). Captured text can be accessed using capturedTexts() + which returns a string list of all captured strings, or using + cap() which returns the captured string for the given index. The + pos() function takes a match index and returns the position in the + string where the match was made (or -1 if there was no match). + + \sa TQRegExpValidator TQString TQStringList + + \target member-function-documentation +*/ + +const int NumBadChars = 64; +#define BadChar( ch ) ( (ch).unicode() % NumBadChars ) + +const int NoOccurrence = INT_MAX; +const int EmptyCapture = INT_MAX; +const int InftyLen = INT_MAX; +const int InftyRep = 1025; +const int EOS = -1; + +static bool isWord( TQChar ch ) +{ + return ch.isLetterOrNumber() || ch == TQChar( '_' ); +} + +/* + Merges two TQMemArrays of ints and puts the result into the first + one. +*/ +static void mergeInto( TQMemArray *a, const TQMemArray& b ) +{ + int asize = a->size(); + int bsize = b.size(); + if ( asize == 0 ) { + *a = b.copy(); +#ifndef TQT_NO_REGEXP_OPTIM + } else if ( bsize == 1 && (*a)[asize - 1] < b[0] ) { + a->resize( asize + 1 ); + (*a)[asize] = b[0]; +#endif + } else if ( bsize >= 1 ) { + int csize = asize + bsize; + TQMemArray c( csize ); + int i = 0, j = 0, k = 0; + while ( i < asize ) { + if ( j < bsize ) { + if ( (*a)[i] == b[j] ) { + i++; + csize--; + } else if ( (*a)[i] < b[j] ) { + c[k++] = (*a)[i++]; + } else { + c[k++] = b[j++]; + } + } else { + memcpy( c.data() + k, (*a).data() + i, + (asize - i) * sizeof(int) ); + break; + } + } + c.resize( csize ); + if ( j < bsize ) + memcpy( c.data() + k, b.data() + j, (bsize - j) * sizeof(int) ); + *a = c; + } +} + +/* + Merges two disjoint TQMaps of (int, int) pairs and puts the result + into the first one. +*/ +static void mergeInto( TQMap *a, const TQMap& b ) +{ + TQMap::ConstIterator it; + for ( it = b.begin(); it != b.end(); ++it ) + a->insert( it.key(), *it ); +} + +/* + Returns the value associated to key k in TQMap m of (int, int) + pairs, or 0 if no such value is explicitly present. +*/ +static int at( const TQMap& m, int k ) +{ + TQMap::ConstIterator it = m.find( k ); + if ( it == m.end() ) + return 0; + else + return *it; +} + +#ifndef TQT_NO_REGEXP_WILDCARD +/* + Translates a wildcard pattern to an equivalent regular expression + pattern (e.g., *.cpp to .*\.cpp). +*/ +static TQString wc2rx( const TQString& wc_str ) +{ + int wclen = wc_str.length(); + TQString rx = TQString::fromLatin1( "" ); + int i = 0; + const TQChar *wc = wc_str.unicode(); + while ( i < wclen ) { + TQChar c = wc[i++]; + switch ( c.unicode() ) { + case '*': + rx += TQString::fromLatin1( ".*" ); + break; + case '?': + rx += TQChar( '.' ); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '\\': + case '^': + case '{': + case '|': + case '}': + rx += TQChar( '\\' ); + rx += c; + break; + case '[': + rx += c; + if ( wc[i] == TQChar('^') ) + rx += wc[i++]; + if ( i < wclen ) { + if ( rx[i] == ']' ) + rx += wc[i++]; + while ( i < wclen && wc[i] != TQChar(']') ) { + if ( wc[i] == '\\' ) + rx += TQChar( '\\' ); + rx += wc[i++]; + } + } + break; + default: + rx += c; + } + } + return rx; +} +#endif + +/* + The class TQRegExpEngine encapsulates a modified nondeterministic + finite automaton (NFA). +*/ +class TQRegExpEngine : public TQShared +{ +public: +#ifndef TQT_NO_REGEXP_CCLASS + /* + The class CharClass represents a set of characters, such as can + be found in regular expressions (e.g., [a-z] denotes the set + {a, b, ..., z}). + */ + class CharClass + { + public: + CharClass(); + CharClass( const CharClass& cc ) { operator=( cc ); } + + CharClass& operator=( const CharClass& cc ); + + void clear(); + bool negative() const { return n; } + void setNegative( bool negative ); + void addCategories( int cats ); + void addRange( ushort from, ushort to ); + void addSingleton( ushort ch ) { addRange( ch, ch ); } + + bool in( TQChar ch ) const; +#ifndef TQT_NO_REGEXP_OPTIM + const TQMemArray& firstOccurrence() const { return occ1; } +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + /* + The struct Range represents a range of characters (e.g., + [0-9] denotes range 48 to 57). + */ + struct Range + { + ushort from; // 48 + ushort to; // 57 + }; + + int c; // character classes + TQMemArray r; // character ranges + bool n; // negative? +#ifndef TQT_NO_REGEXP_OPTIM + TQMemArray occ1; // first-occurrence array +#endif + }; +#else + struct CharClass + { + int dummy; + +#ifndef TQT_NO_REGEXP_OPTIM + CharClass() { occ1.fill( 0, NumBadChars ); } + + const TQMemArray& firstOccurrence() const { return occ1; } + TQMemArray occ1; +#endif + }; +#endif + + TQRegExpEngine( bool caseSensitive ) { setup( caseSensitive ); } + TQRegExpEngine( const TQString& rx, bool caseSensitive ); +#ifndef TQT_NO_REGEXP_OPTIM + ~TQRegExpEngine(); +#endif + + bool isValid() const { return valid; } + bool caseSensitive() const { return cs; } + const TQString& errorString() const { return yyError; } + int numCaptures() const { return officialncap; } + void match( const TQString& str, int pos, bool minimal, bool oneTest, + int caretIndex, TQMemArray& captured ); + int partialMatchLength() const { return mmOneTestMatchedLen; } + + int createState( TQChar ch ); + int createState( const CharClass& cc ); +#ifndef TQT_NO_REGEXP_BACKREF + int createState( int bref ); +#endif + + void addCatTransitions( const TQMemArray& from, + const TQMemArray& to ); +#ifndef TQT_NO_REGEXP_CAPTURE + void addPlusTransitions( const TQMemArray& from, + const TQMemArray& to, int atom ); +#endif + +#ifndef TQT_NO_REGEXP_ANCHOR_ALT + int anchorAlternation( int a, int b ); + int anchorConcatenation( int a, int b ); +#else + int anchorAlternation( int a, int b ) { return a & b; } + int anchorConcatenation( int a, int b ) { return a | b; } +#endif + void addAnchors( int from, int to, int a ); + +#ifndef TQT_NO_REGEXP_OPTIM + void heuristicallyChooseHeuristic(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + +private: + enum { CharClassBit = 0x10000, BackRefBit = 0x20000 }; + + /* + The struct State represents one state in a modified NFA. The + input characters matched are stored in the state instead of on + the transitions, something possible for an automaton + constructed from a regular expression. + */ + struct State + { +#ifndef TQT_NO_REGEXP_CAPTURE + int atom; // which atom does this state belong to? +#endif + int match; // what does it match? (see CharClassBit and BackRefBit) + TQMemArray outs; // out-transitions + TQMap *reenter; // atoms reentered when transiting out + TQMap *anchors; // anchors met when transiting out + +#ifndef TQT_NO_REGEXP_CAPTURE + State( int a, int m ) + : atom( a ), match( m ), reenter( 0 ), anchors( 0 ) { } +#else + State( int m ) + : match( m ), reenter( 0 ), anchors( 0 ) { } +#endif + ~State() { delete reenter; delete anchors; } + }; + +#ifndef TQT_NO_REGEXP_LOOKAHEAD + /* + The struct Lookahead represents a lookahead a la Perl (e.g., + (?=foo) and (?!bar)). + */ + struct Lookahead + { + TQRegExpEngine *eng; // NFA representing the embedded regular expression + bool neg; // negative lookahead? + + Lookahead( TQRegExpEngine *eng0, bool neg0 ) + : eng( eng0 ), neg( neg0 ) { } + ~Lookahead() { delete eng; } + }; +#endif + +#ifndef TQT_NO_REGEXP_CAPTURE + /* + The struct Atom represents one node in the hierarchy of regular + expression atoms. + */ + struct Atom + { + int parent; // index of parent in array of atoms + int capture; // index of capture, from 1 to ncap + }; +#endif + +#ifndef TQT_NO_REGEXP_ANCHOR_ALT + /* + The struct AnchorAlternation represents a pair of anchors with + OR semantics. + */ + struct AnchorAlternation + { + int a; // this anchor... + int b; // ...or this one + }; +#endif + + enum { InitialState = 0, FinalState = 1 }; + void setup( bool caseSensitive ); + int setupState( int match ); + + /* + Let's hope that 13 lookaheads and 14 back-references are + enough. + */ + enum { MaxLookaheads = 13, MaxBackRefs = 14 }; + enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, + Anchor_Word = 0x00000004, Anchor_NonWord = 0x00000008, + Anchor_FirstLookahead = 0x00000010, + Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads, + Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1, + Anchor_Alternation = Anchor_BackRef1Empty << MaxBackRefs, + + Anchor_LookaheadMask = ( Anchor_FirstLookahead - 1 ) ^ + ( (Anchor_FirstLookahead << MaxLookaheads) - 1 ) }; +#ifndef TQT_NO_REGEXP_CAPTURE + int startAtom( bool capture ); + void finishAtom( int atom ) { cf = f[atom].parent; } +#endif + +#ifndef TQT_NO_REGEXP_LOOKAHEAD + int addLookahead( TQRegExpEngine *eng, bool negative ); +#endif + +#ifndef TQT_NO_REGEXP_CAPTURE + bool isBetterCapture( const int *begin1, const int *end1, const int *begin2, + const int *end2 ); +#endif + bool testAnchor( int i, int a, const int *capBegin ); + +#ifndef TQT_NO_REGEXP_OPTIM + bool goodStringMatch(); + bool badCharMatch(); +#else + bool bruteMatch(); +#endif + bool matchHere(); + + TQPtrVector s; // array of states + int ns; // number of states +#ifndef TQT_NO_REGEXP_CAPTURE + TQMemArray f; // atom hierarchy + int nf; // number of atoms + int cf; // current atom +#endif + int officialncap; // number of captures, seen from the outside + int ncap; // number of captures, seen from the inside +#ifndef TQT_NO_REGEXP_CCLASS + TQPtrVector cl; // array of character classes +#endif +#ifndef TQT_NO_REGEXP_LOOKAHEAD + TQPtrVector ahead; // array of lookaheads +#endif +#ifndef TQT_NO_REGEXP_ANCHOR_ALT + TQMemArray aa; // array of (a, b) pairs of anchors +#endif +#ifndef TQT_NO_REGEXP_OPTIM + bool caretAnchored; // does the regexp start with ^? + bool trivial; // is the good-string all that needs to match? +#endif + bool valid; // is the regular expression valid? + bool cs; // case sensitive? +#ifndef TQT_NO_REGEXP_BACKREF + int nbrefs; // number of back-references +#endif + +#ifndef TQT_NO_REGEXP_OPTIM + bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch + + int goodEarlyStart; // the index where goodStr can first occur in a match + int goodLateStart; // the index where goodStr can last occur in a match + TQString goodStr; // the string that any match has to contain + + int minl; // the minimum length of a match + TQMemArray occ1; // first-occurrence array +#endif + + /* + The class Box is an abstraction for a regular expression + fragment. It can also be seen as one node in the syntax tree of + a regular expression with synthetized attributes. + + Its interface is ugly for performance reasons. + */ + class Box + { + public: + Box( TQRegExpEngine *engine ); + Box( const Box& b ) { operator=( b ); } + + Box& operator=( const Box& b ); + + void clear() { operator=( Box(eng) ); } + void set( TQChar ch ); + void set( const CharClass& cc ); +#ifndef TQT_NO_REGEXP_BACKREF + void set( int bref ); +#endif + + void cat( const Box& b ); + void orx( const Box& b ); + void plus( int atom ); + void opt(); + void catAnchor( int a ); +#ifndef TQT_NO_REGEXP_OPTIM + void setupHeuristics(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + void addAnchorsToEngine( const Box& to ) const; + + TQRegExpEngine *eng; // the automaton under construction + TQMemArray ls; // the left states (firstpos) + TQMemArray rs; // the right states (lastpos) + TQMap lanchors; // the left anchors + TQMap ranchors; // the right anchors + int skipanchors; // the anchors to match if the box is skipped + +#ifndef TQT_NO_REGEXP_OPTIM + int earlyStart; // the index where str can first occur + int lateStart; // the index where str can last occur + TQString str; // a string that has to occur in any match + TQString leftStr; // a string occurring at the left of this box + TQString rightStr; // a string occurring at the right of this box + int maxl; // the maximum length of this box (possibly InftyLen) +#endif + + int minl; // the minimum length of this box +#ifndef TQT_NO_REGEXP_OPTIM + TQMemArray occ1; // first-occurrence array +#endif + }; + friend class Box; + + /* + This is the lexical analyzer for regular expressions. + */ + enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen, + Tok_PosLookahead, Tok_NegLookahead, Tok_RightParen, Tok_CharClass, + Tok_Caret, Tok_Quantifier, Tok_Bar, Tok_Word, Tok_NonWord, + Tok_Char = 0x10000, Tok_BackRef = 0x20000 }; + int getChar(); + int getEscape(); +#ifndef TQT_NO_REGEXP_INTERVAL + int getRep( int def ); +#endif +#ifndef TQT_NO_REGEXP_LOOKAHEAD + void skipChars( int n ); +#endif + void error( const char *msg ); + void startTokenizer( const TQChar *rx, int len ); + int getToken(); + + const TQChar *yyIn; // a pointer to the input regular expression pattern + int yyPos0; // the position of yyTok in the input pattern + int yyPos; // the position of the next character to read + int yyLen; // the length of yyIn + int yyCh; // the last character read + CharClass *yyCharClass; // attribute for Tok_CharClass tokens + int yyMinRep; // attribute for Tok_Quantifier + int yyMaxRep; // ditto + TQString yyError; // syntax error or overflow during parsing? + + /* + This is the syntactic analyzer for regular expressions. + */ + int parse( const TQChar *rx, int len ); + void parseAtom( Box *box ); + void parseFactor( Box *box ); + void parseTerm( Box *box ); + void parseExpression( Box *box ); + + int yyTok; // the last token read + bool yyMayCapture; // set this to FALSE to disable capturing + + /* + This is the engine state during matching. + */ + const TQString *mmStr; // a pointer to the input TQString + const TQChar *mmIn; // a pointer to the input string data + int mmPos; // the current position in the string + int mmCaretPos; + int mmLen; // the length of the input string + bool mmMinimal; // minimal matching? + TQMemArray mmBigArray; // big TQMemArray array + int *mmInNextStack; // is state is mmNextStack? + int *mmCurStack; // stack of current states + int *mmNextStack; // stack of next states + int *mmCurCapBegin; // start of current states' captures + int *mmNextCapBegin; // start of next states' captures + int *mmCurCapEnd; // end of current states' captures + int *mmNextCapEnd; // end of next states' captures + int *mmTempCapBegin; // start of temporary captures + int *mmTempCapEnd; // end of temporary captures + int *mmCapBegin; // start of captures for a next state + int *mmCapEnd; // end of captures for a next state + int *mmSlideTab; // bump-along slide table for bad-character heuristic + int mmSlideTabSize; // size of slide table +#ifndef TQT_NO_REGEXP_BACKREF + TQIntDict mmSleeping; // dictionary of back-reference sleepers +#endif + int mmMatchLen; // length of match + int mmOneTestMatchedLen; // length of partial match +}; + +TQRegExpEngine::TQRegExpEngine( const TQString& rx, bool caseSensitive ) +#ifndef TQT_NO_REGEXP_BACKREF + : mmSleeping( 101 ) +#endif +{ + setup( caseSensitive ); + valid = ( parse(rx.unicode(), rx.length()) == (int) rx.length() ); + if ( !valid ) { +#ifndef TQT_NO_REGEXP_OPTIM + trivial = FALSE; +#endif + error( RXERR_LEFTDELIM ); + } +} + +#ifndef TQT_NO_REGEXP_OPTIM +TQRegExpEngine::~TQRegExpEngine() +{ +} +#endif + +/* + Tries to match in str and returns an array of (begin, length) pairs + for captured text. If there is no match, all pairs are (-1, -1). +*/ +void TQRegExpEngine::match( const TQString& str, int pos, bool minimal, + bool oneTest, int caretIndex, + TQMemArray& captured ) +{ + bool matched = FALSE; + +#ifndef TQT_NO_REGEXP_OPTIM + if ( trivial && !oneTest ) { + mmPos = str.find( goodStr, pos, cs ); + mmMatchLen = goodStr.length(); + matched = ( mmPos != -1 ); + } else +#endif + { + mmStr = &str; + mmIn = str.unicode(); + if ( mmIn == 0 ) + mmIn = &TQChar::null; + mmPos = pos; + mmCaretPos = caretIndex; + mmLen = str.length(); + mmMinimal = minimal; + mmMatchLen = 0; + mmOneTestMatchedLen = 0; + + if ( valid && mmPos >= 0 && mmPos <= mmLen ) { +#ifndef TQT_NO_REGEXP_OPTIM + if ( oneTest ) { + matched = matchHere(); + } else { + if ( mmPos <= mmLen - minl ) { + if ( caretAnchored ) { + matched = matchHere(); + } else if ( useGoodStringHeuristic ) { + matched = goodStringMatch(); + } else { + matched = badCharMatch(); + } + } + } +#else + matched = oneTest ? matchHere() : bruteMatch(); +#endif + } + } + + int capturedSize = 2 + 2 * officialncap; + captured.detach(); + captured.resize( capturedSize ); + if ( matched ) { + captured[0] = mmPos; + captured[1] = mmMatchLen; + for ( int j = 0; j < officialncap; j++ ) { + int len = mmCapEnd[j] - mmCapBegin[j]; + captured[2 + 2 * j] = len > 0 ? mmPos + mmCapBegin[j] : 0; + captured[2 + 2 * j + 1] = len; + } + } else { + // we rely on 2's complement here + memset( captured.data(), -1, capturedSize * sizeof(int) ); + } +} + +/* + The three following functions add one state to the automaton and + return the number of the state. +*/ + +int TQRegExpEngine::createState( TQChar ch ) +{ + return setupState( ch.unicode() ); +} + +int TQRegExpEngine::createState( const CharClass& cc ) +{ +#ifndef TQT_NO_REGEXP_CCLASS + int n = cl.size(); + cl.resize( n + 1 ); + cl.insert( n, new CharClass(cc) ); + return setupState( CharClassBit | n ); +#else + Q_UNUSED( cc ); + return setupState( CharClassBit ); +#endif +} + +#ifndef TQT_NO_REGEXP_BACKREF +int TQRegExpEngine::createState( int bref ) +{ + if ( bref > nbrefs ) { + nbrefs = bref; + if ( nbrefs > MaxBackRefs ) { + error( RXERR_LIMIT ); + return 0; + } + } + return setupState( BackRefBit | bref ); +} +#endif + +/* + The two following functions add a transition between all pairs of + states (i, j) where i is fond in from, and j is found in to. + + Cat-transitions are distinguished from plus-transitions for + capturing. +*/ + +void TQRegExpEngine::addCatTransitions( const TQMemArray& from, + const TQMemArray& to ) +{ + for ( int i = 0; i < (int) from.size(); i++ ) { + State *st = s[from[i]]; + mergeInto( &st->outs, to ); + } +} + +#ifndef TQT_NO_REGEXP_CAPTURE +void TQRegExpEngine::addPlusTransitions( const TQMemArray& from, + const TQMemArray& to, int atom ) +{ + for ( int i = 0; i < (int) from.size(); i++ ) { + State *st = s[from[i]]; + TQMemArray oldOuts = st->outs.copy(); + mergeInto( &st->outs, to ); + if ( f[atom].capture >= 0 ) { + if ( st->reenter == 0 ) + st->reenter = new TQMap; + for ( int j = 0; j < (int) to.size(); j++ ) { + if ( !st->reenter->contains(to[j]) && + oldOuts.bsearch(to[j]) < 0 ) + st->reenter->insert( to[j], atom ); + } + } + } +} +#endif + +#ifndef TQT_NO_REGEXP_ANCHOR_ALT +/* + Returns an anchor that means a OR b. +*/ +int TQRegExpEngine::anchorAlternation( int a, int b ) +{ + if ( ((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0 ) + return a & b; + + int n = aa.size(); +#ifndef TQT_NO_REGEXP_OPTIM + if ( n > 0 && aa[n - 1].a == a && aa[n - 1].b == b ) + return Anchor_Alternation | ( n - 1 ); +#endif + + aa.resize( n + 1 ); + aa[n].a = a; + aa[n].b = b; + return Anchor_Alternation | n; +} + +/* + Returns an anchor that means a AND b. +*/ +int TQRegExpEngine::anchorConcatenation( int a, int b ) +{ + if ( ((a | b) & Anchor_Alternation) == 0 ) + return a | b; + if ( (b & Anchor_Alternation) != 0 ) + tqSwap( a, b ); + + int aprime = anchorConcatenation( aa[a ^ Anchor_Alternation].a, b ); + int bprime = anchorConcatenation( aa[a ^ Anchor_Alternation].b, b ); + return anchorAlternation( aprime, bprime ); +} +#endif + +/* + Adds anchor a on a transition caracterised by its from state and + its to state. +*/ +void TQRegExpEngine::addAnchors( int from, int to, int a ) +{ + State *st = s[from]; + if ( st->anchors == 0 ) + st->anchors = new TQMap; + if ( st->anchors->contains(to) ) + a = anchorAlternation( (*st->anchors)[to], a ); + st->anchors->insert( to, a ); +} + +#ifndef TQT_NO_REGEXP_OPTIM +/* + This function chooses between the good-string and the bad-character + heuristics. It computes two scores and chooses the heuristic with + the highest score. + + Here are some common-sense constraints on the scores that should be + respected if the formulas are ever modified: (1) If goodStr is + empty, the good-string heuristic scores 0. (2) If the regular + expression is trivial, the good-string heuristic should be used. + (3) If the search is case insensitive, the good-string heuristic + should be used, unless it scores 0. (Case insensitivity turns all + entries of occ1 to 0.) (4) If (goodLateStart - goodEarlyStart) is + big, the good-string heuristic should score less. +*/ +void TQRegExpEngine::heuristicallyChooseHeuristic() +{ + if ( minl == 0 ) { + useGoodStringHeuristic = FALSE; + } else if ( trivial ) { + useGoodStringHeuristic = TRUE; + } else { + /* + Magic formula: The good string has to constitute a good + proportion of the minimum-length string, and appear at a + more-or-less known index. + */ + int goodStringScore = ( 64 * goodStr.length() / minl ) - + ( goodLateStart - goodEarlyStart ); + /* + Less magic formula: We pick some characters at random, and + check whether they are good or bad. + */ + int badCharScore = 0; + int step = TQMAX( 1, NumBadChars / 32 ); + for ( int i = 1; i < NumBadChars; i += step ) { + if ( occ1[i] == NoOccurrence ) + badCharScore += minl; + else + badCharScore += occ1[i]; + } + badCharScore /= minl; + useGoodStringHeuristic = ( goodStringScore > badCharScore ); + } +} +#endif + +#if defined(QT_DEBUG) +void TQRegExpEngine::dump() const +{ + int i, j; + tqDebug( "Case %ssensitive engine", cs ? "" : "in" ); + tqDebug( " States" ); + for ( i = 0; i < ns; i++ ) { + tqDebug( " %d%s", i, + i == InitialState ? " (initial)" : + i == FinalState ? " (final)" : "" ); +#ifndef TQT_NO_REGEXP_CAPTURE + tqDebug( " in atom %d", s[i]->atom ); +#endif + int m = s[i]->match; + if ( (m & CharClassBit) != 0 ) { + tqDebug( " match character class %d", m ^ CharClassBit ); +#ifndef TQT_NO_REGEXP_CCLASS + cl[m ^ CharClassBit]->dump(); +#else + tqDebug( " negative character class" ); +#endif + } else if ( (m & BackRefBit) != 0 ) { + tqDebug( " match back-reference %d", m ^ BackRefBit ); + } else if ( m >= 0x20 && m <= 0x7e ) { + tqDebug( " match 0x%.4x (%c)", m, m ); + } else { + tqDebug( " match 0x%.4x", m ); + } + for ( j = 0; j < (int) s[i]->outs.size(); j++ ) { + int next = s[i]->outs[j]; + tqDebug( " -> %d", next ); + if ( s[i]->reenter != 0 && s[i]->reenter->contains(next) ) + tqDebug( " [reenter %d]", (*s[i]->reenter)[next] ); + if ( s[i]->anchors != 0 && at(*s[i]->anchors, next) != 0 ) + tqDebug( " [anchors 0x%.8x]", (*s[i]->anchors)[next] ); + } + } +#ifndef TQT_NO_REGEXP_CAPTURE + if ( nf > 0 ) { + tqDebug( " Atom Parent Capture" ); + for ( i = 0; i < nf; i++ ) + tqDebug( " %6d %6d %6d", i, f[i].parent, f[i].capture ); + } +#endif +#ifndef TQT_NO_REGEXP_ANCHOR_ALT + for ( i = 0; i < (int) aa.size(); i++ ) + tqDebug( " Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, + aa[i].b ); +#endif +} +#endif + +void TQRegExpEngine::setup( bool caseSensitive ) +{ + s.setAutoDelete( TRUE ); + s.resize( 32 ); + ns = 0; +#ifndef TQT_NO_REGEXP_CAPTURE + f.resize( 32 ); + nf = 0; + cf = -1; +#endif + officialncap = 0; + ncap = 0; +#ifndef TQT_NO_REGEXP_CCLASS + cl.setAutoDelete( TRUE ); +#endif +#ifndef TQT_NO_REGEXP_LOOKAHEAD + ahead.setAutoDelete( TRUE ); +#endif +#ifndef TQT_NO_REGEXP_OPTIM + caretAnchored = TRUE; + trivial = TRUE; +#endif + valid = FALSE; + cs = caseSensitive; +#ifndef TQT_NO_REGEXP_BACKREF + nbrefs = 0; +#endif +#ifndef TQT_NO_REGEXP_OPTIM + useGoodStringHeuristic = TRUE; + minl = 0; + occ1.fill( 0, NumBadChars ); +#endif +} + +int TQRegExpEngine::setupState( int match ) +{ + if ( (ns & (ns + 1)) == 0 && ns + 1 >= (int) s.size() ) + s.resize( (ns + 1) << 1 ); +#ifndef TQT_NO_REGEXP_CAPTURE + s.insert( ns, new State(cf, match) ); +#else + s.insert( ns, new State(match) ); +#endif + return ns++; +} + +#ifndef TQT_NO_REGEXP_CAPTURE +/* + Functions startAtom() and finishAtom() should be called to delimit + atoms. When a state is created, it is assigned to the current atom. + The information is later used for capturing. +*/ +int TQRegExpEngine::startAtom( bool capture ) +{ + if ( (nf & (nf + 1)) == 0 && nf + 1 >= (int) f.size() ) + f.resize( (nf + 1) << 1 ); + f[nf].parent = cf; + cf = nf++; + f[cf].capture = capture ? ncap++ : -1; + return cf; +} +#endif + +#ifndef TQT_NO_REGEXP_LOOKAHEAD +/* + Creates a lookahead anchor. +*/ +int TQRegExpEngine::addLookahead( TQRegExpEngine *eng, bool negative ) +{ + int n = ahead.size(); + if ( n == MaxLookaheads ) { + error( RXERR_LIMIT ); + return 0; + } + ahead.resize( n + 1 ); + ahead.insert( n, new Lookahead(eng, negative) ); + return Anchor_FirstLookahead << n; +} +#endif + +#ifndef TQT_NO_REGEXP_CAPTURE +/* + We want the longest leftmost captures. +*/ +bool TQRegExpEngine::isBetterCapture( const int *begin1, const int *end1, + const int *begin2, const int *end2 ) +{ + for ( int i = 0; i < ncap; i++ ) { + int delta = begin2[i] - begin1[i]; // it has to start early... + if ( delta == 0 ) + delta = end1[i] - end2[i]; // ...and end late (like a party) + + if ( delta != 0 ) + return delta > 0; + } + return FALSE; +} +#endif + +/* + Returns TRUE if anchor a matches at position mmPos + i in the input + string, otherwise FALSE. +*/ +bool TQRegExpEngine::testAnchor( int i, int a, const int *capBegin ) +{ + int j; + +#ifndef TQT_NO_REGEXP_ANCHOR_ALT + if ( (a & Anchor_Alternation) != 0 ) { + return testAnchor( i, aa[a ^ Anchor_Alternation].a, capBegin ) || + testAnchor( i, aa[a ^ Anchor_Alternation].b, capBegin ); + } +#endif + + if ( (a & Anchor_Caret) != 0 ) { + if ( mmPos + i != mmCaretPos ) + return FALSE; + } + if ( (a & Anchor_Dollar) != 0 ) { + if ( mmPos + i != mmLen ) + return FALSE; + } +#ifndef TQT_NO_REGEXP_ESCAPE + if ( (a & (Anchor_Word | Anchor_NonWord)) != 0 ) { + bool before = FALSE; + bool after = FALSE; + if ( mmPos + i != 0 ) + before = isWord( mmIn[mmPos + i - 1] ); + if ( mmPos + i != mmLen ) + after = isWord( mmIn[mmPos + i] ); + if ( (a & Anchor_Word) != 0 && (before == after) ) + return FALSE; + if ( (a & Anchor_NonWord) != 0 && (before != after) ) + return FALSE; + } +#endif +#ifndef TQT_NO_REGEXP_LOOKAHEAD + if ( (a & Anchor_LookaheadMask) != 0 ) { + TQConstString cstr = TQConstString( (TQChar *) mmIn + mmPos + i, + mmLen - mmPos - i ); + for ( j = 0; j < (int) ahead.size(); j++ ) { + if ( (a & (Anchor_FirstLookahead << j)) != 0 ) { + TQMemArray captured; + ahead[j]->eng->match( cstr.string(), 0, TRUE, TRUE, + mmCaretPos - mmPos - i, captured ); + if ( (captured[0] == 0) == ahead[j]->neg ) + return FALSE; + } + } + } +#endif +#ifndef TQT_NO_REGEXP_CAPTURE +#ifndef TQT_NO_REGEXP_BACKREF + for ( j = 0; j < nbrefs; j++ ) { + if ( (a & (Anchor_BackRef1Empty << j)) != 0 ) { + if ( capBegin[j] != EmptyCapture ) + return FALSE; + } + } +#endif +#endif + return TRUE; +} + +#ifndef TQT_NO_REGEXP_OPTIM +/* + The three following functions are what Jeffrey Friedl would call + transmissions (or bump-alongs). Using one or the other should make + no difference except in performance. +*/ + +bool TQRegExpEngine::goodStringMatch() +{ + int k = mmPos + goodEarlyStart; + while ( (k = mmStr->find(goodStr, k, cs)) != -1 ) { + int from = k - goodLateStart; + int to = k - goodEarlyStart; + if ( from > mmPos ) + mmPos = from; + + while ( mmPos <= to ) { + if ( matchHere() ) + return TRUE; + mmPos++; + } + k++; + } + return FALSE; +} + +bool TQRegExpEngine::badCharMatch() +{ + int slideHead = 0; + int slideNext = 0; + int i; + int lastPos = mmLen - minl; + memset( mmSlideTab, 0, mmSlideTabSize * sizeof(int) ); + + /* + Set up the slide table, used for the bad-character heuristic, + using the table of first occurrence of each character. + */ + for ( i = 0; i < minl; i++ ) { + int sk = occ1[BadChar(mmIn[mmPos + i])]; + if ( sk == NoOccurrence ) + sk = i + 1; + if ( sk > 0 ) { + int k = i + 1 - sk; + if ( k < 0 ) { + sk = i + 1; + k = 0; + } + if ( sk > mmSlideTab[k] ) + mmSlideTab[k] = sk; + } + } + + if ( mmPos > lastPos ) + return FALSE; + + for ( ;; ) { + if ( ++slideNext >= mmSlideTabSize ) + slideNext = 0; + if ( mmSlideTab[slideHead] > 0 ) { + if ( mmSlideTab[slideHead] - 1 > mmSlideTab[slideNext] ) + mmSlideTab[slideNext] = mmSlideTab[slideHead] - 1; + mmSlideTab[slideHead] = 0; + } else { + if ( matchHere() ) + return TRUE; + } + + if ( mmPos == lastPos ) + break; + + /* + Update the slide table. This code has much in common with + the initialization code. + */ + int sk = occ1[BadChar(mmIn[mmPos + minl])]; + if ( sk == NoOccurrence ) { + mmSlideTab[slideNext] = minl; + } else if ( sk > 0 ) { + int k = slideNext + minl - sk; + if ( k >= mmSlideTabSize ) + k -= mmSlideTabSize; + if ( sk > mmSlideTab[k] ) + mmSlideTab[k] = sk; + } + slideHead = slideNext; + mmPos++; + } + return FALSE; +} +#else +bool TQRegExpEngine::bruteMatch() +{ + while ( mmPos <= mmLen ) { + if ( matchHere() ) + return TRUE; + mmPos++; + } + return FALSE; +} +#endif + +/* + Here's the core of the engine. It tries to do a match here and now. +*/ +bool TQRegExpEngine::matchHere() +{ + int ncur = 1, nnext = 0; + int i = 0, j, k, m; + bool stop = FALSE; + + mmMatchLen = -1; + mmOneTestMatchedLen = -1; + mmCurStack[0] = InitialState; + +#ifndef TQT_NO_REGEXP_CAPTURE + if ( ncap > 0 ) { + for ( j = 0; j < ncap; j++ ) { + mmCurCapBegin[j] = EmptyCapture; + mmCurCapEnd[j] = EmptyCapture; + } + } +#endif + +#ifndef TQT_NO_REGEXP_BACKREF + int *zzZ = 0; + + while ( (ncur > 0 || !mmSleeping.isEmpty()) && i <= mmLen - mmPos && + !stop ) +#else + while ( ncur > 0 && i <= mmLen - mmPos && !stop ) +#endif + { + int ch = ( i < mmLen - mmPos ) ? mmIn[mmPos + i].unicode() : 0; + for ( j = 0; j < ncur; j++ ) { + int cur = mmCurStack[j]; + State *scur = s[cur]; + TQMemArray& outs = scur->outs; + for ( k = 0; k < (int) outs.size(); k++ ) { + int next = outs[k]; + State *snext = s[next]; + bool in = TRUE; +#ifndef TQT_NO_REGEXP_BACKREF + int needSomeSleep = 0; +#endif + + /* + First, check if the anchors are anchored properly. + */ + if ( scur->anchors != 0 ) { + int a = at( *scur->anchors, next ); + if ( a != 0 && !testAnchor(i, a, mmCurCapBegin + j * ncap) ) + in = FALSE; + } + /* + If indeed they are, check if the input character is + correct for this transition. + */ + if ( in ) { + m = snext->match; + if ( (m & (CharClassBit | BackRefBit)) == 0 ) { + if ( cs ) + in = ( m == ch ); + else + in = ( TQChar(m).lower() == TQChar(ch).lower() ); + } else if ( next == FinalState ) { + mmMatchLen = i; + stop = mmMinimal; + in = TRUE; + } else if ( (m & CharClassBit) != 0 ) { +#ifndef TQT_NO_REGEXP_CCLASS + const CharClass *cc = cl[m ^ CharClassBit]; + if ( cs ) + in = cc->in( ch ); + else if ( cc->negative() ) + in = cc->in( TQChar(ch).lower() ) && + cc->in( TQChar(ch).upper() ); + else + in = cc->in( TQChar(ch).lower() ) || + cc->in( TQChar(ch).upper() ); +#endif +#ifndef TQT_NO_REGEXP_BACKREF + } else { /* ( (m & BackRefBit) != 0 ) */ + int bref = m ^ BackRefBit; + int ell = j * ncap + ( bref - 1 ); + + in = bref <= ncap && mmCurCapBegin[ell] != EmptyCapture; + if ( in ) { + if ( cs ) + in = ( mmIn[mmPos + mmCurCapBegin[ell]] + == TQChar(ch) ); + else + in = ( mmIn[mmPos + mmCurCapBegin[ell]].lower() + == TQChar(ch).lower() ); + } + + if ( in ) { + int delta; + if ( mmCurCapEnd[ell] == EmptyCapture ) + delta = i - mmCurCapBegin[ell]; + else + delta = mmCurCapEnd[ell] - mmCurCapBegin[ell]; + + in = ( delta <= mmLen - (mmPos + i) ); + if ( in && delta > 1 ) { + int n = 1; + if ( cs ) { + while ( n < delta ) { + if ( mmIn[mmPos + + mmCurCapBegin[ell] + n] != + mmIn[mmPos + i + n] ) + break; + n++; + } + } else { + while ( n < delta ) { + TQChar a = mmIn[mmPos + + mmCurCapBegin[ell] + n]; + TQChar b = mmIn[mmPos + i + n]; + if ( a.lower() != b.lower() ) + break; + n++; + } + } + in = ( n == delta ); + if ( in ) + needSomeSleep = delta - 1; + } + } +#endif + } + } + + /* + We must now update our data structures. + */ + if ( in ) { +#ifndef TQT_NO_REGEXP_CAPTURE + int *capBegin, *capEnd; +#endif + /* + If the next state was not encountered yet, all + is fine. + */ + if ( (m = mmInNextStack[next]) == -1 ) { + m = nnext++; + mmNextStack[m] = next; + mmInNextStack[next] = m; +#ifndef TQT_NO_REGEXP_CAPTURE + capBegin = mmNextCapBegin + m * ncap; + capEnd = mmNextCapEnd + m * ncap; + + /* + Otherwise, we'll first maintain captures in + temporary arrays, and decide at the end whether + it's best to keep the previous capture zones or + the new ones. + */ + } else { + capBegin = mmTempCapBegin; + capEnd = mmTempCapEnd; +#endif + } + +#ifndef TQT_NO_REGEXP_CAPTURE + /* + Updating the capture zones is much of a task. + */ + if ( ncap > 0 ) { + memcpy( capBegin, mmCurCapBegin + j * ncap, + ncap * sizeof(int) ); + memcpy( capEnd, mmCurCapEnd + j * ncap, + ncap * sizeof(int) ); + int c = scur->atom, n = snext->atom; + int p = -1, q = -1; + int cap; + + /* + Lemma 1. For any x in the range [0..nf), we + have f[x].parent < x. + + Proof. By looking at startAtom(), it is + clear that cf < nf holds all the time, and + thus that f[nf].parent < nf. + */ + + /* + If we are reentering an atom, we empty all + capture zones inside it. + */ + if ( scur->reenter != 0 && + (q = at(*scur->reenter, next)) != 0 ) { + TQBitArray b; + b.fill( FALSE, nf ); + b.setBit( q, TRUE ); + for ( int ell = q + 1; ell < nf; ell++ ) { + if ( b.testBit(f[ell].parent) ) { + b.setBit( ell, TRUE ); + cap = f[ell].capture; + if ( cap >= 0 ) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } + } + } + p = f[q].parent; + + /* + Otherwise, close the capture zones we are + leaving. We are leaving f[c].capture, + f[f[c].parent].capture, + f[f[f[c].parent].parent].capture, ..., + until f[x].capture, with x such that + f[x].parent is the youngest common ancestor + for c and n. + + We go up along c's and n's ancestry until + we find x. + */ + } else { + p = c; + q = n; + while ( p != q ) { + if ( p > q ) { + cap = f[p].capture; + if ( cap >= 0 ) { + if ( capBegin[cap] == i ) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } else { + capEnd[cap] = i; + } + } + p = f[p].parent; + } else { + q = f[q].parent; + } + } + } + + /* + In any case, we now open the capture zones + we are entering. We work upwards from n + until we reach p (the parent of the atom we + reenter or the youngest common ancestor). + */ + while ( n > p ) { + cap = f[n].capture; + if ( cap >= 0 ) { + capBegin[cap] = i; + capEnd[cap] = EmptyCapture; + } + n = f[n].parent; + } + /* + If the next state was already in + mmNextStack, we must choose carefully which + capture zones we want to keep. + */ + if ( capBegin == mmTempCapBegin && + isBetterCapture(capBegin, capEnd, + mmNextCapBegin + m * ncap, + mmNextCapEnd + m * ncap) ) { + memcpy( mmNextCapBegin + m * ncap, capBegin, + ncap * sizeof(int) ); + memcpy( mmNextCapEnd + m * ncap, capEnd, + ncap * sizeof(int) ); + } + } +#ifndef TQT_NO_REGEXP_BACKREF + /* + We are done with updating the capture zones. + It's now time to put the next state to sleep, + if it needs to, and to remove it from + mmNextStack. + */ + if ( needSomeSleep > 0 ) { + zzZ = new int[1 + 2 * ncap]; + zzZ[0] = next; + if ( ncap > 0 ) { + memcpy( zzZ + 1, capBegin, ncap * sizeof(int) ); + memcpy( zzZ + 1 + ncap, capEnd, + ncap * sizeof(int) ); + } + mmInNextStack[mmNextStack[--nnext]] = -1; + mmSleeping.insert( i + needSomeSleep, zzZ ); + } +#endif +#endif + } + } + } +#ifndef TQT_NO_REGEXP_CAPTURE + /* + If we reached the final state, hurray! Copy the captured + zone. + */ + if ( ncap > 0 && (m = mmInNextStack[FinalState]) != -1 ) { + memcpy( mmCapBegin, mmNextCapBegin + m * ncap, ncap * sizeof(int) ); + memcpy( mmCapEnd, mmNextCapEnd + m * ncap, ncap * sizeof(int) ); + } +#ifndef TQT_NO_REGEXP_BACKREF + /* + It's time to wake up the sleepers. + */ + if ( !mmSleeping.isEmpty() ) { + while ( (zzZ = mmSleeping.take(i)) != 0 ) { + int next = zzZ[0]; + int *capBegin = zzZ + 1; + int *capEnd = zzZ + 1 + ncap; + bool copyOver = TRUE; + + if ( (m = mmInNextStack[zzZ[0]]) == -1 ) { + m = nnext++; + mmNextStack[m] = next; + mmInNextStack[next] = m; + } else { + copyOver = isBetterCapture( mmNextCapBegin + m * ncap, + mmNextCapEnd + m * ncap, + capBegin, capEnd ); + } + if ( copyOver ) { + memcpy( mmNextCapBegin + m * ncap, capBegin, + ncap * sizeof(int) ); + memcpy( mmNextCapEnd + m * ncap, capEnd, + ncap * sizeof(int) ); + } + delete[] zzZ; + } + } +#endif +#endif + for ( j = 0; j < nnext; j++ ) + mmInNextStack[mmNextStack[j]] = -1; + + // avoid needless iteration that confuses mmOneTestMatchedLen + if ( nnext == 1 && mmNextStack[0] == FinalState +#ifndef TQT_NO_REGEXP_BACKREF + && mmSleeping.isEmpty() +#endif + ) + stop = TRUE; + + tqSwap( mmCurStack, mmNextStack ); +#ifndef TQT_NO_REGEXP_CAPTURE + tqSwap( mmCurCapBegin, mmNextCapBegin ); + tqSwap( mmCurCapEnd, mmNextCapEnd ); +#endif + ncur = nnext; + nnext = 0; + i++; + } + +#ifndef TQT_NO_REGEXP_BACKREF + /* + If minimal matching is enabled, we might have some sleepers + left. + */ + while ( !mmSleeping.isEmpty() ) { + zzZ = mmSleeping.take( *TQIntDictIterator(mmSleeping) ); + delete[] zzZ; + } +#endif + + mmOneTestMatchedLen = i - 1; + return ( mmMatchLen >= 0 ); +} + +#ifndef TQT_NO_REGEXP_CCLASS + +TQRegExpEngine::CharClass::CharClass() + : c( 0 ), n( FALSE ) +{ +#ifndef TQT_NO_REGEXP_OPTIM + occ1.fill( NoOccurrence, NumBadChars ); +#endif +} + +TQRegExpEngine::CharClass& TQRegExpEngine::CharClass::operator=( + const CharClass& cc ) +{ + c = cc.c; + r = cc.r.copy(); + n = cc.n; +#ifndef TQT_NO_REGEXP_OPTIM + occ1 = cc.occ1; +#endif + return *this; +} + +void TQRegExpEngine::CharClass::clear() +{ + c = 0; + r.resize( 0 ); + n = FALSE; +} + +void TQRegExpEngine::CharClass::setNegative( bool negative ) +{ + n = negative; +#ifndef TQT_NO_REGEXP_OPTIM + occ1.fill( 0, NumBadChars ); +#endif +} + +void TQRegExpEngine::CharClass::addCategories( int cats ) +{ + c |= cats; +#ifndef TQT_NO_REGEXP_OPTIM + occ1.fill( 0, NumBadChars ); +#endif +} + +void TQRegExpEngine::CharClass::addRange( ushort from, ushort to ) +{ + if ( from > to ) + tqSwap( from, to ); + int m = r.size(); + r.resize( m + 1 ); + r[m].from = from; + r[m].to = to; + +#ifndef TQT_NO_REGEXP_OPTIM + int i; + + if ( to - from < NumBadChars ) { + occ1.detach(); + if ( from % NumBadChars <= to % NumBadChars ) { + for ( i = from % NumBadChars; i <= to % NumBadChars; i++ ) + occ1[i] = 0; + } else { + for ( i = 0; i <= to % NumBadChars; i++ ) + occ1[i] = 0; + for ( i = from % NumBadChars; i < NumBadChars; i++ ) + occ1[i] = 0; + } + } else { + occ1.fill( 0, NumBadChars ); + } +#endif +} + +bool TQRegExpEngine::CharClass::in( TQChar ch ) const +{ +#ifndef TQT_NO_REGEXP_OPTIM + if ( occ1[BadChar(ch)] == NoOccurrence ) + return n; +#endif + + if ( c != 0 && (c & (1 << (int) ch.category())) != 0 ) + return !n; + for ( int i = 0; i < (int) r.size(); i++ ) { + if ( ch.unicode() >= r[i].from && ch.unicode() <= r[i].to ) + return !n; + } + return n; +} + +#if defined(QT_DEBUG) +void TQRegExpEngine::CharClass::dump() const +{ + int i; + tqDebug( " %stive character class", n ? "nega" : "posi" ); +#ifndef TQT_NO_REGEXP_CCLASS + if ( c != 0 ) + tqDebug( " categories 0x%.8x", c ); +#endif + for ( i = 0; i < (int) r.size(); i++ ) + tqDebug( " 0x%.4x through 0x%.4x", r[i].from, r[i].to ); +} +#endif +#endif + +TQRegExpEngine::Box::Box( TQRegExpEngine *engine ) + : eng( engine ), skipanchors( 0 ) +#ifndef TQT_NO_REGEXP_OPTIM + , earlyStart( 0 ), lateStart( 0 ), maxl( 0 ) +#endif +{ +#ifndef TQT_NO_REGEXP_OPTIM + occ1.fill( NoOccurrence, NumBadChars ); +#endif + minl = 0; +} + +TQRegExpEngine::Box& TQRegExpEngine::Box::operator=( const Box& b ) +{ + eng = b.eng; + ls = b.ls; + rs = b.rs; + lanchors = b.lanchors; + ranchors = b.ranchors; + skipanchors = b.skipanchors; +#ifndef TQT_NO_REGEXP_OPTIM + earlyStart = b.earlyStart; + lateStart = b.lateStart; + str = b.str; + leftStr = b.leftStr; + rightStr = b.rightStr; + maxl = b.maxl; + occ1 = b.occ1; +#endif + minl = b.minl; + return *this; +} + +void TQRegExpEngine::Box::set( TQChar ch ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( ch ); + rs = ls; + rs.detach(); +#ifndef TQT_NO_REGEXP_OPTIM + str = ch; + leftStr = ch; + rightStr = ch; + maxl = 1; + occ1.detach(); + occ1[BadChar(ch)] = 0; +#endif + minl = 1; +} + +void TQRegExpEngine::Box::set( const CharClass& cc ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( cc ); + rs = ls; + rs.detach(); +#ifndef TQT_NO_REGEXP_OPTIM + maxl = 1; + occ1 = cc.firstOccurrence(); +#endif + minl = 1; +} + +#ifndef TQT_NO_REGEXP_BACKREF +void TQRegExpEngine::Box::set( int bref ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( bref ); + rs = ls; + rs.detach(); + if ( bref >= 1 && bref <= MaxBackRefs ) + skipanchors = Anchor_BackRef0Empty << bref; +#ifndef TQT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif + minl = 0; +} +#endif + +void TQRegExpEngine::Box::cat( const Box& b ) +{ + eng->addCatTransitions( rs, b.ls ); + addAnchorsToEngine( b ); + if ( minl == 0 ) { + mergeInto( &lanchors, b.lanchors ); + if ( skipanchors != 0 ) { + for ( int i = 0; i < (int) b.ls.size(); i++ ) { + int a = eng->anchorConcatenation( at(lanchors, b.ls[i]), + skipanchors ); + lanchors.insert( b.ls[i], a ); + } + } + mergeInto( &ls, b.ls ); + } + if ( b.minl == 0 ) { + mergeInto( &ranchors, b.ranchors ); + if ( b.skipanchors != 0 ) { + for ( int i = 0; i < (int) rs.size(); i++ ) { + int a = eng->anchorConcatenation( at(ranchors, rs[i]), + b.skipanchors ); + ranchors.insert( rs[i], a ); + } + } + mergeInto( &rs, b.rs ); + } else { + ranchors = b.ranchors; + rs = b.rs; + } + +#ifndef TQT_NO_REGEXP_OPTIM + if ( maxl != InftyLen ) { + if ( rightStr.length() + b.leftStr.length() > + TQMAX(str.length(), b.str.length()) ) { + earlyStart = minl - rightStr.length(); + lateStart = maxl - rightStr.length(); + str = rightStr + b.leftStr; + } else if ( b.str.length() > str.length() ) { + earlyStart = minl + b.earlyStart; + lateStart = maxl + b.lateStart; + str = b.str; + } + } + + if ( (int) leftStr.length() == maxl ) + leftStr += b.leftStr; + + if ( (int) b.rightStr.length() == b.maxl ) { + rightStr += b.rightStr; + } else { + rightStr = b.rightStr; + } + + if ( maxl == InftyLen || b.maxl == InftyLen ) { + maxl = InftyLen; + } else { + maxl += b.maxl; + } + + occ1.detach(); + for ( int i = 0; i < NumBadChars; i++ ) { + if ( b.occ1[i] != NoOccurrence && minl + b.occ1[i] < occ1[i] ) + occ1[i] = minl + b.occ1[i]; + } +#endif + + minl += b.minl; + if ( minl == 0 ) + skipanchors = eng->anchorConcatenation( skipanchors, b.skipanchors ); + else + skipanchors = 0; +} + +void TQRegExpEngine::Box::orx( const Box& b ) +{ + mergeInto( &ls, b.ls ); + mergeInto( &lanchors, b.lanchors ); + mergeInto( &rs, b.rs ); + mergeInto( &ranchors, b.ranchors ); + + if ( b.minl == 0 ) { + if ( minl == 0 ) + skipanchors = eng->anchorAlternation( skipanchors, b.skipanchors ); + else + skipanchors = b.skipanchors; + } + +#ifndef TQT_NO_REGEXP_OPTIM + occ1.detach(); + for ( int i = 0; i < NumBadChars; i++ ) { + if ( occ1[i] > b.occ1[i] ) + occ1[i] = b.occ1[i]; + } + earlyStart = 0; + lateStart = 0; + str = TQString(); + leftStr = TQString(); + rightStr = TQString(); + if ( b.maxl > maxl ) + maxl = b.maxl; +#endif + if ( b.minl < minl ) + minl = b.minl; +} + +void TQRegExpEngine::Box::plus( int atom ) +{ +#ifndef TQT_NO_REGEXP_CAPTURE + eng->addPlusTransitions( rs, ls, atom ); +#else + Q_UNUSED( atom ); + eng->addCatTransitions( rs, ls ); +#endif + addAnchorsToEngine( *this ); +#ifndef TQT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif +} + +void TQRegExpEngine::Box::opt() +{ +#ifndef TQT_NO_REGEXP_OPTIM + earlyStart = 0; + lateStart = 0; + str = TQString(); + leftStr = TQString(); + rightStr = TQString(); +#endif + skipanchors = 0; + minl = 0; +} + +void TQRegExpEngine::Box::catAnchor( int a ) +{ + if ( a != 0 ) { + for ( int i = 0; i < (int) rs.size(); i++ ) { + a = eng->anchorConcatenation( at(ranchors, rs[i]), a ); + ranchors.insert( rs[i], a ); + } + if ( minl == 0 ) + skipanchors = eng->anchorConcatenation( skipanchors, a ); + } +} + +#ifndef TQT_NO_REGEXP_OPTIM +void TQRegExpEngine::Box::setupHeuristics() +{ + eng->goodEarlyStart = earlyStart; + eng->goodLateStart = lateStart; + eng->goodStr = eng->cs ? str : str.lower(); + + eng->minl = minl; + if ( eng->cs ) { + /* + A regular expression such as 112|1 has occ1['2'] = 2 and minl = + 1 at this point. An entry of occ1 has to be at most minl or + infinity for the rest of the algorithm to go well. + + We waited until here before normalizing these cases (instead of + doing it in Box::orx()) because sometimes things improve by + themselves. Consider for example (112|1)34. + */ + for ( int i = 0; i < NumBadChars; i++ ) { + if ( occ1[i] != NoOccurrence && occ1[i] >= minl ) + occ1[i] = minl; + } + eng->occ1 = occ1; + } else { + eng->occ1.fill( 0, NumBadChars ); + } + + eng->heuristicallyChooseHeuristic(); +} +#endif + +#if defined(QT_DEBUG) +void TQRegExpEngine::Box::dump() const +{ + int i; + tqDebug( "Box of at least %d character%s", minl, minl == 1 ? "" : "s" ); + tqDebug( " Left states:" ); + for ( i = 0; i < (int) ls.size(); i++ ) { + if ( at(lanchors, ls[i]) == 0 ) + tqDebug( " %d", ls[i] ); + else + tqDebug( " %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]] ); + } + tqDebug( " Right states:" ); + for ( i = 0; i < (int) rs.size(); i++ ) { + if ( at(ranchors, rs[i]) == 0 ) + tqDebug( " %d", rs[i] ); + else + tqDebug( " %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]] ); + } + tqDebug( " Skip anchors: 0x%.8x", skipanchors ); +} +#endif + +void TQRegExpEngine::Box::addAnchorsToEngine( const Box& to ) const +{ + for ( int i = 0; i < (int) to.ls.size(); i++ ) { + for ( int j = 0; j < (int) rs.size(); j++ ) { + int a = eng->anchorConcatenation( at(ranchors, rs[j]), + at(to.lanchors, to.ls[i]) ); + eng->addAnchors( rs[j], to.ls[i], a ); + } + } +} + +int TQRegExpEngine::getChar() +{ + return ( yyPos == yyLen ) ? EOS : yyIn[yyPos++].unicode(); +} + +int TQRegExpEngine::getEscape() +{ +#ifndef TQT_NO_REGEXP_ESCAPE + const char tab[] = "afnrtv"; // no b, as \b means word boundary + const char backTab[] = "\a\f\n\r\t\v"; + ushort low; + int i; +#endif + ushort val; + int prevCh = yyCh; + + if ( prevCh == EOS ) { + error( RXERR_END ); + return Tok_Char | '\\'; + } + yyCh = getChar(); +#ifndef TQT_NO_REGEXP_ESCAPE + if ( (prevCh & ~0xff) == 0 ) { + const char *p = strchr( tab, prevCh ); + if ( p != 0 ) + return Tok_Char | backTab[p - tab]; + } +#endif + + switch ( prevCh ) { +#ifndef TQT_NO_REGEXP_ESCAPE + case '0': + val = 0; + for ( i = 0; i < 3; i++ ) { + if ( yyCh >= '0' && yyCh <= '7' ) + val = ( val << 3 ) | ( yyCh - '0' ); + else + break; + yyCh = getChar(); + } + if ( (val & ~0377) != 0 ) + error( RXERR_OCTAL ); + return Tok_Char | val; +#endif +#ifndef TQT_NO_REGEXP_ESCAPE + case 'B': + return Tok_NonWord; +#endif +#ifndef TQT_NO_REGEXP_CCLASS + case 'D': + // see TQChar::isDigit() + yyCharClass->addCategories( 0x7fffffef ); + return Tok_CharClass; + case 'S': + // see TQChar::isSpace() + yyCharClass->addCategories( 0x7ffff87f ); + yyCharClass->addRange( 0x0000, 0x0008 ); + yyCharClass->addRange( 0x000e, 0x001f ); + yyCharClass->addRange( 0x007f, 0x009f ); + return Tok_CharClass; + case 'W': + // see TQChar::isLetterOrNumber() + yyCharClass->addCategories( 0x7fe07f8f ); + yyCharClass->addRange( 0x203f, 0x2040 ); + yyCharClass->addSingleton( 0x2040 ); + yyCharClass->addSingleton( 0x30fb ); + yyCharClass->addRange( 0xfe33, 0xfe34 ); + yyCharClass->addRange( 0xfe4d, 0xfe4f ); + yyCharClass->addSingleton( 0xff3f ); + yyCharClass->addSingleton( 0xff65 ); + return Tok_CharClass; +#endif +#ifndef TQT_NO_REGEXP_ESCAPE + case 'b': + return Tok_Word; +#endif +#ifndef TQT_NO_REGEXP_CCLASS + case 'd': + // see TQChar::isDigit() + yyCharClass->addCategories( 0x00000010 ); + return Tok_CharClass; + case 's': + // see TQChar::isSpace() + yyCharClass->addCategories( 0x00000380 ); + yyCharClass->addRange( 0x0009, 0x000d ); + return Tok_CharClass; + case 'w': + // see TQChar::isLetterOrNumber() + yyCharClass->addCategories( 0x000f8070 ); + yyCharClass->addSingleton( 0x005f ); // '_' + return Tok_CharClass; +#endif +#ifndef TQT_NO_REGEXP_ESCAPE + case 'x': + val = 0; + for ( i = 0; i < 4; i++ ) { + low = TQChar( yyCh ).lower(); + if ( low >= '0' && low <= '9' ) + val = ( val << 4 ) | ( low - '0' ); + else if ( low >= 'a' && low <= 'f' ) + val = ( val << 4 ) | ( low - 'a' + 10 ); + else + break; + yyCh = getChar(); + } + return Tok_Char | val; +#endif + default: + if ( prevCh >= '1' && prevCh <= '9' ) { +#ifndef TQT_NO_REGEXP_BACKREF + val = prevCh - '0'; + while ( yyCh >= '0' && yyCh <= '9' ) { + val = ( val * 10 ) + ( yyCh - '0' ); + yyCh = getChar(); + } + return Tok_BackRef | val; +#else + error( RXERR_DISABLED ); +#endif + } + return Tok_Char | prevCh; + } +} + +#ifndef TQT_NO_REGEXP_INTERVAL +int TQRegExpEngine::getRep( int def ) +{ + if ( yyCh >= '0' && yyCh <= '9' ) { + int rep = 0; + do { + rep = 10 * rep + yyCh - '0'; + if ( rep >= InftyRep ) { + error( RXERR_REPETITION ); + rep = def; + } + yyCh = getChar(); + } while ( yyCh >= '0' && yyCh <= '9' ); + return rep; + } else { + return def; + } +} +#endif + +#ifndef TQT_NO_REGEXP_LOOKAHEAD +void TQRegExpEngine::skipChars( int n ) +{ + if ( n > 0 ) { + yyPos += n - 1; + yyCh = getChar(); + } +} +#endif + +void TQRegExpEngine::error( const char *msg ) +{ + if ( yyError.isEmpty() ) + yyError = TQString::fromLatin1( msg ); +} + +void TQRegExpEngine::startTokenizer( const TQChar *rx, int len ) +{ + yyIn = rx; + yyPos0 = 0; + yyPos = 0; + yyLen = len; + yyCh = getChar(); + yyCharClass = new CharClass; + yyMinRep = 0; + yyMaxRep = 0; + yyError = TQString(); +} + +int TQRegExpEngine::getToken() +{ +#ifndef TQT_NO_REGEXP_CCLASS + ushort pendingCh = 0; + bool charPending; + bool rangePending; + int tok; +#endif + int prevCh = yyCh; + + yyPos0 = yyPos - 1; +#ifndef TQT_NO_REGEXP_CCLASS + yyCharClass->clear(); +#endif + yyMinRep = 0; + yyMaxRep = 0; + yyCh = getChar(); + + switch ( prevCh ) { + case EOS: + yyPos0 = yyPos; + return Tok_Eos; + case '$': + return Tok_Dollar; + case '(': + if ( yyCh == '?' ) { + prevCh = getChar(); + yyCh = getChar(); + switch ( prevCh ) { +#ifndef TQT_NO_REGEXP_LOOKAHEAD + case '!': + return Tok_NegLookahead; + case '=': + return Tok_PosLookahead; +#endif + case ':': + return Tok_MagicLeftParen; + default: + error( RXERR_LOOKAHEAD ); + return Tok_MagicLeftParen; + } + } else { + return Tok_LeftParen; + } + case ')': + return Tok_RightParen; + case '*': + yyMinRep = 0; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '+': + yyMinRep = 1; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '.': +#ifndef TQT_NO_REGEXP_CCLASS + yyCharClass->setNegative( TRUE ); +#endif + return Tok_CharClass; + case '?': + yyMinRep = 0; + yyMaxRep = 1; + return Tok_Quantifier; + case '[': +#ifndef TQT_NO_REGEXP_CCLASS + if ( yyCh == '^' ) { + yyCharClass->setNegative( TRUE ); + yyCh = getChar(); + } + charPending = FALSE; + rangePending = FALSE; + do { + if ( yyCh == '-' && charPending && !rangePending ) { + rangePending = TRUE; + yyCh = getChar(); + } else { + if ( charPending && !rangePending ) { + yyCharClass->addSingleton( pendingCh ); + charPending = FALSE; + } + if ( yyCh == '\\' ) { + yyCh = getChar(); + tok = getEscape(); + if ( tok == Tok_Word ) + tok = '\b'; + } else { + tok = Tok_Char | yyCh; + yyCh = getChar(); + } + if ( tok == Tok_CharClass ) { + if ( rangePending ) { + yyCharClass->addSingleton( '-' ); + yyCharClass->addSingleton( pendingCh ); + charPending = FALSE; + rangePending = FALSE; + } + } else if ( (tok & Tok_Char) != 0 ) { + if ( rangePending ) { + yyCharClass->addRange( pendingCh, tok ^ Tok_Char ); + charPending = FALSE; + rangePending = FALSE; + } else { + pendingCh = tok ^ Tok_Char; + charPending = TRUE; + } + } else { + error( RXERR_CHARCLASS ); + } + } + } while ( yyCh != ']' && yyCh != EOS ); + if ( rangePending ) + yyCharClass->addSingleton( '-' ); + if ( charPending ) + yyCharClass->addSingleton( pendingCh ); + if ( yyCh == EOS ) + error( RXERR_END ); + else + yyCh = getChar(); + return Tok_CharClass; +#else + error( RXERR_END ); + return Tok_Char | '['; +#endif + case '\\': + return getEscape(); + case ']': + error( RXERR_LEFTDELIM ); + return Tok_Char | ']'; + case '^': + return Tok_Caret; + case '{': +#ifndef TQT_NO_REGEXP_INTERVAL + yyMinRep = getRep( 0 ); + yyMaxRep = yyMinRep; + if ( yyCh == ',' ) { + yyCh = getChar(); + yyMaxRep = getRep( InftyRep ); + } + if ( yyMaxRep < yyMinRep ) + tqSwap( yyMinRep, yyMaxRep ); + if ( yyCh != '}' ) + error( RXERR_REPETITION ); + yyCh = getChar(); + return Tok_Quantifier; +#else + error( RXERR_DISABLED ); + return Tok_Char | '{'; +#endif + case '|': + return Tok_Bar; + case '}': + error( RXERR_LEFTDELIM ); + return Tok_Char | '}'; + default: + return Tok_Char | prevCh; + } +} + +int TQRegExpEngine::parse( const TQChar *pattern, int len ) +{ + valid = TRUE; + startTokenizer( pattern, len ); + yyTok = getToken(); +#ifndef TQT_NO_REGEXP_CAPTURE + yyMayCapture = TRUE; +#else + yyMayCapture = FALSE; +#endif + +#ifndef TQT_NO_REGEXP_CAPTURE + int atom = startAtom( FALSE ); +#endif + CharClass anything; + Box box( this ); // create InitialState + box.set( anything ); + Box rightBox( this ); // create FinalState + rightBox.set( anything ); + + Box middleBox( this ); + parseExpression( &middleBox ); +#ifndef TQT_NO_REGEXP_CAPTURE + finishAtom( atom ); +#endif +#ifndef TQT_NO_REGEXP_OPTIM + middleBox.setupHeuristics(); +#endif + box.cat( middleBox ); + box.cat( rightBox ); + delete yyCharClass; + yyCharClass = 0; + + officialncap = ncap; +#ifndef TQT_NO_REGEXP_BACKREF + if ( nbrefs > ncap ) + ncap = nbrefs; +#endif + + /* + We use one TQMemArray for all the big data used a lot in + matchHere() and friends. + */ +#ifndef TQT_NO_REGEXP_OPTIM + mmSlideTabSize = TQMAX( minl + 1, 16 ); +#else + mmSlideTabSize = 0; +#endif + mmBigArray.resize( (3 + 4 * ncap) * ns + 4 * ncap + mmSlideTabSize ); + + mmInNextStack = mmBigArray.data(); + memset( mmInNextStack, -1, ns * sizeof(int) ); + mmCurStack = mmInNextStack + ns; + mmNextStack = mmInNextStack + 2 * ns; + + mmCurCapBegin = mmInNextStack + 3 * ns; + mmNextCapBegin = mmCurCapBegin + ncap * ns; + mmCurCapEnd = mmCurCapBegin + 2 * ncap * ns; + mmNextCapEnd = mmCurCapBegin + 3 * ncap * ns; + + mmTempCapBegin = mmCurCapBegin + 4 * ncap * ns; + mmTempCapEnd = mmTempCapBegin + ncap; + mmCapBegin = mmTempCapBegin + 2 * ncap; + mmCapEnd = mmTempCapBegin + 3 * ncap; + + mmSlideTab = mmTempCapBegin + 4 * ncap; + + if ( !yyError.isEmpty() ) + return -1; + +#ifndef TQT_NO_REGEXP_OPTIM + State *sinit = s[InitialState]; + caretAnchored = ( sinit->anchors != 0 ); + if ( caretAnchored ) { + TQMap& anchors = *sinit->anchors; + TQMap::ConstIterator a; + for ( a = anchors.begin(); a != anchors.end(); ++a ) { + if ( +#ifndef TQT_NO_REGEXP_ANCHOR_ALT + (*a & Anchor_Alternation) != 0 || +#endif + (*a & Anchor_Caret) == 0 ) { + caretAnchored = FALSE; + break; + } + } + } +#endif + return yyPos0; +} + +void TQRegExpEngine::parseAtom( Box *box ) +{ +#ifndef TQT_NO_REGEXP_LOOKAHEAD + TQRegExpEngine *eng = 0; + bool neg; + int len; +#endif + + if ( (yyTok & Tok_Char) != 0 ) { + box->set( TQChar(yyTok ^ Tok_Char) ); + } else { +#ifndef TQT_NO_REGEXP_OPTIM + trivial = FALSE; +#endif + switch ( yyTok ) { + case Tok_Dollar: + box->catAnchor( Anchor_Dollar ); + break; + case Tok_Caret: + box->catAnchor( Anchor_Caret ); + break; +#ifndef TQT_NO_REGEXP_LOOKAHEAD + case Tok_PosLookahead: + case Tok_NegLookahead: + neg = ( yyTok == Tok_NegLookahead ); + eng = new TQRegExpEngine( cs ); + len = eng->parse( yyIn + yyPos - 1, yyLen - yyPos + 1 ); + if ( len >= 0 ) + skipChars( len ); + else + error( RXERR_LOOKAHEAD ); + box->catAnchor( addLookahead(eng, neg) ); + yyTok = getToken(); + if ( yyTok != Tok_RightParen ) + error( RXERR_LOOKAHEAD ); + break; +#endif +#ifndef TQT_NO_REGEXP_ESCAPE + case Tok_Word: + box->catAnchor( Anchor_Word ); + break; + case Tok_NonWord: + box->catAnchor( Anchor_NonWord ); + break; +#endif + case Tok_LeftParen: + case Tok_MagicLeftParen: + yyTok = getToken(); + parseExpression( box ); + if ( yyTok != Tok_RightParen ) + error( RXERR_END ); + break; + case Tok_CharClass: + box->set( *yyCharClass ); + break; + case Tok_Quantifier: + error( RXERR_REPETITION ); + break; + default: +#ifndef TQT_NO_REGEXP_BACKREF + if ( (yyTok & Tok_BackRef) != 0 ) + box->set( yyTok ^ Tok_BackRef ); + else +#endif + error( RXERR_DISABLED ); + } + } + yyTok = getToken(); +} + +void TQRegExpEngine::parseFactor( Box *box ) +{ +#ifndef TQT_NO_REGEXP_CAPTURE + int atom = startAtom( yyMayCapture && yyTok == Tok_LeftParen ); +#else + static const int atom = 0; +#endif + +#ifndef TQT_NO_REGEXP_INTERVAL +#define YYREDO() \ + yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \ + *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok + + const TQChar *in = yyIn; + int pos0 = yyPos0; + int pos = yyPos; + int len = yyLen; + int ch = yyCh; + CharClass charClass; + if ( yyTok == Tok_CharClass ) + charClass = *yyCharClass; + int tok = yyTok; + bool mayCapture = yyMayCapture; +#endif + + parseAtom( box ); +#ifndef TQT_NO_REGEXP_CAPTURE + finishAtom( atom ); +#endif + + if ( yyTok == Tok_Quantifier ) { +#ifndef TQT_NO_REGEXP_OPTIM + trivial = FALSE; +#endif + if ( yyMaxRep == InftyRep ) { + box->plus( atom ); +#ifndef TQT_NO_REGEXP_INTERVAL + } else if ( yyMaxRep == 0 ) { + box->clear(); +#endif + } + if ( yyMinRep == 0 ) + box->opt(); + +#ifndef TQT_NO_REGEXP_INTERVAL + yyMayCapture = FALSE; + int alpha = ( yyMinRep == 0 ) ? 0 : yyMinRep - 1; + int beta = ( yyMaxRep == InftyRep ) ? 0 : yyMaxRep - ( alpha + 1 ); + + Box rightBox( this ); + int i; + + for ( i = 0; i < beta; i++ ) { + YYREDO(); + Box leftBox( this ); + parseAtom( &leftBox ); + leftBox.cat( rightBox ); + leftBox.opt(); + rightBox = leftBox; + } + for ( i = 0; i < alpha; i++ ) { + YYREDO(); + Box leftBox( this ); + parseAtom( &leftBox ); + leftBox.cat( rightBox ); + rightBox = leftBox; + } + rightBox.cat( *box ); + *box = rightBox; +#endif + yyTok = getToken(); +#ifndef TQT_NO_REGEXP_INTERVAL + yyMayCapture = mayCapture; +#endif + } +#undef YYREDO +} + +void TQRegExpEngine::parseTerm( Box *box ) +{ +#ifndef TQT_NO_REGEXP_OPTIM + if ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) + parseFactor( box ); +#endif + while ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) { + Box rightBox( this ); + parseFactor( &rightBox ); + box->cat( rightBox ); + } +} + +void TQRegExpEngine::parseExpression( Box *box ) +{ + parseTerm( box ); + while ( yyTok == Tok_Bar ) { +#ifndef TQT_NO_REGEXP_OPTIM + trivial = FALSE; +#endif + Box rightBox( this ); + yyTok = getToken(); + parseTerm( &rightBox ); + box->orx( rightBox ); + } +} + +/* + The struct TQRegExpPrivate contains the private data of a regular + expression other than the automaton. It makes it possible for many + TQRegExp objects to use the same TQRegExpEngine object with different + TQRegExpPrivate objects. +*/ +struct TQRegExpPrivate +{ + TQString pattern; // regular-expression or wildcard pattern + TQString rxpattern; // regular-expression pattern +#ifndef TQT_NO_REGEXP_WILDCARD + bool wc : 1; // wildcard mode? +#endif + bool min : 1; // minimal matching? (instead of maximal) + bool cs : 1; // case sensitive? +#ifndef TQT_NO_REGEXP_CAPTURE + TQString t; // last string passed to TQRegExp::search() or searchRev() + TQStringList capturedCache; // what TQRegExp::capturedTexts() returned last +#endif + TQMemArray captured; // what TQRegExpEngine::search() returned last + + TQRegExpPrivate() { captured.fill( -1, 2 ); } +}; + +#ifndef TQT_NO_REGEXP_OPTIM +static TQSingleCleanupHandler > cleanup_cache; +# ifndef TQT_THREAD_SUPPORT +static TQCache *engineCache = 0; +# endif // TQT_THREAD_SUPPORT +#endif // TQT_NO_REGEXP_OPTIM + +static void regexpEngine( TQRegExpEngine *&eng, const TQString &pattern, + bool caseSensitive, bool deref ) +{ +# ifdef TQT_THREAD_SUPPORT + static TQThreadStorage *> engineCaches; + TQCache *engineCache = 0; + TQThreadInstance *currentThread = TQThreadInstance::current(); + if (currentThread) + engineCache = engineCaches.localData(); +#endif // TQT_THREAD_SUPPORT + + if ( !deref ) { +#ifndef TQT_NO_REGEXP_OPTIM +# ifdef TQT_THREAD_SUPPORT + if ( currentThread ) +# endif + { + if ( engineCache != 0 ) { + eng = engineCache->take( pattern ); + if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { + delete eng; + } else { + eng->ref(); + return; + } + } + } +#endif // TQT_NO_REGEXP_OPTIM + eng = new TQRegExpEngine( pattern, caseSensitive ); + return; + } + + if ( eng->deref() ) { +#ifndef TQT_NO_REGEXP_OPTIM +# ifdef TQT_THREAD_SUPPORT + if ( currentThread ) +# endif + { + if ( engineCache == 0 ) { + engineCache = new TQCache; + engineCache->setAutoDelete( TRUE ); +# ifdef TQT_THREAD_SUPPORT + engineCaches.setLocalData(engineCache); +# else + cleanup_cache.set( &engineCache ); +# endif // !TQT_THREAD_SUPPORT + } + if ( !pattern.isNull() && + engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) + return; + } +#else + Q_UNUSED( pattern ); +#endif // TQT_NO_REGEXP_OPTIM + delete eng; + eng = 0; + } +} + +/*! + \enum TQRegExp::CaretMode + + The CaretMode enum defines the different meanings of the caret + (^) in a regular expression. The possible values are: + + \value CaretAtZero + The caret corresponds to index 0 in the searched string. + + \value CaretAtOffset + The caret corresponds to the start offset of the search. + + \value CaretWontMatch + The caret never matches. +*/ + +/*! + Constructs an empty regexp. + + \sa isValid() errorString() +*/ +TQRegExp::TQRegExp() + : eng( 0 ) +{ + priv = new TQRegExpPrivate; +#ifndef TQT_NO_REGEXP_WILDCARD + priv->wc = FALSE; +#endif + priv->min = FALSE; + priv->cs = TRUE; +} + +/*! + Constructs a regular expression object for the given \a pattern + string. The pattern must be given using wildcard notation if \a + wildcard is TRUE (default is FALSE). The pattern is case + sensitive, unless \a caseSensitive is FALSE. Matching is greedy + (maximal), but can be changed by calling setMinimal(). + + \sa setPattern() setCaseSensitive() setWildcard() setMinimal() +*/ +TQRegExp::TQRegExp( const TQString& pattern, bool caseSensitive, bool wildcard ) + : eng( 0 ) +{ + priv = new TQRegExpPrivate; + priv->pattern = pattern; +#ifndef TQT_NO_REGEXP_WILDCARD + priv->wc = wildcard; +#endif + priv->min = FALSE; + priv->cs = caseSensitive; +} + +/*! + Constructs a regular expression as a copy of \a rx. + + \sa operator=() +*/ +TQRegExp::TQRegExp( const TQRegExp& rx ) + : eng( 0 ) +{ + priv = new TQRegExpPrivate; + operator=( rx ); +} + +/*! + Destroys the regular expression and cleans up its internal data. +*/ +TQRegExp::~TQRegExp() +{ + invalidateEngine(); + delete priv; +} + +/*! + Copies the regular expression \a rx and returns a reference to the + copy. The case sensitivity, wildcard and minimal matching options + are also copied. +*/ +TQRegExp& TQRegExp::operator=( const TQRegExp& rx ) +{ + TQRegExpEngine *otherEng = rx.eng; + if ( otherEng != 0 ) + otherEng->ref(); + invalidateEngine(); + eng = otherEng; + priv->pattern = rx.priv->pattern; + priv->rxpattern = rx.priv->rxpattern; +#ifndef TQT_NO_REGEXP_WILDCARD + priv->wc = rx.priv->wc; +#endif + priv->min = rx.priv->min; + priv->cs = rx.priv->cs; +#ifndef TQT_NO_REGEXP_CAPTURE + priv->t = rx.priv->t; + priv->capturedCache = rx.priv->capturedCache; +#endif + priv->captured = rx.priv->captured; + return *this; +} + +/*! + Returns TRUE if this regular expression is equal to \a rx; + otherwise returns FALSE. + + Two TQRegExp objects are equal if they have the same pattern + strings and the same settings for case sensitivity, wildcard and + minimal matching. +*/ +bool TQRegExp::operator==( const TQRegExp& rx ) const +{ + return priv->pattern == rx.priv->pattern && +#ifndef TQT_NO_REGEXP_WILDCARD + priv->wc == rx.priv->wc && +#endif + priv->min == rx.priv->min && + priv->cs == rx.priv->cs; +} + +/*! + \fn bool TQRegExp::operator!=( const TQRegExp& rx ) const + + Returns TRUE if this regular expression is not equal to \a rx; + otherwise returns FALSE. + + \sa operator==() +*/ + +/*! + Returns TRUE if the pattern string is empty; otherwise returns + FALSE. + + If you call exactMatch() with an empty pattern on an empty string + it will return TRUE; otherwise it returns FALSE since it operates + over the whole string. If you call search() with an empty pattern + on \e any string it will return the start offset (0 by default) + because the empty pattern matches the 'emptiness' at the start of + the string. In this case the length of the match returned by + matchedLength() will be 0. + + See TQString::isEmpty(). +*/ + +bool TQRegExp::isEmpty() const +{ + return priv->pattern.isEmpty(); +} + +/*! + Returns TRUE if the regular expression is valid; otherwise returns + FALSE. An invalid regular expression never matches. + + The pattern [a-z is an example of an invalid pattern, since + it lacks a closing square bracket. + + Note that the validity of a regexp may also depend on the setting + of the wildcard flag, for example *.html is a valid + wildcard regexp but an invalid full regexp. + + \sa errorString() +*/ +bool TQRegExp::isValid() const +{ + if ( priv->pattern.isEmpty() ) { + return TRUE; + } else { + prepareEngine(); + return eng->isValid(); + } +} + +/*! + Returns the pattern string of the regular expression. The pattern + has either regular expression syntax or wildcard syntax, depending + on wildcard(). + + \sa setPattern() +*/ +TQString TQRegExp::pattern() const +{ + return priv->pattern; +} + +/*! + Sets the pattern string to \a pattern. The case sensitivity, + wildcard and minimal matching options are not changed. + + \sa pattern() +*/ +void TQRegExp::setPattern( const TQString& pattern ) +{ + if ( priv->pattern != pattern ) { + priv->pattern = pattern; + invalidateEngine(); + } +} + +/*! + Returns TRUE if case sensitivity is enabled; otherwise returns + FALSE. The default is TRUE. + + \sa setCaseSensitive() +*/ +bool TQRegExp::caseSensitive() const +{ + return priv->cs; +} + +/*! + Sets case sensitive matching to \a sensitive. + + If \a sensitive is TRUE, \\.txt$ matches \c{readme.txt} but + not \c{README.TXT}. + + \sa caseSensitive() +*/ +void TQRegExp::setCaseSensitive( bool sensitive ) +{ + if ( sensitive != priv->cs ) { + priv->cs = sensitive; + invalidateEngine(); + } +} + +#ifndef TQT_NO_REGEXP_WILDCARD +/*! + Returns TRUE if wildcard mode is enabled; otherwise returns FALSE. + The default is FALSE. + + \sa setWildcard() +*/ +bool TQRegExp::wildcard() const +{ + return priv->wc; +} + +/*! + Sets the wildcard mode for the regular expression. The default is + FALSE. + + Setting \a wildcard to TRUE enables simple shell-like wildcard + matching. (See \link #wildcard-matching wildcard matching + (globbing) \endlink.) + + For example, r*.txt matches the string \c{readme.txt} in + wildcard mode, but does not match \c{readme}. + + \sa wildcard() +*/ +void TQRegExp::setWildcard( bool wildcard ) +{ + if ( wildcard != priv->wc ) { + priv->wc = wildcard; + invalidateEngine(); + } +} +#endif + +/*! + Returns TRUE if minimal (non-greedy) matching is enabled; + otherwise returns FALSE. + + \sa setMinimal() +*/ +bool TQRegExp::minimal() const +{ + return priv->min; +} + +/*! + Enables or disables minimal matching. If \a minimal is FALSE, + matching is greedy (maximal) which is the default. + + For example, suppose we have the input string "We must be + \bold\, very \bold\!" and the pattern + \.*\. With the default greedy (maximal) matching, + the match is "We must be \bold\, very + \bold\!". But with minimal (non-greedy) matching the + first match is: "We must be \bold\, very + \bold\!" and the second match is "We must be \bold\, + very \bold\!". In practice we might use the pattern + \[^\<]+\ instead, although this will still fail for + nested tags. + + \sa minimal() +*/ +void TQRegExp::setMinimal( bool minimal ) +{ + priv->min = minimal; +} + +/*! + Returns TRUE if \a str is matched exactly by this regular + expression; otherwise returns FALSE. You can determine how much of + the string was matched by calling matchedLength(). + + For a given regexp string, R, exactMatch("R") is the equivalent of + search("^R$") since exactMatch() effectively encloses the regexp + in the start of string and end of string anchors, except that it + sets matchedLength() differently. + + For example, if the regular expression is blue, then + exactMatch() returns TRUE only for input \c blue. For inputs \c + bluebell, \c blutak and \c lightblue, exactMatch() returns FALSE + and matchedLength() will return 4, 3 and 0 respectively. + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \sa search() searchRev() TQRegExpValidator +*/ +bool TQRegExp::exactMatch( const TQString& str ) const +{ + prepareEngineForMatch( str ); + eng->match( str, 0, priv->min, TRUE, 0, priv->captured ); + if ( priv->captured[1] == (int) str.length() ) { + return TRUE; + } else { + priv->captured[0] = 0; + priv->captured[1] = eng->partialMatchLength(); + return FALSE; + } +} + +#ifndef TQT_NO_COMPAT +/*! \obsolete + + Attempts to match in \a str, starting from position \a index. + Returns the position of the match, or -1 if there was no match. + + The length of the match is stored in \a *len, unless \a len is a + null pointer. + + If \a indexIsStart is TRUE (the default), the position \a index in + the string will match the start of string anchor, ^, in the + regexp, if present. Otherwise, position 0 in \a str will match. + + Use search() and matchedLength() instead of this function. + + \sa TQString::mid() TQConstString +*/ +int TQRegExp::match( const TQString& str, int index, int *len, + bool indexIsStart ) const +{ + int pos = search( str, index, indexIsStart ? CaretAtOffset : CaretAtZero ); + if ( len != 0 ) + *len = matchedLength(); + return pos; +} +#endif // TQT_NO_COMPAT + +int TQRegExp::search( const TQString& str, int offset ) const +{ + return search( str, offset, CaretAtZero ); +} + +/*! + Attempts to find a match in \a str from position \a offset (0 by + default). If \a offset is -1, the search starts at the last + character; if -2, at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no + match. + + The \a caretMode parameter can be used to instruct whether ^ + should match at index 0 or at \a offset. + + You might prefer to use TQString::find(), TQString::contains() or + even TQStringList::grep(). To replace matches use + TQString::replace(). + + Example: + \code + TQString str = "offsets: 1.23 .50 71.00 6.00"; + TQRegExp rx( "\\d*\\.\\d+" ); // primitive floating point matching + int count = 0; + int pos = 0; + while ( (pos = rx.search(str, pos)) != -1 ) { + count++; + pos += rx.matchedLength(); + } + // pos will be 9, 14, 18 and finally 24; count will end up as 4 + \endcode + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \sa searchRev() exactMatch() +*/ + +int TQRegExp::search( const TQString& str, int offset, CaretMode caretMode ) const +{ + prepareEngineForMatch( str ); + if ( offset < 0 ) + offset += str.length(); + eng->match( str, offset, priv->min, FALSE, caretIndex(offset, caretMode), + priv->captured ); + return priv->captured[0]; +} + + +int TQRegExp::searchRev( const TQString& str, int offset ) const +{ + return searchRev( str, offset, CaretAtZero ); +} + +/*! + Attempts to find a match backwards in \a str from position \a + offset. If \a offset is -1 (the default), the search starts at the + last character; if -2, at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no + match. + + The \a caretMode parameter can be used to instruct whether ^ + should match at index 0 or at \a offset. + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \warning Searching backwards is much slower than searching + forwards. + + \sa search() exactMatch() +*/ + +int TQRegExp::searchRev( const TQString& str, int offset, + CaretMode caretMode ) const +{ + prepareEngineForMatch( str ); + if ( offset < 0 ) + offset += str.length(); + if ( offset < 0 || offset > (int) str.length() ) { + priv->captured.detach(); + priv->captured.fill( -1 ); + return -1; + } + + while ( offset >= 0 ) { + eng->match( str, offset, priv->min, TRUE, caretIndex(offset, caretMode), + priv->captured ); + if ( priv->captured[0] == offset ) + return offset; + offset--; + } + return -1; +} + +/*! + Returns the length of the last matched string, or -1 if there was + no match. + + \sa exactMatch() search() searchRev() +*/ +int TQRegExp::matchedLength() const +{ + return priv->captured[1]; +} + +#ifndef TQT_NO_REGEXP_CAPTURE +/*! + Returns the number of captures contained in the regular expression. + */ +int TQRegExp::numCaptures() const +{ + prepareEngine(); + return eng->numCaptures(); +} + +/*! + Returns a list of the captured text strings. + + The first string in the list is the entire matched string. Each + subsequent list element contains a string that matched a + (capturing) subexpression of the regexp. + + For example: + \code + TQRegExp rx( "(\\d+)(\\s*)(cm|inch(es)?)" ); + int pos = rx.search( "Length: 36 inches" ); + TQStringList list = rx.capturedTexts(); + // list is now ( "36 inches", "36", " ", "inches", "es" ) + \endcode + + The above example also captures elements that may be present but + which we have no interest in. This problem can be solved by using + non-capturing parentheses: + + \code + TQRegExp rx( "(\\d+)(?:\\s*)(cm|inch(?:es)?)" ); + int pos = rx.search( "Length: 36 inches" ); + TQStringList list = rx.capturedTexts(); + // list is now ( "36 inches", "36", "inches" ) + \endcode + + Note that if you want to iterate over the list, you should iterate + over a copy, e.g. + \code + TQStringList list = rx.capturedTexts(); + TQStringList::Iterator it = list.begin(); + while( it != list.end() ) { + myProcessing( *it ); + ++it; + } + \endcode + + Some regexps can match an indeterminate number of times. For + example if the input string is "Offsets: 12 14 99 231 7" and the + regexp, \c{rx}, is (\\d+)+, we would hope to get a list of + all the numbers matched. However, after calling + \c{rx.search(str)}, capturedTexts() will return the list ( "12", + "12" ), i.e. the entire match was "12" and the first subexpression + matched was "12". The correct approach is to use cap() in a \link + #cap_in_a_loop loop \endlink. + + The order of elements in the string list is as follows. The first + element is the entire matching string. Each subsequent element + corresponds to the next capturing open left parentheses. Thus + capturedTexts()[1] is the text of the first capturing parentheses, + capturedTexts()[2] is the text of the second and so on + (corresponding to $1, $2, etc., in some other regexp languages). + + \sa cap() pos() exactMatch() search() searchRev() +*/ +TQStringList TQRegExp::capturedTexts() +{ + if ( priv->capturedCache.isEmpty() ) { + for ( int i = 0; i < (int) priv->captured.size(); i += 2 ) { + TQString m; + if ( priv->captured[i + 1] == 0 ) + m = TQString::fromLatin1( "" ); + else if ( priv->captured[i] >= 0 ) + m = priv->t.mid( priv->captured[i], + priv->captured[i + 1] ); + priv->capturedCache.append( m ); + } + priv->t = TQString::null; + } + return priv->capturedCache; +} + +/*! + Returns the text captured by the \a nth subexpression. The entire + match has index 0 and the parenthesized subexpressions have + indices starting from 1 (excluding non-capturing parentheses). + + \code + TQRegExp rxlen( "(\\d+)(?:\\s*)(cm|inch)" ); + int pos = rxlen.search( "Length: 189cm" ); + if ( pos > -1 ) { + TQString value = rxlen.cap( 1 ); // "189" + TQString unit = rxlen.cap( 2 ); // "cm" + // ... + } + \endcode + + The order of elements matched by cap() is as follows. The first + element, cap(0), is the entire matching string. Each subsequent + element corresponds to the next capturing open left parentheses. + Thus cap(1) is the text of the first capturing parentheses, cap(2) + is the text of the second, and so on. + + \target cap_in_a_loop + Some patterns may lead to a number of matches which cannot be + determined in advance, for example: + + \code + TQRegExp rx( "(\\d+)" ); + str = "Offsets: 12 14 99 231 7"; + TQStringList list; + pos = 0; + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + if ( pos > -1 ) { + list += rx.cap( 1 ); + pos += rx.matchedLength(); + } + } + // list contains "12", "14", "99", "231", "7" + \endcode + + \sa capturedTexts() pos() exactMatch() search() searchRev() +*/ +TQString TQRegExp::cap( int nth ) +{ + if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) { + return TQString::null; + } else { + return capturedTexts()[nth]; + } +} + +/*! + Returns the position of the \a nth captured text in the searched + string. If \a nth is 0 (the default), pos() returns the position + of the whole match. + + Example: + \code + TQRegExp rx( "/([a-z]+)/([a-z]+)" ); + rx.search( "Output /dev/null" ); // returns 7 (position of /dev/null) + rx.pos( 0 ); // returns 7 (position of /dev/null) + rx.pos( 1 ); // returns 8 (position of dev) + rx.pos( 2 ); // returns 12 (position of null) + \endcode + + For zero-length matches, pos() always returns -1. (For example, if + cap(4) would return an empty string, pos(4) returns -1.) This is + due to an implementation tradeoff. + + \sa capturedTexts() exactMatch() search() searchRev() +*/ +int TQRegExp::pos( int nth ) +{ + if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) + return -1; + else + return priv->captured[2 * nth]; +} + +/*! + Returns a text string that explains why a regexp pattern is + invalid the case being; otherwise returns "no error occurred". + + \sa isValid() +*/ +TQString TQRegExp::errorString() +{ + if ( isValid() ) { + return TQString( RXERR_OK ); + } else { + return eng->errorString(); + } +} +#endif + +/*! + Returns the string \a str with every regexp special character + escaped with a backslash. The special characters are $, (, ), *, +, + ., ?, [, \, ], ^, {, | and }. + + Example: + \code + s1 = TQRegExp::escape( "bingo" ); // s1 == "bingo" + s2 = TQRegExp::escape( "f(x)" ); // s2 == "f\\(x\\)" + \endcode + + This function is useful to construct regexp patterns dynamically: + + \code + TQRegExp rx( "(" + TQRegExp::escape(name) + + "|" + TQRegExp::escape(alias) + ")" ); + \endcode +*/ +TQString TQRegExp::escape( const TQString& str ) +{ + static const char meta[] = "$()*+.?[\\]^{|}"; + TQString quoted = str; + int i = 0; + + while ( i < (int) quoted.length() ) { + if ( strchr(meta, quoted[i].latin1()) != 0 ) + quoted.insert( i++, "\\" ); + i++; + } + return quoted; +} + +void TQRegExp::prepareEngine() const +{ + if ( eng == 0 ) { +#ifndef TQT_NO_REGEXP_WILDCARD + if ( priv->wc ) + priv->rxpattern = wc2rx( priv->pattern ); + else +#endif + priv->rxpattern = priv->pattern.isNull() ? TQString::fromLatin1( "" ) + : priv->pattern; + TQRegExp *that = (TQRegExp *) this; + // that->eng = newEngine( priv->rxpattern, priv->cs ); + regexpEngine( that->eng, priv->rxpattern, priv->cs, FALSE ); + priv->captured.detach(); + priv->captured.fill( -1, 2 + 2 * eng->numCaptures() ); + } +} + +void TQRegExp::prepareEngineForMatch( const TQString& str ) const +{ + prepareEngine(); +#ifndef TQT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#else + Q_UNUSED( str ); +#endif +} + +void TQRegExp::invalidateEngine() +{ + if ( eng != 0 ) { + regexpEngine( eng, priv->rxpattern, priv->cs, TRUE ); + priv->rxpattern = TQString(); + eng = 0; + } +} + +int TQRegExp::caretIndex( int offset, CaretMode caretMode ) +{ + if ( caretMode == CaretAtZero ) { + return 0; + } else if ( caretMode == CaretAtOffset ) { + return offset; + } else { // CaretWontMatch + return -1; + } +} + +#endif // TQT_NO_REGEXP diff --git a/src/tools/tqregexp.h b/src/tools/tqregexp.h new file mode 100644 index 000000000..d8aca02c0 --- /dev/null +++ b/src/tools/tqregexp.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Definition of TQRegExp class +** +** Created : 950126 +** +** 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 requirements 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. +** +**********************************************************************/ + +#ifndef TQREGEXP_H +#define TQREGEXP_H + +#ifndef QT_H +#include "tqstringlist.h" +#endif // QT_H + +#ifndef TQT_NO_REGEXP +class TQRegExpEngine; +struct TQRegExpPrivate; + +class TQ_EXPORT TQRegExp +{ +public: + enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; + + TQRegExp(); + TQRegExp( const TQString& pattern, bool caseSensitive = TRUE, + bool wildcard = FALSE ); + TQRegExp( const TQRegExp& rx ); + ~TQRegExp(); + TQRegExp& operator=( const TQRegExp& rx ); + + bool operator==( const TQRegExp& rx ) const; + bool operator!=( const TQRegExp& rx ) const { return !operator==( rx ); } + + bool isEmpty() const; + bool isValid() const; + TQString pattern() const; + void setPattern( const TQString& pattern ); + bool caseSensitive() const; + void setCaseSensitive( bool sensitive ); +#ifndef TQT_NO_REGEXP_WILDCARD + bool wildcard() const; + void setWildcard( bool wildcard ); +#endif + bool minimal() const; + void setMinimal( bool minimal ); + + bool exactMatch( const TQString& str ) const; +#ifndef TQT_NO_COMPAT + int match( const TQString& str, int index = 0, int *len = 0, + bool indexIsStart = TRUE ) const; +#endif + +#if defined(Q_QDOC) + int search( const TQString& str, int offset = 0, + CaretMode caretMode = CaretAtZero ) const; + int searchRev( const TQString& str, int offset = -1, + CaretMode caretMode = CaretAtZero ) const; +#else + // ### TQt 4.0: reduce these four to two functions + int search( const TQString& str, int offset = 0 ) const; + int search( const TQString& str, int offset, CaretMode caretMode ) const; + int searchRev( const TQString& str, int offset = -1 ) const; + int searchRev( const TQString& str, int offset, CaretMode caretMode ) const; +#endif + int matchedLength() const; +#ifndef TQT_NO_REGEXP_CAPTURE + int numCaptures() const; + TQStringList capturedTexts(); + TQString cap( int nth = 0 ); + int pos( int nth = 0 ); + TQString errorString(); +#endif + + static TQString escape( const TQString& str ); + +private: + void prepareEngine() const; + void prepareEngineForMatch( const TQString& str ) const; + void invalidateEngine(); + + static int caretIndex( int offset, CaretMode caretMode ); + + TQRegExpEngine *eng; + TQRegExpPrivate *priv; +}; +#endif // TQT_NO_REGEXP +#endif // TQREGEXP_H diff --git a/src/tools/tqstring.cpp b/src/tools/tqstring.cpp index 71eced17d..86b1add58 100644 --- a/src/tools/tqstring.cpp +++ b/src/tools/tqstring.cpp @@ -51,7 +51,7 @@ // #define MAKE_QSTRING_THREAD_SAFE 1 #include "tqstring.h" -#include "ntqregexp.h" +#include "tqregexp.h" #include "ntqdatastream.h" #ifndef TQT_NO_TEXTCODEC #include "tqtextcodec.h" @@ -1380,7 +1380,7 @@ char* TQString::unicodeToLatin1(const TQChar *uc, uint l, bool unpaged) 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 ntqregexp.html regex\endlink using + that match a particular \link tqregexp.html regex\endlink using TQStringList::grep(). Note for C programmers @@ -4673,7 +4673,7 @@ TQString &TQString::replace( const TQString & before, const TQString & after ) // s == "ba" \endcode - For regexps containing \link ntqregexp.html#capturing-text capturing + For regexps containing \link tqregexp.html#capturing-text capturing parentheses \endlink, occurrences of \\1, \\2, ..., in \a after are replaced with \a{rx}.cap(1), cap(2), ... diff --git a/src/tools/tqstring.h b/src/tools/tqstring.h index ce9ccf108..253ba3a03 100644 --- a/src/tools/tqstring.h +++ b/src/tools/tqstring.h @@ -43,7 +43,7 @@ #define TQSTRING_H #ifndef QT_H -#include "ntqcstring.h" +#include "tqcstring.h" #endif // QT_H #ifndef TQT_NO_CAST_ASCII diff --git a/src/tools/tqstringlist.cpp b/src/tools/tqstringlist.cpp index 48bbbd541..8e08a4f08 100644 --- a/src/tools/tqstringlist.cpp +++ b/src/tools/tqstringlist.cpp @@ -41,7 +41,7 @@ #include "tqstringlist.h" #ifndef TQT_NO_STRINGLIST -#include "ntqregexp.h" +#include "tqregexp.h" #include "tqstrlist.h" #include "ntqdatastream.h" #include "ntqtl.h" @@ -388,7 +388,7 @@ TQStringList& TQStringList::gres( const TQString &before, const TQString &after, // list == ["olpha", "beta", "gamma", "epsilon"] \endcode - For regexps containing \link ntqregexp.html#capturing-text + For regexps containing \link tqregexp.html#capturing-text capturing parentheses \endlink, occurrences of \\1, \\2, ..., in \a after are replaced with \a{rx}.cap(1), cap(2), ... diff --git a/src/tools/tqtextstream.cpp b/src/tools/tqtextstream.cpp index 218c9b106..0a911b0ed 100644 --- a/src/tools/tqtextstream.cpp +++ b/src/tools/tqtextstream.cpp @@ -42,7 +42,7 @@ #ifndef TQT_NO_TEXTSTREAM #include "tqtextcodec.h" -#include "ntqregexp.h" +#include "tqregexp.h" #include "ntqbuffer.h" #include "ntqfile.h" #include -- cgit v1.2.1