// ____ ______ __ // / __ \ / ____// / // / /_/ // / / / // / ____// /___ / /___ PixInsight Class Library // /_/ \____//_____/ PCL 2.4.23 // ---------------------------------------------------------------------------- // pcl/String.h - Released 2022-03-12T18:59:29Z // ---------------------------------------------------------------------------- // This file is part of the PixInsight Class Library (PCL). // PCL is a multiplatform C++ framework for development of PixInsight modules. // // Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved. // // Redistribution and use in both source and binary forms, with or without // modification, is permitted provided that the following conditions are met: // // 1. All redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. All redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names // of their contributors, may be used to endorse or promote products derived // from this software without specific prior written permission. For written // permission, please contact info@pixinsight.com. // // 4. All products derived from this software, in any form whatsoever, must // reproduce the following acknowledgment in the end-user documentation // and/or other materials provided with the product: // // "This product is based on software from the PixInsight project, developed // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)." // // Alternatively, if that is where third-party acknowledgments normally // appear, this acknowledgment must be reproduced in the product itself. // // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE, // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // ---------------------------------------------------------------------------- #ifndef __PCL_String_h #define __PCL_String_h /// \file pcl/String.h #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __PCL_ALIGNED_STRING_ALLOCATION # include # define PCL_STRING_ALLOCATOR AlignedAllocator #else # include # define PCL_STRING_ALLOCATOR StandardAllocator #endif #ifndef __PCL_NO_STRING_COMPLEX # include #endif #ifndef __PCL_NO_STRING_OSTREAM # ifndef _MSC_VER # define _GLIBCXX_USE_WCHAR_T 1 # endif # include #endif #ifdef __PCL_QT_INTERFACE # include # include # include # define PCL_GET_CHARPTR_FROM_QSTRING( qs ) (qs.toLatin1().data()) # define PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ((char16_type*)( qs.utf16() )) # define PCL_GET_QSTRING_FROM_CHAR16PTR( s ) (QString::fromUtf16( (const ushort*)(s) )) # define PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) (qb.data()) # define PCL_QDATE_FMT_STR "yyyy/MM/dd" # define PCL_QDATETIME_FMT_STR "yyyy/MM/dd hh:mm:ss" #endif namespace pcl { // ---------------------------------------------------------------------------- /*! * \namespace pcl::RandomizationOption * \brief String randomization options * * * * * * * * * * * *
RandomizationOption::Lowercase Generate random lowercase alphabetic characters: [a..z]
RandomizationOption::Uppercase Generate random uppercase alphabetic characters: [A..Z]
RandomizationOption::Alpha Generate random lowercase and uppercase alphabetic characters: [a..zA..Z]
RandomizationOption::Digits Generate random decimal digits: [0..9]
RandomizationOption::Symbols Generate random symbol characters: .#/[]() etc.
RandomizationOption::HexDigits Generate random hexadecimal digits: [0..9a..f], or [0..9A..F] if Uppercase is set.
RandomizationOption::BinDigits Generate random binary digits: [01].
RandomizationOption::FullRange Generate random characters in the whole range of code points except zero.
RandomizationOption::Default Default options: Alpha|Digits
*/ namespace RandomizationOption { enum mask_type { Lowercase = 0x00000001, // Generate random lowercase alphabetic characters: a..z Uppercase = 0x00000002, // Generate random uppercase alphabetic characters: A..Z Alpha = Lowercase|Uppercase, // Generate random alphabetic characters: a..zA..Z Digits = 0x00000004, // Generate random decimal digits: 0..9 Symbols = 0x00000008, // Generate random symbol characters: .#/[]() etc HexDigits = 0x00000010, // Generate hexadecimal digits: 0..9a..f or 0..9A..F BinDigits = 0x00000020, // Generate binary digits: 0 and 1 FullRange = 0x80000000, // Generate random characters in the whole range of code points except zero Default = Alpha|Digits }; }; /*! * \class pcl::RandomizationOptions * \brief A collection of string randomization options. */ typedef Flags RandomizationOptions; // ---------------------------------------------------------------------------- /*! * \defgroup sexagesimal_conversion Sexagesimal String Representation and Parsing */ /*! * \struct SexagesimalConversionOptions * \brief Formatting options for string sexagesimal representations. * * \ingroup sexagesimal_conversion * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), * AngleConversionOptions, LongitudeConversionOptions, RAConversionOptions, * LatitudeConversionOptions, DecConversionOptions */ struct PCL_CLASS SexagesimalConversionOptions { /*! * Number of represented items. Can be 1, 2 or 3. All items but the last one * are represented as integer values. The last item is represented as a * floating point value with the specified precision. The default value is * three items. */ unsigned items : 2; /*! * Number of decimal digits for the last represented sexagesimal item. The * default value is two decimal digits. */ unsigned precision : 4; /*! * Whether to always prepend a sign character to the first represented item, * even '+' for positive values. This is false by default. */ bool sign : 1; /*! * Width of the integer part of the first represented item in characters, * including the sign when applicable. When the specified width is larger * than the length of the represented item, it is left-padded with padding * characters as necessary. The default is zero, which means that no padding * is performed for the first item by default. */ unsigned width : 4; /*! * A single character used for separation of sexagesimal components. The * default separator is a colon character, ':'. */ char separator; /*! * A single character used for padding right-justified representations of * first sexagesimal components. See the width member. The default padding * character is the white space, ' '. */ char padding; /*! * Default constructor. */ constexpr SexagesimalConversionOptions( unsigned items_ = 3, unsigned precision_ = 2, bool sign_ = false, unsigned width_ = 0, char separator_ = ':', char padding_ = ' ' ) : items( items_ ) , precision( precision_ ) , sign( sign_ ) , width( width_ ) , separator( separator_ ) , padding( padding_ ) { } /*! * Copy constructor. */ SexagesimalConversionOptions( const SexagesimalConversionOptions& ) = default; /*! * Copy assignment operator. Returns a reference to this object. */ SexagesimalConversionOptions& operator =( const SexagesimalConversionOptions& ) = default; }; // ---------------------------------------------------------------------------- /*! * \struct AngleConversionOptions * \brief A set of options specific for string representations of angles. * * This is a convenience structure to ease string representations of angles in * the range [0°,360°) as degrees, minutes and seconds of arc. * * \ingroup sexagesimal_conversion * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), * SexagesimalConversionOptions, LongitudeConversionOptions, * RAConversionOptions, LatitudeConversionOptions, DecConversionOptions */ struct PCL_CLASS AngleConversionOptions : public SexagesimalConversionOptions { /*! * Constructs an %AngleConversionOptions structure initialized for the * specified \a precision and first item \a width and \a padding character. * The string representation will consist of three items separated by * spaces. If \a width is nonzero, the first item will be represented * right-justified within a field of \a width \a padding characters. */ constexpr AngleConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' ) : SexagesimalConversionOptions( 3/*items*/, precision, false/*sign*/, width, ' '/*separator*/, padding ) {} }; // ---------------------------------------------------------------------------- /*! * \struct LongitudeConversionOptions * \brief A set of options specific for string representations of longitude * angles. * * This is a convenience structure to ease string representations of angles in * the range [-180°,+180°] as degrees, minutes and seconds of arc. * * \ingroup sexagesimal_conversion * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), * SexagesimalConversionOptions, AngleConversionOptions, RAConversionOptions, * LatitudeConversionOptions, DecConversionOptions */ struct PCL_CLASS LongitudeConversionOptions : public SexagesimalConversionOptions { /*! * Constructs a %LongitudeConversionOptions structure initialized for the * specified \a precision and first item \a width and \a padding character. * The string representation will consist of three items separated by * spaces. If \a width is nonzero, the first item will be represented * right-justified within a field of \a width \a padding characters, * including a leading sign character. */ constexpr LongitudeConversionOptions( unsigned precision = 2, unsigned width = 4, char padding = ' ' ) : SexagesimalConversionOptions( 3/*items*/, precision, true/*sign*/, width, ' '/*separator*/, padding ) {} }; // ---------------------------------------------------------------------------- /*! * \struct RAConversionOptions * \brief A set of options specific for string representations of right * ascensions. * * This is a convenience structure to ease string representations of hour * angles in the range [0h,24h) as hours, minutes and * seconds. * * \ingroup sexagesimal_conversion * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), * SexagesimalConversionOptions, AngleConversionOptions, * LongitudeConversionOptions, LatitudeConversionOptions, DecConversionOptions */ struct PCL_CLASS RAConversionOptions : public SexagesimalConversionOptions { /*! * Constructs a %RAConversionOptions structure initialized for the specified * \a precision and first item \a width and \a padding character. The string * representation will consist of three items separated by spaces. If * \a width is nonzero, the first item will be represented right-justified * within a field of \a width \a padding characters. */ constexpr RAConversionOptions( unsigned precision = 3, unsigned width = 2, char padding = ' ' ) : SexagesimalConversionOptions( 3/*items*/, precision, false/*sign*/, width, ' '/*separator*/, padding ) {} }; // ---------------------------------------------------------------------------- /*! * \struct LatitudeConversionOptions * \brief A set of options specific for string representations of latitude * angles. * * This is a convenience structure to ease string representations of angles in * the range [-90°,+90°] as degrees, minutes and seconds of arc. * * \ingroup sexagesimal_conversion * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), * SexagesimalConversionOptions, AngleConversionOptions, * LongitudeConversionOptions, RAConversionOptions, DecConversionOptions */ struct PCL_CLASS LatitudeConversionOptions : public SexagesimalConversionOptions { /*! * Constructs a %LatitudeConversionOptions structure initialized for the * specified \a precision and first item \a width and \a padding character. * The string representation will consist of three items separated by * spaces. If \a width is nonzero, the first item will be represented * right-justified within a field of \a width \a padding characters, * including a leading sign character. */ constexpr LatitudeConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' ) : SexagesimalConversionOptions( 3/*items*/, precision, true/*sign*/, width, ' '/*separator*/, padding ) {} }; // ---------------------------------------------------------------------------- /*! * \struct DecConversionOptions * \brief A set of options specific for string representations of declination * angles. * * This structure is a convenience alias of LatitudeConversionOptions. * * \ingroup sexagesimal_conversion * \sa IsoString::ToSexagesimal(), String::ToSexagesimal(), * SexagesimalConversionOptions, AngleConversionOptions, * LongitudeConversionOptions, RAConversionOptions, LatitudeConversionOptions */ struct PCL_CLASS DecConversionOptions : public LatitudeConversionOptions { /*! * Constructs a %DecConversionOptions structure initialized for the * specified \a precision and first item \a width and \a padding character. * The string representation will consist of three items separated by * spaces. If \a width is nonzero, the first item will be represented * right-justified within a field of \a width \a padding characters, * including a leading sign character. */ constexpr DecConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' ) : LatitudeConversionOptions( precision, width, padding ) {} }; // ---------------------------------------------------------------------------- /*! * \struct ISO8601ConversionOptions * \brief Formatting options for string representations of dates and times in * ISO 8601 format. * * \sa IsoString::ToISO8601DateTime(), String::ToISO8601DateTime() */ struct PCL_CLASS ISO8601ConversionOptions { /*! * Number of represented time items. Can be 0, 1, 2 or 3. All items but the * last one are represented as integer values. The last item is represented * as a floating point value with the specified precision. The default value * is three time items. */ unsigned timeItems : 2; /*! * Number of decimal digits for the last represented time item. The default * value is three decimal digits. */ unsigned precision : 4; /*! * Whether to append a time zone specifier to the ISO 8601 representation. * The default value is true. */ bool timeZone : 1; /*! * Whether to append the 'Z' special time zone specifier for UTC time, or * the '+00:00' specifier otherwise. The default value is true. */ bool zuluTime : 1; /*! * Default constructor. */ constexpr ISO8601ConversionOptions( unsigned timeItems_ = 3, unsigned precision_ = 3, bool timeZone_ = true, bool zuluTime_ = true ) : timeItems( timeItems_ ) , precision( precision_ ) , timeZone( timeZone_ ) , zuluTime( zuluTime_ ) { } /*! * Copy constructor. */ ISO8601ConversionOptions( const ISO8601ConversionOptions& ) = default; /*! * Copy assignment operator. Returns a reference to this object. */ ISO8601ConversionOptions& operator =( const ISO8601ConversionOptions& ) = default; }; // ---------------------------------------------------------------------------- /*! * \class GenericString * \brief Generic character string. * * %GenericString is a finite, ordered sequence of characters implemented as a * reference-counted, dynamic array of objects of type T, whose fundamental * behavior is specified by an instantiation type R of GenericCharTraits for * the character type T (typically GenericCharTraits, or a derived class such * as CharTraits or IsoCharTraits), and where the type A provides dynamic * allocation for contiguous sequences of elements of type T (StandardAllocator * is used by default). * * On the PixInsight platform, all dynamically allocated strings have been * implemented as two instantiations of the %GenericString template class, * namely the String (UTF-16 string) and IsoString (UTF-8 or ISO/IEC-8859-1 * string) classes. * * \sa String, IsoString, CharTraits, IsoCharTraits */ template class PCL_CLASS GenericString : public DirectContainer { public: /*! * Represents a string character. */ typedef T char_type; /*! * The character traits class used by this string class. */ typedef R char_traits; /*! * The block allocator used by this string class. */ typedef A block_allocator; /*! * The allocator class used by this string class. */ typedef pcl::Allocator allocator; /*! * Null-terminated string of char_type characters. */ typedef T* c_string; /*! * Immutable null-terminated string of char_type characters. */ typedef const T* const_c_string; /*! * String iterator. */ typedef T* iterator; /*! * Immutable string iterator. */ typedef const T* const_iterator; /*! * Reverse string iterator. */ typedef ReverseRandomAccessIterator reverse_iterator; /*! * Reverse immutable string iterator. */ typedef ReverseRandomAccessIterator const_reverse_iterator; // ------------------------------------------------------------------------- /*! * Constant used to signal unsuccessful search operations. */ static const size_type notFound = ~size_type( 0 ); /*! * Corresponds to the maximum possible character index in a string. */ static const size_type maxPos = ~size_type( 0 ); // ------------------------------------------------------------------------- /*! * Constructs an empty string. */ GenericString() { m_data = Data::New(); } /*! * Copy constructor. Increments the reference counter of the string \a s. */ GenericString( const GenericString& s ) : m_data( s.m_data ) { m_data->Attach(); } /*! * Move constructor. */ GenericString( GenericString&& s ) : m_data( s.m_data ) { s.m_data = nullptr; } /*! * Constructs a string with a copy of the null-terminated character sequence * stored in the specified array \a t. */ GenericString( const_c_string t ) { size_type len = R::Length( t ); if ( len > 0 ) { m_data = Data::New( len ); R::Copy( m_data->string, t, len ); } else m_data = Data::New(); } /*! * Constructs a string with a copy of the character sequence defined by the * range [i,j). * * If \a i is greater than or equal to \a j, this constructor creates an * empty string. Otherwise it will assign the specified sequence of * characters. * * \b Important - Note that this constructor is \e not equivalent to: * * \code GenericString( i, 0, j-i ); \endcode * * because the above call would assign a null-terminated sequence, while * this function assigns the specified range unconditionally, even if it * contains null characters. Since this constructor does not have to scan * for a terminating character, it is potentially more efficient. */ GenericString( const_iterator i, const_iterator j ) { if ( i < j ) { size_type len = j - i; m_data = Data::New( len ); R::Copy( m_data->string, i, len ); } else m_data = Data::New(); } /*! * Constructs a string and initializes it with characters taken from the * specified initializer list \a l. * * This constructor is equivalent to: * * \code GenericString( l.begin(), l.end() ) \endcode */ GenericString( std::initializer_list l ) : GenericString( l.begin(), l.end() ) { } /*! * Constructs a string with a copy of at most \a n characters stored in the * null-terminated sequence \a t, starting from its \a i-th character. */ GenericString( const_c_string t, size_type i, size_type n ) { size_type len = R::Length( t ); if ( i < len && (n = pcl::Min( n, len-i )) > 0 ) { m_data = Data::New( n ); R::Copy( m_data->string, t+i, n ); } else m_data = Data::New(); } /*! * Constructs a string with \a n copies of a character \a c. */ GenericString( char_type c, size_type n = 1 ) { if ( n > 0 ) { m_data = Data::New( n ); R::Fill( m_data->string, c, n ); } else m_data = Data::New(); } /*! * Destroys this string. Decrements the reference counter of the string data * and, if it becomes unreferenced, it is destroyed and deallocated. */ ~GenericString() { if ( m_data != nullptr ) { DetachFromData(); m_data = nullptr; } } /*! * Returns true iff this string uniquely references its string data. * * \sa EnsureUnique(), IsAliasOf() */ bool IsUnique() const noexcept { return m_data->IsUnique(); } /*! * Returns true iff this string is an alias of another string \a s. * * Two strings are aliases if both share the same string data. * * \sa IsUnique(), EnsureUnique() */ bool IsAliasOf( const GenericString& s ) const noexcept { return m_data == s.m_data; } /*! * Ensures that this string uniquely references its string data. * * If necessary, this member function generates a duplicate of the string * data, references it, and then decrements the reference counter of the * original string data. * * \sa IsUnique(), IsAliasOf() */ void EnsureUnique() { if ( !IsUnique() ) { size_type len = Length(); Data* newData = Data::New( len ); if ( len > 0 ) R::Copy( newData->string, m_data->string, len ); DetachFromData(); m_data = newData; } } /*! * Returns the number of bytes necessary to store a single character in this * string. * * This member function returns the R::BytesPerChar() static member function * of the char traits class R. */ static size_type BytesPerChar() noexcept { return R::BytesPerChar(); } /*! * Returns the total number of bytes required to store the string data * referenced by this string, \e excluding the terminating null character. * * \sa Length(), Capacity() */ size_type Size() const noexcept { return Length()*BytesPerChar(); } /*! * Returns the length of this string in characters. This \e excludes the * terminating null character. * * \sa IsEmpty(), Available(), Capacity(), Size() */ size_type Length() const noexcept { return m_data->end - m_data->string; } /*! * Returns the total capacity of this string in characters. * * The capacity of a string is the maximum number of characters that can be * stored before requiring a reallocation of string data. * * \sa Available(), Length(), Size() */ size_type Capacity() const noexcept { return m_data->capacity - m_data->string; } /*! * Returns the number of characters available in this string. * * The number of available characters is equal to Capacity() - Length(). * * \sa Capacity(), Length(), Size() */ size_type Available() const noexcept { return m_data->capacity - m_data->end; } /*! * Returns true only if this string is valid. A string is valid if it * references an internal string structure, even if it is an empty string. * * In general, all %GenericString objects are valid with only two * exceptions: * * \li Objects that have been move-copied or move-assigned to other strings. * \li Objects that have been invalidated explicitly by calling Transfer(). * * An invalid string object cannot be used and should be destroyed * immediately. Invalid strings are always destroyed automatically during * move construction and move assignment operations. * * \sa IsEmpty() */ bool IsValid() const noexcept { return m_data != nullptr; } /*! * Returns true only if this string is empty. * * An empty string has zero length and stores no characters. * * \sa IsValid(), Length(), Available(), Capacity(), Size() */ bool IsEmpty() const noexcept { return m_data->string == m_data->end; } /*! * Returns the minimum valid character index. * * This member function exists for compatibility with PCL containers. It * always returns zero. * * \sa UpperBound(), Length() */ size_type LowerBound() const noexcept { return 0; } /*! * Returns the maximum valid character index. * * The returned value is equal to Length()-1. If this string is empty, the * index returned by this member function is invalid and equal to maxPos. * * \sa LowerBound(), Length() */ size_type UpperBound() const noexcept { PCL_PRECONDITION( !IsEmpty() ) return Length()-1; } /*! * Returns a reference to the (immutable) allocator object in this string. * * \sa SetAllocator() */ const allocator& Allocator() const noexcept { return m_data->alloc; } /*! * Sets the allocator object used by this string to a copy of the specified * allocator \a a. * * If this string is not unique, it is made unique before returning from * this member function. * * \sa Allocator() */ void SetAllocator( const allocator& a ) { EnsureUnique(); m_data->alloc = a; } /*! * Returns an iterator located at the \a i-th character of this string. * The character index \a i must be in the range [0,Length()). * * If this string is not unique, it is made unique before returning from * this member function. * * If this string is empty, or if the specified index \a i is out of range, * calling this member function is an error that leads to an invalid result. * * \sa operator []( size_type ) */ iterator At( size_type i ) { PCL_PRECONDITION( i < Length() ) EnsureUnique(); return m_data->string + i; } /*! * Returns an immutable iterator located at the \a i-th character in this * string. The character index \a i must be in the range [0,Length()). * * If this string is empty, or if the specified index \a i is out of range, * calling this member function is an error that leads to an invalid result. * * \sa operator []( size_type ) const */ const_iterator At( size_type i ) const noexcept { PCL_PRECONDITION( i < Length() ) return m_data->string + i; } /*! * Returns a reference to the \a i-th character in this string. The * character index \a i must be in the range [0,Length()). * * If this string is not unique, it is made unique before returning from * this member function. * * If this string is empty, or if the specified index \a i is out of range, * calling this member function is an error that leads to an invalid result. * * \sa At(), operator *() */ char_type& operator []( size_type i ) { return *At( i ); } /*! * Returns a copy of the \a i-th character in this string. The character * index \a i must be in the range [0,Length()). * * If this string is empty, or if the specified index \a i is out of range, * calling this member function is an error that leads to an invalid result. * * \sa At() const, operator *() const */ char_type operator []( size_type i ) const noexcept { return *At( i ); } /*! * Returns a reference to the first character in this string. * * This is a convenience member function, equivalent to *At( 0 ). * * \sa operator []( size_type ), At() */ char_type& operator *() { EnsureUnique(); return *m_data->string; } /*! * Returns a copy of the first character in this string. * * This is a convenience member function, equivalent to *At( 0 ). * * \sa operator []( size_type ) const, At() */ char_type operator *() const noexcept { return *m_data->string; } /*! * Returns a mutable iterator pointing to the first character of this * string. * * If this string is not unique, it is made unique before returning from * this member function. * * If this string is empty, this member function returns \c nullptr. * * \sa End() */ iterator Begin() { EnsureUnique(); return m_data->string; } /*! * Returns an immutable iterator pointing to the first character of this * string. * * If this string is empty, this member function returns \c nullptr. * * \sa End() const */ const_iterator Begin() const noexcept { return m_data->string; } /*! * Returns a mutable iterator pointing to the end of this string. The * returned iterator points to the next-to-last character of this string. * * If this string is not unique, it is made unique before returning from * this member function. * * If this string is empty, this member function returns \c nullptr. * * \sa Begin() */ iterator End() { EnsureUnique(); return m_data->end; } /*! * Returns an immutable iterator pointing to the end of this string. The * returned iterator points to the next-to-last character of this string. * * If this string is empty, this member function returns \c nullptr. * * \sa Begin() const */ const_iterator End() const noexcept { return m_data->end; } /*! * Returns a reverse mutable iterator pointing to the reverse * beginning of this string. The returned iterator points to the last * character of this string. * * If this string is not unique, it is made unique before returning from * this member function. * * If this string is empty, this member function returns a null reverse * iterator. * * \sa ReverseEnd() */ reverse_iterator ReverseBegin() { EnsureUnique(); return (m_data->string < m_data->end) ? m_data->end-1 : nullptr; } /*! * Returns an immutable reverse iterator pointing to the reverse * beginning of this string. The returned iterator points to the last * character of this string. * * If this string is empty, this member function returns a null reverse * iterator. * * \sa ReverseEnd() const */ const_reverse_iterator ReverseBegin() const noexcept { return (m_data->string < m_data->end) ? m_data->end-1 : nullptr; } /*! * Returns a reverse mutable iterator pointing to the reverse end * of this string. The returned iterator points to the * previous-to-first character of this string. * * If this string is not unique, it is made unique before returning from * this member function. * * If this string is empty, this member function returns a null reverse * iterator. * * \sa ReverseBegin() */ reverse_iterator ReverseEnd() { EnsureUnique(); return (m_data->string < m_data->end) ? m_data->string-1 : nullptr; } /*! * Returns an immutable reverse iterator pointing to the reverse * end of this string. The returned iterator points to the * previous-to-first character of this string. * * If this string is empty, this member function returns a null reverse * iterator. * * \sa ReverseBegin() const */ const_reverse_iterator ReverseEnd() const noexcept { return (m_data->string < m_data->end) ? m_data->string-1 : nullptr; } /*! * Returns the zero-based character index corresponding to a valid iterator * \a i in this string. This is equivalent to \a i - Begin(). * * The specified iterator must be posterior to or located at the starting * iterator of this string, as returned by Begin(). However, for performance * reasons this condition is neither enforced nor verified. If an invalid * iterator is specified, then this function, as well as any subsequent use * of the returned character index, may invoke undefined behavior. */ size_type IndexAt( const_iterator i ) const noexcept { PCL_PRECONDITION( i >= m_data->string ) return i - m_data->string; } #ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS /*! * STL-compatible iteration. Equivalent to Begin(). */ iterator begin() { return Begin(); } /*! * STL-compatible iteration. Equivalent to Begin() const. */ const_iterator begin() const noexcept { return Begin(); } /*! * STL-compatible iteration. Equivalent to End(). */ iterator end() { return End(); } /*! * STL-compatible iteration. Equivalent to End() const. */ const_iterator end() const noexcept { return End(); } #endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS /*! * Returns a pointer to the immutable internal data array of this string. * * If this string is empty, this member function returns a pointer to a * static, null-terminated, unmodifiable empty string (the "" C string). * This function always returns a valid pointer to existing character data. */ const_c_string c_str() const noexcept { static const char_type theNullChar = char_traits::Null(); return IsEmpty() ? &theNullChar : Begin(); } /*! * Copy assignment operator. Returns a reference to this object. * * This operator calls Assign() with the specified source string \a s. */ GenericString& operator =( const GenericString& s ) { Assign( s ); return *this; } /*! * Assigns a string \a s to this string. * * If this instance and the specified source instance \a s reference * different string data, then the data previously referenced by this object * is dereferenced. If the previous data becomes unreferenced, it is * destroyed and deallocated. Then the data being referenced by \a s is also * referenced by this object. * * If this instance and the specified source instance \a s already reference * the same string data, then this function does nothing. * * \sa Transfer() */ void Assign( const GenericString& s ) { s.m_data->Attach(); DetachFromData(); m_data = s.m_data; } /*! * Move assignment operator. Returns a reference to this object. * * This operator calls Transfer() with the specified source string \a s. */ GenericString& operator =( GenericString&& s ) { Transfer( s ); return *this; } /*! * Transfers data from another object \a s to this string. * * Decrements the reference counter of the current string data. If the data * becomes unreferenced, it is destroyed and deallocated. The string data * referenced by the source object \a s is then transferred to this object. * * \warning The source string \a s will be an invalid object after calling * this function, and hence should be destroyed immediately. Any attempt to * access an invalid object will most likely lead to a crash. * * \sa Assign() */ void Transfer( GenericString& s ) { DetachFromData(); m_data = s.m_data; s.m_data = nullptr; } /*! * Transfers data from another object \a s to this string. * * See Transfer( GenericString& ) for detailed information. */ void Transfer( GenericString&& s ) { DetachFromData(); m_data = s.m_data; s.m_data = nullptr; } /*! * Assigns a copy of the null-terminated character sequence stored in the * specified array \a t to this string. Returns a reference to this object. */ GenericString& operator =( const_c_string t ) { Assign( t ); return *this; } /*! * Assigns a single character \a c to this string. Returns a reference to * this object. */ GenericString& operator =( char_type c ) { Assign( c, 1 ); return *this; } /*! * Assigns a substring of at most \a n characters from a source string \a s, * starting from its \a i-th character, to this string. */ void Assign( const GenericString& s, size_type i, size_type n ) { Transfer( s.Substring( i, n ) ); } /*! * Assigns a copy of the null-terminated character sequence stored in the * specified array \a t to this string. * * If \a t is a pointer to the contents of this string (or, equivalently, an * iterator on this string), this function invokes undefined behavior. */ void Assign( const_c_string t ) { size_type len = R::Length( t ); if ( len > 0 ) { MaybeReallocate( len ); R::Copy( m_data->string, t, len ); } else Clear(); } /*! * Assigns a copy of the character sequence defined by the range [i,j) to * this string. * * If \a i is greater than or equal to \a j, this function empties the string * by calling Clear(). Otherwise this function will assign the specified * sequence of characters. * * If \a i and/or \a j are iterators on this string, this function invokes * undefined behavior. * * \b Important - Note that this function is \e not equivalent to: * * \code Assign( i, 0, j-i ); \endcode * * because the above call would assign a null-terminated sequence, while * this function assigns the specified range unconditionally, even if it * contains null characters. Since this function does not have to scan for * a terminating character, it is potentially much more efficient. */ void Assign( const_iterator i, const_iterator j ) { if ( i < j ) { size_type len = j - i; MaybeReallocate( len ); R::Copy( m_data->string, i, len ); } else Clear(); } /*! * Assigns a sequence of characters defined by the specified initializer * list \a l to this string. This function is equivalent to: * * \code Assign( l.begin(), l.end() ) \endcode */ void Assign( std::initializer_list l ) { Assign( l.begin(), l.end() ); } /*! * Assigns a copy of at most \a n characters stored in the null-terminated * sequence \a t, starting from its \a i-th character, to this string. * * If \a t is the null pointer, or \a i is greater than the length of \a t, * or \a n is zero, this function empties the string by calling Clear(). * * If \a t is a pointer to the contents of this string (or, equivalently, an * iterator on this string), this function invokes undefined behavior. * * The character count \a n will be constrained to copy existing characters * from the null-terminated source sequence. */ void Assign( const_c_string t, size_type i, size_type n ) { size_type len = R::Length( t ); if ( i < len && (n = pcl::Min( n, len-i )) > 0 ) { MaybeReallocate( n ); R::Copy( m_data->string, t+i, n ); } else Clear(); } /*! * Assigns \a n copies of the specified character \a c to this string. If * either \a c is the null character or \a n is zero, this function empties * the string by calling Clear(). */ void Assign( char_type c, size_type n = 1 ) { if ( !R::IsNull( c ) && n > 0 ) { MaybeReallocate( n ); R::Fill( m_data->string, c, n ); } else Clear(); } /*! * Exchanges this string with another string \a s. */ void Swap( GenericString& s ) noexcept { pcl::Swap( m_data, s.m_data ); } /*! * Fills this string (if not empty) with the specified character \a c. * * \note The null terminating character can legally be specified as a * filling character with this function. In this case the internal string * pointer will be seen as an empty string by C library routines (such as * strlen or strcpy) and other applications after calling this function, * although it will continue storing the same allocated data block. */ void Fill( char_type c ) { size_type len = Length(); if ( len > 0 ) { if ( !IsUnique() ) { Data* newData = Data::New( len ); DetachFromData(); m_data = newData; } R::Fill( m_data->string, c, len ); } } /*! * Fills a segment of at most \a n contiguous characters in this string with * the specified character \a c, starting from the \a i-th character. * * If \a i is greater than or equal to the length of this string, then * calling this function has no effect. Otherwise the character count \a n * will be constrained to replace existing characters in this string. * * \note The null terminating character can legally be specified as a * filling character with this function. In this case the internal string * pointer will be seen as an empty string by C library routines (such as * strlen or strcpy) and other applications after calling this function, * although it will continue storing the same allocated data block. */ void Fill( char_type c, size_type i, size_type n = maxPos ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n < len ) EnsureUnique(); else if ( !IsUnique() ) { Data* newData = Data::New( len ); DetachFromData(); m_data = newData; } R::Fill( m_data->string+i, c, n ); } } /*! * Securely fills this string and all instances sharing its string data with * the specified character \a c. * * If no filling character \a c is specified, the string will be filled with * zeros, or null characters. * * The normal data sharing mechanism is ignored on purpose by this function, * so if there are other objects sharing the same string data, all of them * will be affected unconditionally after calling this function. * * This function is useful to ensure that sensitive data, such as user * passwords and user names, are destroyed without the risk of surviving * duplicates as a result of implicit data sharing. * * \note If the specified filling character \a c is zero, or the null * character (the default value), the internal string pointer will be seen * as an empty string by C library routines (such as strlen or strcpy) and * other applications after calling this function, although it will continue * storing the same allocated data block. */ void SecureFill( char c = '\0' ) noexcept { volatile char* s = reinterpret_cast( m_data->string ); for ( size_type n = Capacity()*sizeof( char_type ); n > 0; --n ) *s++ = c; } /*! * Ensures that this string has enough capacity to store \a n characters * plus a terminating null character. * * After calling this member function with \a n > 0, this object is * guaranteed to uniquely reference its string data. */ void Reserve( size_type n ) { if ( n > 0 ) if ( IsUnique() ) { if ( Capacity() < n+1 ) { iterator old = m_data->string; size_type len = Length(); m_data->Reserve( len, n ); if ( old != nullptr ) { if ( len > 0 ) R::Copy( m_data->string, old, len ); m_data->alloc.Deallocate( old ); } } } else { size_type len = Length(); Data* newData = Data::New(); // ### FIXME: unlikely, but this is a potential leak newData->Reserve( len, pcl::Max( len, n ) ); if ( len > 0 ) R::Copy( newData->string, m_data->string, len ); DetachFromData(); m_data = newData; } } /*! * Causes this string to have the specified length \a n in characters. * * If \a n is zero, this function calls Clear() to empty the string. * Otherwise the string data will be shrunk or extended, and possibly * reallocated. If the resulting string is larger than the original, newly * allocated or reserved characters won't be initialized and will have * unpredictable values; in this case it is the caller's responsibility to * write them as appropriate. * * After calling this member function, this object is guaranteed to uniquely * reference its string data. */ void SetLength( size_type n ) { if ( n != Length() ) { if ( n > 0 ) { if ( !IsUnique() || m_data->ShouldReallocate( n ) ) { Data* newData = Data::New( n ); size_type m = Capacity(); if ( m > 0 ) R::Copy( newData->string, m_data->string, pcl::Min( n, m ) ); DetachFromData(); m_data = newData; } else m_data->SetLength( n ); } else Clear(); } else EnsureUnique(); } /*! * Returns a copy of this string resized to have the specified length \a n * in characters. This function is a wrapper for SetLength(); see that * function for important information. */ GenericString SetToLength( size_type n ) const { // NB: This can be done more efficiently if this string is unique. GenericString s( *this ); s.SetLength( n ); return s; } /*! * Resizes this string to match the length of the internal null-terminated * string buffer. * * This member function scans the internal string buffer for a terminating * null character, then calls SetLength() to set the corresponding length in * characters. */ void ResizeToNullTerminated() { SetLength( R::Length( m_data->string ) ); } /*! * Returns a copy of this string resized to match the length of its internal * null-terminated string buffer. */ GenericString ResizedToNullTerminated() const { GenericString s( *this ); s.ResizeToNullTerminated(); return s; } /*! * Causes this string to allocate the exact required memory space to store * its contained characters, plus a terminating null character. * * If the string has excess capacity, a new copy of its existing characters * is generated and stored in a newly allocated memory block that fits them * exactly, then the previous memory block is deallocated. * * If the string is empty, calling this function is equivalent to Clear(). * Note that in this case a previously allocated memory block (by a call to * Reserve()) may also be deallocated. */ void Squeeze() { if ( Available() > 0 ) { size_type len = Length(); if ( len > 0 ) { if ( IsUnique() ) { iterator old = m_data->string; m_data->Allocate( len, 0 ); R::Copy( m_data->string, old, len ); m_data->alloc.Deallocate( old ); } else { Data* newData = Data::New( len, 0 ); R::Copy( newData->string, m_data->string, len ); DetachFromData(); m_data = newData; } } else Clear(); } } /*! * Returns a copy of this string allocated to the exact required memory * space to store its contained characters and a terminating null character. */ GenericString Squeezed() const { // NB: This can be done more efficiently if this string is unique. GenericString s( *this ); s.Squeeze(); return s; } /*! * Releases the data in this string. * * This member function returns a pointer to the string data block * referenced by this object, after ensuring that it is uniquely referenced. * If the string is empty, this function may return the null pointer. * * Before returning, this member function empties this string without * deallocating its string data. The caller is then responsible for * destructing and/or deallocating the returned block when it is no longer * required. */ c_string Release() { EnsureUnique(); iterator string = m_data->string; m_data->Reset(); return string; } /*! * Copies characters from this string to a null-terminated character array. * * \param[out] dst Destination character array. * * \param maxCharsToCopy The total number of characters that can be stored * at the \a dst array, \e including a null terminating * character. * * \param i Index of the first character to be copied from this * string. * * This function copies at most \a maxCharsToCopy-1 characters from this * string (or Length()-i, whichever is less) to the \a dst array. Then a * null terminating character is appended to \a dst. */ void c_copy( iterator dst, size_type maxCharsToCopy, size_type i = 0 ) const noexcept { if ( dst != nullptr ) if ( maxCharsToCopy > 0 ) { if ( --maxCharsToCopy > 0 ) { size_type len = Length(); if ( i < len ) { size_type n = pcl::Min( maxCharsToCopy, len-i ); R::Copy( dst, m_data->string+i, n ); dst += n; } } *dst = R::Null(); } } /*! * Inserts a copy of the string \a s at the index \a i in this string. */ template void Insert( size_type i, const GenericString& s ) { size_type n = s.Length(); if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len R::Copy( m_data->string+i, s.m_data->string, n ); } } /*! * Inserts a copy of the character sequence defined by the range [p,q) at * the index \a i in this string. * * If \a p is greater than or equal to \a q, calling this member function * has no effect. */ void Insert( size_type i, const_iterator p, const_iterator q ) { if ( p < q ) { size_type n = q - p; UninitializedGrow( i, n ); // -> 0 <= i <= len R::Copy( m_data->string+i, p, n ); } } /*! * Inserts a null-terminated character sequence \a t at the index \a i in * this string. */ void Insert( size_type i, const_c_string t ) { size_type n = R::Length( t ); if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len R::Copy( m_data->string+i, t, n ); } } /*! * Inserts at most the first \a n characters of a null-terminated character * sequence \a t at the index \a i in this string. */ void Insert( size_type i, const_c_string t, size_type n ) { if ( (n = pcl::Min( n, R::Length( t ) )) > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len R::Copy( m_data->string+i, t, n ); } } /*! * Inserts \a n copies of a character \a c at the index \a i in this string. */ void Insert( size_type i, char_type c, size_type n = 1 ) { if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len R::Fill( m_data->string+i, c, n ); } } /*! * Appends a copy of the specified string \a s to this string. */ template void Append( const GenericString& s ) { Insert( maxPos, s ); } /*! * Appends a copy of a string by calling Append( s ). Returns a reference to * this object. */ template GenericString& operator +=( const GenericString& s ) { Append( s ); return *this; } /*! * Appends a copy of the character sequence defined by the range [i,j) to * this string. * * If \a i is greater than or equal to \a j, calling this member function * has no effect. */ void Append( const_iterator i, const_iterator j ) { Insert( maxPos, i, j ); } /*! * Appends a copy of the first \a n characters of a null-terminated * character sequence \a t to this string. */ void Append( const_c_string t, size_type n ) { Insert( maxPos, t, n ); } /*! * Appends a copy of a null-terminated character sequence to this string. */ void Append( const_c_string t ) { Insert( maxPos, t ); } /*! * Appends a copy of a null-terminated string by calling Append( t ). * Returns a reference to this object. */ GenericString& operator +=( const_c_string t ) { Append( t ); return *this; } /*! * Appends \a n copies of a character \a c to this string. */ void Append( char_type c, size_type n = 1 ) { Insert( maxPos, c, n ); } /*! * A synonym for Append( const GenericString& ), provided for compatibility * with PCL container classes. */ template void Add( const GenericString& s ) { Append( s ); } /*! * A synonym for Append( const_iterator, const_iterator ), provided for * compatibility with PCL container classes. */ void Add( const_iterator i, const_iterator j ) { Append( i, j ); } /*! * A synonym for Append( const_c_string, size_type ), provided for compatibility * with PCL container classes. */ void Add( const_c_string t, size_type n ) { Append( t, n ); } /*! * A synonym for Append( const_c_string ), provided for compatibility with PCL * container classes. */ void Add( const_c_string t ) { Append( t ); } /*! * A synonym for Append( char_type, size_type ), provided for compatibility with PCL * container classes. */ void Add( char_type c, size_type n = 1 ) { Append( c, n ); } /*! * Appends a copy of the specified character \a c to this string. Returns a * reference to this object. */ GenericString& operator +=( char_type c ) { Append( c ); return *this; } /*! * Inserts a copy of the specified string \a s at the beginning of this * string. */ template void Prepend( const GenericString& s ) { Insert( 0, s ); } /*! * Inserts a copy of a string \a s at the beginning of this string. Returns * a reference to this object. */ template GenericString& operator -=( const GenericString& s ) { Prepend( s ); return *this; } /*! * Inserts a copy of the character sequence defined by the range [i,j) at * the beginning of this string. * * If \a i is greater than or equal to \a j, calling this member function * has no effect. */ void Prepend( const_iterator i, const_iterator j ) { Insert( 0, i, j ); } /*! * Inserts a copy of the first \a n characters of a character array \a t at * the beginning of this string. */ void Prepend( const_c_string t, size_type n ) { Insert( 0, t, n ); } /*! * Inserts a copy of the null-terminated character sequence \a t at the * beginning of this string. */ void Prepend( const_c_string t ) { Insert( 0, t ); } /*! * Inserts a copy of the null-terminated sequence \a t at the beginning of * this string. Returns a reference to this object. */ GenericString& operator -=( const_c_string t ) { Prepend( t ); return *this; } /*! * Inserts \a n copies of a character \a c at the beginning of this string. */ void Prepend( char_type c, size_type n = 1 ) { Insert( 0, c, n ); } /*! * Inserts a copy of the specified character \a c at the beginning of this * string. Returns a reference to this object. */ GenericString& operator -=( char_type c ) { Prepend( c ); return *this; } /*! * Replaces a segment of \a n contiguous characters, starting at the \a i-th * character in this string, with a copy of a string \a s. */ template void Replace( size_type i, size_type n, const GenericString& s ) { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n != len ) { size_type ns = s.Length(); if ( ns > 0 ) { if ( n < ns ) UninitializedGrow( i, ns-n ); else if ( ns < n ) Delete( i, n-ns ); else EnsureUnique(); R::Copy( m_data->string+i, s.m_data->string, ns ); } else Delete( i, n ); } else Assign( s ); } } } /*! * Replaces a segment of at most \a n contiguous characters, starting at the * \a i-th character in this string, with a copy of a null-terminated * sequence \a t. * * If \a t is a pointer to the contents of this string (or, equivalently, an * iterator on this string), this function invokes undefined behavior. */ void Replace( size_type i, size_type n, const_c_string t ) { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n != len ) { size_type nt = R::Length( t ); if ( nt > 0 ) { if ( n < nt ) UninitializedGrow( i, nt-n ); else if ( nt < n ) Delete( i, n-nt ); else EnsureUnique(); R::Copy( m_data->string+i, t, nt ); } else Delete( i, n ); } else Assign( t ); } } } /*! * Replaces a segment of at most \a n contiguous characters, starting at the * \a i-th character in this string, with \a nc copies of a character \a c. */ void Replace( size_type i, size_type n, char_type c, size_type nc = 1 ) { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n != len ) { if ( nc > 0 ) { if ( n < nc ) UninitializedGrow( i, nc-n ); else if ( nc < n ) Delete( i, n-nc ); else EnsureUnique(); R::Fill( m_data->string+i, c, nc ); } else Delete( i, n ); } else Assign( c, nc ); } } } /*! * Replaces all occurrences of a character \a c1 with \a c2 in a segment of * \a n contiguous characters starting at the \a i-th character in this * string. */ void ReplaceChar( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) { ReplaceChar( c1, c2, i, n, true/*case*/ ); } /*! * Replaces all occurrences of a character \a c1 with \a c2 in a segment of * \a n contiguous characters starting at the \a i-th character in this * string. * * This member function performs case-insensitive character comparisons. */ void ReplaceCharIC( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) { ReplaceChar( c1, c2, i, n, false/*case*/ ); } /*! * Replaces all occurrences of a string \a s1 with \a s2 in a segment of * contiguous characters starting at the \a i-th character, and spanning to * the end of this string. */ template void ReplaceString( const GenericString& s1, const GenericString& s2, size_type i = 0 ) { ReplaceString( s1.m_data->string, s1.Length(), s2.m_data->string, s2.Length(), i, true/*case*/ ); } /*! * Replaces all occurrences of a null-terminated string \a t1 with \a t2 in * a segment of contiguous characters starting at the \a i-th character, and * spanning to the end of this string. */ void ReplaceString( const_c_string t1, const_c_string t2, size_type i = 0 ) { ReplaceString( t1, R::Length( t1 ), t2, R::Length( t2 ), i, true/*case*/ ); } /*! * Replaces all occurrences of a string \a s1 with \a s2 in a segment of * contiguous characters starting at the \a i-th character, and spanning to * the end of this string. * * This member function performs case-insensitive string comparisons. */ template void ReplaceStringIC( const GenericString& s1, const GenericString& s2, size_type i = 0 ) { ReplaceString( s1.m_data->string, s1.Length(), s2.m_data->string, s2.Length(), i, false/*case*/ ); } /*! * Replaces all occurrences of a null-terminated string \a t1 with \a t2 in * a segment of contiguous characters starting at the \a i-th character, and * spanning to the end of this string. * * This member function performs case-insensitive string comparisons. */ void ReplaceStringIC( const_c_string t1, const_c_string t2, size_type i = 0 ) { ReplaceString( t1, R::Length( t1 ), t2, R::Length( t2 ), i, false/*case*/ ); } /*! * Deletes a contiguous segment of at most \a n characters starting at the * \a i-th character in this string. */ void Delete( size_type i, size_type n = 1 ) { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n < len ) { size_type newLen = len-n; if ( !IsUnique() || m_data->ShouldReallocate( newLen ) ) { Data* newData = Data::New( newLen ); if ( i > 0 ) R::Copy( newData->string, m_data->string, i ); if ( i < newLen ) R::Copy( newData->string+i, m_data->string+i+n, newLen-i ); DetachFromData(); m_data = newData; } else { if ( i < newLen ) R::CopyOverlapped( m_data->string+i, m_data->string+i+n, newLen-i ); m_data->SetLength( newLen ); } } else Clear(); } } } /*! * Deletes a segment of contiguous characters starting from the \a i-th * character and spanning to the end of this string. */ void DeleteRight( size_type i ) { Delete( i, maxPos ); } /*! * Deletes the initial segment of at most \a i contiguous characters in this * string. */ void DeleteLeft( size_type i ) { Delete( 0, i ); } /*! * Deletes all occurrences of the \a c character in a segment of contiguous * characters starting from the \a i-th character and spanning to the end of * this string. */ void DeleteChar( char_type c, size_type i = 0 ) { ReplaceString( &c, 1, nullptr, 0, i, true/*case*/ ); } /*! * Deletes all occurrences of the \a c character in a segment of contiguous * characters starting from the \a i-th character and spanning to the end of * this string. * * This member function performs case-insensitive character comparisons. */ void DeleteCharIC( char_type c, size_type i = 0 ) { ReplaceString( &c, 1, nullptr, 0, i, false/*case*/ ); } /*! * Deletes all occurrences of a string \a s in a segment of contiguous * characters starting from the \a i-th character and spanning to the end of * this string. */ template void DeleteString( const GenericString& s, size_type i = 0 ) { ReplaceString( s.m_data->string, s.Length(), nullptr, 0, i, true/*case*/ ); } /*! * Deletes all occurrences of a null-terminated string \a s in a segment of * contiguous characters starting from the \a i-th character and spanning to * the end of this string. */ void DeleteString( const_c_string t, size_type i = 0 ) { ReplaceString( t, R::Length( t ), nullptr, 0, i, true/*case*/ ); } /*! * Deletes all occurrences of a string \a s in a segment of contiguous * characters starting from the \a i-th character and spanning to the end of * this string. * * This member function performs case-insensitive string comparisons. */ template void DeleteStringIC( const GenericString& s, size_type i = 0 ) { ReplaceString( s.m_data->string, s.Length(), nullptr, 0, i, false/*case*/ ); } /*! * Deletes all occurrences of a null-terminated string \a s in a segment of * contiguous characters starting from the \a i-th character and spanning to * the end of this string. * * This member function performs case-insensitive string comparisons. */ void DeleteStringIC( const_c_string t, size_type i = 0 ) { ReplaceString( t, R::Length( t ), nullptr, 0, i, false/*case*/ ); } /*! * Removes all characters in this string, yielding an empty string. * * If this string is empty, then calling this member function has no effect. * * If this string uniquely references its string data, it is destroyed and * deallocated; otherwise its reference counter is decremented. Then a new, * empty string data structure is created and uniquely referenced. */ void Clear() { if ( !IsEmpty() ) if ( IsUnique() ) m_data->Deallocate(); else { Data* newData = Data::New(); DetachFromData(); m_data = newData; } } /*! * Returns a string with a copy of at most \a n contiguous characters * starting at the \a i-th character in this string. */ GenericString Substring( size_type i, size_type n = maxPos ) const { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n > 0 ) { if ( n < len ) { GenericString t; t.m_data->Allocate( n ); R::Copy( t.m_data->string, m_data->string+i, n ); return t; } return *this; } } return GenericString(); } /*! * Returns a string with a copy of the at most \a n contiguous initial * characters of this string. */ GenericString Left( size_type n ) const { size_type len = Length(); n = pcl::Min( n, len ); if ( n > 0 ) { if ( n < len ) { GenericString t; t.m_data->Allocate( n ); R::Copy( t.m_data->string, m_data->string, n ); return t; } return *this; } return GenericString(); } /*! * Returns a string with a copy of the at most \a n contiguous ending * characters of this string. */ GenericString Right( size_type n ) const { size_type len = Length(); n = pcl::Min( n, len ); if ( n > 0 ) { if ( n < len ) { GenericString t; t.m_data->Allocate( n ); R::Copy( t.m_data->string, m_data->string+len-n, n ); return t; } return *this; } return GenericString(); } /*! * Returns the suffix of this string starting at index \a i. Calling this * member function is equivalent to: * * \code Right( Length()-i ) \endcode */ GenericString Suffix( size_type i ) const { return Substring( i ); } /*! * Returns the prefix of this string ending at index \a i. Calling this * member function is equivalent to: * * \code Left( i-1 ) \endcode */ GenericString Prefix( size_type i ) const { return Left( (i > 0) ? i-1 : 0 ); } /*! * Gets a sequence of \e tokens (substrings) extracted from this string. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a StringList. * * \param s The token separator string. * * \param trim True to \e trim the extracted tokens. If this parameter is * true, existing leading and trailing whitespace characters * will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type Break( C& list, const GenericString& s, bool trim = false, size_type i = 0 ) const { size_type count = 0; size_type len = Length(); if ( i < len ) { size_type n = s.Length(); if ( n > 0 ) for ( SearchEngine S( s.m_data->string, n, true/*case*/ ); ; ) { size_type j = S( m_data->string, i, len ); GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + n; } } return count; } /*! * Gets a sequence of \e tokens (substrings) extracted from this string. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a * StringList. * * \param s The token separator null-terminated string. * * \param trim True to \e trim the extracted tokens. If this parameter * is true, existing leading and trailing whitespace * characters will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type Break( C& list, const_c_string s, bool trim = false, size_type i = 0 ) const { size_type count = 0; size_type len = Length(); if ( i < len ) { size_type n = R::Length( s ); if ( n > 0 ) for ( SearchEngine S( s, n, true/*case*/ ); ; ) { size_type j = S( m_data->string, i, len ); GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + n; } } return count; } /*! * Gets a sequence of \e tokens (substrings) extracted from this string. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a StringList. * * \param c The token separator character. Tokens will be separated by * sequences of one or more instances of this character. * * \param trim True to \e trim the extracted tokens. If this parameter is * true, existing leading and trailing whitespace characters * will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type Break( C& list, char_type c, bool trim = false, size_type i = 0 ) const { size_type count = 0; size_type len = Length(); if ( i < len ) { for ( ;; ) { size_type j = i; for ( const_iterator p = m_data->string + i; j < len; ++j, ++p ) if ( *p == c ) break; GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + 1; } } return count; } /*! * Gets a sequence of \e tokens (substrings) extracted from this string. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a StringList. * * \param ca An array of token separator characters. Tokens will be * separated by instances of any character included in this * array. The template argument S must have type conversion * semantics to the character type of this string class * (char_type). If this array is empty, calling this function * has no effect and zero is returned. * * \param trim True to \e trim the extracted tokens. If this parameter is * true, existing leading and trailing whitespace characters * will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type Break( C& list, const Array& ca, bool trim = false, size_type i = 0 ) const { size_type count = 0; if ( !ca.IsEmpty() ) { size_type len = Length(); if ( i < len ) { for ( ;; ) { size_type j = i; for ( const_iterator p = m_data->string + i; j < len; ++j, ++p ) for ( auto c : ca ) if ( *p == char_type( c ) ) goto __Break_1; __Break_1: GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + 1; } } } return count; } /*! * Gets a sequence of \e tokens (substrings) extracted from this string by * performing case-insensitive comparisons with a token separation string. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a StringList. * * \param s The token separator string. This function performs * case-insensitive string comparisons to locate instances of * this string. * * \param trim True to \e trim the extracted tokens. If this parameter is * true, existing leading and trailing whitespace characters * will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type BreakIC( C& list, const GenericString& s, bool trim = false, size_type i = 0 ) const { size_type count = 0; size_type len = Length(); if ( i < len ) { size_type n = s.Length(); if ( n > 0 ) { for ( SearchEngine S( s.m_data->string, n, false/*case*/ ); ; ) { size_type j = S( m_data->string, i, len ); GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + n; } } } return count; } /*! * Gets a sequence of \e tokens (substrings) extracted from this string by * performing case-insensitive comparisons with a null-terminated token * separation string. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a * StringList. * * \param s The token separator null-terminated string. This * function performs case-insensitive string comparisons * to locate instances of this string. * * \param trim True to \e trim the extracted tokens. If this parameter * is true, existing leading and trailing whitespace * characters will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type BreakIC( C& list, const_c_string s, bool trim = false, size_type i = 0 ) const { size_type count = 0; size_type len = Length(); if ( i < len ) { size_type n = R::Length( s ); if ( n > 0 ) { for ( SearchEngine S( s, n, false/*case*/ ); ; ) { size_type j = S( m_data->string, i, len ); GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + n; } } } return count; } /*! * Gets a sequence of \e tokens (substrings) extracted from this string by * performing case-insensitive comparisons with a token separator character. * * \param[out] list The list of extracted tokens. Must be a reference to a * container, such as Array or List, or a derived class. * Typically, this parameter is a reference to a StringList. * * \param c The token separator character. Tokens will be separated by * sequences of one or more instances of this character. This * function performs case-insensitive character comparisons * to locate instances of this character. * * \param trim True to \e trim the extracted tokens. If this parameter is * true, existing leading and trailing whitespace characters * will be removed from each extracted token. * * \param i Starting character index. * * Returns the number of tokens extracted and added to the list. */ template size_type BreakIC( C& list, char_type c, bool trim = false, size_type i = 0 ) const { size_type count = 0; size_type len = Length(); if ( i < len ) { c = R::ToCaseFolded( c ); for ( ;; ) { size_type j = i; for ( const_iterator p = m_data->string + i; j < len; ++j, ++p ) if ( R::ToCaseFolded( *p ) == c ) break; GenericString t; if ( i < j ) { const_iterator l = m_data->string + i; size_type m = j - i; if ( trim ) { const_iterator r = l + m; l = R::SearchTrimLeft( l, r ); m = R::SearchTrimRight( l, r ) - l; } if ( m > 0 ) { t.m_data->Allocate( m ); R::Copy( t.m_data->string, l, m ); } } list.Add( t ); ++count; if ( j == len ) break; i = j + 1; } } return count; } /*! * Returns the first character in this string, or a null character * (R::Null()) if this string is empty. */ char_type FirstChar() const noexcept { return (m_data->string != nullptr) ? *m_data->string : R::Null(); } /*! * Returns the last character in this string, or a null character * (R::Null()) if this string is empty. */ char_type LastChar() const noexcept { return (m_data->string < m_data->end) ? *(m_data->end-1) : R::Null(); } /*! * Returns true iff this string begins with the specified substring \a s. */ template bool StartsWith( const GenericString& s ) const noexcept { if ( s.IsEmpty() || Length() < s.Length() ) return false; for ( const_iterator p = m_data->string, q = s.m_data->string; q < s.m_data->end; ++p, ++q ) if ( *p != *q ) return false; return true; } /*! * Returns true iff this string begins with the specified null-terminated * sequence \a t. */ bool StartsWith( const_c_string t ) const noexcept { size_type n = R::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->string, e = p+n; p < e; ++p, ++t ) if ( *p != *t ) return false; return true; } /*! * Returns true iff this string begins with the specified character \a c. */ bool StartsWith( char_type c ) const noexcept { return m_data->string < m_data->end && *m_data->string == c; } /*! * Returns true iff this string begins with the specified substring \a s, * performing case-insensitive character comparisons. */ template bool StartsWithIC( const GenericString& s ) const noexcept { if ( s.IsEmpty() || Length() < s.Length() ) return false; for ( const_iterator p = m_data->string, q = s.m_data->string; q < s.m_data->end; ++p, ++q ) if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *q ) ) return false; return true; } /*! * Returns true iff this string begins with the specified null-terminated * sequence \a t, performing case-insensitive character comparisons. */ bool StartsWithIC( const_c_string t ) const noexcept { size_type n = R::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->string, e = p+n; p < e; ++p, ++t ) if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *t ) ) return false; return true; } /*! * Returns true iff this string begins with the specified character \a c, * performing a case-insensitive character comparison. */ bool StartsWithIC( char_type c ) const noexcept { return m_data->string < m_data->end && R::ToCaseFolded( *m_data->string ) == R::ToCaseFolded( c ); } /*! * Returns true iff this string ends with the specified substring \a s. */ template bool EndsWith( const GenericString& s ) const noexcept { size_type n = s.Length(); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->end-n, q = s.m_data->string; p < m_data->end; ++p, ++q ) if ( *p != *q ) return false; return true; } /*! * Returns true iff this string ends with the specified null-terminated * string \a t. */ bool EndsWith( const_c_string t ) const noexcept { size_type n = R::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) if ( *p != *t ) return false; return true; } /*! * Returns true iff this string ends with the specified character \a c. */ bool EndsWith( char_type c ) const noexcept { return m_data->string < m_data->end && *(m_data->end-1) == c; } /*! * Returns true iff this string ends with the specified substring \a s, * performing case-insensitive character comparisons. */ template bool EndsWithIC( const GenericString& s ) const noexcept { size_type n = s.Length(); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->end-n, q = s.m_data->string; p < m_data->end; ++p, ++q ) if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *q ) ) return false; return true; } /*! * Returns true iff this string ends with the specified null-terminated * string \a t, performing case-insensitive character comparisons. */ bool EndsWithIC( const_c_string t ) const noexcept { size_type n = R::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *t ) ) return false; return true; } /*! * Returns true iff this string ends with the specified character \a c, * performing a case-insensitive character comparison. */ bool EndsWithIC( char_type c ) const noexcept { return m_data->string < m_data->end && R::ToCaseFolded( *(m_data->end-1) ) == R::ToCaseFolded( c ); } /*! * Returns the starting index \a k of the first occurrence of a substring * \a s in this string, such that \a k >= \a i. Returns notFound if such * occurrence does not exist. */ template size_type FindFirst( const GenericString& s, size_type i = 0 ) const noexcept { size_type len = Length(); i = SearchEngine( s.m_data->string, s.Length(), true/*case*/ )( m_data->string, i, len ); return (i < len) ? i : notFound; } /*! * Returns the starting index \a k of the first occurrence of a * null-terminated substring \a t in this string, such that \a k >= \a i. * Returns notFound if such occurrence does not exist. */ size_type FindFirst( const_c_string t, size_type i = 0 ) const noexcept { size_type len = Length(); i = SearchEngine( t, R::Length( t ), true/*case*/ )( m_data->string, i, len ); return (i < len) ? i : notFound; } /*! * Returns the index \a k of the first occurrence of a character \a c in * this string, such that \a k >= \a i. Returns notFound if such occurrence * does not exist. */ size_type FindFirst( char_type c, size_type i = 0 ) const noexcept { for ( const_iterator p = m_data->string+i; p < m_data->end; ++p ) if ( *p == c ) return p - m_data->string; return notFound; } /*! * Returns the starting index \a k of the first occurrence of a substring * \a s in this string, such that \a k >= \a i. Returns notFound if such * occurrence does not exist. * * This member function performs case-insensitive string comparisons to find * an instance of the substring \a s. */ template size_type FindFirstIC( const GenericString& s, size_type i = 0 ) const noexcept { size_type len = Length(); i = SearchEngine( s.m_data->string, s.Length(), false/*case*/ )( m_data->string, i, len ); return (i < len) ? i : notFound; } /*! * Returns the starting index \a k of the first occurrence of a * null-terminated substring \a s in this string, such that \a k >= \a i. * Returns notFound if such occurrence does not exist. * * This member function performs case-insensitive string comparisons to find * an instance of the substring \a s. */ size_type FindFirstIC( const_c_string t, size_type i = 0 ) const noexcept { size_type len = Length(); i = SearchEngine( t, R::Length( t ), false/*case*/ )( m_data->string, i, len ); return (i < len) ? i : notFound; } /*! * Returns the index \a k of the first occurrence of a character \a c in * this string, such that \a k >= \a i. Returns notFound if such occurrence * does not exist. * * This member function performs case-insensitive character comparisons to * find an instance of the character \a c. */ size_type FindFirstIC( char_type c, size_type i = 0 ) const noexcept { c = R::ToCaseFolded( c ); for ( const_iterator p = m_data->string+i; p < m_data->end; ++p ) if ( R::ToCaseFolded( *p ) == c ) return p - m_data->string; return notFound; } /*! * A synonym for FindFirst( const GenericString&, size_type ). */ template size_type Find( const GenericString& s, size_type i = 0 ) const noexcept { return FindFirst( s, i ); } /*! * A synonym for FindFirst( const_c_string, size_type ). */ size_type Find( const_c_string t, size_type i = 0 ) const noexcept { return FindFirst( t, i ); } /*! * A synonym for FindFirst( char_type, size_type ). */ size_type Find( char_type c, size_type i = 0 ) const noexcept { return FindFirst( c, i ); } /*! * A synonym for FindFirstIC( const GenericString&, size_type ). */ template size_type FindIC( const GenericString& s, size_type i = 0 ) const noexcept { return FindFirstIC( s, i ); } /*! * A synonym for FindFirstIC( const_c_string, size_type ). */ size_type FindIC( const_c_string t, size_type i = 0 ) const noexcept { return FindFirstIC( t, i ); } /*! * A synonym for FindFirstIC( char_type, size_type ). */ size_type FindIC( char_type c, size_type i = 0 ) const noexcept { return FindFirstIC( c, i ); } /*! * Returns the starting index \a k of the last occurrence of a substring * \a s in this string, such that: * * \a k <= \a r - \a n, * * where \a n is the length of the substring \a s. Returns notFound if such * occurrence does not exist. */ template size_type FindLast( const GenericString& s, size_type r = maxPos ) const noexcept { r = pcl::Min( r, Length() ); size_type i = SearchEngine( s.m_data->string, s.Length(), true/*case*/, true/*last*/ )( m_data->string, 0, r ); return (i < r) ? i : notFound; } /*! * Returns the starting index \a k of the last occurrence of a * null-terminated substring \a t in this string, such that: * * 0 <= \a k <= \a r - \a n, * * where \a n is the length of the substring \a t. Returns notFound if such * occurrence does not exist. */ size_type FindLast( const_c_string t, size_type r = maxPos ) const noexcept { r = pcl::Min( r, Length() ); size_type i = SearchEngine( t, R::Length( t ), true/*case*/, true/*last*/ )( m_data->string, 0, r ); return (i < r) ? i : notFound; } /*! * Returns the index \a k of the last occurrence of a character \a c in this * string, such that \a k < \a r. Returns notFound if such occurrence does * not exist. */ size_type FindLast( char_type c, size_type r = maxPos ) const noexcept { r = pcl::Min( r, Length() ); for ( const_iterator p = m_data->string+r; r > 0; --r ) if ( *--p == c ) return r - 1; return notFound; } /*! * Returns the starting index \a k of the last occurrence of a substring * \a s in this string, such that: * * \a k <= \a r - \a n, * * where \a n is the length of the substring \a s. Returns notFound if such * occurrence does not exist. * * This member function performs case-insensitive string comparisons to * find an instance of the specified substring \a s. */ template size_type FindLastIC( const GenericString& s, size_type r = maxPos ) const noexcept { r = pcl::Min( r, Length() ); size_type i = SearchEngine( s.m_data->string, s.Length(), false/*case*/, true/*last*/ )( m_data->string, 0, r ); return (i < r) ? i : notFound; } /*! * Returns the starting index \a k of the last occurrence of a * null-terminated substring \a t in this string, such that: * * 0 <= \a k <= \a r - \a n, * * where \a n is the length of the substring \a t. Returns notFound if such * occurrence does not exist. * * This member function performs case-insensitive string comparisons to * find an instance of the specified substring \a t. */ size_type FindLastIC( const_c_string t, size_type r = maxPos ) const noexcept { r = pcl::Min( r, Length() ); size_type i = SearchEngine( t, R::Length( t ), false/*case*/, true/*last*/ )( m_data->string, 0, r ); return (i < r) ? i : notFound; } /*! * Returns the index \a k of the last occurrence of a character \a c in this * string, such that \a k < \a r. Returns notFound if such occurrence does * not exist. * * This member function performs case-insensitive character comparisons to * find an instance of the specified character \a c. */ size_type FindLastIC( char_type c, size_type r = maxPos ) const noexcept { c = R::ToCaseFolded( c ); r = pcl::Min( r, Length() ); for ( const_iterator p = m_data->string+r; r > 0; --r ) if ( R::ToCaseFolded( *--p ) == c ) return r - 1; return notFound; } /*! * Returns true iff this string contains a substring \a s. */ template bool Contains( const GenericString& s ) const noexcept { return Find( s ) != notFound; } /*! * Returns true iff this string contains a null-terminated substring \a t. */ bool Contains( const_c_string t ) const noexcept { return Find( t ) != notFound; } /*! * Returns true iff this string contains a character \a c. */ bool Contains( char_type c ) const noexcept { return Find( c ) != notFound; } /*! * Returns true iff this string contains a substring \a s. * * This member function performs case-insensitive string comparisons to * find an instance of the specified substring \a s. */ template bool ContainsIC( const GenericString& s ) const noexcept { return FindIC( s ) != notFound; } /*! * Returns true iff this string contains a null-terminated substring \a t. * * This member function performs case-insensitive string comparisons to * find an instance of the specified substring \a t. */ bool ContainsIC( const_c_string t ) const noexcept { return FindIC( t ) != notFound; } /*! * Returns true iff this string contains a character \a c. * * This member function performs case-insensitive character comparisons to * find an instance of the specified character \a c. */ bool ContainsIC( char_type c ) const noexcept { return FindIC( c ) != notFound; } /*! * Removes all leading and trailing trimable characters. * * Trimable characters are determined by the traits class R. A character * \a c is trimable if R::IsTrimable( c ) is true. Generally, the set of * trimable characters corresponds to the set of white space characters. * * \sa Trimmed(); */ void Trim() { const_iterator l = R::SearchTrimLeft( m_data->string, m_data->end ); const_iterator r = R::SearchTrimRight( l, m_data->end ); if ( m_data->string < l || r < m_data->end ) Trim( l, r - l ); } /*! * Removes all leading trimable characters. * * Trimable characters are determined by the traits class R. A character * \a c is trimable if R::IsTrimable( c ) is true. Generally, the set of * trimable characters corresponds to the set of white space characters. * * \sa TrimmedLeft(); */ void TrimLeft() { const_iterator l = R::SearchTrimLeft( m_data->string, m_data->end ); if ( m_data->string < l ) Trim( l, m_data->end - l ); } /*! * Removes all trailing trimable characters. * * Trimable characters are determined by the traits class R. A character * \a c is trimable if R::IsTrimable( c ) is true. Generally, the set of * trimable characters corresponds to the set of white space characters. * * \sa TrimmedRight(); */ void TrimRight() { const_iterator r = R::SearchTrimRight( m_data->string, m_data->end ); if ( r < m_data->end ) Trim( m_data->string, r - m_data->string ); } /*! * Returns a duplicate of this string with all leading and trailing * trimable characters removed. * \sa Trim() */ GenericString Trimmed() const { GenericString s( *this ); s.Trim(); return s; } /*! * Returns a duplicate of this string with all leading trimable * characters removed. * \sa TrimLeft() */ GenericString TrimmedLeft() const { GenericString s( *this ); s.TrimLeft(); return s; } /*! * Returns a duplicate of this string with all trailing trimable * characters removed. * \sa TrimRight() */ GenericString TrimmedRight() const { GenericString s( *this ); s.TrimRight(); return s; } /*! * Ensures that this string is enclosed by a leading and a trailing instance * of the specified character \a c. If this string is already enclosed by * \a c, this function does nothing. * \sa Enclosed() */ void EnsureEnclosed( char_type c ) { int encloseLeft = 1; int encloseRight = 1; size_type len = Length(); if ( len > 0 ) { if ( *m_data->string == c ) encloseLeft = 0; if ( *(m_data->end-1) == c ) if ( len > 1 ) encloseRight = 0; else encloseLeft = 0; } size_type n = len + encloseLeft + encloseRight; if ( n > len ) { if ( !IsUnique() || m_data->ShouldReallocate( n ) ) { Data* newData = Data::New( n ); R::Copy( newData->string + encloseLeft, m_data->string, len ); DetachFromData(); m_data = newData; } else { m_data->SetLength( n ); R::CopyOverlapped( m_data->string + encloseLeft, m_data->string, len ); } if ( encloseLeft ) *m_data->string = c; if ( encloseRight ) *(m_data->end-1) = c; } } /*! * Returns a duplicate of this string enclosed by the specified character. * If this string is already enclosed by \a c, this function returns an * unmodified copy. * \sa EnsureEnclosed() */ GenericString Enclosed( char_type c ) const { GenericString s( *this ); s.EnsureEnclosed( c ); return s; } /*! * Ensures that this string is enclosed by a leading and a trailing instance * of the single quote character ('). If this string is already single * quoted, this function does nothing. * \sa SingleQuoted() */ void EnsureSingleQuoted() { EnsureEnclosed( R::SingleQuote() ); } /*! * Returns a duplicate of this string enclosed by single quote characters * ('). If this string is already single quoted, this function returns an * unmodified copy. * \sa EnsureSingleQuoted() */ GenericString SingleQuoted() const { GenericString s( *this ); s.EnsureSingleQuoted(); return s; } /*! * Ensures that this string is enclosed by a leading and a trailing instance * of the double quote character ("). If this string is already double * quoted, this function does nothing. * \sa DoubleQuoted() */ void EnsureDoubleQuoted() { EnsureEnclosed( R::DoubleQuote() ); } /*! * Returns a duplicate of this string enclosed by double quote characters * ("). If this string is already double quoted, this function returns an * unmodified copy. * \sa EnsureDoubleQuoted() */ GenericString DoubleQuoted() const { GenericString s( *this ); s.EnsureDoubleQuoted(); return s; } /*! * Unquotes this string. * * If the string starts and ends with single quote characters, the result is * the same string with the quotes removed and its length decremented by * two. The same happens if the string starts and ends with double quote * characters. * * If the string does not start and end with the same quote character, this * function has no effect. * * \sa Unquoted() */ void Unquote() { size_type len = Length(); if ( len > 1 ) if ( *m_data->string == R::SingleQuote() && *(m_data->end-1) == R::SingleQuote() || *m_data->string == R::DoubleQuote() && *(m_data->end-1) == R::DoubleQuote() ) if ( IsUnique() ) { R::CopyOverlapped( m_data->string, m_data->string+1, len-2 ); m_data->SetLength( len-2 ); } else { Data* newData = Data::New( len-2 ); R::Copy( newData->string, m_data->string+1, len-2 ); DetachFromData(); m_data = newData; } } /*! * Returns an unquoted duplicate of this string. * \sa Unquote() */ GenericString Unquoted() const { GenericString s( *this ); s.Unquote(); return s; } /*! * Pads this string to the right, using the specified \a fill character, up * to the specified \a width. * * If the current length \e n of this string is less than the specified * \a width, \a width - \e n copies of the \a fill character will be * appended to the string. If the current length is greater than or equal to * \a width, this function has no effect. * * \sa JustifyRight(), JustifyCenter(), LeftJustified() */ void JustifyLeft( size_type width, char_type fill = R::Blank() ) { size_type len = Length(); if ( len < width ) Append( fill, width-len ); } /*! * Pads this string to the left, using the specified \a fill character, up * to the specified \a width. * * If the current length \e n of this string is less than the specified * \a width, \a width - \e n copies of the \a fill character will be * prepended to the string. If the current length is greater than or equal to * \a width, this function has no effect. * * \sa JustifyLeft(), JustifyCenter(), RightJustified() */ void JustifyRight( size_type width, char_type fill = R::Blank() ) { size_type len = Length(); if ( len < width ) Prepend( fill, width-len ); } /*! * Pads this string equally to the left and right, using the specified * \a fill character, up to the specified \a width. * * If the current length \e n of this string is less than the specified * \a width, let \e m = \a width - \e n, and let \e m2 = \e m/2. Then \e m2 * copies of the \a fill character will be prepended to the string, and * \e m - \e m2 \a fill characters will be appended. If the current length * is greater than or equal to \a width, this function has no effect. * * \sa JustifyLeft(), JustifyRight(), CenterJustified() */ void JustifyCenter( size_type width, char_type fill = R::Blank() ) { size_type len = Length(); if ( len < width ) { size_type n = width-len; size_type n2 = n >> 1; Prepend( fill, n2 ); Append( fill, n-n2 ); } } /*! * Returns a duplicate of this string padded to the right, using the * specified \a fill character, up to the specified \a width. * * \sa JustifyLeft(), RightJustified(), CenterJustified() */ GenericString LeftJustified( size_type width, char_type fill = R::Blank() ) const { GenericString s( *this ); s.JustifyLeft( width, fill ); return s; } /*! * Returns a duplicate of this string padded to the left, using the * specified \a fill character, up to the specified \a width. * * \sa JustifyRight(), LeftJustified(), CenterJustified() */ GenericString RightJustified( size_type width, char_type fill = R::Blank() ) const { GenericString s( *this ); s.JustifyRight( width, fill ); return s; } /*! * Returns a duplicate of this string padded equally to the left and right, * using the specified \a fill character, up to the specified \a width. * * \sa JustifyCenter(), LeftJustified(), RightJustified() */ GenericString CenterJustified( size_type width, char_type fill = R::Blank() ) const { GenericString s( *this ); s.JustifyCenter( width, fill ); return s; } /*! * Compares numeric character values between two strings. * * \param s A string to which this string will be compared. * * \param caseSensitive When true, a case-sensitive comparison is * performed; otherwise the comparison does not * distinguish between lowercase and uppercase * characters. The default value of this parameter * is true. * * Performs a character-to-character comparison of numeric character values * between this string and the specified string \a s, and returns an integer * that indicates the comparison result: * * \li 0 if both strings are equal. * \li +1 if this string postcedes the specified string \a s. * \li -1 if this string precedes the specified string \a s. * * This function ignores the current platform locale. It considers Unicode * code points exclusively. For case-insensitive comparisons, a standard * Unicode case folding transformation is applied to each character pair. */ template int CompareCodePoints( const GenericString& s, bool caseSensitive = true ) const noexcept { return R::CompareCodePoints( m_data->string, Length(), s.m_data->string, s.Length(), caseSensitive ); } /*! * Compares numeric character values a string and a null-terminated string. * * \param t The starting address of a null-terminated string * to which this string will be compared. * * \param caseSensitive When true, a case-sensitive comparison is * performed; otherwise the comparison does not * distinguish between lowercase and uppercase * characters. The default value of this parameter * is true. * * Performs a character-to-character comparison of numeric character values * between this string and the specified null-terminated string \a t, and * returns an integer that indicates the comparison result: * * \li 0 if both strings are equal. * \li +1 if this string postcedes the specified string \a t. * \li -1 if this string precedes the specified string \a t. * * This function ignores the current platform locale. It considers Unicode * code points exclusively. For case-insensitive comparisons, a standard * Unicode case folding transformation is applied to each character pair. */ int CompareCodePoints( const_c_string t, bool caseSensitive = true ) const noexcept { return R::CompareCodePoints( m_data->string, Length(), t, R::Length( t ), caseSensitive ); } /*! * Compares numeric character values a string and a null-terminated string. * * \param c A single character to which this string will be * compared. * * \param caseSensitive When true, a case-sensitive comparison is * performed; otherwise the comparison does not * distinguish between lowercase and uppercase * characters. The default value of this parameter * is true. * * Performs a comparison between this string and the specified character * \a c, and returns an integer that indicates the comparison result: * * \li 0 if this string is equal to \a c. * \li +1 if this string postcedes the character \a c. * \li -1 if this string precedes the character \a c. * * The performed comparison is equivalent to a comparison of this string * with a fictitious string of length one, whose only character was equal to * the specified character \a c. * * This function ignores the current platform locale. It considers Unicode * code points exclusively. For case-insensitive comparisons, a standard * Unicode case folding transformation is applied to each character pair. */ int CompareCodePoints( char_type c, bool caseSensitive = true ) const noexcept { return R::CompareCodePoints( m_data->string, Length(), &c, 1, caseSensitive ); } /*! * Lexicographical comparison between two strings. * * \param s A string to which this string will be compared. * * \param caseSensitive When true, a case-sensitive comparison is performed; * otherwise the comparison does not distinguish * between lowercase and uppercase characters (as * defined by the selected locale). The default value * of this parameter is true. * * \param localeAware When true, a locale-dependent comparison is done * which takes into account the currently selected user * locale (language and variants). When false, a * locale-invariant comparison is carried out by * comparing character code points (which is faster). * The default value of this parameter is true. * * Performs a character-to-character comparison between this string and the * specified string \a s, and returns an integer that indicates the * comparison result: * * \li 0 if both strings are equal. * \li +1 if this string postcedes the specified string \a s. * \li -1 if this string precedes the specified string \a s. */ template int Compare( const GenericString& s, bool caseSensitive = true, bool localeAware = true ) const noexcept { return R::Compare( m_data->string, Length(), s.m_data->string, s.Length(), caseSensitive, localeAware ); } /*! * Lexicographical comparison to a null-terminated string. * * \param t The starting address of a null-terminated string to * which this string will be compared. * * \param caseSensitive When true, a case-sensitive comparison is performed; * otherwise the comparison does not distinguish * between lowercase and uppercase characters (as * defined by the selected locale). The default value * of this parameter is true. * * \param localeAware When true, a locale-dependent comparison is done * which takes into account the currently selected user * locale (language and variants). When false, a * locale-invariant comparison is carried out by * comparing character code points (which is faster). * The default value of this parameter is true. * * Performs a character-to-character comparison between this string and the * specified null-terminated string \a t, and returns an integer that * indicates the comparison result: * * \li 0 if both strings are equal. * \li +1 if this string postcedes the specified string \a t. * \li -1 if this string precedes the specified string \a t. */ int Compare( const_c_string t, bool caseSensitive = true, bool localeAware = true ) const noexcept { return R::Compare( m_data->string, Length(), t, R::Length( t ), caseSensitive, localeAware ); } /*! * Lexicographical comparison to a single character. * * \param c A character to which this string will be compared. * * \param caseSensitive When true, a case-sensitive comparison is performed; * otherwise the comparison does not distinguish * between lowercase and uppercase characters (as * defined by the selected locale). The default value * of this parameter is true. * * \param localeAware When true, a locale-dependent comparison is done * which takes into account the currently selected user * locale (language and variants). When false, a * locale-invariant comparison is carried out by * comparing character code points (which is faster). * The default value of this parameter is true. * * Performs a comparison between this string and the specified character * \a c, and returns an integer that indicates the comparison result: * * \li 0 if this string is equal to \a c. * \li +1 if this string postcedes the character \a c. * \li -1 if this string precedes the character \a c. * * The performed comparison is equivalent to a comparison of this string * with a fictitious string of length one, whose only character was equal to * the specified character \a c. */ int Compare( char_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept { return R::Compare( m_data->string, Length(), &c, 1, caseSensitive, localeAware ); } /*! * Case-insensitive lexicographical comparison between two strings. * * \param s A string to which this string will be compared. * * \param localeAware When true, a locale-dependent comparison is done * which takes into account the currently selected user * locale (language and variants). When false, a * locale-invariant comparison is carried out by * comparing character code points (which is faster). * The default value of this parameter is true. * * Performs a character-to-character, case-insensitive comparison between * this string and the specified string \a s, and returns an integer that * indicates the comparison result: * * \li 0 if both strings are equal. * \li +1 if this string postcedes the specified string \a s. * \li -1 if this string precedes the specified string \a s. */ template int CompareIC( const GenericString& s, bool localeAware = true ) const noexcept { return R::Compare( m_data->string, Length(), s.m_data->string, s.Length(), false/*caseSensitive*/, localeAware ); } /*! * Case-insensitive lexicographical comparison to a null-terminated string. * * \param t The starting address of a null-terminated string to * which this string will be compared. * * \param localeAware When true, a locale-dependent comparison is done * which takes into account the currently selected user * locale (language and variants). When false, a * locale-invariant comparison is carried out by * comparing character code points (which is faster). * The default value of this parameter is true. * * Performs a character-to-character, case-insensitive comparison between * this string and the specified null-terminated string \a t, and returns an * integer that indicates the comparison result: * * \li 0 if both strings are equal. * \li +1 if this string postcedes the specified string \a s. * \li -1 if this string precedes the specified string \a s. */ int CompareIC( const_c_string t, bool localeAware = true ) const noexcept { return R::Compare( m_data->string, Length(), t, R::Length( t ), false/*caseSensitive*/, localeAware ); } /*! * Case-insensitive lexicographical comparison to a single character. * * \param c A character to which this string will be compared. * * \param localeAware When true, a locale-dependent comparison is done * which takes into account the currently selected user * locale (language and variants). When false, a * locale-invariant comparison is carried out by * comparing character code points (which is faster). * The default value of this parameter is true. * * Performs a case-insensitive comparison between this string and the * specified character \a c, and returns an integer that indicates the * comparison result: * * \li 0 if this string is equal to \a c. * \li +1 if this string postcedes the character \a c. * \li -1 if this string precedes the character \a c. * * The performed comparison is equivalent to a case-insensitive comparison * of this string with a fictitious string of length one, whose only * character was equal to \a c. */ int CompareIC( char_type c, bool localeAware = true ) const noexcept { return R::Compare( m_data->string, Length(), &c, 1, false/*caseSensitive*/, localeAware ); } /*! * Wildcard string matching. * * \param pattern The pattern string. May contain multiple instances * of the wildcard characters '*' and '?'. * * \param caseSensitive When true, a case-sensitive comparison is * performed; otherwise the comparison does not * distinguish between lowercase and uppercase * characters. The default value is true. * * Returns true iff this string matches the specified \a pattern. If either * this string or the pattern is empty, this function always returns false * conventionally, even if the pattern is a single asterisk '*'. */ template bool WildMatch( const GenericString& pattern, bool caseSensitive = true ) const noexcept { return R::WildMatch( m_data->string, Length(), pattern.m_data->string, pattern.Length(), caseSensitive ); } /*! * Wildcard string matching (case-insensitive). * * \param pattern The pattern string. May contain multiple instances * of the wildcard characters '*' and '?'. * * This function performs case-insensitive comparisons between string and * non-wild pattern characters. * * Returns true iff this string matches the specified \a pattern. If either * this string or the pattern is empty, this function always returns false * conventionally, even if the pattern is a single asterisk '*'. */ template bool WildMatchIC( const GenericString& pattern ) const noexcept { return R::WildMatch( m_data->string, Length(), pattern.m_data->string, pattern.Length(), false/*caseSensitive*/ ); } /*! * Wildcard string matching with a null-terminated pattern. * * \param pattern The pattern string. May contain multiple instances * of the wildcard characters '*' and '?'. * * \param caseSensitive When true, a case-sensitive comparison is * performed; otherwise the comparison does not * distinguish between lowercase and uppercase * characters. The default value is true. * * Returns true iff this string matches the specified \a pattern. If either * this string or the pattern is empty, this function always returns false * conventionally, even if the pattern is a single asterisk '*'. */ bool WildMatch( const_c_string pattern, bool caseSensitive = true ) const noexcept { return R::WildMatch( m_data->string, Length(), pattern, R::Length( pattern ), caseSensitive ); } /*! * Wildcard string matching with a null-terminated pattern * (case-insensitive). * * \param pattern The pattern string. May contain multiple instances * of the wildcard characters '*' and '?'. * * This function performs case-insensitive comparisons between string and * non-wild pattern characters. * * Returns true iff this string matches the specified \a pattern. If either * this string or the pattern is empty, this function always returns false * conventionally, even if the pattern is a single asterisk '*'. */ bool WildMatchIC( const_c_string pattern ) const noexcept { return R::WildMatch( m_data->string, Length(), pattern, R::Length( pattern ), false/*caseSensitive*/ ); } /*! * Returns true iff this string contains one or more wildcard characters * (asterisk '*' or question mark '?'). */ bool HasWildcards() const noexcept { for ( iterator i = m_data->string; i < m_data->end; ++i ) if ( R::IsWildcard( *i ) ) return true; return false; } /*! * Replaces all characters in this string with their \e case \e folded * counterparts. */ void ToCaseFolded() { size_type len = Length(); if ( len > 0 ) { EnsureUnique(); R::ToCaseFolded( m_data->string, len ); } } /*! * Replaces all \e uppercase characters in this string with their * \e lowercase counterparts. */ void ToLowercase() { size_type len = Length(); if ( len > 0 ) { EnsureUnique(); R::ToLowercase( m_data->string, len ); } } /*! * Replaces all \e lowercase characters in this string with their * \e uppercase counterparts. */ void ToUppercase() { size_type len = Length(); if ( len > 0 ) { EnsureUnique(); R::ToUppercase( m_data->string, len ); } } /*! * Returns a duplicate of this string with all characters replaced with * their case folded counterparts. */ GenericString CaseFolded() const { GenericString s( *this ); s.ToCaseFolded(); return s; } /*! * Returns a duplicate of this string with all uppercase characters replaced * with their lowercase counterparts. */ GenericString Lowercase() const { GenericString s( *this ); s.ToLowercase(); return s; } /*! * Returns a duplicate of this string with all lowercase characters replaced * with their uppercase counterparts. */ GenericString Uppercase() const { GenericString s( *this ); s.ToUppercase(); return s; } /*! * Transposes the characters in this string, so that the first character * becomes the last and the last becomes the first, the second becomes the * next-to-last, and so on. */ void Reverse() { if ( !IsEmpty() ) { EnsureUnique(); for ( iterator i = m_data->string, j = m_data->end; i < --j; ++i ) pcl::Swap( *i, *j ); } } /*! * Returns a duplicate of this string with its characters in reverse order. */ GenericString Reversed() const { GenericString s( *this ); s.Reverse(); return s; } /*! * Sorts the characters of this string in ascending order. */ void Sort() { if ( !IsEmpty() ) { EnsureUnique(); pcl::Sort( m_data->string, m_data->end ); } } /*! * Returns a duplicate of this string with its characters sorted in * ascending order. */ GenericString Sorted() const { GenericString s( *this ); s.Sort(); return s; } /*! * Sorts the characters of this string in ascending order. Ordering is * defined such that for any pair a, b of characters, the specified binary * predicate p( a, b ) is true if a precedes b. */ template void Sort( BP p ) { if ( !IsEmpty() ) { EnsureUnique(); pcl::Sort( m_data->string, m_data->end, p ); } } /*! * Returns a duplicate of this string with its characters sorted in * ascending order with the specified binary predicate \a p. */ template GenericString Sorted( BP p ) const { GenericString s( *this ); s.Sort( p ); return s; } /*! * Returns true iff this string can be interpreted as a numeric literal: * * \li The string is not empty. * * \li It is not exclusively composed of trimable characters. * * \li Its first non-trimable character is either a sign character, a * decimal digit, or a decimal separator. * * \note This member function does \e not guarantee that this string * contains a \e valid numeric literal. It only checks for the \e role of * this string as a token in the context of a syntactic analysis. */ bool IsNumeral() const noexcept { if ( IsEmpty() ) return false; char_type c = *R::SearchTrimLeft( m_data->string, m_data->end ); return R::IsDigit( c ) || R::IsSign( c ) || R::IsDecimalSeparator( c ); } /*! * Returns true iff this string can be interpreted as a symbol identifier: * * \li The string is not empty. * * \li It is not exclusively composed of trimable characters. * * \li Its first non-trimable character is either an alphabetic character or * an underscore character. * * \note This member function does \e not guarantee that this string * contains a \e valid symbol identifier. It only checks for the \e role of * this string as a token in the context of a syntactic analysis. */ bool IsSymbol() const noexcept { if ( IsEmpty() ) return false; char_type c = *R::SearchTrimLeft( m_data->string, m_data->end ); return R::IsSymbolDigit( c ); } /*! * Returns true only if this string contains a valid identifier: * * \li It is not an empty string. * * \li Its first character is either an alphabetic character or an * underscore character. * * \li Its second and successive characters, if they exist, are all of them * either alphabetic characters, decimal digits, or underscores. * * If this string is not a valid identifier, the \a pos variable will be set * equal to the index of the first offending character (the first character * that violates the above conditions). */ bool IsValidIdentifier( distance_type& pos ) const noexcept { if ( IsEmpty() ) { pos = 0; return false; } const_iterator i = m_data->string; if ( R::IsStartingSymbolDigit( *i ) ) for ( ;; ) { if ( ++i == m_data->end ) return true; if ( !R::IsSymbolDigit( *i ) ) break; } pos = i - m_data->string; return false; } /*! * Returns true only if this string contains a valid identifier: * * \li It is not an empty string. * * \li Its first character is either an alphabetic character or an * underscore character. * * \li Its second and successive characters, if they exist, are all of them * either alphabetic characters, decimal digits, or underscores. */ bool IsValidIdentifier() const noexcept { if ( !IsEmpty() ) if ( R::IsStartingSymbolDigit( *m_data->string ) ) { for ( const_iterator i = m_data->string; ++i < m_data->end; ) if ( !R::IsSymbolDigit( *i ) ) return false; return true; } return false; } /*! * Returns a 64-bit non-cryptographic hash value computed for this string. * * This function calls pcl::Hash64() for the internal string buffer. * * The \a seed parameter can be used to generate repeatable hash values. It * can also be set to a random value in compromised environments. */ uint64 Hash64( uint64 seed = 0 ) const noexcept { return pcl::Hash64( m_data->string, Size(), seed ); } /*! * Returns a 32-bit non-cryptographic hash value computed for this string. * * This function calls pcl::Hash32() for the internal string buffer. * * The \a seed parameter can be used to generate repeatable hash values. It * can also be set to a random value in compromised environments. */ uint32 Hash32( uint32 seed = 0 ) const noexcept { return pcl::Hash32( m_data->string, Size(), seed ); } /*! * Returns a non-cryptographic hash value computed for this string. This * function is a synonym for Hash64(). */ uint64 Hash( uint64 seed = 0 ) const noexcept { return Hash64( seed ); } /*! * If the internal free list of string data structures is available, this * function destroys it and returns the number of deleted structures. * Otherwise the function has no effect and returns zero. * * \note This function is \e not thread-safe. */ static size_type DeleteFreeList() { return Data::DeleteFreeList(); } // ------------------------------------------------------------------------- protected: /*! * \internal * Dereferences string data and disposes it if it becomes garbage. */ void DetachFromData() { if ( !m_data->Detach() ) Data::Dispose( m_data ); } /*! * \internal * Internal string reallocation routine. * * Reallocates if necessary, ignoring current string contents. Reallocation * may happen due either to insufficient available space, or (in a * comparatively lazy fashion) to excessive unused space. * * Irrespective of reallocation, this function always updates internal data * pointers to reflect the specified length in characters. */ void MaybeReallocate( size_type len ) { if ( IsUnique() ) { if ( m_data->ShouldReallocate( len ) ) { m_data->Deallocate(); m_data->Allocate( len ); } else m_data->SetLength( len ); } else { Data* newData = Data::New( len ); DetachFromData(); m_data = newData; } } /*! * \internal * Internal string reallocation routine. * * Causes this string to grow by \a n uninitialized characters at the * specified index \a i. The index \a i is updated as a side effect to * ensure that 0 <= \a i <= Length() before reallocation. */ void UninitializedGrow( size_type& i, size_type n ) { size_type len = Length(); size_type newLen = len+n; if ( newLen > len ) { if ( i > len ) i = len; if ( IsUnique() ) { if ( size_type( m_data->capacity - m_data->string ) < newLen+1 ) { iterator old = m_data->string; m_data->Allocate( newLen ); if ( old != nullptr ) { if ( i > 0 ) R::Copy( m_data->string, old, i ); if ( i < len ) R::Copy( m_data->string+i+n, old+i, len-i ); m_data->alloc.Deallocate( old ); } } else { if ( i < len ) R::CopyOverlapped( m_data->string+i+n, m_data->string+i, len-i ); m_data->SetLength( newLen ); } } else { Data* newData = Data::New( newLen ); if ( i > 0 ) R::Copy( newData->string, m_data->string, i ); if ( i < len ) R::Copy( newData->string+i+n, m_data->string+i, len-i ); DetachFromData(); m_data = newData; } } } /*! * \internal * String trimming primitive. */ void Trim( const_iterator left, size_type len ) { if ( len > 0 ) { if ( IsUnique() ) { if ( m_data->ShouldReallocate( len ) ) { iterator old = m_data->string; m_data->Allocate( len ); R::Copy( m_data->string, left, len ); if ( old != nullptr ) m_data->alloc.Deallocate( old ); } else { if ( left != m_data->string ) // trim left R::CopyOverlapped( m_data->string, left, len ); m_data->SetLength( len ); // trim right } } else { Data* newData = Data::New( len ); R::Copy( newData->string, left, len ); DetachFromData(); m_data = newData; } } else Clear(); } /*! * \internal * Character replacement primitive. */ void ReplaceChar( char_type c1, char_type c2, size_type i, size_type n, bool caseSensitive ) { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( caseSensitive ) { for ( iterator p = m_data->string + i, p1 = p + n; p < p1; ++p ) if ( *p == c1 ) { EnsureUnique(); *p = c2; for ( ; ++p < p1; ) if ( *p == c1 ) *p = c2; break; } } else { c1 = R::ToCaseFolded( c1 ); for ( iterator p = m_data->string + i, p1 = p + n; p < p1; ++p ) if ( R::ToCaseFolded( *p ) == c1 ) { EnsureUnique(); *p = c2; for ( ; ++p < p1; ) if ( R::ToCaseFolded( *p ) == c1 ) *p = c2; break; } } } } } /*! * \internal * String replacement primitive. */ void ReplaceString( const_iterator t1, size_type n1, const_iterator t2, size_type n2, size_type i, bool caseSensitive ) { if ( n1 > 0 ) { size_type len = Length(); if ( i < len ) { SearchEngine S( t1, n1, caseSensitive ); if ( n1 == n2 ) { EnsureUnique(); for ( size_type p = i; (p = S( m_data->string, p, len )) < len; p += n1 ) R::Copy( m_data->string + p, t2, n2 ); } else { Array P; for ( size_type p = i; (p = S( m_data->string, p, len )) < len; p += n1 ) P.Add( p ); if ( !P.IsEmpty() ) { size_type newLen = len; if ( n1 < n2 ) newLen += P.Length()*(n2 - n1); else newLen -= P.Length()*(n1 - n2); if ( newLen > 0 ) { Data* newData = Data::New( newLen ); size_type targetIndex = 0; size_type sourceIndex = 0; for ( size_type p : P ) { size_type n = p - sourceIndex; if ( n > 0 ) R::Copy( newData->string+targetIndex, m_data->string+sourceIndex, n ); R::Copy( newData->string+targetIndex+n, t2, n2 ); targetIndex += n + n2; sourceIndex = p + n1; } if ( sourceIndex < len ) R::Copy( newData->string+targetIndex, m_data->string+sourceIndex, len-sourceIndex ); DetachFromData(); m_data = newData; } else Clear(); } } } } } /*! * \internal * \class pcl::GenericString::SearchEngine * \brief Substring search primitive algorithm * * Implements the Boyer-Moore substring search algorithm (mismatched * character heuristic). * * \b References * * \li Robert Sedgewick, Kevin Wayne (2011), Algorithms, 4th Edition, * Addison-Wesley Professional, pp 770-773. * * \li Robert S. Boyer and J. Strother Moore (1977), A fast string * searching algorithm, Communcations of the ACM Vol. 20 No. 10, * pp 762-772. */ class PCL_CLASS SearchEngine { public: /*! * Constructs a substring search engine for the specified \a pattern, * pattern length in characters, and case sensitivity. * * Setting the \a useBoyerMoore parameter to \c false forces use of a * brute-force search routine in all cases (useful for testing purposes * and unique searches on very short strings). Otherwise a Boyer-Moore * substring search algorithm will be used except for patterns of less * than 4 characters. */ SearchEngine( const_iterator pattern, size_type patternLength, bool caseSensitive = true, bool searchLast = false, bool useBoyerMoore = true ) : m_pattern( pattern ) , m_patternLength( int( patternLength ) ) , m_caseSensitive( caseSensitive ) , m_searchLast( searchLast ) , m_useBoyerMoore( useBoyerMoore && m_patternLength > 3 ) { if ( m_useBoyerMoore ) InitSkipList(); } /*! * Performs a substring search in the subset of contiguous characters of * the specified string \a text defined by the range * [\a startIndex,\a endIndex). The search pattern, search direction and * case sensitivity are defined in the class constructor. * * Returns the character index where the first exact match has been * found, or \a endIndex if no match was found. * * We implement the mismatched character heuristic version of * the Boyer-Moore algorithm. */ size_type operator()( const_iterator text, size_type startIndex, size_type endIndex ) const noexcept { if ( endIndex <= startIndex || m_patternLength <= 0 || endIndex-startIndex < size_type( m_patternLength ) || text == nullptr || m_pattern == nullptr ) return endIndex; if ( m_caseSensitive ) { if ( m_useBoyerMoore ) { if ( m_searchLast ) { for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) { int skip = 0; const_iterator t = text + r - i; const_iterator p = m_pattern; for ( int j = m_patternLength; --j >= 0; ) { char_type c = *t++; if ( c != *p++ ) { skip = j - m_skipList[uint8( c )]; if ( skip < 1 ) skip = 1; break; } } if ( skip == 0 ) return r - i; i += skip; } } else { for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) { int skip = 0; const_iterator t = text + i + m_patternLength; const_iterator p = m_pattern + m_patternLength; for ( int j = m_patternLength; --j >= 0; ) { char_type c = *--t; if ( c != *--p ) { // ### N.B.: Could do better with a precomputed pattern mismatch table. skip = j - m_skipList[uint8( c )]; if ( skip < 1 ) skip = 1; break; } } if ( skip == 0 ) return i; i += skip; } } } else { // Use a brute force search for very small patterns. if ( m_searchLast ) { for ( size_type i = endIndex-m_patternLength; ; --i ) { const_iterator t = text + i; const_iterator p = m_pattern; for ( int j = m_patternLength; ; ++t, ++p ) { if ( *t != *p ) break; if ( --j == 0 ) return i; } if ( i == startIndex ) break; } } else { for ( size_type i = startIndex, r = endIndex-m_patternLength; ; ++i ) { const_iterator t = text + i; const_iterator p = m_pattern; for ( int j = m_patternLength; ; ++t, ++p ) { if ( *t != *p ) break; if ( --j == 0 ) return i; } if ( i == r ) break; } } } } else { if ( m_useBoyerMoore ) { if ( m_searchLast ) { for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) { int skip = 0; const_iterator t = text + r - i; const_iterator p = m_pattern; for ( int j = m_patternLength; --j >= 0; ) { char_type c = R::ToCaseFolded( *t++ ); if ( c != R::ToCaseFolded( *p++ ) ) { skip = j - m_skipList[uint8( c )]; if ( skip < 1 ) skip = 1; break; } } if ( skip == 0 ) return r - i; i += skip; } } else { for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; ) { int skip = 0; const_iterator t = text + i + m_patternLength; const_iterator p = m_pattern + m_patternLength; for ( int j = m_patternLength; --j >= 0; ) { char_type c = R::ToCaseFolded( *--t ); if ( c != R::ToCaseFolded( *--p ) ) { // ### N.B.: Could do better with a precomputed pattern mismatch table. skip = j - m_skipList[uint8( c )]; if ( skip < 1 ) skip = 1; break; } } if ( skip == 0 ) return i; i += skip; } } } else { // Use a brute force search for very small patterns. if ( m_searchLast ) { for ( size_type i = endIndex-m_patternLength; ; --i ) { const_iterator t = text + i; const_iterator p = m_pattern; for ( int j = m_patternLength; ; ++t, ++p ) { if ( R::ToCaseFolded( *t ) != R::ToCaseFolded( *p ) ) break; if ( --j == 0 ) return i; } if ( i == startIndex ) break; } } else { for ( size_type i = startIndex, r = endIndex-m_patternLength; ; ++i ) { const_iterator t = text + i; const_iterator p = m_pattern; for ( int j = m_patternLength; ; ++t, ++p ) { if ( R::ToCaseFolded( *t ) != R::ToCaseFolded( *p ) ) break; if ( --j == 0 ) return i; } if ( i == r ) break; } } } } return endIndex; } private: int m_skipList[ 256 ]; const_iterator m_pattern; int m_patternLength; bool m_caseSensitive : 1; bool m_searchLast : 1; bool m_useBoyerMoore : 1; void InitSkipList() noexcept { ::memset( m_skipList, 0xff, sizeof( m_skipList ) ); // fill with -1 if ( m_searchLast ) { const_iterator p = m_pattern + m_patternLength; if ( m_caseSensitive ) for ( int i = 0; i < m_patternLength; ++i ) m_skipList[uint8( *--p )] = i; else for ( int i = 0; i < m_patternLength; ++i ) m_skipList[uint8( R::ToCaseFolded( *--p ) )] = i; } else { const_iterator p = m_pattern; if ( m_caseSensitive ) for ( int i = 0; i < m_patternLength; ++i ) m_skipList[uint8( *p++ )] = i; else for ( int i = 0; i < m_patternLength; ++i ) m_skipList[uint8( R::ToCaseFolded( *p++ ) )] = i; } } }; // ------------------------------------------------------------------------- /*! * \internal * \class pcl::GenericString::Data * \brief Reference-counted string data structure */ class PCL_CLASS Data : public ReferenceCounter { private: #ifndef __PCL_NO_STRING_FREE_LIST static Data* freeList; //!< Singly-linked list of free string data structures. static AtomicInt freeLock; //!< Access synchronization for the free list. #endif public: iterator string = nullptr; //!< Beginning of the null-terminated string iterator end = nullptr; //!< End of the string iterator capacity = nullptr; //!< End of the allocated block or link in free list allocator alloc; //!< The allocator object /*! * Constructs an empty string data structure. */ Data() = default; /*! * Constructs a string of \a len characters. */ Data( size_type len ) { Allocate( len ); } /*! * Constructs a string of \a len characters and space allocated for a * maximum of \a total characters (plus terminating null). */ Data( size_type len, size_type total ) { Allocate( len, total ); } /*! * Destroys a string data structure. */ ~Data() { Deallocate(); } /*! * Allocates space to store at least \a total characters plus a * terminating null character, and updates internal pointers to define a * string of \a len characters. * * If \a total < \a len this routine allocates strictly the space * required to store \a len + 1 characters. Otherwise the allocated block * will have an optimized length, generally greater than the number * \a len + 1 of storable characters. */ void Allocate( size_type len, size_type total ) { total = (len <= total) ? alloc.PagedLength( total+1 ) : len+1; // +1 is room for a null terminating character string = alloc.Allocate( total ); capacity = string + total; SetLength( len ); } /*! * Allocates space to store at least \a len characters plus a terminating * null character. This function is a shortcut for Allocate( len, len ). */ void Allocate( size_type len ) { Allocate( len, len ); } /*! * Allocates space to store exactly \a total characters plus a * terminating null character, and updates internal pointers to define a * string of \a len <= \a total characters. * * This routine allocates strictly the space required to store * \a total + 1 characters without length optimization. */ void Reserve( size_type len, size_type total ) { PCL_PRECONDITION( len <= total ) string = alloc.Allocate( total+1 ); capacity = string + total+1; SetLength( pcl::Min( len, total ) ); } /*! * Deallocates string data, yielding an empty structure. */ void Deallocate() { PCL_CHECK( (string == nullptr) ? end == nullptr : string < end ) if ( string != nullptr ) { alloc.Deallocate( string ); Reset(); } } /*! * Returns true iff a reallocation of string data should happen in order * to change the string's length to \a len characters. */ bool ShouldReallocate( size_type len ) const noexcept { size_type m = capacity - string; return m <= len || alloc.ReallocatedLength( m, len+1 ) < (m >> 1); } /*! * Sets the length of the string. Arranges internal pointers and writes a * null string terminating character. */ void SetLength( size_type len ) noexcept { *(end = (string + len)) = R::Null(); } /*! * Sets all string pointers to \c nullptr. */ void Reset() noexcept { string = end = capacity = nullptr; } /*! * Returns a pointer to a free string data structure, or \c nullptr if * none is available. The returned structure must be initialized. * * This function is thread-safe. */ #ifndef __PCL_NO_STRING_FREE_LIST static Data* NextFree() noexcept { if ( freeLock.TestAndSet( 0, 1 ) ) { Data* data = freeList; if ( data != nullptr ) freeList = reinterpret_cast( data->string ); freeLock.Store( 0 ); return data; } return nullptr; } #endif // !__PCL_NO_STRING_FREE_LIST /*! * Returns a free empty string data structure. Retrieves an existing data * structure from the internal free list if available, or creates a new * one otherwise. * * This function is thread-safe. */ static Data* New() { #ifndef __PCL_NO_STRING_FREE_LIST Data* data = NextFree(); if ( data != nullptr ) { data->string = nullptr; return data; } #endif // !__PCL_NO_STRING_FREE_LIST return new Data; } /*! * Returns a free string data structure of the specified length in * characters. Retrieves an existing data structure from the internal * free list if available, or creates a new one otherwise. * * This function is thread-safe. */ static Data* New( size_type len ) { #ifndef __PCL_NO_STRING_FREE_LIST Data* data = NextFree(); if ( data != nullptr ) { data->Allocate( len ); // ### FIXME: If allocation fails, data is a leak. return data; } #endif // !__PCL_NO_STRING_FREE_LIST return new Data( len ); } /*! * Returns a free string data structure with the specified length and * total available space. Retrieves an existing data structure from the * internal free list if available, or creates a new one otherwise. * * This function is thread-safe. */ static Data* New( size_type len, size_type total ) { #ifndef __PCL_NO_STRING_FREE_LIST Data* data = NextFree(); if ( data != nullptr ) { data->Allocate( len, total ); // ### FIXME: If allocation fails, data is a leak. return data; } #endif // !__PCL_NO_STRING_FREE_LIST return new Data( len, total ); } /*! * Deallocates and disposes a string data structure. If the internal free * list is available, the deallocated structure is added to the list for * subsequent reuse. Otherwise the structure is destroyed. * * This function is thread-safe. */ static void Dispose( Data* data ) { PCL_PRECONDITION( data != nullptr ) PCL_CHECK( data->RefCount() == 0 ) #ifndef __PCL_NO_STRING_FREE_LIST if ( freeLock.TestAndSet( 0, 1 ) ) { data->Attach(); data->Deallocate(); data->string = reinterpret_cast( freeList ); freeList = data; freeLock.Store( 0 ); } else #endif // !__PCL_NO_STRING_FREE_LIST delete data; } /*! * If the internal free list is available, this function destroys it and * returns the number of deleted string data structures. Otherwise the * function has no effect and returns zero. * * \note This function is \e not thread-safe. */ static size_type DeleteFreeList() { size_type count = 0; #ifndef __PCL_NO_STRING_FREE_LIST while ( freeList != nullptr ) { Data* data = freeList; freeList = reinterpret_cast( data->string ); data->string = nullptr; delete data; ++count; } #endif // !__PCL_NO_STRING_FREE_LIST return count; } }; /* * The reference-counted string data. */ Data* m_data = nullptr; }; #ifndef __PCL_NO_STRING_FREE_LIST template typename GenericString::Data* GenericString::Data::freeList = nullptr; template AtomicInt GenericString::Data::freeLock; #endif // !__PCL_NO_STRING_FREE_LIST /*! * Exchanges two strings. */ template inline void Swap( GenericString& s1, GenericString& s2 ) noexcept { s1.Swap( s2 ); } // ---------------------------------------------------------------------------- /*! * \defgroup genericstring_relational_ops GenericString Relational Operators */ // ---------------------------------------------------------------------------- /*! * Returns true iff two strings \a s1 and \a s2 are equal. * \ingroup genericstring_relational_ops */ template inline bool operator ==( const GenericString& s1, const GenericString& s2 ) noexcept { return s1.CompareCodePoints( s2 ) == 0; } /*! * Returns true iff a string \a s1 is less than a string \a s2. This function * performs a character-to-character, locale-unaware comparison of numeric * character values. See GenericString<>::CompareCodePoints() for more * information. * \ingroup genericstring_relational_ops */ template inline bool operator <( const GenericString& s1, const GenericString& s2 ) noexcept { return s1.CompareCodePoints( s2 ) < 0; } /*! * Returns true iff a string \a s1 is less than or equal to a string \a s2. * This function performs a character-to-character, locale-unaware comparison * of numeric character values. See GenericString<>::CompareCodePoints() for * more information. * \ingroup genericstring_relational_ops */ template inline bool operator <=( const GenericString& s1, const GenericString& s2 ) noexcept { return s1.CompareCodePoints( s2 ) <= 0; } /*! * Returns true iff a string \a s1 is greater than a string \a s2. This * function performs a character-to-character, locale-unaware comparison of * numeric character values. See GenericString<>::CompareCodePoints() for more * information. * \ingroup genericstring_relational_ops */ template inline bool operator >( const GenericString& s1, const GenericString& s2 ) noexcept { return s1.CompareCodePoints( s2 ) > 0; } /*! * Returns true iff a string \a s1 is greater than or equal to a string \a s2. * This function performs a character-to-character, locale-unaware comparison * of numeric character values. See GenericString<>::CompareCodePoints() for * more information. * \ingroup genericstring_relational_ops */ template inline bool operator >=( const GenericString& s1, const GenericString& s2 ) noexcept { return s1.CompareCodePoints( s2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Returns true iff a string \a s1 is equal to a null-terminated string \a t2. * \ingroup genericstring_relational_ops */ template inline bool operator ==( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept { return s1.CompareCodePoints( t2 ) == 0; } /*! * Returns true iff a string \a s1 is less than a null-terminated string \a t2. * This function performs a character-to-character, locale-unaware comparison * of numeric character values. See GenericString<>::CompareCodePoints() for * more information. * \ingroup genericstring_relational_ops */ template inline bool operator <( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept { return s1.CompareCodePoints( t2 ) < 0; } /*! * Returns true iff a string \a s1 is less than or equal to a null-terminated * string \a t2. This function performs a character-to-character, * locale-unaware comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator <=( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept { return s1.CompareCodePoints( t2 ) <= 0; } /*! * Returns true iff a string \a s1 is greater than a null-terminated string * \a t2. This function performs a character-to-character, locale-unaware * comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator >( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept { return s1.CompareCodePoints( t2 ) > 0; } /*! * Returns true iff a string \a s1 is greater than or equal to a * null-terminated string \a t2. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator >=( const GenericString& s1, typename GenericString::const_c_string t2 ) noexcept { return s1.CompareCodePoints( t2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Returns true iff a null-terminated string \a t1 is equal to a string \a s2. * \ingroup genericstring_relational_ops */ template inline bool operator ==( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( t1 ) == 0; } /*! * Returns true iff a null-terminated string \a t1 is less than a string \a s2. * This function performs a character-to-character, locale-unaware comparison * of numeric character values. See GenericString<>::CompareCodePoints() for * more information. * \ingroup genericstring_relational_ops */ template inline bool operator <( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( t1 ) > 0; } /*! * Returns true iff a null-terminated string \a t1 is less than or equal to a * string \a s2. This function performs a character-to-character, * locale-unaware comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator <=( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( t1 ) >= 0; } /*! * Returns true iff a null-terminated string \a t1 is greater than a string * \a s2. This function performs a character-to-character, locale-unaware * comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator >( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( t1 ) < 0; } /*! * Returns true iff a null-terminated string \a t1 is greater than or equal to * a string \a s2. This function performs a character-to-character, * locale-unaware comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator >=( typename GenericString::const_c_string t1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( t1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * Returns true iff a string \a s1 is equal to a character \a c2. * \ingroup genericstring_relational_ops */ template inline bool operator ==( const GenericString& s1, typename GenericString::char_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) == 0; } /*! * Returns true iff a string \a s1 is less than a character \a c2. This * function performs a character-to-character, locale-unaware comparison of * numeric character values. See GenericString<>::CompareCodePoints() for more * information. * \ingroup genericstring_relational_ops */ template inline bool operator <( const GenericString& s1, typename GenericString::char_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) < 0; } /*! * Returns true iff a string \a s1 is less than or equal to a character \a c2. * This function performs a character-to-character, locale-unaware comparison * of numeric character values. See GenericString<>::CompareCodePoints() for * more information. * \ingroup genericstring_relational_ops */ template inline bool operator <=( const GenericString& s1, typename GenericString::char_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) <= 0; } /*! * Returns true iff a string \a s1 is greater than a character \a c2. This * function performs a character-to-character, locale-unaware comparison of * numeric character values. See GenericString<>::CompareCodePoints() for more * information. * \ingroup genericstring_relational_ops */ template inline bool operator >( const GenericString& s1, typename GenericString::char_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) > 0; } /*! * Returns true iff a string \a s1 is greater than or equal to a character * \a c2. This function performs a character-to-character, locale-unaware * comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator >=( const GenericString& s1, typename GenericString::char_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Returns true iff a character \a c1 is equal to a string \a s2. * \ingroup genericstring_relational_ops */ template inline bool operator ==( typename GenericString::char_type c1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( c1 ) == 0; } /*! * Returns true iff a character \a c1 is less than a string \a s2. This * function performs a character-to-character, locale-unaware comparison of * numeric character values. See GenericString<>::CompareCodePoints() for more * information. * \ingroup genericstring_relational_ops */ template inline bool operator <( typename GenericString::char_type c1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( c1 ) > 0; } /*! * Returns true iff a character \a c1 is less than or equal to a string \a s2. * This function performs a character-to-character, locale-unaware comparison * of numeric character values. See GenericString<>::CompareCodePoints() for * more information. * \ingroup genericstring_relational_ops */ template inline bool operator <=( typename GenericString::char_type c1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( c1 ) >= 0; } /*! * Returns true iff a character \a c1 is greater than a string \a s2. This * function performs a character-to-character, locale-unaware comparison of * numeric character values. See GenericString<>::CompareCodePoints() for more * information. * \ingroup genericstring_relational_ops */ template inline bool operator >( typename GenericString::char_type c1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( c1 ) < 0; } /*! * Returns true iff a character \a c1 is greater than or equal to a string * \a s2. This function performs a character-to-character, locale-unaware * comparison of numeric character values. See * GenericString<>::CompareCodePoints() for more information. * \ingroup genericstring_relational_ops */ template inline bool operator >=( typename GenericString::char_type c1, const GenericString& s2 ) noexcept { return s2.CompareCodePoints( c1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * \class IsoString * \brief Eight-bit string (ISO/IEC-8859-1 or UTF-8 string) * * %IsoString derives from a template instantiation of GenericString for the * \c char type. On the PixInsight platform, %IsoString represents a dynamic * ISO/IEC-8859-1 string, an 8-bit Unicode Transformation Format (UTF-8) * string, or even a sequence of ASCII (or Latin-1) characters, depending on * the context and type of transformations applied. * * \sa String */ class PCL_CLASS IsoString : public GenericString { public: /*! * Base class of %IsoString. */ typedef GenericString string_base; /*! * Represents a character pertaining to an %IsoString object. */ typedef string_base::char_type char_type; /*! * The character traits class used by this template instantiation. */ typedef string_base::char_traits char_traits; /*! * The block allocator used by this template instantiation. */ typedef string_base::block_allocator block_allocator; /*! * The allocator class used by this template instantiation. */ typedef string_base::allocator allocator; /*! * Null-terminated sequence of 8-bit characters. */ typedef string_base::c_string c_string; /*! * Immutable null-terminated sequence of 8-bit characters. */ typedef string_base::const_c_string const_c_string; /*! * %IsoString iterator. */ typedef string_base::iterator iterator; /*! * Immutable %IsoString iterator. */ typedef string_base::const_iterator const_iterator; /*! * Reverse %IsoString iterator. */ typedef string_base::reverse_iterator reverse_iterator; /*! * Immutable reverse %IsoString iterator. */ typedef string_base::const_reverse_iterator const_reverse_iterator; /*! * Represents a Unicode (UTF-16) string. * \note This type must be defined as the same template instantiation used * for the String class. */ typedef GenericString ustring_base; /*! * Represents a Unicode (UTF-16) character. */ typedef ustring_base::char_type uchar_type; /*! * Unicode (UTF-16) character traits class. */ typedef ustring_base::char_traits uchar_traits; /*! * Null-terminated sequence of UTF-16 characters. */ typedef ustring_base::c_string c_ustring; /*! * Immutable null-terminated sequence of UTF-16 characters. */ typedef ustring_base::const_c_string const_c_ustring; /*! * Unicode (UTF-16) string iterator. */ typedef ustring_base::iterator uchar_iterator; /*! * Immutable Unicode (UTF-16) string iterator. */ typedef ustring_base::const_iterator const_uchar_iterator; // ------------------------------------------------------------------------- /*! * Constructs an empty %IsoString object. */ IsoString() = default; /*! * Constructs an %IsoString object as a shallow copy of the specified * \c string_base string \a s (copy constructor from the base class). */ IsoString( const string_base& s ) : string_base( s ) { } /*! * Copy constructor. */ IsoString( const IsoString& ) = default; /*! * Constructs an %IsoString object by transferring data from the specified * \c string_base string \a s (move constructor from the base class). */ IsoString( string_base&& s ) : string_base( std::move( s ) ) { } /*! * Move constructor. */ IsoString( IsoString&& ) = default; /*! * Constructs an %IsoString as a copy of the specified Unicode string \a s, * transformed to ISO/IEC-8859-1. Characters in the Unicode string that * cannot be converted to ISO/IEC-8859-1 (that is, code points greater than * 0x100) will have undefined values in the 8-bit string. Undefined values * are represented with question mark characters (?). */ explicit IsoString( const ustring_base& s ) { (void)operator =( s ); } /*! * Constructs an %IsoString as a copy of a null-terminated string \a t. */ IsoString( const_c_string t ) : string_base( t ) { } /*! * Constructs an %IsoString with the \a n first characters of the * null-terminated string \a t, starting from its \a i-th character. */ IsoString( const_c_string t, size_type i, size_type n ) : string_base( t, i, n ) { } /*! * Constructs an %IsoString with \a n copies of a character \a c. */ IsoString( char_type c, size_type n = 1 ) : string_base( c, n ) { } /*! * Constructs an %IsoString with a copy of the character sequence defined by * the range [i,j). */ IsoString( const_iterator i, const_iterator j ) : string_base( i, j ) { } /*! * Constructs an %IsoString with a copy of the character sequence stored in * the specified initializer list \a l. * * This constructor is equivalent to: * * \code IsoString( l.begin(), l.end() ) \endcode */ IsoString( std::initializer_list l ) : IsoString( l.begin(), l.end() ) { } /*! * Constructs an %IsoString as a copy of the null-terminated Unicode * (UTF-16) string \a t, transformed to ISO/IEC-8859-1. * * If the specified Unicode string \a t contains characters that cannot be * converted to ISO/IEC-8859-1 characters, the corresponding characters in * this string will have undefined values. For conversions from UTF-16 to * UTF-8, see String::ToUTF8() and String::UTF16ToUTF8(). */ explicit IsoString( const_c_ustring t ) { (void)operator =( t ); } /*! * Constructs an %IsoString with the \a n first characters of the * null-terminated Unicode (UTF-16) string \a t, starting from its \a i-th * character, transformed to ISO/IEC-8859-1. * * If the specified Unicode string \a t contains characters that cannot be * converted to ISO/IEC-8859-1 characters, the corresponding characters in * this string will have undefined values. For conversions from UTF-16 to * UTF-8, see String::ToUTF8() and String::UTF16ToUTF8(). */ IsoString( const_c_ustring t, size_type i, size_type n ); /*! * Constructs an %IsoString with a copy of the bytes stored in the specified * ByteArray object. * * Source unsigned 8-bit integers will be reinterpreted as signed 8-bit * characters. */ explicit IsoString( const ByteArray& B ) : IsoString( const_iterator( B.Begin() ), const_iterator( B.End() ) ) { } /*! * Constructs an %IsoString as a literal representation of a \c bool value. */ explicit IsoString( bool x ) : string_base( x ? "true" : "false" ) { } /*! * Constructs an %IsoString as a literal representation of a * \c signed \c short value. */ explicit IsoString( short x ) { (void)Format( "%hd", x ); } /*! * Constructs an %IsoString as a literal representation of an * \c unsigned \c short value. */ explicit IsoString( unsigned short x ) { (void)Format( "%hu", x ); } /*! * Constructs an %IsoString as a literal representation of a * \c signed \c int value. */ explicit IsoString( int x ) { (void)Format( "%i", x ); } /*! * Constructs an %IsoString as a literal representation of an * \c unsigned \c int value. */ explicit IsoString( unsigned int x ) { (void)Format( "%u", x ); } /*! * Constructs an %IsoString as a literal representation of a * \c signed \c long value. */ explicit IsoString( long x ) { (void)Format( "%ld", x ); } /*! * Constructs an %IsoString as a literal representation of an * \c unsigned \c long value. */ explicit IsoString( unsigned long x ) { (void)Format( "%lu", x ); } /*! * Constructs an %IsoString as a literal representation of a * \c signed \c long \c long value. */ explicit IsoString( long long x ) { (void)Format( "%lli", x ); } /*! * Constructs an %IsoString as a literal representation of an * \c unsigned \c long \c long value. */ explicit IsoString( unsigned long long x ) { (void)Format( "%llu", x ); } /*! * Constructs an %IsoString as a literal representation of a * \c float value. */ explicit IsoString( float x ) { (void)Format( "%.7g", x ); } /*! * Constructs an %IsoString as a literal representation of a * \c double value. */ explicit IsoString( double x ) { (void)Format( "%.16g", x ); } /*! * Constructs an %IsoString as a literal representation of a * \c long \c double value. */ explicit IsoString( long double x ) { #ifdef _MSC_VER (void)Format( "%.16Lg", x ); #else (void)Format( "%.18Lg", x ); #endif } #ifndef __PCL_NO_STRING_COMPLEX /*! * Constructs an %IsoString as a literal representation of an * \c fcomplex value. */ explicit IsoString( Complex& x ) { (void)Format( "{%.7g,%.7g}", x.Real(), x.Imag() ); } /*! * Constructs an %IsoString as a literal representation of a * \c dcomplex value. */ explicit IsoString( Complex& x ) { (void)Format( "{%.16g,%.16g}", x.Real(), x.Imag() ); } /*! * Constructs an %IsoString as a literal representation of an * \c lcomplex value. */ explicit IsoString( Complex& x ) { #ifdef _MSC_VER (void)Format( "{%.16Lg,%.16Lg}", x.Real(), x.Imag() ); #else (void)Format( "{%.18Lg,%.18Lg}", x.Real(), x.Imag() ); #endif } #endif // !__PCL_NO_STRING_COMPLEX #ifdef __PCL_QT_INTERFACE explicit IsoString( const QString& qs ) : string_base( qs.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHARPTR_FROM_QSTRING( qs ) ) ) { } explicit IsoString( const QByteArray& qb ) : string_base( qb.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) ) ) { } explicit IsoString( const QDate& qd ) : string_base( iterator( PCL_GET_CHARPTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ) ) { } explicit IsoString( const QDateTime& qdt ) : string_base( iterator( PCL_GET_CHARPTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ) ) { } #endif // ------------------------------------------------------------------------- /*! * Copy assignment operator. Returns a reference to this object. */ IsoString& operator =( const IsoString& s ) { Assign( s ); return *this; } /*! * Move assignment operator. Returns a reference to this object. */ IsoString& operator =( IsoString&& s ) { Transfer( s ); return *this; } /*! * Assigns a shallow copy of the \c string_base string \a s to this string. * Returns a reference to this object. */ IsoString& operator =( const string_base& s ) { Assign( s ); return *this; } /*! * Transfers the data from the \c string_base string \a s to this string * (move assignment from base class). Returns a reference to this object. */ IsoString& operator =( string_base&& s ) { Transfer( s ); return *this; } /*! * Assigns a copy of the Unicode string \a s (UTF-16) to this string, after * converting source UTF-16 characters to ISO/IEC-8859-1 characters. Returns * a reference to this object. * * If the specified UTF-16 string contains characters that cannot be * converted to ISO/IEC-8859-1, the corresponding characters in this string * will have undefined values. For conversions from UTF-16 to UTF-8, see * String::ToUTF8() and String::UTF16ToUTF8(). */ IsoString& operator =( const ustring_base& s ) { return operator =( s.Begin() ); } /*! * Assigns a copy of the null-terminated string \a t to this string. Returns * a reference to this object. */ IsoString& operator =( const_c_string t ) { Assign( t ); return *this; } /*! * Assigns a single copy of a character \a c to this string. Returns a * reference to this object. */ IsoString& operator =( char_type c ) { Assign( c, 1 ); return *this; } /*! * Assigns a copy of the null-terminated Unicode string \a s (UTF-16) to * this string, after converting source UTF-16 characters to ISO/IEC-8859-1 * characters. Returns a reference to this object. * * If the specified UTF-16 string contains characters that cannot be * converted to ISO/IEC-8859-1, the corresponding characters in this string * will have undefined values. For conversions from UTF-16 to UTF-8, see * String::ToUTF8() and String::UTF16ToUTF8(). */ IsoString& operator =( const_c_ustring t ); #ifdef __PCL_QT_INTERFACE IsoString& operator =( const QString& qs ) { if ( qs.isEmpty() ) Clear(); else Assign( PCL_GET_CHARPTR_FROM_QSTRING( qs ) ); return *this; } IsoString& operator =( const QByteArray& qb ) { if ( qb.isEmpty() ) Clear(); else Assign( PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) ); return *this; } IsoString& operator =( const QDate& qd ) { Assign( PCL_GET_CHARPTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ); return *this; } IsoString& operator =( const QDateTime& qdt ) { Assign( PCL_GET_CHARPTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ); return *this; } #endif // ------------------------------------------------------------------------- IsoString SetToLength( size_type n ) const { return string_base::SetToLength( n ); } IsoString ResizedToNullTerminated() const { return string_base::ResizedToNullTerminated(); } IsoString Squeezed() const { return string_base::Squeezed(); } // ------------------------------------------------------------------------- IsoString Substring( size_type i, size_type n = maxPos ) const { return string_base::Substring( i, n ); } IsoString Left( size_type n ) const { return string_base::Left( n ); } IsoString Right( size_type n ) const { return string_base::Right( n ); } IsoString Suffix( size_type i ) const { return string_base::Suffix( i ); } IsoString Prefix( size_type i ) const { return string_base::Prefix( i ); } // ------------------------------------------------------------------------- IsoString Trimmed() const { return string_base::Trimmed(); } IsoString TrimmedLeft() const { return string_base::TrimmedLeft(); } IsoString TrimmedRight() const { return string_base::TrimmedRight(); } // ------------------------------------------------------------------------- IsoString LeftJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const { return string_base::LeftJustified( width, fill ); } IsoString RightJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const { return string_base::RightJustified( width, fill ); } IsoString CenterJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const { return string_base::CenterJustified( width, fill ); } // ------------------------------------------------------------------------- IsoString Enclosed( char_type c ) const { return string_base::Enclosed( c ); } IsoString SingleQuoted() const { return string_base::SingleQuoted(); } IsoString DoubleQuoted() const { return string_base::DoubleQuoted(); } IsoString Unquoted() const { return string_base::Unquoted(); } // ------------------------------------------------------------------------- IsoString CaseFolded() const { return string_base::CaseFolded(); } IsoString Lowercase() const { return string_base::Lowercase(); } IsoString Uppercase() const { return string_base::Uppercase(); } // ------------------------------------------------------------------------- IsoString Reversed() const { return string_base::Reversed(); } IsoString Sorted() const { return string_base::Sorted(); } template IsoString Sorted( BP p ) const { return string_base::Sorted( p ); } // ------------------------------------------------------------------------- /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * character. Returns a reference to this string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template IsoString& ToSeparated( const C& c, char_type separator ) { Clear(); return c.ToSeparated( *this, separator ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * character, and built using an \a append binary function. Returns a * reference to this string. * * The binary function must be of the form: * * \code void append( IsoString& s, char c ); \endcode * * where \a c is being appended to \a s. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template IsoString& ToSeparated( const C& c, char_type separator, AF append ) { Clear(); return c.ToSeparated( *this, separator, append ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator string. * Returns a reference to this string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template IsoString& ToSeparated( const C& c, const IsoString& separator ) { Clear(); return c.ToSeparated( *this, separator ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator string, * and built using an \a append binary function. Returns a reference to this * string. * * The binary function must be of the form: * * \code void append( IsoString& s1, const IsoString& s2 ); \endcode * * where \a s2 is being appended to \a s1. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template IsoString& ToSeparated( const C& c, const IsoString& separator, AF append ) { Clear(); return c.ToSeparated( *this, separator, append ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * null-terminated string. Returns a reference to this string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template IsoString& ToSeparated( const C& c, const_c_string separator ) { return ToSeparated( c, IsoString( separator ) ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * null-terminated string, and built using an \a append binary function. * Returns a reference to this string. * * The binary function must be of the form: * * \code void append( IsoString& s1, const char* s2 ); \endcode * * where \a s2 is being appended to \a s1. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template IsoString& ToSeparated( const C& c, const_c_string separator, AF append ) { return ToSeparated( c, IsoString( separator ), append ); } /*! * Replaces the contents of this string with a sequence of comma-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, ',' ); \endcode */ template IsoString& ToCommaSeparated( const C& c ) { return ToSeparated( c, IsoCharTraits::Comma() ); } /*! * Replaces the contents of this string with a sequence of colon-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, ':' ); \endcode */ template IsoString& ToColonSeparated( const C& c ) { return ToSeparated( c, IsoCharTraits::Colon() ); } /*! * Replaces the contents of this string with a sequence of space-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, ' ' ); \endcode */ template IsoString& ToSpaceSeparated( const C& c ) { return ToSeparated( c, IsoCharTraits::Blank() ); } /*! * Replaces the contents of this string with a sequence of * tabulator-separated tokens extracted from a container \a c. Returns a * reference to this string. * * This member function is equivalent to: * * \code ToSeparated( c, '\t' ); \endcode */ template IsoString& ToTabSeparated( const C& c ) { return ToSeparated( c, IsoCharTraits::Tab() ); } /*! * Replaces the contents of this string with a sequence of new line * separated tokens extracted from a container \a c. Returns a reference to * this string. * * This member function is equivalent to: * * \code ToSeparated( c, '\n' ); \endcode */ template IsoString& ToNewLineSeparated( const C& c ) { return ToSeparated( c, IsoCharTraits::LF() ); } /*! * Replaces the contents of this string with a sequence of null-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, '\0' ); \endcode */ template IsoString& ToNullSeparated( const C& c ) { return ToSeparated( c, IsoCharTraits::Null() ); } /*! * Replaces the contents of this string with a hyphenated sequence of tokens * extracted from a container \a c. Returns a reference to this string. * * This member function is equivalent to: * * \code ToSeparated( c, '-' ); \endcode */ template IsoString& ToHyphenated( const C& c ) { return ToSeparated( c, IsoCharTraits::Hyphen() ); } // ------------------------------------------------------------------------- /*! * Replaces all occurrences of HTML special characters in this string with * valid HTML entities. Returns a reference to this string. * * The following replacements are performed: * * '&' (ampersand) becomes "\&" \n * '"' (double quote) becomes "\"" \n * "'" (single quote) becomes "\'" \n * '<' (less than) becomes "\<" \n * '>' (greater than) becomes "\>" * * \sa EncodedHTMLSpecialChars(), ToDecodedHTMLSpecialChars() */ IsoString& ToEncodedHTMLSpecialChars(); /*! * Returns a duplicate of this string with all occurrences of HTML special * characters replaced with valid HTML entities. * * \sa ToEncodedHTMLSpecialChars(), DecodedHTMLSpecialChars() */ IsoString EncodedHTMLSpecialChars() const { return IsoString( *this ).ToEncodedHTMLSpecialChars(); } /*! * Replaces all occurrences of special HTML entities in this string with * their corresponding plain text character equivalents. Returns a reference * to this string. * * The following replacements are performed: * * "\&" (ampersand) becomes '&' \n * "\"" (double quote) becomes '"' \n * "\'" (single quote) becomes "'" \n * "\'" (apostrophe) becomes "'" \n * "\<" (less than) becomes '<' \n * "\>" (greater than) becomes '>' * * \sa DecodedHTMLSpecialChars(), ToEncodedHTMLSpecialChars() */ IsoString& ToDecodedHTMLSpecialChars(); /*! * Returns a duplicate of this string with all occurrences of special HTML * entities replaced with their corresponding plain text character * equivalents. * * \sa ToDecodedHTMLSpecialChars(), EncodedHTMLSpecialChars() */ IsoString DecodedHTMLSpecialChars() const { return IsoString( *this ).ToDecodedHTMLSpecialChars(); } /*! * Returns a URL-encoded string that represents a binary \a data block of * the specified \a length in bytes. * * In a URL-encoded string, all characters that are not a-z, A-Z, 0-9, '-', * '.', '_' or '~' are replaced with their percent-encoded representation * %NN, where NN is a zero-padded, two-digit uppercase hexadecimal number. * See RFC 3986 (http://tools.ietf.org/html/rfc3986). * * \sa ToURLEncoded( const C& ), ToURLEncoded() */ static IsoString ToURLEncoded( const void* data, size_type length ); /*! * Returns a URL-encoded string for a container \a c, whose contents are * treated as raw binary data. The objects stored in the container * are considered as a sequence of bytes, irrespective of their actual data * types or the classes they are instances of. * * The type C represents an array of contiguous objects, and must provide * PCL container semantics: the Begin() and Length() standard container * functions are required. * * \sa ToURLEncoded( const void*, size_type ) */ template static IsoString ToURLEncoded( const C& c ) { return ToURLEncoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); } /*! * Replaces all characters that are not a-z, A-Z, 0-9, '-', '.', '_' or '~' * with their percent-encoded representation %NN, where NN is a zero-padded, * two-digit uppercase hexadecimal number. Returns a reference to this * string. See RFC 3986 / URI Generic Syntax, for more information on URL * encodings. * * \sa URLEncoded(), ToURLDecoded() */ IsoString& ToURLEncoded(); /*! * Returns a URL-encoded duplicate of this string. See ToURLEncoded() for * detailed information. * * \sa ToURLEncoded(), URLDecoded() */ IsoString URLEncoded() const { return IsoString( *this ).ToURLEncoded(); } /*! * Decodes a URL-encoded string stored as a raw \a data vector of the * specified \a length in bytes. Returns the decoded binary raw data as a * ByteArray object. * * This function replaces all percent-encoded character representations in * the specified \a data vector with their actual characters in the output * array. * * \sa FromURLEncoded(), ToURLEncoded( const void*, size_type ) */ static ByteArray FromURLEncoded( const void* data, size_type length ); /*! * Decodes a URL-encoded generic string represented as a container \a c. * Returns the decoded binary raw data as a ByteArray object. * * \sa FromURLEncoded( const void*, size_type ), * ToURLEncoded( const void*, size_type ) */ template static ByteArray FromURLEncoded( const C& c ) { return FromURLEncoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); } /*! * Decodes this URL-encoded string, and returns the decoded binary raw data * as a ByteArray object. * * This function replaces all percent-encoded character representations in * this string with their actual characters in the output array. * * If this string is empty, this function returns an empty %ByteArray. * * \sa FromURLEncoded( const void*, size_type ), ToURLEncoded() */ ByteArray FromURLEncoded() const { return FromURLEncoded( Begin(), Length() ); } /*! * Decodes a URL-encoded string stored as a raw \a data vector of the * specified \a length in bytes. Returns the decoded data stored as an 8-bit * string. * * This function replaces all percent-encoded character representations in * the specified \a data vector with their actual characters in the output * string. * * \sa ToURLDecoded(), URLDecoded() */ static IsoString ToURLDecoded( const void* data, size_type length ); /*! * Decodes a URL-encoded generic string represented as a container \a c. * Returns the decoded data stored as an 8-bit string. * * \sa ToURLDecoded( const void*, size_type ), ToURLDecoded(), URLDecoded() */ template static IsoString ToURLDecoded( const C& c ) { return ToURLDecoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); } /*! * Replaces all percent-encoded representations of characters with their * actual characters. Returns a reference to this string. * * This is the reverse transformation to URL encoding. See ToURLEncoded() * for more information. * * \sa URLDecoded(), ToURLEncoded(), FromURLEncoded() */ IsoString& ToURLDecoded(); /*! * Returns a URL-decoded duplicate of this string. See ToURLDecoded() for * detailed information. * * \sa ToURLDecoded(), URLEncoded() */ IsoString URLDecoded() const { return IsoString( *this ).ToURLDecoded(); } // ------------------------------------------------------------------------- #ifdef __PCL_QT_INTERFACE operator QString() const { return QString( c_str() ); } operator QByteArray() const { return QByteArray( c_str() ); } operator QDate() const { return QDate::fromString( c_str(), PCL_QDATE_FMT_STR ); } operator QDateTime() const { return QDateTime::fromString( c_str(), PCL_QDATETIME_FMT_STR ); } #endif /*! * Replaces the contents of this string with a formatted representation of a * variable-length set of values. Returns a reference to this string. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ IsoString& Format( const_c_string fmt, ... ) { va_list paramList; va_start( paramList, fmt ); (void)VFormat( fmt, paramList ); va_end( paramList ); return *this; } /*! * Appends a formatted representation of a variable-length set of values to * the current contents of this string. Returns a reference to this string. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ IsoString& AppendFormat( const_c_string fmt, ... ) { va_list paramList; va_start( paramList, fmt ); (void)AppendVFormat( fmt, paramList ); va_end( paramList ); return *this; } /*! * Replaces the contents of this string with a formatted representation of a * variable-length set of values, specified as a \c va_list standard * parameter list. Returns the number of characters generated. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ int VFormat( const_c_string fmt, va_list paramList ); /*! * Appends a formatted representation of a variable-length set of values, * specified as a \c va_list standard parameter list, to the current * contents of this string. Returns the number of characters appended. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ int AppendVFormat( const_c_string fmt, va_list paramList ); // ------------------------------------------------------------------------- /*! * Returns a UTF-16 string with a converted copy of this %IsoString object. * * This function assumes that this %IsoString object contains only valid * ISO/IEC-8859-1 characters. To perform UTF-8 to UTF-16 conversions, see * UTF8ToUTF16() and MBSToWCS(). * * \sa UTF8ToUTF16(), MBSToWCS() */ ustring_base ToString() const { ustring_base s; s.SetLength( Length() ); uchar_iterator p = s.Begin(); for ( const_iterator i = m_data->string; i < m_data->end; ++p, ++i ) *p = uchar_type( *i ); return s; } /*! * Returns a UTF-16 string with a representation of a subset of \a n * contiguous UTF-8 characters from this %IsoString object, starting at the * \a i-th character. * * \sa ToString(), MBSToWCS() */ ustring_base UTF8ToUTF16( size_type i = 0, size_type n = maxPos ) const; // implemented inline after String /*! * Returns a copy of this multibyte string converted to a UTF-16 * string. This conversion is dependent on the current locale. * * In the event of conversion error (if there are invalid multibyte * characters in the source string) this routine returns an empty string. * * This member function is a convenience wrapper for the mbstowcs() routine * of the standard C runtime library. Note that on platforms where the size * of wchar_t is four bytes (e.g. Linux) this routine performs an additional * conversion from UTF-32 to UTF-16. On platforms where the size of wchar_t * is two bytes (e.g. Windows), the conversion is direct. * * \sa UTF8ToUTF16(), ToString() */ ustring_base MBSToWCS() const; #ifdef __PCL_QT_INTERFACE QString ToQString() const { return operator QString(); } QByteArray ToQByteArray() const { return operator QByteArray(); } QDate ToQDate() const { return operator QDate(); } QDateTime ToQDateTime() const { return operator QDateTime(); } #endif /*! * Evaluates this string as a Boolean literal, and returns the result as a * \c bool value. * * Returns \c true if this string is equal to "1", "true", "TRUE" or "T". * Returns \c false if this string is equal to "0", "false", "FALSE" or "F". * Otherwise this function throws a ParseError exception. * * \sa TryToBool() */ bool ToBool() const; /*! * Attempts to evaluate this string as a Boolean literal. * * If this string can legally be converted to a Boolean value, this function * returns \c true and stores the evaluation result in the \a value * variable. A string can only be converted to Boolean type if it is equal * to either "1", "true", "TRUE", "T", "0", "false", "FALSE" or "F". * * If this string cannot be converted to a Boolean value, this function * returns \c false and does not change the \a value variable. This function * does not throw any exception. * * \sa ToBool() */ bool TryToBool( bool& value ) const noexcept; /*! * Evaluates this string as a floating point numeric literal, and returns * the result as a \c float value. * * For information about the legal syntax of a floating point literal, see * the documentation for the ToDouble() member function. * * If this string doesn't contain a valid floating point literal, or if the * range of \c float is exceeded, this member function throws a ParseError * exception. * * \sa TryToFloat() */ float ToFloat() const; /*! * Attempts to evaluate this string as a floating point numeric literal. * * If this string can legally be converted to a floating point number, this * function returns \c true and stores the evaluation result in the \a value * variable. For information about the legal syntax of a floating point * literal, see the documentation for the ToDouble() member function. * * If this string cannot be converted to a floating point number, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \sa ToFloat() */ bool TryToFloat( float& value ) const noexcept; /*! * Evaluates this string as a floating point literal, and returns the result * as a \c double value. * * The source string is expected to have the following format (informal * format specification): * * [+|-][\][.[\]][\[+|-]\] * * where \ and \ are optional sequences of * decimal digits from 0 to 9, \ is an exponent specifier * (the letter 'e' (or 'E')), and \ is a sequence of decimal * digits specifying a power of ten that multiplies the preceding numeric * constant. At least a one-digit integer part, or a one-digit decimal part, * is mandatory. FORTRAN exponent specifiers ('d' and 'f' (or 'D' and 'F')) * are also recognized by this implementation. * * If this string doesn't contain a valid floating point literal, or if the * range of \c double is exceeded, this member function throws a ParseError * exception. * * \sa TryToDouble() */ double ToDouble() const; /*! * Attempts to evaluate this string as a floating point numeric literal. * * If this string can legally be converted to a floating point number, this * function returns \c true and stores the evaluation result in the \a value * variable. For information about the legal syntax of a floating point * literal, see the documentation for the ToDouble() member function. * * If this string cannot be converted to a floating point number, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \sa ToDouble() */ bool TryToDouble( double& value ) const noexcept; /*! * Evaluates this string as an integer literal, and returns the result as a * \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code long n = s.ToInt( 0 ); \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string doesn't contain a valid integer literal, or if the range * of \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToInt() */ long ToInt() const { return ToInt( 0 ); } /*! * Attempts to evaluate this string as an integer numeric literal. * * If this string can legally be converted to an integer number, this * function returns \c true and stores the evaluation result in the \a value * variable. * * Calling this member function for a string \c s is equivalent to: * * \code * int v; * if ( s.TryToInt( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an integer number, this function * returns \c false and does not change the \a value variable. This function * does not throw any exception. * * \sa ToInt() */ bool TryToInt( int& value ) const noexcept { return TryToInt( value, 0 ); } /*! * Evaluates this string as an integer literal in the specified \a base, and * returns the result as a \c long value. * * If \a base is 0, the source string is expected to represent either a * decimal constant, an octal constant, or a hexadecimal constant, any of * which optionally preceded by a sign character (+ or -). A decimal * constant begins with a non-zero digit, and consists of a sequence of * decimal digits from '0' to '9'. An octal begins with the prefix '0', * optionally followed by a sequence of the digits 0 to 7 only. A * hexadecimal constant begins with the prefix '0x' or '0X', which must be * followed by a sequence of decimal digits and letters from 'a' (or 'A') * to 'f' (or 'F'), whose corresponding decimal values are from 10 to 15, * respectively. * * Other legal values of \a base, from 2 to 36, specify the expected base of * the integer constant represented by the source string. Decimal digits and * letters from 'a' (or 'A') to 'z' (or 'Z') are used to represent all * possible digits in the specified base, as necessary. * * If this string doesn't contain a valid integer literal in the specified * \a base, if an illegal \a base is specified, or if the range of \c long * is exceeded, this member function throws a ParseError exception. * * \sa TryToInt( int&, int ) const */ long ToInt( int base ) const; /*! * Attempts to evaluate this string as an integer numeric literal in the * specified \a base. * * If this string can legally be converted to an integer number in the * specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an integer number in the specified * \a base, this function returns \c false and does not change the \a value * variable. This function does not throw any exception. * * \sa ToInt( int ) const */ bool TryToInt( int& value, int base ) const noexcept; /*! * Evaluates this string as an unsigned integer literal, and returns the * result as an \c unsigned \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code unsigned long n = s.ToUInt( 0 ); \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string doesn't contain a valid unsigned integer literal, or if * the range of \c unsigned \c long is exceeded, this member function throws * a ParseError exception. * * \sa TryToUInt() */ unsigned long ToUInt() const { return ToUInt( 0 ); } /*! * Attempts to evaluate this string as an unsigned integer literal. * * If this string can legally be converted to an unsigned integer number, * this function returns \c true and stores the evaluation result in the * \a value variable. * * Calling this member function for a string \c s is equivalent to: * * \code * unsigned v; * if ( s.TryToUInt( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an integer number, this function * returns \c false and does not change the \a value variable. This function * does not throw any exception. * * \sa ToUInt() */ bool TryToUInt( unsigned& value ) const noexcept { return TryToUInt( value, 0 ); } /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as an \c unsigned \c long value. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). The only exception * is that for this member function, only a + sign is legal preceding the * numeric constant represented by the source string. * * If this string doesn't contain a valid integer literal in the specified * \a base, if an illegal \a base is specified, or if the range of * \c unsigned \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToUInt( unsigned&, int ) const */ unsigned long ToUInt( int base ) const; /*! * Attempts to evaluate this string as an unsigned integer literal in the * specified \a base. * * If this string can legally be converted to an unsigned integer number in * the specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * See the documentation under ToUInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an unsigned integer number in the * specified \a base, this function returns \c false and does not change the * \a value variable. This function does not throw any exception. * * \sa ToUInt( int ) const */ bool TryToUInt( unsigned& value, int base ) const noexcept; /*! * Evaluates this string as an integer literal, and returns the result as a * \c long \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code long long n = s.ToInt64( 0 ); \endcode * * If this string doesn't contain a valid integer literal, or if the range * of \c long \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToInt64() */ long long ToInt64() const { return ToInt64( 0 ); } /*! * Attempts to evaluate this string as a 64-bit integer numeric literal in * the specified \a base. * * If this string can legally be converted to a 64-bit integer number in the * specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * Calling this member function for a string \c s is equivalent to: * * \code * long long v; * if ( s.TryToInt64( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to a 64-bit integer number, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \sa ToInt64() */ bool TryToInt64( long long& value ) const noexcept { return TryToInt64( value, 0 ); } /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as a \c long \c long value. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string doesn't contain a valid integer literal in the specified * \a base, if an illegal \a base is specified, or if the range of * \c long \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToInt64( long long&, int ) const */ long long ToInt64( int base ) const; /*! * Attempts to evaluate this string as a 64-bit integer numeric literal in * the specified \a base. * * If this string can legally be converted to a 64-bit integer number in the * specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string cannot be converted to a 64-bit integer number in the * specified \a base, this function returns \c false and does not change the * \a value variable. This function does not throw any exception. * * \sa ToInt64( int ) const */ bool TryToInt64( long long& value, int base ) const noexcept; /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as an \c unsigned \c long \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code unsigned long long n = s.ToUInt64( 0 ); \endcode * * If this string doesn't contain a valid unsigned integer literal, or if * the range of \c unsigned \c long \c long is exceeded, this member * function throws a ParseError exception. * * \sa TryToUInt64() */ unsigned long long ToUInt64() const { return ToUInt64( 0 ); } /*! * Attempts to evaluate this string as a 64-bit unsigned integer numeric * literal in the specified \a base. * * If this string can legally be converted to a 64-bit unsigned integer * number in the specified \a base, this function returns \c true and stores * the evaluation result in the \a value variable. * * Calling this member function for a string \c s is equivalent to: * * \code * unsigned long long v; * if ( s.TryToUInt64( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to a 64-bit unsigned integer number, * this function returns \c false and does not change the \a value variable. * This function does not throw any exception. * * \sa ToUInt64() */ bool TryToUInt64( unsigned long long& value ) const noexcept { return TryToUInt64( value, 0 ); } /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as an \c unsigned \c long \c long value. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string doesn't contain a valid unsigned integer literal in the * specified \a base, if an illegal \a base is specified, or if the range of * \c unsigned \c long \c long is exceeded, this member function throws a * ParseError exception. * * \sa TryToUInt64( unsigned long long&, int ) const */ unsigned long long ToUInt64( int base ) const; /*! * Attempts to evaluate this string as an unsigned 64-bit integer numeric * literal in the specified \a base. * * If this string can legally be converted to an unsigned 64-bit integer * number in the specified \a base, this function returns \c true and stores * the evaluation result in the \a value variable. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string cannot be converted to an unsigned 64-bit integer number * in the specified \a base, this function returns \c false and does not * change the \a value variable. This function does not throw any exception. * * \sa ToUInt64( int ) const */ bool TryToUInt64( unsigned long long& value, int base ) const noexcept; /*! * Evaluates this string as a sexagesimal numeric literal representation, * and returns the result as a \c double value. * * The source string is expected to have the following format: * * [+|-]\[\\[\\]][.[\]] * * where \, \, \ and \ are sequences of * decimal digits from 0 to 9, and \ is any sequence of characters * specified as the \a separator argument. The default separator is the * colon character, ':'. * * The result is equal to: * * \ * (\ + \/60 + \/3600) * * where omitted optional components are taken as zero, and \ is -1 * iff a minus sign '-' leads the representation, or +1 otherwise. * * If this string doesn't contain a valid sexagesimal numeric literal, or if * the range of \c double is exceeded, this member function throws a * ParseError exception. * * \ingroup sexagesimal_conversion * \sa TrySexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() */ double SexagesimalToDouble( const IsoString& separator = ':' ) const { int sign, s1, s2; double s3; ParseSexagesimal( sign, s1, s2, s3, separator ); return sign*(s1 + (s2 + s3/60)/60); } double SexagesimalToDouble( char separator ) const { return SexagesimalToDouble( IsoString( separator ) ); } double SexagesimalToDouble( const ustring_base& separator ) const { return SexagesimalToDouble( IsoString( separator ) ); } /*! * Evaluates this string as a sexagesimal numeric literal representation * with the specified set of \a separators, and returns the result as a * \c double value. * * This function is identical to SexagesimalToDouble( const IsoString& ), * but a set of separator characters is specified as a dynamic array. Any * occurrence of a character contained by \a separators will be valid as a * token separator. * * \ingroup sexagesimal_conversion * \sa TrySexagesimalToDouble( double&, const Array<>& ) */ double SexagesimalToDouble( const Array& separators ) const { int sign, s1, s2; double s3; ParseSexagesimal( sign, s1, s2, s3, separators ); return sign*(s1 + (s2 + s3/60)/60); } /*! * Attempts to evaluate this string as a sexagesimal numeric literal with * the specified \a separator. * * If this string can legally be evaluated as a sexagesimal literal and * converted to a floating point number, this function stores the evaluation * result in the specified \a value variable and returns \c true. For * information about the legal syntax of a sexagesimal literal, see the * documentation for SexagesimalToDouble(). * * If this string cannot be evaluated as a sexagesimal literal, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \ingroup sexagesimal_conversion * \sa SexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() */ bool TrySexagesimalToDouble( double& value, const IsoString& separator = ':' ) const noexcept { int sign, s1, s2; double s3; if ( TryParseSexagesimal( sign, s1, s2, s3, separator ) ) { value = sign*(s1 + (s2 + s3/60)/60); return true; } return false; } bool TrySexagesimalToDouble( double& value, char separator ) const noexcept { return TrySexagesimalToDouble( value, IsoString( separator ) ); } bool TrySexagesimalToDouble( double& value, const ustring_base& separator ) const noexcept { return TrySexagesimalToDouble( value, IsoString( separator ) ); } /*! * Attempts to evaluate this string as a sexagesimal numeric literal with * the specified set of \a separators. * * This function is identical to * TrySexagesimalToDouble( double&, const IsoString& ), but a set of * separator characters is specified as a dynamic array. Any occurrence of a * character contained by \a separators will be valid as a token separator. * * \ingroup sexagesimal_conversion * \sa SexagesimalToDouble( const Array<>& ) */ bool TrySexagesimalToDouble( double& value, const Array& separators ) const noexcept { int sign, s1, s2; double s3; if ( TryParseSexagesimal( sign, s1, s2, s3, separators ) ) { value = sign*(s1 + (s2 + s3/60)/60); return true; } return false; } /*! * Evaluates this string as a sexagesimal numeric literal representation, * using the specified \a separator, and stores the resulting components in * the specified \a sign, \a s1, \a s2 and \a s3 variables. * * The output value of \a sign is either -1 or +1, respectively for negative * and positive values. * * For information about the legal syntax of a sexagesimal literal, see the * documentation for SexagesimalToDouble(). * * This function stores \e canonical minutes and seconds components, * irrespective of the actual component values represented by this string. * The output sexagesimal component values are such that: * * 0 ≤ \a s1 \n * 0 ≤ \a s2 < 60 \n * 0 ≤ \a s3 < 60 \n * * If this string doesn't contain a valid sexagesimal numeric literal, or if * the range of \c double is exceeded, this member function throws a * ParseError exception. * * \ingroup sexagesimal_conversion * \sa TryParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() */ void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const IsoString& separator = ':' ) const; void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, char separator ) const { ParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); } void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const ustring_base& separator ) const { ParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); } /*! * Evaluates this string as a sexagesimal numeric literal representation, * using the specified set of \a separators, and stores the resulting * components in the specified \a sign, \a s1, \a s2 and \a s3 variables. * * This function is identical to * ParseSexagesimal( int&, int&, int&, double&, const IsoString& ), but a * set of separator characters is specified as a dynamic array. Any * occurrence of a character contained by \a separators will be valid as a * token separator. * * \ingroup sexagesimal_conversion * \sa TryParseSexagesimal( int&, int&, int&, double&, const Array<>& ) */ void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const; /*! * Attempts to evaluate this string as a sexagesimal numeric literal * representation, using the specified \a separator. If successful, stores * the resulting components in the specified \a sign, \a s1, \a s2 and \a s3 * variables, and returns \c true. For more information on syntax and * output values and ranges, see the documentation for ParseSexagesimal(). * * If this string cannot be evaluated as a sexagesimal literal, this * function returns \c false and does not change any of the \a sign, \a s1, * \a s2 and \a s3 variables. This function does not throw any exception. * * \ingroup sexagesimal_conversion * \sa ParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() */ bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const IsoString& separator = ':' ) const noexcept; bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, char separator ) const noexcept { return TryParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); } bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const ustring_base& separator ) const noexcept { return TryParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) ); } /*! * Attempts to evaluate this string as a sexagesimal numeric literal * representation, using the specified set of \a separators. * * This function is identical to * TryParseSexagesimal( int&, int&, int&, double&, const IsoString& ), but a * set of separator characters is specified as a dynamic array. Any * occurrence of a character contained by \a separators will be valid as a * token separator. * * \ingroup sexagesimal_conversion * \sa ParseSexagesimal( int&, int&, int&, double&, const Array<>& ) */ bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const noexcept; /*! * Returns a sexagesimal ASCII representation of the specified components * \a sign, \a s1, \a s2 and \a s3, generated with the specified conversion * \a options. * * The generated representation will correspond to a negative value iff * \a sign < 0, positive otherwise. * * The generated representation is of the form: * * [+|-]\[\\[\\]][.[\]] * * where the second and third sexagesimal components are canonicalized: * * 0 ≤ \ < 60 * 0 ≤ \ < 60 * * irrespective of the original \a s2 and \a s3 argument values. * * \ingroup sexagesimal_conversion * \sa SexagesimalToDouble(), SexagesimalConversionOptions, * AngleConversionOptions, LongitudeConversionOptions, RAConversionOptions, * LatitudeConversionOptions, DecConversionOptions */ static IsoString ToSexagesimal( int sign, double s1, double s2, double s3, const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ); /*! * Returns a sexagesimal ASCII representation of the specified decimal value * \a d, generated with the specified conversion \a options. * * Calling this member function is equivalent to: * * \code ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); \endcode * * \ingroup sexagesimal_conversion */ static IsoString ToSexagesimal( double d, const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ) { return ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); } /*! * Evaluates this string as a date and time specification in ISO 8601 * extended format, and stores the resulting components in the specified * variables. * * \param year On output, the year of the date. * * \param month On output, the month of the date in the range [1,12]. * * \param day On output, the day of the date in the range [1,31]. * * \param dayf On output, the day fraction corresponding to the time * specification, in the range [0,1). * * \param tz On output, the time zone offset in hours, in the range * [-12,+12]. * * In ISO 8601 extended representations, decimal fractions must be divided * from integer parts exclusively by the full stop or dot character ('.', * ASCII code point 46(10) = 2E(16)). * * \sa TryParseISO8601DateTime(), TimePoint::FromString() */ void ParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const; /*! * Attempts to evaluate this string as a date and time specification in ISO * 8601 extended format. If successful, stores the resulting components in * the specified \a year, \a month, \a day and \a dayf and \a tz variables, * and returns \c true. For more information on syntax and * output values and ranges, see the ParseISO8601DateTime(). * * If this string cannot be evaluated as a valid date and time in ISO 8601 * format, this function returns \c false and does not change any of the * passed variables. This function does not throw any exception. * * \sa ParseISO8601DateTime(), TimePoint::TryFromString() */ bool TryParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const noexcept; /*! * Returns an ASCII representation of a date and time in ISO 8601 extended * format. * * \param year The year of the date. * * \param month The month of the date in the range [1,12]. * * \param day The day of the date in the range [1,31]. * * \param dayf The day fraction corresponding to the time specification, * in the range [0,1). * * \param tz The time zone offset in hours, in the range [-12,+12]. The * default value is zero, to be interpreted as UTC. * * \param options Optional settings to control the representation of date * and time in ISO 8601 format. * * \sa CurrentUTCISO8601DateTime(), CurrentLocalISO8601DateTime(), * ParseISO8601DateTime(), ISO8601ConversionOptions, * TimePoint::ToIsoString() */ static IsoString ToISO8601DateTime( int year, int month, int day, double dayf, double tz = 0, const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); /*! * Returns an ASCII representation of the current UTC date and time in ISO * 8601 extended format. * * \param options Optional settings to control the representation of date * and time in ISO 8601 format. * * \sa CurrentLocalISO8601DateTime(), ToISO8601DateTime(), * ISO8601ConversionOptions, TimePoint::Now() */ static IsoString CurrentUTCISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); /*! * Returns an ASCII representation of the current local date and time in ISO * 8601 extended format. * * \param options Optional settings to control the representation of date * and time in ISO 8601 format. * * \sa CurrentUTCISO8601DateTime(), ToISO8601DateTime(), * ISO8601ConversionOptions */ static IsoString CurrentLocalISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); /*! * Returns an hex-encoded string for a binary \a data block of the specified * \a length in bytes. The hex-encoded string is composed of hexadecimal * digits: 0-9 and a-f, and its length is twice that of the input length. * * \sa ToHex( const C& ), ToBase64(), ToByteArray() */ static IsoString ToHex( const void* data, size_type length ); /*! * Returns an hex-encoded string for a container \a c, whose contents are * treated as raw binary data. The objects stored in the container * are considered as a sequence of bytes, irrespective of their actual data * types or the classes they are instances of. * * The type C represents an array of contiguous objects, and must provide * PCL container semantics: the Begin() and Length() standard container * functions are required. * * \sa ToHex( const void*, size_type ) */ template static IsoString ToHex( const C& c ) { return ToHex( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); } /*! * Returns a Base64-encoded string for a binary \a data block of the * specified \a length in bytes. * * Base64 is a MIME content transfer encoding of binary data translated into * a base 64 representation composed of printable characters. See RFC 1421 * (http://tools.ietf.org/html/rfc1421). * * \sa ToBase64( const C& ), ToHex(), ToByteArray() */ static IsoString ToBase64( const void* data, size_type length ); /*! * Returns a Base64-encoded string for a container \a c, whose contents are * treated as raw binary data. The objects stored in the container * are considered as a sequence of bytes, irrespective of their actual data * types or the classes they are instances of. * * The type C represents an array of contiguous objects, and must provide * PCL container semantics: the Begin() and Length() standard container * functions are required. * * \sa ToBase64( const void*, size_type ), ToByteArray() */ template static IsoString ToBase64( const C& c ) { return ToBase64( c.Begin(), c.Length()*sizeof( *c.Begin() ) ); } /*! * Returns a ByteArray object that stores a copy of this string. In the * returned array, source 8-bit characters have been reinterpreted as * unsigned 8-bit integers. * * \sa ToBase64(), ToHex() */ ByteArray ToByteArray() const { return ByteArray( Begin(), End() ); } /*! * Decodes an hex-encoded string, and returns the decoded binary raw data * stored in a ByteArray object. * * This function expects this string to be hex-encoded; if it isn't, or if * it contains invalid hexadecimal digits, a ParseError exception will be * thrown. * * If this string is empty, this function returns an empty %ByteArray. * * \sa ToHex(), FromBase64() */ ByteArray FromHex() const; /*! * Decodes a Base64-encoded string, and returns the decoded binary raw data * stored in a ByteArray object. * * This function expects this string to be Base64-encoded; if it isn't, or * if it contains an invalid Base64 representation, a ParseError exception * will be thrown. * * If this string is empty, this function returns an empty %ByteArray. * * \sa ToBase64(), FromHex() */ ByteArray FromBase64() const; /*! * Generates a string of \a n random 8-bit code points, with character types * and ranges as prescribed by the specified \a options. * * \sa RandomizationOption */ static IsoString Random( size_type n, RandomizationOptions options = RandomizationOption::Default ); /*! * Generates a universally unique identifier (UUID) in canonical form. * * The canonical UUID has 36 characters with the following format: * * xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx * * where 'x' represents a lowercase hexadecimal digit, '4' is the UUID * version indicator (version 4 = truly random UUID), and 'y' is one of '8', * '9', 'a', or 'b'. */ static IsoString UUID(); }; // ---------------------------------------------------------------------------- /*! * \defgroup isostring_concatenation_ops IsoString Concatenation Operators */ /*! * Returns a string with the concatenation of two strings \a s1 and \a s2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( const IsoString::string_base& s1, const IsoString::string_base& s2 ) { IsoString s( s1 ); s.Append( s2 ); return s; } /*! * Returns a string with the concatenation of two strings \a s1 (rvalue * reference) and \a s2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::string_base&& s1, const IsoString::string_base& s2 ) { s1.Append( s2 ); return IsoString( std::move( s1 ) ); } /*! * Returns a string with the concatenation of two strings \a s1 (rvalue * reference) and \a s2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString&& s1, const IsoString::string_base& s2 ) { s1.Append( s2 ); return std::move( s1 ); } /*! * Returns a string with the concatenation of two strings \a s1 and \a s2 * (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( const IsoString::string_base& s1, IsoString::string_base&& s2 ) { s2.Prepend( s1 ); return IsoString( std::move( s2 ) ); } /*! * Returns a string with the concatenation of two strings \a s1 and \a s2 * (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( const IsoString::string_base& s1, IsoString&& s2 ) { s2.Prepend( s1 ); return std::move( s2 ); } /*! * Returns a string with the concatenation of two strings \a s1 (rvalue * reference) and \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::string_base&& s1, IsoString::string_base&& s2 ) { s1.Append( s2 ); return IsoString( std::move( s1 ) ); } /*! * Returns a string with the concatenation of two strings \a s1 (rvalue * reference) and \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString&& s1, IsoString::string_base&& s2 ) { s1.Append( s2 ); return std::move( s1 ); } /*! * Returns a string with the concatenation of two strings \a s1 (rvalue * reference) and \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::string_base&& s1, IsoString&& s2 ) { s1.Append( s2 ); return IsoString( std::move( s1 ) ); } /*! * Returns a string with the concatenation of two strings \a s1 (rvalue * reference) and \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString&& s1, IsoString&& s2 ) { s1.Append( s2 ); return std::move( s1 ); } // ---------------------------------------------------------------------------- /*! * Returns a string with the concatenation of a string \a s1 and a * null-terminated string \a t2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( const IsoString::string_base& s1, IsoString::const_c_string t2 ) { IsoString s = s1; s.Append( t2 ); return s; } /*! * Returns a string with the concatenation of a string \a s1 (rvalue reference) * and a null-terminated string \a t2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::string_base&& s1, IsoString::const_c_string t2 ) { s1.Append( t2 ); return IsoString( std::move( s1 ) ); } /*! * Returns a string with the concatenation of a string \a s1 (rvalue reference) * and a null-terminated string \a t2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString&& s1, IsoString::const_c_string t2 ) { s1.Append( t2 ); return std::move( s1 ); } /*! * Returns a string with the concatenation of a null-terminated string \a t1 * and a string \a s2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::const_c_string t1, const IsoString::string_base& s2 ) { IsoString s = s2; s.Prepend( t1 ); return s; } /*! * Returns a string with the concatenation of a null-terminated string \a t1 * and a string \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::const_c_string t1, IsoString::string_base&& s2 ) { s2.Prepend( t1 ); return IsoString( std::move( s2 ) ); } /*! * Returns a string with the concatenation of a null-terminated string \a t1 * and a string \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::const_c_string t1, IsoString&& s2 ) { s2.Prepend( t1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a string with the concatenation of a string \a s1 and a single * character \a c2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( const IsoString::string_base& s1, IsoString::char_type c2 ) { IsoString s = s1; s.Append( c2 ); return s; } /*! * Returns a string with the concatenation of a string \a s1 (rvalue reference) * and a single character \a c2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::string_base&& s1, IsoString::char_type c2 ) { s1.Append( c2 ); return IsoString( std::move( s1 ) ); } /*! * Returns a string with the concatenation of a string \a s1 (rvalue reference) * and a single character \a c2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString&& s1, IsoString::char_type c2 ) { s1.Append( c2 ); return std::move( s1 ); } /*! * Returns a string with the concatenation of a single character \a c1 and a * string \a s2. * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::char_type c1, const IsoString::string_base& s2 ) { IsoString s = s2; s.Prepend( c1 ); return s; } /*! * Returns a string with the concatenation of a single character \a c1 and a * string \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::char_type c1, IsoString::string_base&& s2 ) { s2.Prepend( c1 ); return IsoString( std::move( s2 ) ); } /*! * Returns a string with the concatenation of a single character \a c1 and a * string \a s2 (rvalue reference). * \ingroup isostring_concatenation_ops */ inline IsoString operator +( IsoString::char_type c1, IsoString&& s2 ) { s2.Prepend( c1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Appends a string \a s2 to a string \a s1. Returns a reference to the * left-hand operand string \a s1 * \ingroup isostring_concatenation_ops */ inline IsoString& operator <<( IsoString& s1, const IsoString::string_base& s2 ) { s1.Append( s2 ); return s1; } /*! * Appends a string \a s2 to a string \a s1. Returns a reference to the * left-hand operand string \a s1 * \ingroup isostring_concatenation_ops */ inline IsoString& operator <<( IsoString&& s1, const IsoString::string_base& s2 ) { s1.Append( s2 ); return s1; } /*! * Appends a null-terminated string \a t2 to a string \a s1. Returns a * reference to the left-hand operand string \a s1 * \ingroup isostring_concatenation_ops */ inline IsoString& operator <<( IsoString& s1, IsoString::const_c_string t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a null-terminated string \a t2 to a string \a s1. Returns a * reference to the left-hand operand string \a s1 * \ingroup isostring_concatenation_ops */ inline IsoString& operator <<( IsoString&& s1, IsoString::const_c_string t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a single character \a c2 to a string \a s1. Returns a reference to * the left-hand operand string \a s1 * \ingroup isostring_concatenation_ops */ inline IsoString& operator <<( IsoString& s1, IsoString::char_type c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a single character \a c2 to a string \a s1. Returns a reference to * the left-hand operand string \a s1 * \ingroup isostring_concatenation_ops */ inline IsoString& operator <<( IsoString&& s1, IsoString::char_type c2 ) { s1.Append( c2 ); return s1; } // ---------------------------------------------------------------------------- #ifndef __PCL_NO_STRING_OSTREAM inline std::ostream& operator <<( std::ostream& o, const IsoString& s ) { return o << s.c_str(); } #endif // ---------------------------------------------------------------------------- /*! * \class String * \brief Unicode (UTF-16) string * * %String derives from an instantiation of GenericString for \c char16_type. * It represents a dynamic string of characters in 16-bit Unicode * Transformation Format (UTF-16) on the PixInsight platform. * * \sa IsoString */ class PCL_CLASS String : public GenericString { public: /*! * Base class of %String. */ typedef GenericString string_base; /*! * Represents a character pertaining to a %String object. */ typedef string_base::char_type char_type; /*! * The character traits class used by this template instantiation. */ typedef string_base::char_traits char_traits; /*! * The block allocator used by this template instantiation. */ typedef string_base::block_allocator block_allocator; /*! * The allocator class used by this template instantiation. */ typedef string_base::allocator allocator; /*! * Null-terminated sequence of UTF-16 characters. */ typedef string_base::c_string c_string; /*! * Immutable null-terminated sequence of UTF-16 characters. */ typedef string_base::const_c_string const_c_string; /* * Null-terminated UTF-16 string - C++11 compatibility. */ typedef char16_t* c16_string; /* * Immutable null-terminated UTF-16 string - C++11 compatibility. */ typedef const char16_t* const_c16_string; /*! * %String iterator. */ typedef string_base::iterator iterator; /*! * Immutable %String iterator. */ typedef string_base::const_iterator const_iterator; /*! * Reverse %String iterator. */ typedef string_base::reverse_iterator reverse_iterator; /*! * Immutable reverse %String iterator. */ typedef string_base::const_reverse_iterator const_reverse_iterator; /*! * Represents an 8-bit string. Depending on the context, this type * represents a sequence of ISO/IEC-8859-1, ASCII, or UTF-8 code points. * * \note This type must be defined as the same template instantiation used * for the IsoString class. */ typedef GenericString string8_base; /*! * Represents an 8-bit character (ISO/IEC-8859-1, ASCII or UTF-8). */ typedef string8_base::char_type char8_type; /*! * 8-bit character traits class. */ typedef string8_base::char_traits char8_traits; /*! * Null-terminated sequence of 8-bit characters. */ typedef string8_base::c_string c_string8; /*! * Immutable null-terminated sequence of 8-bit characters. */ typedef string8_base::const_c_string const_c_string8; /*! * 8-bit string iterator. */ typedef string8_base::iterator char8_iterator; /*! * Immutable 8-bit string iterator. */ typedef string8_base::const_iterator const_char8_iterator; // ------------------------------------------------------------------------- /*! * Constructs an empty %String object. */ String() = default; /*! * Constructs a %String object as a copy of the specified \c string_base * string \a s (copy constructor from the base class). */ String( const string_base& s ) : string_base( s ) { } /*! * Copy constructor. */ String( const String& ) = default; /*! * Constructs a %String object by transferring data from the specified * \c string_base string \a s (move constructor from the base class). */ String( string_base&& s ) : string_base( std::move( s ) ) { } /*! * Move constructor. */ String( String&& ) = default; /*! * Constructs a %String as a transformed copy of the specified 8-bit, * ISO/IEC-8859-1 string \a s. */ String( const string8_base& s ) { Assign( s ); } /*! * Constructs a %String as a copy of a null-terminated string \a t. */ String( const_iterator t ) : string_base( t ) { } /*! * Constructs a %String with the \a n first characters of the * null-terminated string \a t, starting from its \a i-th character. */ String( const_iterator t, size_type i, size_type n ) : string_base( t, i, n ) { } /*! * Constructs a %String with \a n copies of a UTF-16 character \a c. */ String( char_type c, size_type n ) : string_base( c, n ) { } /*! * Constructs a %String with a copy of the character sequence defined by * the range [i,j). */ String( const_iterator i, const_iterator j ) : string_base( i, j ) { } /*! * Constructs a %String with a copy of the character sequence stored in the * specified initializer list \a l. * * This constructor is equivalent to: * * \code String( l.begin(), l.end() ) \endcode */ String( std::initializer_list l ) : String( l.begin(), l.end() ) { } /*! * Constructs a %String as a copy of a null-terminated string \a t of * \c char16_t characters. */ String( const char16_t* t ) : string_base( reinterpret_cast( t ) ) { } /*! * Constructs a %String with the \a n first characters of the * null-terminated string \a t of \c char16_t characters, starting from its * \a i-th character. */ String( const char16_t* t, size_type i, size_type n ) : string_base( reinterpret_cast( t ), i, n ) { } /*! * Constructs a %String with \a n copies of a \c char16_t character \a c. */ String( char16_t c, size_type n ) : string_base( char_type( c ), n ) { } /*! * Constructs a %String as a copy of a null-terminated string \a t of * \c wchar_t characters. */ String( const wchar_t* t ) { Assign( t ); } /*! * Constructs a %String with the \a n first characters of the * null-terminated string \a t of \c wchar_t characters, starting from its * \a i-th character. */ String( const wchar_t* t, size_type i, size_type n ) { Assign( t, i, n ); } /*! * Constructs a %String with \a n copies of a \c wchar_t character \a c. */ String( wchar_t c, size_type n ) : string_base( char_type( c ), n ) { } /*! * Constructs a %String as a transformed copy of the null-terminated 8-bit, * ISO/IEC-8859-1 string \a t. */ String( const_c_string8 t ) { Assign( t ); } /*! * Constructs a %String with the \a n first characters of the * null-terminated, 8-bit ISO/IEC-8859-1 string \a t, starting from its * \a i-th character. */ String( const_c_string8 t, size_type i, size_type n ) { Assign( t, i, n ); } /*! * Constructs a %String with the sequence of 8-bit characters in the range * [i,j) of 8-bit string iterators. */ String( const_char8_iterator i, const_char8_iterator j ) { Assign( i, j ); } /*! * Constructs a %String with a copy of the 8-bit ISO/IEC-8859-1 character * sequence stored in the specified initializer list \a l. * * This constructor is equivalent to: * * \code String( l.begin(), l.end() ) \endcode */ String( std::initializer_list l ) : String( l.begin(), l.end() ) { } /*! * Constructs a %String object with \a n copies of an ISO/IEC-8859-1 * character \a c. */ String( char8_type c, size_type n = 1 ) : string_base( char_type( c ), n ) { } /*! * Constructs a %String as a literal representation of a \c bool value. */ explicit String( bool x ) { Assign( x ? "true" : "false" ); } /*! * Constructs a %String as a literal representation of a * \c signed \c short value. */ explicit String( short x ) { (void)Format( L"%hd", x ); } /*! * Constructs a %String as a literal representation of an * \c unsigned \c short value. */ explicit String( unsigned short x ) { (void)Format( L"%hu", x ); } /*! * Constructs a %String as a literal representation of a * \c signed \c int value. */ explicit String( int x ) { (void)Format( L"%i", x ); } /*! * Constructs a %String as a literal representation of an * \c unsigned \c int value. */ explicit String( unsigned int x ) { (void)Format( L"%u", x ); } /*! * Constructs a %String as a literal representation of a * \c signed \c long value. */ explicit String( long x ) { (void)Format( L"%ld", x ); } /*! * Constructs a %String as a literal representation of an * \c unsigned \c long value. */ explicit String( unsigned long x ) { (void)Format( L"%lu", x ); } /*! * Constructs a %String as a literal representation of a * \c signed \c long \c long value. */ explicit String( long long x ) { (void)Format( L"%lli", x ); } /*! * Constructs a %String as a literal representation of an * \c unsigned \c long \c long value. */ explicit String( unsigned long long x ) { (void)Format( L"%llu", x ); } /*! * Constructs a %String as a literal representation of a * \c float value. */ explicit String( float x ) { (void)Format( L"%.7g", x ); } /*! * Constructs a %String as a literal representation of a * \c double value. */ explicit String( double x ) { (void)Format( L"%.16g", x ); } /*! * Constructs a %String as a literal representation of a * \c long \c double value. */ explicit String( long double x ) { #ifdef _MSC_VER (void)Format( L"%.16Lg", x ); #else (void)Format( L"%.18Lg", x ); #endif } #ifndef __PCL_NO_STRING_COMPLEX /*! * Constructs a %String as a literal representation of an \c fcomplex value. */ explicit String( Complex& x ) { (void)Format( L"{%.7g,%.7g}", x.Real(), x.Imag() ); } /*! * Constructs a %String as a literal representation of a \c dcomplex value. */ explicit String( Complex& x ) { (void)Format( L"{%.16g,%.16g}", x.Real(), x.Imag() ); } /*! * Constructs a %String as a literal representation of an \c lcomplex value. */ explicit String( Complex& x ) { #ifdef _MSC_VER (void)Format( L"{%.16Lg,%.16Lg}", x.Real(), x.Imag() ); #else (void)Format( L"{%.18Lg,%.18Lg}", x.Real(), x.Imag() ); #endif } #endif // !__PCL_NO_STRING_COMPLEX #ifdef __PCL_QT_INTERFACE explicit String( const QString& qs ) : string_base( qs.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ) ) { } explicit String( const QDate& qd ) : string_base( iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ) ) { } explicit String( const QDateTime& qdt ) : string_base( iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ) ) { } #endif // ------------------------------------------------------------------------- /*! * Copy assignment operator. Returns a reference to this object. */ String& operator =( const String& s ) { string_base::Assign( s ); return *this; } /*! * Move assignment operator. Returns a reference to this object. */ String& operator =( String&& s ) { string_base::Transfer( s ); return *this; } /*! * Assigns a shallow copy of the \c string_base string \a s to this string. * Returns a reference to this object. */ String& operator =( const string_base& s ) { string_base::Assign( s ); return *this; } /*! * Transfers the data from the \c string_base string \a s to this string * (move assignment from base class). Returns a reference to this object. */ String& operator =( string_base&& s ) { string_base::Transfer( s ); return *this; } /*! * Assigns a copy of the 8-bit ISO/IEC-8859-1 string \a s to this string. * Returns a reference to this object. */ String& operator =( const string8_base& s ) { Assign( s ); return *this; } /*! * Assigns a copy of the null-terminated string \a t to this string. Returns * a reference to this object. */ String& operator =( const_iterator t ) { string_base::Assign( t ); return *this; } /*! * Assigns a single copy of a character \a c to this string. Returns a * reference to this object. */ String& operator =( char_type c ) { string_base::Assign( c ); return *this; } /*! * Assigns a copy of the null-terminated string \a t of \c char16_t to this * string. Returns a reference to this object. */ String& operator =( const char16_t* t ) { string_base::Assign( reinterpret_cast( t ) ); return *this; } /*! * Assigns a single copy of a \c char16_t character \a c to this string. * Returns a reference to this object. */ String& operator =( char16_t c ) { string_base::Assign( char_type( c ) ); return *this; } /*! * Assigns a copy of the null-terminated string \a t of \c wchar_t to this * string. Returns a reference to this object. */ String& operator =( const wchar_t* t ) { Assign( t ); return *this; } /*! * Assigns a single copy of a \c wchar_t character \a c to this string. * Returns a reference to this object. */ String& operator =( wchar_t c ) { Assign( c ); return *this; } /*! * Assigns a copy of the null-terminated 8-bit ISO/IEC-8859-1 string \a t to * this string. Returns a reference to this object. */ String& operator =( const_c_string8 t ) { Assign( t ); return *this; } /*! * Assigns a single copy of an ISO/IEC-8859-1 character \a c to this string. * Returns a reference to this object. */ String& operator =( char8_type c ) { Assign( c ); return *this; } #ifdef __PCL_QT_INTERFACE String& operator =( const QString& qs ) { if ( qs.isEmpty() ) Clear(); else string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ); return *this; } String& operator =( const QDate& qd ) { string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ); return *this; } String& operator =( const QDateTime& qdt ) { string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ); return *this; } #endif // ------------------------------------------------------------------------- /*! * Assigns a string \a s to this string. */ void Assign( const String& s ) { string_base::Assign( s ); } /*! * Assigns a contiguous segment of \a n characters of a string \a s, * starting from its \a i-th character, to this string. */ void Assign( const String& s, size_type i, size_type n ) { string_base::Assign( s, i, n ); } /*! * Assigns a null-terminated string \a t to this string. */ void Assign( const_iterator t ) { string_base::Assign( t ); } /*! * Assigns a sequence of characters defined by the range [i,j) to this * string. */ void Assign( const_iterator i, const_iterator j ) { string_base::Assign( i, j ); } /*! * Assigns a sequence of characters defined by the specified initializer * list \a l to this string. This function is equivalent to: * * \code Assign( l.begin(), l.end() ) \endcode */ void Assign( std::initializer_list l ) { Assign( l.begin(), l.end() ); } /*! * Assigns a contiguous segment of at most \a n characters of a * null-terminated sequence \a t, starting from its \a i-th character, to * this string. */ void Assign( const_iterator t, size_type i, size_type n ) { string_base::Assign( t, i, n ); } /*! * Assigns \a n copies of a character \a c to this string. */ void Assign( char_type c, size_type n = 1 ) { string_base::Assign( c, n ); } /*! * Assigns a null-terminated string \a t of \c char16_t to this string. */ void Assign( const char16_t* t ) { string_base::Assign( reinterpret_cast( t ) ); } /*! * Assigns a contiguous segment of \a n characters of a null-terminated * string \a t of \c char16_t, starting from its \a i-th character, to this * string. */ void Assign( const char16_t* t, size_type i, size_type n ) { string_base::Assign( reinterpret_cast( t ), i, n ); } /*! * Assigns \a n copies of a \c char16_t character \a c to this string. */ void Assign( char16_t c, size_type n = 1 ) { string_base::Assign( char_type( c ), n ); } /*! * Assigns a null-terminated string \a t of \c wchar_t to this string. */ void Assign( const wchar_t* t ); /*! * Assigns a contiguous segment of \a n characters of a null-terminated * string \a t of \c wchar_t, starting from its \a i-th character, to this * string. */ void Assign( const wchar_t* t, size_type i, size_type n ); /*! * Assigns \a n copies of a \c wchar_t character \a c to this string. */ void Assign( wchar_t c, size_type n = 1 ) { string_base::Assign( char_type( c ), n ); } /*! * Assigns a copy of the 8-bit ISO/IEC-8859-1 string \a s to this string. */ void Assign( const string8_base& s ) { size_type n = s.Length(); if ( n > 0 ) { MaybeReallocate( n ); const_char8_iterator t = s.Begin(); PCL_IVDEP for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) *i = char_type( uint8( *t ) ); } else Clear(); } /*! * Assigns a null-terminated 8-bit ISO/IEC-8859-1 string \a t to this * object. */ void Assign( const_c_string8 t ) { size_type n = char8_traits::Length( t ); if ( n > 0 ) { MaybeReallocate( n ); PCL_IVDEP for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) *i = char_type( uint8( *t ) ); } else Clear(); } /*! * Assigns a contiguous segment of \a n characters of a null-terminated * 8-bit ISO/IEC-8859-1 string \a t, starting from its \a i-th character, to * this string. */ void Assign( const_c_string8 t, size_type i, size_type n ) { size_type len = char8_traits::Length( t ); if ( i < len ) { n = pcl::Min( n, len-i ); MaybeReallocate( n ); t += i; PCL_IVDEP for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) *i = char_type( uint8( *t ) ); } else Clear(); } /*! * Assigns a contiguous sequence of 8-bit ISO/IEC-8859-1 characters in the * range [i,j) to this string, replacing its previous contents. */ void Assign( const_char8_iterator p, const_char8_iterator q ) { if ( p < q ) { MaybeReallocate( q - p ); PCL_IVDEP for ( iterator i = m_data->string; i < m_data->end; ++i, ++p ) *i = char_type( uint8( *p ) ); } else Clear(); } /*! * Assigns a sequence of 8-bit ISO/IEC-8859-1 characters defined by the * specified initializer list \a l to this string. This function is * equivalent to: * * \code Assign( l.begin(), l.end() ) \endcode */ void Assign( std::initializer_list l ) { Assign( l.begin(), l.end() ); } /*! * Assigns \a n copies of an ISO/IEC-8859-1 character \a c to this string. */ void Assign( char8_type c, size_type n = 1 ) { string_base::Assign( char_type( c ), n ); } // ------------------------------------------------------------------------- void Insert( size_type i, const String& s ) { string_base::Insert( i, s ); } void Insert( size_type i, const_iterator p, const_iterator q ) { string_base::Insert( i, p, q ); } void Insert( size_type i, const_iterator t ) { string_base::Insert( i, t ); } void Insert( size_type i, const_iterator t, size_type n ) { string_base::Insert( i, t, n ); } void Insert( size_type i, char_type c, size_type n = 1 ) { string_base::Insert( i, c, n ); } void Insert( size_type i, const char16_t* t ) { string_base::Insert( i, reinterpret_cast( t ) ); } void Insert( size_type i, char16_t c, size_type n = 1 ) { string_base::Insert( i, String( c, n ) ); } void Insert( size_type i, const wchar_t* t ) { #ifdef __PCL_WINDOWS string_base::Insert( i, reinterpret_cast( t ) ); #else string_base::Insert( i, String( t ) ); #endif } void Insert( size_type i, wchar_t c, size_type n = 1 ) { string_base::Insert( i, String( c, n ) ); } void Insert( size_type i, const string8_base& s, size_type n ) { n = pcl::Min( n, s.Length() ); if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len const_char8_iterator t = s.Begin(); PCL_IVDEP for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) *p = char_type( uint8( *t ) ); } } void Insert( size_type i, const string8_base& s ) { size_type n = s.Length(); if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len const_char8_iterator t = s.Begin(); PCL_IVDEP for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) *p = char_type( uint8( *t ) ); } } void Insert( size_type i, const_c_string8 t ) { size_type n = char8_traits::Length( t ); if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len PCL_IVDEP for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) *p = char_type( uint8( *t ) ); } } void Insert( size_type i, const_c_string8 t, size_type n ) { n = pcl::Min( n, char8_traits::Length( t ) ); if ( n > 0 ) { UninitializedGrow( i, n ); // -> 0 <= i <= len PCL_IVDEP for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t ) *p = char_type( uint8( *t ) ); } } void Insert( size_type i, const_char8_iterator p, const_char8_iterator q ) { if ( p < q ) { size_type n = q - p; UninitializedGrow( i, n ); // -> 0 <= i <= len PCL_IVDEP for ( iterator r = m_data->string+i, s = r+n; r < s; ++r, ++p ) *r = char_type( uint8( *p ) ); } } void Insert( size_type i, char8_type c, size_type n = 1 ) { string_base::Insert( i, char_type( c ), n ); } // ------------------------------------------------------------------------- void Append( const String& s ) { string_base::Append( s ); } String& operator +=( const String& s ) { Append( s ); return *this; } void Append( const_iterator i, const_iterator j ) { string_base::Append( i, j ); } void Append( const_iterator t ) { string_base::Append( t ); } String& operator +=( const_iterator t ) { Append( t ); return *this; } void Append( const_iterator t, size_type n ) { string_base::Append( t, n ); } void Append( char_type c, size_type n = 1 ) { string_base::Append( c, n ); } String& operator +=( char_type c ) { Append( c ); return *this; } void Append( const char16_t* t ) { string_base::Append( reinterpret_cast( t ) ); } String& operator +=( const char16_t* t ) { Append( t ); return *this; } void Append( char16_t c, size_type n = 1 ) { string_base::Append( char_type( c ), n ); } String& operator +=( char16_t c ) { Append( c ); return *this; } void Append( const wchar_t* t ) { #ifdef __PCL_WINDOWS string_base::Append( reinterpret_cast( t ) ); #else string_base::Append( String( t ) ); #endif } String& operator +=( const wchar_t* t ) { Append( t ); return *this; } void Append( wchar_t c, size_type n = 1 ) { string_base::Append( char_type( c ), n ); } String& operator +=( wchar_t c ) { Append( c ); return *this; } void Append( const string8_base& s ) { Insert( maxPos, s ); } String& operator +=( const string8_base& s ) { Append( s ); return *this; } void Append( const string8_base& s, size_type n ) { Insert( maxPos, s, n ); } void Append( const_c_string8 t ) { Insert( maxPos, t ); } String& operator +=( const_c_string8 t ) { Append( t ); return *this; } void Append( const_c_string8 t, size_type n ) { Insert( maxPos, t, n ); } void Append( const_char8_iterator p, const_char8_iterator q ) { Insert( maxPos, p, q ); } void Append( char8_type c, size_type n = 1 ) { string_base::Append( char_type( c ), n ); } String& operator +=( char8_type c ) { Append( c ); return *this; } void Add( const String& s ) { Append( s ); } void Add( const_iterator i, const_iterator j ) { Append( i, j ); } void Add( const_iterator t ) { Append( t ); } void Add( const_iterator t, size_type n ) { Append( t, n ); } void Add( char_type c, size_type n = 1 ) { Append( c, n ); } void Add( const char16_t* t ) { Append( t ); } void Add( char16_t c, size_type n = 1 ) { Append( c, n ); } void Add( const wchar_t* t ) { Append( t ); } void Add( wchar_t c, size_type n = 1 ) { Append( c, n ); } void Add( const string8_base& s ) { Append( s ); } void Add( const string8_base& s, size_type n ) { Append( s, n ); } void Add( const_c_string8 t ) { Append( t ); } void Add( const_c_string8 t, size_type n ) { Append( t, n ); } void Add( const_char8_iterator p, const_char8_iterator q ) { Append( p, q ); } void Add( char8_type c, size_type n = 1 ) { Append( c, n ); } // ------------------------------------------------------------------------- void Prepend( const String& s ) { string_base::Prepend( s ); } String& operator -=( const String& s ) { Prepend( s ); return *this; } void Prepend( const_iterator i, const_iterator j ) { string_base::Prepend( i, j ); } void Prepend( const_iterator t ) { string_base::Prepend( t ); } String& operator -=( const_iterator t ) { Prepend( t ); return *this; } void Prepend( const_iterator t, size_type n ) { string_base::Prepend( t, n ); } void Prepend( char_type c, size_type n = 1 ) { string_base::Prepend( c, n ); } String& operator -=( char_type c ) { Prepend( c ); return *this; } void Prepend( const char16_t* t ) { string_base::Prepend( reinterpret_cast( t ) ); } String& operator -=( const char16_t* t ) { Prepend( t ); return *this; } void Prepend( char16_t c, size_type n = 1 ) { string_base::Prepend( char_type( c ), n ); } String& operator -=( char16_t c ) { Prepend( c ); return *this; } void Prepend( const wchar_t* t ) { #ifdef __PCL_WINDOWS string_base::Prepend( reinterpret_cast( t ) ); #else string_base::Prepend( String( t ) ); #endif } String& operator -=( const wchar_t* t ) { Prepend( t ); return *this; } void Prepend( wchar_t c, size_type n = 1 ) { string_base::Prepend( char_type( c ), n ); } String& operator -=( wchar_t c ) { Prepend( c ); return *this; } void Prepend( const string8_base& s ) { Insert( 0, s ); } String& operator -=( const string8_base& s ) { Prepend( s ); return *this; } void Prepend( const string8_base& s, size_type n ) { Insert( 0, s, n ); } void Prepend( const_c_string8 t ) { Insert( 0, t ); } String& operator -=( const_c_string8 t ) { Prepend( t ); return *this; } void Prepend( const_c_string8 t, size_type n ) { Insert( 0, t, n ); } void Prepend( const_char8_iterator p, const_char8_iterator q ) { Insert( 0, p, q ); } void Prepend( char8_type c, size_type n = 1 ) { string_base::Prepend( String( c, n ) ); } String& operator -=( char8_type c ) { Prepend( c ); return *this; } // ------------------------------------------------------------------------- void Replace( size_type i, size_type n, const String& s ) { string_base::Replace( i, n, s ); } void Replace( size_type i, size_type n, const_iterator t ) { string_base::Replace( i, n, t ); } void Replace( size_type i, size_type n, char_type c, size_type nc = 1 ) { string_base::Replace( i, n, c, nc ); } void Replace( size_type i, size_type n, const char16_t* t ) { string_base::Replace( i, n, reinterpret_cast( t ) ); } void Replace( size_type i, size_type n, char16_t c, size_type nc = 1 ) { string_base::Replace( i, n, char_type( c ), nc ); } void Replace( size_type i, size_type n, const wchar_t* t ) { #ifdef __PCL_WINDOWS string_base::Replace( i, n, reinterpret_cast( t ) ); #else string_base::Replace( i, n, String( t ) ); #endif } void Replace( size_type i, size_type n, wchar_t c, size_type nc = 1 ) { string_base::Replace( i, n, char_type( c ), nc ); } void Replace( size_type i, size_type n, const_c_string8 t ) { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); if ( n == len ) Assign( t ); else { size_type nt = char8_traits::Length( t ); if ( nt > 0 ) { if ( n < nt ) UninitializedGrow( i, nt-n ); else if ( nt < n ) Delete( i, n-nt ); else EnsureUnique(); PCL_IVDEP for ( iterator p = m_data->string+i, q = p+nt; p < q; ++p, ++t ) *p = char_type( *t ); } else Delete( i, n ); } } } } void Replace( size_type i, size_type n, char8_type c, size_type nc = 1 ) { string_base::Replace( i, n, char_type( c ), nc ); } // ------------------------------------------------------------------------- void ReplaceChar( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceChar( c1, c2, i, n ); } void ReplaceCharIC( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceCharIC( c1, c2, i, n ); } void ReplaceChar( char16_t c1, char16_t c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n ); } void ReplaceCharIC( char16_t c1, char16_t c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n ); } void ReplaceChar( wchar_t c1, wchar_t c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n ); } void ReplaceCharIC( wchar_t c1, wchar_t c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n ); } void ReplaceChar( char8_type c1, char8_type c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n ); } void ReplaceCharIC( char8_type c1, char8_type c2, size_type i = 0, size_type n = maxPos ) { string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n ); } // ------------------------------------------------------------------------- void ReplaceString( const String& s1, const String& s2, size_type i = 0 ) { string_base::ReplaceString( s1, s2, i ); } void ReplaceStringIC( const String& s1, const String& s2, size_type i = 0 ) { string_base::ReplaceStringIC( s1, s2, i ); } void ReplaceString( const_iterator t1, const_iterator t2, size_type i = 0 ) { string_base::ReplaceString( t1, t2, i ); } void ReplaceStringIC( const_iterator t1, const_iterator t2, size_type i = 0 ) { string_base::ReplaceStringIC( t1, t2, i ); } void ReplaceString( const char16_t* t1, const char16_t* t2, size_type i = 0 ) { string_base::ReplaceString( reinterpret_cast( t1 ), reinterpret_cast( t2 ), i ); } void ReplaceStringIC( const char16_t* t1, const char16_t* t2, size_type i = 0 ) { string_base::ReplaceStringIC( reinterpret_cast( t1 ), reinterpret_cast( t2 ), i ); } void ReplaceString( const wchar_t* t1, const wchar_t* t2, size_type i = 0 ) { #ifdef __PCL_WINDOWS string_base::ReplaceString( reinterpret_cast( t1 ), reinterpret_cast( t2 ), i ); #else string_base::ReplaceString( String( t1 ), String( t2 ), i ); #endif } void ReplaceStringIC( const wchar_t* t1, const wchar_t* t2, size_type i = 0 ) { #ifdef __PCL_WINDOWS string_base::ReplaceStringIC( reinterpret_cast( t1 ), reinterpret_cast( t2 ), i ); #else string_base::ReplaceStringIC( String( t1 ), String( t2 ), i ); #endif } void ReplaceString( const_c_string8 t1, const_c_string8 t2, size_type i = 0 ) { string_base::ReplaceString( String( t1 ), String( t2 ), i ); } void ReplaceStringIC( const_c_string8 t1, const_c_string8 t2, size_type i = 0 ) { string_base::ReplaceStringIC( String( t1 ), String( t2 ), i ); } // ------------------------------------------------------------------------- void DeleteChar( char_type c, size_type i = 0 ) { string_base::DeleteChar( c, i ); } void DeleteCharIC( char_type c, size_type i = 0 ) { string_base::DeleteCharIC( c, i ); } void DeleteChar( char16_t c, size_type i = 0 ) { string_base::DeleteChar( char_type( c ), i ); } void DeleteCharIC( char16_t c, size_type i = 0 ) { string_base::DeleteCharIC( char_type( c ), i ); } void DeleteChar( wchar_t c, size_type i = 0 ) { string_base::DeleteChar( char_type( c ), i ); } void DeleteCharIC( wchar_t c, size_type i = 0 ) { string_base::DeleteCharIC( char_type( c ), i ); } void DeleteChar( char8_type c, size_type i = 0 ) { string_base::DeleteChar( char_type( c ), i ); } void DeleteCharIC( char8_type c, size_type i = 0 ) { string_base::DeleteCharIC( char_type( c ), i ); } // ------------------------------------------------------------------------- void DeleteString( const String& s, size_type i = 0 ) { string_base::DeleteString( s, i ); } void DeleteStringIC( const String& s, size_type i = 0 ) { string_base::DeleteStringIC( s, i ); } void DeleteString( const_iterator t, size_type i = 0 ) { string_base::DeleteString( t, i ); } void DeleteStringIC( const_iterator t, size_type i = 0 ) { string_base::DeleteStringIC( t, i ); } void DeleteString( const char16_t* t, size_type i = 0 ) { string_base::DeleteString( reinterpret_cast( t ), i ); } void DeleteStringIC( const char16_t* t, size_type i = 0 ) { string_base::DeleteStringIC( reinterpret_cast( t ), i ); } void DeleteString( const wchar_t* t, size_type i = 0 ) { #ifdef __PCL_WINDOWS string_base::DeleteString( reinterpret_cast( t ), i ); #else string_base::DeleteString( String( t ), i ); #endif } void DeleteStringIC( const wchar_t* t, size_type i = 0 ) { #ifdef __PCL_WINDOWS string_base::DeleteStringIC( reinterpret_cast( t ), i ); #else string_base::DeleteStringIC( String( t ), i ); #endif } void DeleteString( const_c_string8 t, size_type i = 0 ) { string_base::DeleteString( String( t ), i ); } void DeleteStringIC( const_c_string8 t, size_type i = 0 ) { string_base::DeleteStringIC( String( t ), i ); } // ------------------------------------------------------------------------- bool StartsWith( const String& s ) const noexcept { return string_base::StartsWith( s ); } bool StartsWith( const_iterator t ) const noexcept { return string_base::StartsWith( t ); } bool StartsWith( char_type c ) const noexcept { return string_base::StartsWith( c ); } bool StartsWithIC( const String& s ) const noexcept { return string_base::StartsWithIC( s ); } bool StartsWithIC( const_iterator t ) const noexcept { return string_base::StartsWithIC( t ); } bool StartsWithIC( char_type c ) const noexcept { return string_base::StartsWithIC( c ); } bool StartsWith( const char16_t* t ) const noexcept { return string_base::StartsWith( reinterpret_cast( t ) ); } bool StartsWith( char16_t c ) const noexcept { return string_base::StartsWith( char_type( c ) ); } bool StartsWithIC( const char16_t* t ) const noexcept { return string_base::StartsWithIC( reinterpret_cast( t ) ); } bool StartsWithIC( char16_t c ) const noexcept { return string_base::StartsWithIC( char_type( c ) ); } bool StartsWith( const wchar_t* t ) const noexcept { #ifdef __PCL_WINDOWS return string_base::StartsWith( reinterpret_cast( t ) ); #else return string_base::StartsWith( String( t ) ); #endif } bool StartsWith( wchar_t c ) const noexcept { return string_base::StartsWith( char_type( c ) ); } bool StartsWithIC( const wchar_t* t ) const noexcept { #ifdef __PCL_WINDOWS return string_base::StartsWithIC( reinterpret_cast( t ) ); #else return string_base::StartsWithIC( String( t ) ); #endif } bool StartsWithIC( wchar_t c ) const noexcept { return string_base::StartsWithIC( char_type( c ) ); } bool StartsWith( const_c_string8 t ) const noexcept { size_type n = char8_traits::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->string, q = p+n; p < q; ++p, ++t ) if ( *p != char_type( *t ) ) return false; return true; } bool StartsWith( char8_type c ) const noexcept { return string_base::StartsWith( char_type( c ) ); } bool StartsWithIC( const_c_string8 t ) const noexcept { size_type n = char8_traits::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->string, q = p+n; p < q; ++p, ++t ) if ( char_traits::ToCaseFolded( *p ) != char_type( char8_traits::ToCaseFolded( *t ) ) ) return false; return true; } bool StartsWithIC( char8_type c ) const noexcept { return string_base::StartsWithIC( char_type( c ) ); } // ------------------------------------------------------------------------- bool EndsWith( const String& s ) const noexcept { return string_base::EndsWith( s ); } bool EndsWith( const_iterator t ) const noexcept { return string_base::EndsWith( t ); } bool EndsWith( char_type c ) const noexcept { return string_base::EndsWith( c ); } bool EndsWithIC( const String& s ) const noexcept { return string_base::EndsWithIC( s ); } bool EndsWithIC( const_iterator t ) const noexcept { return string_base::EndsWithIC( t ); } bool EndsWithIC( char_type c ) const noexcept { return string_base::EndsWithIC( c ); } bool EndsWith( const char16_t* t ) const noexcept { return string_base::EndsWith( reinterpret_cast( t ) ); } bool EndsWith( char16_t c ) const noexcept { return string_base::EndsWith( char_type( c ) ); } bool EndsWithIC( const char16_t* t ) const noexcept { return string_base::EndsWithIC( reinterpret_cast( t ) ); } bool EndsWithIC( char16_t c ) const noexcept { return string_base::EndsWithIC( char_type( c ) ); } bool EndsWith( const wchar_t* t ) const noexcept { #ifdef __PCL_WINDOWS return string_base::EndsWith( reinterpret_cast( t ) ); #else return string_base::EndsWith( String( t ) ); #endif } bool EndsWith( wchar_t c ) const noexcept { return string_base::EndsWith( char_type( c ) ); } bool EndsWithIC( const wchar_t* t ) const noexcept { #ifdef __PCL_WINDOWS return string_base::EndsWithIC( reinterpret_cast( t ) ); #else return string_base::EndsWithIC( String( t ) ); #endif } bool EndsWithIC( wchar_t c ) const noexcept { return string_base::EndsWithIC( char_type( c ) ); } bool EndsWith( const_c_string8 t ) const noexcept { size_type n = char8_traits::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) if ( *p != char_type( *t ) ) return false; return true; } bool EndsWith( char8_type c ) const noexcept { return string_base::EndsWith( char_type( c ) ); } bool EndsWithIC( const_c_string8 t ) const noexcept { size_type n = char8_traits::Length( t ); if ( n == 0 || Length() < n ) return false; for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t ) if ( char_traits::ToCaseFolded( *p ) != char_type( char8_traits::ToCaseFolded( *t ) ) ) return false; return true; } bool EndsWithIC( char8_type c ) const noexcept { return string_base::EndsWithIC( char_type( c ) ); } // ------------------------------------------------------------------------- size_type FindFirst( const String& s, size_type i = 0 ) const noexcept { return string_base::FindFirst( s, i ); } size_type FindFirst( const_iterator t, size_type i = 0 ) const noexcept { return string_base::FindFirst( t, i ); } size_type FindFirst( char_type c, size_type i = 0 ) const noexcept { return string_base::FindFirst( c, i ); } size_type FindFirstIC( const String& s, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( s, i ); } size_type FindFirstIC( const_iterator t, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( t, i ); } size_type FindFirstIC( char_type c, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( c, i ); } size_type FindFirst( const char16_t* t, size_type i = 0 ) const noexcept { return string_base::FindFirst( reinterpret_cast( t ), i ); } size_type FindFirst( char16_t c, size_type i = 0 ) const noexcept { return string_base::FindFirst( char_type( c ), i ); } size_type FindFirstIC( const char16_t* t, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( reinterpret_cast( t ), i ); } size_type FindFirstIC( char16_t c, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( char_type( c ), i ); } size_type FindFirst( const wchar_t* t, size_type i = 0 ) const noexcept { #ifdef __PCL_WINDOWS return string_base::FindFirst( reinterpret_cast( t ), i ); #else return string_base::FindFirst( String( t ), i ); #endif } size_type FindFirst( wchar_t c, size_type i = 0 ) const noexcept { return string_base::FindFirst( char_type( c ), i ); } size_type FindFirstIC( const wchar_t* t, size_type i = 0 ) const noexcept { #ifdef __PCL_WINDOWS return string_base::FindFirstIC( reinterpret_cast( t ), i ); #else return string_base::FindFirstIC( String( t ), i ); #endif } size_type FindFirstIC( wchar_t c, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( char_type( c ), i ); } size_type FindFirst( const_c_string8 t, size_type i = 0 ) const noexcept { return string_base::FindFirst( String( t ), i ); } size_type FindFirst( char8_type c, size_type i = 0 ) const noexcept { return string_base::FindFirst( char_type( c ), i ); } size_type FindFirstIC( const_c_string8 t, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( String( t ), i ); } size_type FindFirstIC( char8_type c, size_type i = 0 ) const noexcept { return string_base::FindFirstIC( char_type( c ), i ); } // size_type Find( const String& s, size_type i = 0 ) const noexcept { return FindFirst( s, i ); } size_type Find( const_iterator t, size_type i = 0 ) const noexcept { return FindFirst( t, i ); } size_type Find( char_type c, size_type i = 0 ) const noexcept { return FindFirst( c, i ); } size_type Find( const char16_t* t, size_type i = 0 ) const noexcept { return FindFirst( t, i ); } size_type Find( char16_t c, size_type i = 0 ) const noexcept { return FindFirst( c, i ); } size_type Find( const wchar_t* t, size_type i = 0 ) const noexcept { return FindFirst( t, i ); } size_type Find( wchar_t c, size_type i = 0 ) const noexcept { return FindFirst( c, i ); } size_type Find( const_c_string8 t, size_type i = 0 ) const noexcept { return FindFirst( t, i ); } size_type Find( char8_type c, size_type i = 0 ) const noexcept { return FindFirst( c, i ); } size_type FindIC( const String& s, size_type i = 0 ) const noexcept { return FindFirstIC( s, i ); } size_type FindIC( const_iterator t, size_type i = 0 ) const noexcept { return FindFirstIC( t, i ); } size_type FindIC( char_type c, size_type i = 0 ) const noexcept { return FindFirstIC( c, i ); } size_type FindIC( const char16_t* t, size_type i = 0 ) const noexcept { return FindFirstIC( t, i ); } size_type FindIC( char16_t c, size_type i = 0 ) const noexcept { return FindFirstIC( c, i ); } size_type FindIC( const wchar_t* t, size_type i = 0 ) const noexcept { return FindFirstIC( t, i ); } size_type FindIC( wchar_t c, size_type i = 0 ) const noexcept { return FindFirstIC( c, i ); } size_type FindIC( const_c_string8 t, size_type i = 0 ) const noexcept { return FindFirstIC( t, i ); } size_type FindIC( char8_type c, size_type i = 0 ) const noexcept { return FindFirstIC( c, i ); } // ------------------------------------------------------------------------- size_type FindLast( const String& s, size_type r = maxPos ) const noexcept { return string_base::FindLast( s, r ); } size_type FindLast( const_iterator t, size_type r = maxPos ) const noexcept { return string_base::FindLast( t, r ); } size_type FindLast( char_type c, size_type r = maxPos ) const noexcept { return string_base::FindLast( c, r ); } size_type FindLastIC( const String& s, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( s, r ); } size_type FindLastIC( const_iterator t, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( t, r ); } size_type FindLastIC( char_type c, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( c, r ); } size_type FindLast( const char16_t* t, size_type r = maxPos ) const noexcept { return string_base::FindLast( reinterpret_cast( t ), r ); } size_type FindLast( char16_t c, size_type r = maxPos ) const noexcept { return string_base::FindLast( char_type( c ), r ); } size_type FindLastIC( const char16_t* t, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( reinterpret_cast( t ), r ); } size_type FindLastIC( char16_t c, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( char_type( c ), r ); } size_type FindLast( const wchar_t* t, size_type r = maxPos ) const noexcept { #ifdef __PCL_WINDOWS return string_base::FindLast( reinterpret_cast( t ), r ); #else return string_base::FindLast( String( t ), r ); #endif } size_type FindLast( wchar_t c, size_type r = maxPos ) const noexcept { return string_base::FindLast( char_type( c ), r ); } size_type FindLastIC( const wchar_t* t, size_type r = maxPos ) const noexcept { #ifdef __PCL_WINDOWS return string_base::FindLastIC( reinterpret_cast( t ), r ); #else return string_base::FindLastIC( String( t ), r ); #endif } size_type FindLastIC( wchar_t c, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( char_type( c ), r ); } size_type FindLast( const_c_string8 t, size_type r = maxPos ) const noexcept { return string_base::FindLast( String( t ), r ); } size_type FindLast( char8_type c, size_type r = maxPos ) const noexcept { return string_base::FindLast( char_type( c ), r ); } size_type FindLastIC( const_c_string8 t, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( String( t ), r ); } size_type FindLastIC( char8_type c, size_type r = maxPos ) const noexcept { return string_base::FindLastIC( char_type( c ), r ); } // ------------------------------------------------------------------------- bool Contains( const String& s ) const noexcept { return string_base::Contains( s ); } bool Contains( const_iterator t ) const noexcept { return string_base::Contains( t ); } bool Contains( char_type c ) const noexcept { return string_base::Contains( c ); } bool ContainsIC( const String& s ) const noexcept { return string_base::ContainsIC( s ); } bool ContainsIC( const_iterator t ) const noexcept { return string_base::ContainsIC( t ); } bool ContainsIC( char_type c ) const noexcept { return string_base::ContainsIC( c ); } bool Contains( const char16_t* t ) const noexcept { return string_base::Contains( reinterpret_cast( t ) ); } bool Contains( char16_t c ) const noexcept { return string_base::Contains( char_type( c ) ); } bool ContainsIC( const char16_t* t ) const noexcept { return string_base::ContainsIC( reinterpret_cast( t ) ); } bool ContainsIC( char16_t c ) const noexcept { return string_base::ContainsIC( char_type( c ) ); } bool Contains( const wchar_t* t ) const noexcept { #ifdef __PCL_WINDOWS return string_base::Contains( reinterpret_cast( t ) ); #else return string_base::Contains( String( t ) ); #endif } bool Contains( wchar_t c ) const noexcept { return string_base::Contains( char_type( c ) ); } bool ContainsIC( const wchar_t* t ) const noexcept { #ifdef __PCL_WINDOWS return string_base::ContainsIC( reinterpret_cast( t ) ); #else return string_base::ContainsIC( String( t ) ); #endif } bool ContainsIC( wchar_t c ) const noexcept { return string_base::ContainsIC( char_type( c ) ); } bool Contains( const_c_string8 t ) const noexcept { return string_base::Contains( String( t ) ); } bool Contains( char8_type c ) const noexcept { return string_base::Contains( char_type( c ) ); } bool ContainsIC( const_c_string8 t ) const noexcept { return string_base::ContainsIC( String( t ) ); } bool ContainsIC( char8_type c ) const noexcept { return string_base::ContainsIC( char_type( c ) ); } // ------------------------------------------------------------------------- int CompareCodePoints( const String& s, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( s, caseSensitive ); } int CompareCodePoints( const_iterator t, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( t, caseSensitive ); } int CompareCodePoints( char_type c, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( c, caseSensitive ); } int CompareCodePoints( const char16_t* t, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( reinterpret_cast( t ), caseSensitive ); } int CompareCodePoints( char16_t c, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( char_type( c ), caseSensitive ); } int CompareCodePoints( const wchar_t* t, bool caseSensitive = true ) const noexcept { #ifdef __PCL_WINDOWS return string_base::CompareCodePoints( reinterpret_cast( t ), caseSensitive ); #else return string_base::CompareCodePoints( String( t ), caseSensitive ); #endif } int CompareCodePoints( wchar_t c, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( char_type( c ), caseSensitive ); } int CompareCodePoints( const_c_string8 t, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( String( t ), caseSensitive ); } int CompareCodePoints( char8_type c, bool caseSensitive = true ) const noexcept { return string_base::CompareCodePoints( char_type( c ), caseSensitive ); } // ------------------------------------------------------------------------- int Compare( const String& s, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( s, caseSensitive, localeAware ); } int Compare( const_iterator t, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( t, caseSensitive, localeAware ); } int Compare( char_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( c, caseSensitive, localeAware ); } int CompareIC( const String& s, bool localeAware = true ) const noexcept { return string_base::CompareIC( s, localeAware ); } int CompareIC( const_iterator t, bool localeAware = true ) const noexcept { return string_base::CompareIC( t, localeAware ); } int CompareIC( char_type c, bool localeAware = true ) const noexcept { return string_base::CompareIC( c, localeAware ); } int Compare( const char16_t* t, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( reinterpret_cast( t ), caseSensitive, localeAware ); } int Compare( char16_t c, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( char_type( c ), caseSensitive, localeAware ); } int CompareIC( const char16_t* t, bool localeAware = true ) const noexcept { return string_base::CompareIC( reinterpret_cast( t ), localeAware ); } int CompareIC( char16_t c, bool localeAware = true ) const noexcept { return string_base::CompareIC( char_type( c ), localeAware ); } int Compare( const wchar_t* t, bool caseSensitive = true, bool localeAware = true ) const noexcept { #ifdef __PCL_WINDOWS return string_base::Compare( reinterpret_cast( t ), caseSensitive, localeAware ); #else return string_base::Compare( String( t ), caseSensitive, localeAware ); #endif } int Compare( wchar_t c, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( char_type( c ), caseSensitive, localeAware ); } int CompareIC( const wchar_t* t, bool localeAware = true ) const noexcept { #ifdef __PCL_WINDOWS return string_base::CompareIC( reinterpret_cast( t ), localeAware ); #else return string_base::CompareIC( String( t ), localeAware ); #endif } int CompareIC( wchar_t c, bool localeAware = true ) const noexcept { return string_base::CompareIC( char_type( c ), localeAware ); } int Compare( const_c_string8 t, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( String( t ), caseSensitive, localeAware ); } int Compare( char8_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept { return string_base::Compare( char_type( c ), caseSensitive, localeAware ); } int CompareIC( const_c_string8 t, bool localeAware = true ) const noexcept { return string_base::CompareIC( String( t ), localeAware ); } int CompareIC( char8_type c, bool localeAware = true ) const noexcept { return string_base::CompareIC( char_type( c ), localeAware ); } // ------------------------------------------------------------------------- bool WildMatch( const String& pattern, bool caseSensitive = true ) const noexcept { return string_base::WildMatch( pattern, caseSensitive ); } bool WildMatchIC( const String& pattern ) const noexcept { return string_base::WildMatchIC( pattern ); } bool WildMatch( const_iterator pattern, bool caseSensitive = true ) const noexcept { return string_base::WildMatch( pattern, caseSensitive ); } bool WildMatchIC( const_iterator pattern ) const noexcept { return string_base::WildMatchIC( pattern ); } bool WildMatch( const string8_base& pattern, bool caseSensitive = true ) const noexcept { return char_traits::WildMatch( m_data->string, Length(), pattern.Begin(), pattern.Length(), caseSensitive ); } bool WildMatchIC( const string8_base& pattern ) const noexcept { return char_traits::WildMatch( m_data->string, Length(), pattern.Begin(), pattern.Length(), false/*caseSensitive*/ ); } bool WildMatch( const_c_string8 pattern, bool caseSensitive = true ) const noexcept { return char_traits::WildMatch( m_data->string, Length(), pattern, char8_traits::Length( pattern ), caseSensitive ); } bool WildMatchIC( const_c_string8 pattern ) const noexcept { return char_traits::WildMatch( m_data->string, Length(), pattern, char8_traits::Length( pattern ), false/*caseSensitive*/ ); } // ------------------------------------------------------------------------- String SetToLength( size_type n ) const { return string_base::SetToLength( n ); } String ResizedToNullTerminated() const { return string_base::ResizedToNullTerminated(); } String Squeezed() const { return string_base::Squeezed(); } // ------------------------------------------------------------------------- String Substring( size_type i, size_type n = maxPos ) const { return string_base::Substring( i, n ); } String Left( size_type n ) const { return string_base::Left( n ); } String Right( size_type n ) const { return string_base::Right( n ); } String Suffix( size_type i ) const { return string_base::Suffix( i ); } String Prefix( size_type i ) const { return string_base::Prefix( i ); } // ------------------------------------------------------------------------- template size_type Break( C& list, const String& s, bool trim = false, size_type i = 0 ) const { return string_base::Break( list, s, trim, i ); } template size_type Break( C& list, const string8_base& s, bool trim = false, size_type i = 0 ) const { return string_base::Break( list, String( s ), trim, i ); } template size_type Break( C& list, const_c_string8 s, bool trim = false, size_type i = 0 ) const { return string_base::Break( list, String( s ), trim, i ); } template size_type Break( C& list, char_type c, bool trim = false, size_type i = 0 ) const { return string_base::Break( list, c, trim, i ); } template size_type Break( C& list, char8_type c, bool trim = false, size_type i = 0 ) const { return string_base::Break( list, char_type( c ), trim, i ); } template size_type Break( C& list, const Array& ca, bool trim = false, size_type i = 0 ) const { return string_base::Break( list, ca, trim, i ); } // ------------------------------------------------------------------------- template size_type BreakIC( C& list, const String& s, bool trim = false, size_type i = 0 ) const { return string_base::BreakIC( list, s, trim, i ); } template size_type BreakIC( C& list, const string8_base& s, bool trim = false, size_type i = 0 ) const { return string_base::BreakIC( list, String( s ), trim, i ); } template size_type BreakIC( C& list, const_c_string8 s, bool trim = false, size_type i = 0 ) const { return string_base::BreakIC( list, String( s ), trim, i ); } template size_type BreakIC( C& list, char_type c, bool trim = false, size_type i = 0 ) const { return string_base::BreakIC( list, c, trim, i ); } template size_type BreakIC( C& list, char8_type c, bool trim = false, size_type i = 0 ) const { return string_base::BreakIC( list, char_type( c ), trim, i ); } // ------------------------------------------------------------------------- String Trimmed() const { return string_base::Trimmed(); } String TrimmedLeft() const { return string_base::TrimmedLeft(); } String TrimmedRight() const { return string_base::TrimmedRight(); } // ------------------------------------------------------------------------- String LeftJustified( size_type width, char_type fill = CharTraits::Blank() ) const { return string_base::LeftJustified( width, fill ); } String RightJustified( size_type width, char_type fill = CharTraits::Blank() ) const { return string_base::RightJustified( width, fill ); } String CenterJustified( size_type width, char_type fill = CharTraits::Blank() ) const { return string_base::CenterJustified( width, fill ); } // ------------------------------------------------------------------------- String Enclosed( char_type c ) const { return string_base::Enclosed( c ); } String SingleQuoted() const { return string_base::SingleQuoted(); } String DoubleQuoted() const { return string_base::DoubleQuoted(); } String Unquoted() const { return string_base::Unquoted(); } // ------------------------------------------------------------------------- String CaseFolded() const { return string_base::CaseFolded(); } String Lowercase() const { return string_base::Lowercase(); } String Uppercase() const { return string_base::Uppercase(); } // ------------------------------------------------------------------------- String Reversed() const { return string_base::Reversed(); } String Sorted() const { return string_base::Sorted(); } template String Sorted( BP p ) const { return string_base::Sorted( p ); } // ------------------------------------------------------------------------- /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * character. Returns a reference to this string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, char_type separator ) { Clear(); return c.ToSeparated( *this, separator ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * character, and built using an \a append binary function. Returns a * reference to this string. * * The binary function must be of the form: * * \code void append( String& s, char16_type c ); \endcode * * where \a c is being appended to \a s. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, char_type separator, AF append ) { Clear(); return c.ToSeparated( *this, separator, append ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator string. * Returns a reference to this string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, const String& separator ) { Clear(); return c.ToSeparated( *this, separator ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator string, * and built using an \a append binary function. Returns a reference to this * string. * * The binary function must be of the form: * * \code void append( String& s1, const String& s2 ); \endcode * * where \a s2 is being appended to \a s1. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, const String& separator, AF append ) { Clear(); return c.ToSeparated( *this, separator, append ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * null-terminated string. Returns a reference to this string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, const_c_string separator ) { return ToSeparated( c, String( separator ) ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * null-terminated string, and built using an \a append binary function. * Returns a reference to this string. * * The binary function must be of the form: * * \code void append( String& s1, const char16_type* s2 ); \endcode * * where \a s2 is being appended to \a s1. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, const_c_string separator, AF append ) { return ToSeparated( c, String( separator ), append ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * null-terminated 8-bit string (const char*). Returns a reference to this * string. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, const_c_string8 separator ) { return ToSeparated( c, String( separator ) ); } /*! * Replaces the contents of this string with a sequence of tokens extracted * from a container \a c, separated with the specified \a separator * null-terminated 8-bit string (const char*), and built using an \a append * binary function. Returns a reference to this string. * * The binary function must be of the form: * * \code void append( String& s1, const char* s2 ); \endcode * * where \a s2 is being appended to \a s1. * * The container type C must have separated list generation semantics. All * iterable PCL containers such as Array, Vector, etc. provide the necessary * ToSeparated member functions. */ template String& ToSeparated( const C& c, const_c_string8 separator, AF append ) { return ToSeparated( c, String( separator ), append ); } /*! * Replaces the contents of this string with a sequence of comma-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( ',' ) ); \endcode */ template String& ToCommaSeparated( const C& c ) { return ToSeparated( c, CharTraits::Comma() ); } /*! * Replaces the contents of this string with a sequence of colon-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( ':' ) ); \endcode */ template String& ToColonSeparated( const C& c ) { return ToSeparated( c, CharTraits::Colon() ); } /*! * Replaces the contents of this string with a sequence of space-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( ' ' ) ); \endcode */ template String& ToSpaceSeparated( const C& c ) { return ToSeparated( c, CharTraits::Blank() ); } /*! * Replaces the contents of this string with a sequence of * tabulator-separated tokens extracted from a container \a c. Returns a * reference to this string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( '\t' ) ); \endcode */ template String& ToTabSeparated( const C& c ) { return ToSeparated( c, CharTraits::Tab() ); } /*! * Replaces the contents of this string with a sequence of new line * separated tokens extracted from a container \a c. Returns a reference to * this string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( '\n' ) ); \endcode */ template String& ToNewLineSeparated( const C& c ) { return ToSeparated( c, CharTraits::LF() ); } /*! * Replaces the contents of this string with a sequence of null-separated * tokens extracted from a container \a c. Returns a reference to this * string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( '\0' ) ); \endcode */ template String& ToNullSeparated( const C& c ) { return ToSeparated( c, CharTraits::Null() ); } /*! * Replaces the contents of this string with a hyphenated sequence of tokens * extracted from a container \a c. Returns a reference to this string. * * This member function is equivalent to: * * \code ToSeparated( c, char16_type( '-' ) ); \endcode */ template String& ToHyphenated( const C& c ) { return ToSeparated( c, CharTraits::Hyphen() ); } // ------------------------------------------------------------------------- /*! * Replaces all occurrences of HTML special characters in this string with * valid HTML entities. Returns a reference to this string. * * The following replacements are performed: * * '&' (ampersand) becomes "\&" \n * '"' (double quote) becomes "\"" \n * "'" (single quote) becomes "\'" \n * '<' (less than) becomes "\<" \n * '>' (greater than) becomes "\>" * * \sa EncodedHTMLSpecialChars(), ToDecodedHTMLSpecialChars() */ String& ToEncodedHTMLSpecialChars(); /*! * Returns a duplicate of this string with all occurrences of HTML special * characters replaced with valid HTML entities. * * \sa ToEncodedHTMLSpecialChars(), DecodedHTMLSpecialChars() */ String EncodedHTMLSpecialChars() const { return String( *this ).ToEncodedHTMLSpecialChars(); } /*! * Replaces all occurrences of special HTML entities in this string with * their corresponding plain text character equivalents. Returns a reference * to this string. * * The following replacements are performed: * * "\&" (ampersand) becomes '&' \n * "\"" (double quote) becomes '"' \n * "\'" (single quote) becomes "'" \n * "\'" (apostrophe) becomes "'" \n * "\<" (less than) becomes '<' \n * "\>" (greater than) becomes '>' * * \sa DecodedHTMLSpecialChars(), ToEncodedHTMLSpecialChars() */ String& ToDecodedHTMLSpecialChars(); /*! * Returns a duplicate of this string with all occurrences of special HTML * entities replaced with their corresponding plain text character * equivalents. * * \sa ToDecodedHTMLSpecialChars(), EncodedHTMLSpecialChars() */ String DecodedHTMLSpecialChars() const { return String( *this ).ToDecodedHTMLSpecialChars(); } // ------------------------------------------------------------------------- #ifdef __PCL_QT_INTERFACE operator QString() const { return PCL_GET_QSTRING_FROM_CHAR16PTR( c_str() ); } operator QDate() const { return QDate::fromString( operator QString(), PCL_QDATE_FMT_STR ); } operator QDateTime() const { return QDateTime::fromString( operator QString(), PCL_QDATETIME_FMT_STR ); } #endif /*! * Replaces the contents of this string with a formatted representation of a * variable-length set of values. Returns a reference to this string. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ String& Format( const_c_string8 fmt, ... ) { va_list paramList; va_start( paramList, fmt ); (void)VFormat( fmt, paramList ); va_end( paramList ); return *this; } /*! * Appends a formatted representation of a variable-length set of values to * the current contents of this string. Returns a reference to this string. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ String& AppendFormat( const_c_string8 fmt, ... ) { va_list paramList; va_start( paramList, fmt ); (void)AppendVFormat( fmt, paramList ); va_end( paramList ); return *this; } /*! * Replaces the contents of this string with a formatted representation of a * variable-length set of values, specified as a \c va_list standard * parameter list. Returns the number of characters generated. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ int VFormat( const_c_string8 fmt, va_list paramList ) { IsoString s; int count = s.VFormat( fmt, paramList ); Assign( s ); return count; } /*! * Appends a formatted representation of a variable-length set of values, * specified as a \c va_list standard parameter list, to the current * contents of this string. Returns the number of characters appended. * * The \a fmt null-terminated string is a standard printf format * string. It follows the same rules as its counterpart parameter in * the standard printf( const char* fmt, ... ) C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ int AppendVFormat( const_c_string8 fmt, va_list paramList ) { IsoString s; int count = s.VFormat( fmt, paramList ); Append( s ); return count; } /*! * Replaces the contents of this string with a formatted representation of a * variable-length set of values. Returns a reference to this string. * * The \a fmt null-terminated string is a standard printf format * string of \c wchar_t characters. It follows the same rules as its * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) * C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ String& Format( const wchar_t* fmt, ... ) { va_list paramList; va_start( paramList, fmt ); (void)VFormat( fmt, paramList ); va_end( paramList ); return *this; } /*! * Appends a formatted representation of a variable-length set of values to * the current contents of this string. Returns a reference to this string. * * The \a fmt null-terminated string is a standard printf format * string of \c wchar_t characters. It follows the same rules as its * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) * C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ String& AppendFormat( const wchar_t* fmt, ... ) { va_list paramList; va_start( paramList, fmt ); (void)AppendVFormat( fmt, paramList ); va_end( paramList ); return *this; } /*! * Replaces the contents of this string with a formatted representation of a * variable-length set of values, specified as a \c va_list standard * parameter list. Returns the number of characters generated. * * The \a fmt null-terminated string is a standard printf format * string of \c wchar_t characters. It follows the same rules as its * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) * C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ int VFormat( const wchar_t* fmt, va_list paramList ); /*! * Appends a formatted representation of a variable-length set of values, * specified as a \c va_list standard parameter list, to the current * contents of this string. Returns the number of characters appended. * * The \a fmt null-terminated string is a standard printf format * string of \c wchar_t characters. It follows the same rules as its * counterpart parameter in the standard wprintf( const wchar_t* fmt, ... ) * C runtime function. * * The required space to store the resulting formatted output is calculated * and allocated transparently. */ int AppendVFormat( const wchar_t* fmt, va_list paramList ); // ------------------------------------------------------------------------- /*! * Conversion of a UTF-8 substring to a UTF-16 string. * * Converts a contiguous sequence of \a n characters starting at the \a i-th * position of the specified null-terminated UTF-8 \a string. Returns the * resulting UTF-16 string. * * \sa UTF16ToUTF8(), UTF16ToUTF32(), UTF32ToUTF16() */ static String UTF8ToUTF16( const_c_string8 string, size_type i = 0, size_type n = maxPos ); /*! * Conversion of a UTF-16 substring to a UTF-8 string. * * Converts a contiguous sequence of \a n characters starting at the \a i-th * position of the specified null-terminated UTF-16 \a string. Returns the * resulting UTF-8 string. * * \sa UTF8ToUTF16(), UTF16ToUTF32(), UTF32ToUTF16() */ static IsoString UTF16ToUTF8( const_c_string string, size_type i = 0, size_type n = maxPos ); /*! * Conversion of a UTF-16 substring to a UTF-32 string. * * Converts a contiguous sequence of \a n characters starting at the \a i-th * position of the specified null-terminated UTF-16 \a string. Returns the * resulting UTF-32 string as a dynamic array. * * \sa UTF8ToUTF16(), UTF16ToUTF8(), UTF32ToUTF16() */ static Array UTF16ToUTF32( const_c_string string, size_type i = 0, size_type n = maxPos ); /*! * Conversion of a UTF-32 substring to a UTF-16 string. * * Converts a contiguous sequence of \a n characters starting at the \a i-th * position of the specified null-terminated UTF-32 \a string. Returns the * resulting UTF-16 string. * * \sa UTF8ToUTF16(), UTF16ToUTF8(), UTF16ToUTF32() */ static String UTF32ToUTF16( const uint32* string, size_type i = 0, size_type n = maxPos ); // ------------------------------------------------------------------------- /*! * Returns an 8-bit, ISO/IEC-8859-1 string with a converted copy of this * %String object. Characters in this string that cannot be converted to * ISO-8859-1 (that is, characters with code points greater than 0x100) will * have undefined values in the returned string. Undefined values are * represented with question mark characters (?). * * \sa ToUTF8(), ToMBS(), ToUTF32(), To7BitASCII() */ IsoString ToIsoString() const; /*! * Returns a 7-bit ASCII string with a converted copy of this %String * object. Characters in this string that cannot be converted to the 7-bit * ASCII set (that is, characters with code points greater than 0x80) will * have undefined values in the returned string. Undefined values are * represented with question mark characters (?). * * \sa ToIsoString(), ToUTF8(), ToMBS(), ToUTF32() */ IsoString To7BitASCII() const; /*! * Returns an 8-bit string with a UTF-8 representation of a subset of \a n * contiguous UTF-16 characters from this %String object, starting at the * \a i-th character. * * \sa ToMBS(), ToLocal8Bit(), ToIsoString(), ToUTF32() */ IsoString ToUTF8( size_type i = 0, size_type n = maxPos ) const { return UTF16ToUTF8( Begin(), i, n ); } /*! * Returns a copy of this Unicode string converted to a multibyte * string. This conversion is dependent on the current locale. * * In the event of conversion error (if there are invalid wide characters in * the source string) this routine returns an empty string. * * This member function is a convenience wrapper for the wcstombs() routine * of the standard C runtime library. Note that on platforms where the size * of wchar_t is four bytes (e.g. Linux) this routine performs an additional * conversion from UTF-16 to UTF-32. On platforms where the size of wchar_t * is two bytes (e.g. Windows), the conversion is direct. * * \sa ToUTF8(), ToLocal8Bit(), ToIsoString(), ToUTF32(); */ IsoString ToMBS() const; /*! * Returns a copy of this Unicode string converted to an 8-bit * locale-dependent string. On UNIX/Linux systems (FreeBSD, Linux, Mac OS X) * this function is equivalent to ToUTF8(). On Windows, this function * returns ToMBS(). * * \sa ToUTF8(), ToMBS(); */ IsoString ToLocal8Bit() const { #ifdef __PCL_WINDOWS return ToMBS(); #else return ToUTF8(); #endif } /*! * Returns a copy of a contiguous segment of \a n characters of this string, * starting from its \a i-th character, as a dynamic array of \c wchar_t. A * null terminating character (L'\\0' specifically) is always appended to * the resulting array. * * Depending on the platform, the \c wchar_t type may be 16-bit wide * (Windows) or 32-bit wide (UNIX/Linux). The char16_type used by %String is * always a 16-bit character (UTF-16) on all supported platforms. * * This member function provides a platform-independent way to obtain the * contents of a %String object as a standard null-terminated string of * \c wchar_t characters. * * On platforms where wchar_t occupies four bytes (UNIX/Linux), this * function assumes that this %String object contains no surrogates. For a * generalized conversion from UTF-16 to UTF-32, see ToUTF32(). * * \sa ToUTF32(), ToUTF8(), ToMBS(), ToIsoString() */ Array ToWCharArray( size_type i = 0, size_type n = maxPos ) const { if ( n > 0 ) { size_type len = Length(); if ( i < len ) { n = pcl::Min( n, len-i ); Array a( n+1, wchar_t( 0 ) ); #ifdef __PCL_WINDOWS char_traits::Copy( reinterpret_cast( a.Begin() ), m_data->string+i, n ); #else Array::iterator w = a.Begin(); for ( const_iterator s = m_data->string+i, e = s+n; s < e; ++w, ++s ) *w = wchar_t( *s ); #endif // __PCL_WINDOWS return a; } } return Array( size_type( 1 ), wchar_t( 0 ) ); } /*! * Returns a dynamic array of 32-bit integers with a UTF-32 representation * of a subset of \a n contiguous UTF-16 characters from this %String * object, starting at the \a i-th character. A null terminating character * (uint32( 0 ) specifically) is always appended to the resulting array. * * \sa ToWCharArray(), ToUTF8(), ToMBS(), ToIsoString() */ Array ToUTF32( size_type i = 0, size_type n = maxPos ) const { return UTF16ToUTF32( Begin(), i, n ); } #ifdef __PCL_QT_INTERFACE QString ToQString() const { return operator QString(); } QDate ToQDate() const { return operator QDate(); } QDateTime ToQDateTime() const { return operator QDateTime(); } #endif /*! * Evaluates this string as a Boolean literal, and returns the result as a * \c bool value. * * Returns \c true if this string is equal to "1", "true", "TRUE" or "T". * Returns \c false if this string is equal to "0", "false", "FALSE" or "F". * Otherwise this function throws a ParseError exception. * * \sa TryToBool() */ bool ToBool() const; /*! * Attempts to evaluate this string as a Boolean literal. * * If this string can legally be converted to a Boolean value, this function * returns \c true and stores the evaluation result in the \a value * variable. A string can only be converted to Boolean type if it is equal * to either "1", "true", "TRUE", "T", "0", "false", "FALSE" or "F". * * If this string cannot be converted to a Boolean value, this function * returns \c false and does not change the \a value variable. This function * does not throw any exception. * * \sa ToBool() */ bool TryToBool( bool& value ) const noexcept; /*! * Evaluates this string as a floating point numeric literal, and returns * the result as a \c float value. * * For information about the legal syntax of a floating point literal, see * the documentation for the ToDouble() member function. * * If this string doesn't contain a valid floating point literal, or if the * range of \c float is exceeded, this member function throws a ParseError * exception. * * \sa TryToFloat() */ float ToFloat() const; /*! * Attempts to evaluate this string as a floating point numeric literal. * * If this string can legally be converted to a floating point number, this * function returns \c true and stores the evaluation result in the \a value * variable. For information about the legal syntax of a floating point * literal, see the documentation for the ToDouble() member function. * * If this string cannot be converted to a floating point number, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \sa ToFloat() */ bool TryToFloat( float& value ) const noexcept; /*! * Evaluates this string as a floating point literal, and returns the result * as a \c double value. * * The source string is expected to have the following format (informal * format specification): * * [+|-][\][.[\]][\[+|-]\] * * where \ and \ are optional sequences of * decimal digits from 0 to 9, \ is an exponent specifier * (the letter 'e' (or 'E')), and \ is a sequence of decimal * digits specifying a power of ten that multiplies the preceding numeric * constant. At least a one-digit integer part, or a one-digit decimal part, * is mandatory. FORTRAN exponent specifiers ('d' and 'f' (or 'D' and 'F')) * are also recognized by this implementation. * * If this string doesn't contain a valid floating point literal, or if the * range of \c double is exceeded, this member function throws a ParseError * exception. * * \sa TryToDouble() */ double ToDouble() const; /*! * Attempts to evaluate this string as a floating point numeric literal. * * If this string can legally be converted to a floating point number, this * function returns \c true and stores the evaluation result in the \a value * variable. For information about the legal syntax of a floating point * literal, see the documentation for the ToDouble() member function. * * If this string cannot be converted to a floating point number, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \sa ToDouble() */ bool TryToDouble( double& value ) const noexcept; /*! * Evaluates this string as an integer literal, and returns the result as a * \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code long n = s.ToInt( 0 ); \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string doesn't contain a valid integer literal, or if the range * of \c long is exceeded, this member function throws a ParseError exception. * * \sa TryToInt() */ long ToInt() const { return ToInt( 0 ); } /*! * Attempts to evaluate this string as an integer numeric literal. * * If this string can legally be converted to an integer number, this * function returns \c true and stores the evaluation result in the \a value * variable. * * Calling this member function for a string \c s is equivalent to: * * \code * int v; * if ( s.TryToInt( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an integer number, this function * returns \c false and does not change the \a value variable. This function * does not throw any exception. * * \sa ToInt() */ bool TryToInt( int& value ) const noexcept { return TryToInt( value, 0 ); } /*! * Evaluates this string as an integer literal in the specified \a base, and * returns the result as a \c long value. * * If \a base is 0, the source string is expected to represent either a * decimal constant, an octal constant, or a hexadecimal constant, any of * which optionally preceded by a sign character (+ or -). A decimal * constant begins with a non-zero digit, and consists of a sequence of * decimal digits from '0' to '9'. An octal begins with the prefix '0', * optionally followed by a sequence of the digits 0 to 7 only. A * hexadecimal constant begins with the prefix '0x' or '0X', which must be * followed by a sequence of decimal digits and letters from 'a' (or 'A') * to 'f' (or 'F'), whose corresponding decimal values are from 10 to 15, * respectively. * * Other legal values of \a base, from 2 to 36, specify the expected base of * the integer constant represented by the source string. Decimal digits and * letters from 'a' (or 'A') to 'z' (or 'Z') are used to represent all * possible digits in the specified base, as necessary. * * If this string doesn't contain a valid integer literal in the specified * \a base, if an illegal \a base is specified, or if the range of \c long * is exceeded, this member function throws a ParseError exception. * * \sa TryToInt( int&, int ) const */ long ToInt( int base ) const; /*! * Attempts to evaluate this string as an integer numeric literal in the * specified \a base. * * If this string can legally be converted to an integer number in the * specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an integer number in the specified * \a base, this function returns \c false and does not change the \a value * variable. This function does not throw any exception. * * \sa ToInt( int ) const */ bool TryToInt( int& value, int base ) const noexcept; /*! * Evaluates this string as an unsigned integer literal, and returns the * result as an \c unsigned \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code unsigned long n = s.ToUInt( 0 ); \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string doesn't contain a valid unsigned integer literal, or if * the range of \c unsigned \c long is exceeded, this member function throws * a ParseError exception. * * \sa TryToUInt() */ unsigned long ToUInt() const { return ToUInt( 0 ); } /*! * Attempts to evaluate this string as an unsigned integer literal. * * If this string can legally be converted to an unsigned integer number, * this function returns \c true and stores the evaluation result in the * \a value variable. * * Calling this member function for a string \c s is equivalent to: * * \code * unsigned v; * if ( s.TryToUInt( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an integer number, this function * returns \c false and does not change the \a value variable. This function * does not throw any exception. * * \sa ToUInt() */ bool TryToUInt( unsigned& value ) const noexcept { return TryToUInt( value, 0 ); } /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as an \c unsigned \c long value. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). The only exception * is that for this member function, only a + sign is legal preceding the * numeric constant represented by the source string. * * If this string doesn't contain a valid integer literal in the specified * \a base, if an illegal \a base is specified, or if the range of * \c unsigned \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToUInt( unsigned&, int ) const */ unsigned long ToUInt( int base ) const; /*! * Attempts to evaluate this string as an unsigned integer literal in the * specified \a base. * * If this string can legally be converted to an unsigned integer number in * the specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * See the documentation under ToUInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to an unsigned integer number in the * specified \a base, this function returns \c false and does not change the * \a value variable. This function does not throw any exception. * * \sa ToUInt( int ) const */ bool TryToUInt( unsigned& value, int base ) const noexcept; /*! * Evaluates this string as an integer literal, and returns the result as a * \c long \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code long long n = s.ToInt64( 0 ); \endcode * * If this string doesn't contain a valid integer literal, or if the range * of \c long \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToInt64() */ long long ToInt64() const { return ToInt64( 0 ); } /*! * Attempts to evaluate this string as a 64-bit integer numeric literal in * the specified \a base. * * If this string can legally be converted to a 64-bit integer number in the * specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * Calling this member function for a string \c s is equivalent to: * * \code * long long v; * if ( s.TryToInt64( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to a 64-bit integer number, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \sa ToInt64() */ bool TryToInt64( long long& value ) const noexcept { return TryToInt64( value, 0 ); } /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as a \c long \c long value. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string doesn't contain a valid integer literal in the specified * \a base, if an illegal \a base is specified, or if the range of * \c long \c long is exceeded, this member function throws a ParseError * exception. * * \sa TryToInt64( long long&, int ) const */ long long ToInt64( int base ) const; /*! * Attempts to evaluate this string as a 64-bit integer numeric literal in * the specified \a base. * * If this string can legally be converted to a 64-bit integer number in the * specified \a base, this function returns \c true and stores the * evaluation result in the \a value variable. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string cannot be converted to a 64-bit integer number in the * specified \a base, this function returns \c false and does not change the * \a value variable. This function does not throw any exception. * * \sa ToInt64( int ) const */ bool TryToInt64( long long& value, int base ) const noexcept; /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as an \c unsigned \c long \c long value. * * Calling this member function for a string \c s is equivalent to: * * \code unsigned long long n = s.ToUInt64( 0 ); \endcode * * If this string doesn't contain a valid unsigned integer literal, or if * the range of \c unsigned \c long \c long is exceeded, this member * function throws a ParseError exception. * * \sa TryToUInt64() */ unsigned long long ToUInt64() const { return ToUInt64( 0 ); } /*! * Attempts to evaluate this string as a 64-bit unsigned integer numeric * literal in the specified \a base. * * If this string can legally be converted to a 64-bit unsigned integer * number in the specified \a base, this function returns \c true and stores * the evaluation result in the \a value variable. * * Calling this member function for a string \c s is equivalent to: * * \code * unsigned long long v; * if ( s.TryToUInt64( v, 0 ) ) ... * \endcode * * See the documentation under ToInt( int ) for information about automatic * base conversions when \a base=0 is specified. * * If this string cannot be converted to a 64-bit unsigned integer number, * this function returns \c false and does not change the \a value variable. * This function does not throw any exception. * * \sa ToUInt64() */ bool TryToUInt64( unsigned long long& value ) const noexcept { return TryToUInt64( value, 0 ); } /*! * Evaluates this string as an unsigned integer literal in the specified * \a base, and returns the result as an \c unsigned \c long \c long value. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string doesn't contain a valid unsigned integer literal in the * specified \a base, if an illegal \a base is specified, or if the range of * \c unsigned \c long \c long is exceeded, this member function throws a * ParseError exception. * * \sa TryToUInt64( unsigned long long&, int ) const */ unsigned long long ToUInt64( int base ) const; /*! * Attempts to evaluate this string as an unsigned 64-bit integer numeric * literal in the specified \a base. * * If this string can legally be converted to an unsigned 64-bit integer * number in the specified \a base, this function returns \c true and stores * the evaluation result in the \a value variable. * * For information about possible values of \a base and how these are * interpreted, see the documentation under ToInt( int ). * * If this string cannot be converted to an unsigned 64-bit integer number * in the specified \a base, this function returns \c false and does not * change the \a value variable. This function does not throw any exception. * * \sa ToUInt64( int ) const */ bool TryToUInt64( unsigned long long& value, int base ) const noexcept; /*! * Evaluates this string as a sexagesimal numeric literal representation, * and returns the result as a \c double value. * * The source string is expected to have the following format: * * [+|-]\[\\[\\]][.[\]] * * where \, \, \ and \ are sequences of * decimal digits from 0 to 9, and \ is any sequence of characters * specified as the \a separator argument. The default separator is the * colon character, ':'. * * The result is equal to: * * \ * (\ + \/60 + \/3600) * * where omitted optional components are taken as zero, and \ is -1 * iff a minus sign '-' leads the representation, or +1 otherwise. * * If this string doesn't contain a valid sexagesimal numeric literal, or if * the range of \c double is exceeded, this member function throws a * ParseError exception. * * \ingroup sexagesimal_conversion * \sa TrySexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() */ double SexagesimalToDouble( const String& separator = ':' ) const { int sign, s1, s2; double s3; ParseSexagesimal( sign, s1, s2, s3, separator ); return sign*(s1 + (s2 + s3/60)/60); } /*! * Evaluates this string as a sexagesimal numeric literal representation * with the specified set of \a separators, and returns the result as a * \c double value. * * This function is identical to SexagesimalToDouble( const String& ), but a * set of separator characters is specified as a dynamic array. Any * occurrence of a character contained by \a separators will be valid as a * token separator. * * \ingroup sexagesimal_conversion * \sa TrySexagesimalToDouble( double&, const Array<>& ) */ double SexagesimalToDouble( const Array& separators ) const { int sign, s1, s2; double s3; ParseSexagesimal( sign, s1, s2, s3, separators ); return sign*(s1 + (s2 + s3/60)/60); } /*! * Attempts to evaluate this string as a sexagesimal numeric literal with * the specified \a separator. * * If this string can legally be evaluated as a sexagesimal literal and * converted to a floating point number, this function stores the evaluation * result in the specified \a value variable and returns \c true. For * information about the legal syntax of a sexagesimal literal, see the * documentation for SexagesimalToDouble(). * * If this string cannot be evaluated as a sexagesimal literal, this * function returns \c false and does not change the \a value variable. This * function does not throw any exception. * * \ingroup sexagesimal_conversion * \sa SexagesimalToDouble(), ParseSexagesimal(), TryParseSexagesimal() */ bool TrySexagesimalToDouble( double& value, const String& separator = ':' ) const noexcept { int sign, s1, s2; double s3; if ( TryParseSexagesimal( sign, s1, s2, s3, separator ) ) { value = sign*(s1 + (s2 + s3/60)/60); return true; } return false; } /*! * Attempts to evaluate this string as a sexagesimal numeric literal with * the specified set of \a separators. * * This function is identical to * TrySexagesimalToDouble( double&, const String& ), but a set of separator * characters is specified as a dynamic array. Any occurrence of a character * contained by \a separators will be valid as a token separator. * * \ingroup sexagesimal_conversion * \sa SexagesimalToDouble( const Array<>& ) */ bool TrySexagesimalToDouble( double& value, const Array& separators ) const noexcept { int sign, s1, s2; double s3; if ( TryParseSexagesimal( sign, s1, s2, s3, separators ) ) { value = sign*(s1 + (s2 + s3/60)/60); return true; } return false; } /*! * Evaluates this string as a sexagesimal numeric literal representation, * using the specified \a separator, and stores the resulting components in * the specified \a sign, \a s1, \a s2 and \a s3 variables. * * The output value of \a sign is either -1 or +1, respectively for negative * and positive values. * * For information about the legal syntax of a sexagesimal literal, see the * documentation for SexagesimalToDouble(). * * This function stores \e canonical minutes and seconds components, * irrespective of the actual component values represented by this string. * The output sexagesimal component values are such that: * * 0 ≤ \a s1 \n * 0 ≤ \a s2 < 60 \n * 0 ≤ \a s3 < 60 \n * * If this string doesn't contain a valid sexagesimal numeric literal, or if * the range of \c double is exceeded, this member function throws a * ParseError exception. * * \ingroup sexagesimal_conversion * \sa TryParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() */ void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const String& separator = ':' ) const; /*! * Evaluates this string as a sexagesimal numeric literal representation, * using the specified set of \a separators, and stores the resulting * components in the specified \a sign, \a s1, \a s2 and \a s3 variables. * * This function is identical to * ParseSexagesimal( int&, int&, int&, double&, const String& ), but a set * of separator characters is specified as a dynamic array. Any occurrence * of a character contained by \a separators will be valid as a token * separator. * * \ingroup sexagesimal_conversion * \sa TryParseSexagesimal( int&, int&, int&, double&, const Array<>& ) */ void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const; /*! * Attempts to evaluate this string as a sexagesimal numeric literal * representation, using the specified \a separator. If successful, stores * the resulting components in the specified \a sign, \a s1, \a s2 and \a s3 * variables, and returns \c true. For more information on syntax and * output values and ranges, see the documentation for ParseSexagesimal(). * * If this string cannot be evaluated as a sexagesimal literal, this * function returns \c false and does not change any of the \a sign, \a s1, * \a s2 and \a s3 variables. This function does not throw any exception. * * \ingroup sexagesimal_conversion * \sa ParseSexagesimal(), SexagesimalToDouble(), TrySexagesimalToDouble() */ bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const String& separator = ':' ) const noexcept; /*! * Attempts to evaluate this string as a sexagesimal numeric literal * representation, using the specified set of \a separators. * * This function is identical to * TryParseSexagesimal( int&, int&, int&, double&, const String& ), but a * set of separator characters is specified as a dynamic array. Any * occurrence of a character contained by \a separators will be valid as a * token separator. * * \ingroup sexagesimal_conversion * \sa ParseSexagesimal( int&, int&, int&, double&, const Array<>& ) */ bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array& separators ) const noexcept; /*! * Returns a sexagesimal ASCII representation of the specified components * \a sign, \a s1, \a s2 and \a s3, generated with the specified conversion * \a options. * * The generated representation will correspond to a negative value iff * \a sign < 0, positive otherwise. * * The generated representation is of the form: * * [+|-]\[\\[\\]][.[\]] * * where the second and third sexagesimal components are canonicalized: * * 0 ≤ \ < 60 * 0 ≤ \ < 60 * * irrespective of the original \a s2 and \a s3 argument values. * * \ingroup sexagesimal_conversion * \sa SexagesimalToDouble(), SexagesimalConversionOptions, * AngleConversionOptions, LongitudeConversionOptions, RAConversionOptions, * LatitudeConversionOptions, DecConversionOptions */ static String ToSexagesimal( int sign, double s1, double s2, double s3, const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ); /*! * Returns a sexagesimal ASCII representation of the specified decimal value * \a d, generated with the specified conversion \a options. * * Calling this member function is equivalent to: * * \code ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); \endcode * * \ingroup sexagesimal_conversion */ static String ToSexagesimal( double d, const SexagesimalConversionOptions& options = SexagesimalConversionOptions() ) { return ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options ); } /*! * Evaluates this string as a date and time specification in ISO 8601 * extended format, and stores the resulting components in the specified * variables. * * \param year On output, the year of the date. * * \param month On output, the month of the date in the range [1,12]. * * \param day On output, the day of the date in the range [1,31]. * * \param dayf On output, the day fraction corresponding to the time * specification, in the range [0,1). * * \param tz On output, the time zone offset in hours, in the range * [-12,+12]. * * In ISO 8601 extended representations, decimal fractions must be divided * from integer parts exclusively by the full stop or dot character ('.', * ASCII code point 46(10) = 2E(16)). * * \sa TryParseISO8601DateTime(), TimePoint::FromString() */ void ParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const; /*! * Attempts to evaluate this string as a date and time specification in ISO * 8601 extended format. If successful, stores the resulting components in * the specified \a year, \a month, \a day and \a dayf and \a tz variables, * and returns \c true. For more information on syntax and * output values and ranges, see the ParseISO8601DateTime(). * * If this string cannot be evaluated as a valid date and time in ISO 8601 * format, this function returns \c false and does not change any of the * passed variables. This function does not throw any exception. * * \sa ParseISO8601DateTime(), TimePoint::TryFromString() */ bool TryParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const noexcept; /*! * Returns a string representation of a date and time in ISO 8601 extended * format. * * \param year The year of the date. * * \param month The month of the date in the range [1,12]. * * \param day The day of the date in the range [1,31]. * * \param dayf The day fraction corresponding to the time specification, * in the range [0,1). * * \param tz The time zone offset in hours, in the range [-12,+12]. The * default value is zero, to be interpreted as UTC. * * \param options Optional settings to control the representation of date * and time in ISO 8601 format. * * \sa CurrentUTCISO8601DateTime(), CurrentLocalISO8601DateTime(), * ParseISO8601DateTime(), ISO8601ConversionOptions, * TimePoint::ToString() */ static String ToISO8601DateTime( int year, int month, int day, double dayf, double tz = 0, const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); /*! * Returns an ASCII representation of the current UTC date and time in ISO * 8601 extended format. * * \param options Optional settings to control the representation of date * and time in ISO 8601 format. * * \sa CurrentLocalISO8601DateTime(), ToISO8601DateTime(), * ISO8601ConversionOptions, TimePoint::Now() */ static String CurrentUTCISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); /*! * Returns an ASCII representation of the current local date and time in ISO * 8601 extended format. * * \param options Optional settings to control the representation of date * and time in ISO 8601 format. * * \sa CurrentUTCISO8601DateTime(), ToISO8601DateTime(), * ISO8601ConversionOptions */ static String CurrentLocalISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() ); /*! * Generates a string of \a n random 16-bit code points, with character * types and ranges as prescribed by the specified \a options. * * \sa RandomizationOption */ static String Random( size_type n, RandomizationOptions options = RandomizationOption::Default ); /*! * Generates a universally unique identifier (UUID) in canonical form. * * The canonical UUID has 36 characters with the following format: * * xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx * * where 'x' represents a lowercase hexadecimal digit, '4' is the UUID * version indicator (version 4 = truly random UUID), and 'y' is one of '8', * '9', 'a', or 'b'. */ static String UUID(); }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- inline IsoString::IsoString( const_c_ustring t, size_type p, size_type n ) { size_type len = uchar_traits::Length( t ); if ( p < len ) { m_data->Allocate( n = pcl::Min( n, len-p ) ); t += p; for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) *i = char_type( uint8( *t ) ); } } inline IsoString& IsoString::operator =( const_c_ustring t ) { size_type len = uchar_traits::Length( t ); if ( len > 0 ) { MaybeReallocate( len ); for ( iterator i = m_data->string; i < m_data->end; ++i, ++t ) *i = char_type( uint8( *t ) ); } else Clear(); return *this; } inline IsoString::ustring_base IsoString::UTF8ToUTF16( size_type i, size_type n ) const { return String::UTF8ToUTF16( Begin(), i, n ); } // ---------------------------------------------------------------------------- /*! * \defgroup string_concatenation_ops String Concatenation Operators */ /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * and \a s2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, const String::string_base& s2 ) { String s = s1; s.Append( s2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * (rvalue reference) and \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, const String::string_base& s2 ) { s1.Append( s2 ); return String( std::move( s1 ) ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * (rvalue reference) and \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, const String::string_base& s2 ) { s1.Append( s2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * and \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, String::string_base&& s2 ) { s2.Prepend( s1 ); return String( std::move( s2 ) ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * and \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, String&& s2 ) { s2.Prepend( s1 ); return std::move( s2 ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * (rvalue reference) and \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, String::string_base&& s2 ) { s1.Append( s2 ); return String( std::move( s1 ) ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * (rvalue reference) and \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, String::string_base&& s2 ) { s1.Append( s2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * (rvalue reference) and \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, String&& s2 ) { s1.Append( s2 ); return String( std::move( s1 ) ); } /*! * Returns a UTF-16 string with the concatenation of two UTF-16 strings \a s1 * (rvalue reference) and \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, String&& s2 ) { s1.Append( s2 ); return std::move( s1 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a null-terminated UTF-16 string \a t2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, String::const_iterator t2 ) { String s = s1; s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated UTF-16 string \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, String::const_iterator t2 ) { s1.Append( t2 ); return String( std::move( s1 ) ); } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated UTF-16 string \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, String::const_iterator t2 ) { s1.Append( t2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a null-terminated UTF-16 * string \a t1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String::const_iterator t1, const String::string_base& s2 ) { String s = s2; s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated UTF-16 * string \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::const_iterator t1, String::string_base&& s2 ) { s2.Prepend( t1 ); return String( std::move( s2 ) ); } /*! * Returns a UTF-16 string with the concatenation of a null-terminated UTF-16 * string \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::const_iterator t1, String&& s2 ) { s2.Prepend( t1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a single UTF-16 character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, String::char_type c2 ) { String s = s1; s.Append( c2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single UTF-16 character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, String::char_type c2 ) { s1.Append( c2 ); return String( std::move( s1 ) ); } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single UTF-16 character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, String::char_type c2 ) { s1.Append( c2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a single UTF-16 character * \a c1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String::char_type c1, const String::string_base& s2 ) { String s = s2; s.Prepend( c1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a single UTF-16 character * \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::char_type c1, String::string_base&& s2 ) { s2.Prepend( c1 ); return String( std::move( s2 ) ); } /*! * Returns a UTF-16 string with the concatenation of a single UTF-16 character * \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::char_type c1, String&& s2 ) { s2.Prepend( c1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a null-terminated string of \c char16_t \a t2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, const char16_t* t2 ) { String s = s1; s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated string of \c char16_t \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, const char16_t* t2 ) { String s = std::move( s1 ); s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated string of \c char16_t \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, const char16_t* t2 ) { s1.Append( t2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a null-terminated string * of \c char16_t \a t1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( const char16_t* t1, const String::string_base& s2 ) { String s = s2; s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated string * of \c char16_t \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const char16_t* t1, String::string_base&& s2 ) { String s = std::move( s2 ); s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated string * of \c char16_t \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const char16_t* t1, String&& s2 ) { s2.Prepend( t1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a single \c char16_t character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, char16_t c2 ) { String s = s1; s.Append( c2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single \c char16_t character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, char16_t c2 ) { String s = std::move( s1 ); s.Append( c2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single \c char16_t character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, char16_t c2 ) { s1.Append( c2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a single \c char16_t * character \a c1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( char16_t c1, const String::string_base& s2 ) { String s = s2; s.Prepend( c1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a single \c char16_t * character \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( char16_t c1, String::string_base&& s2 ) { String s = std::move( s2 ); s.Prepend( c1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a single \c char16_t * character \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( char16_t c1, String&& s2 ) { s2.Prepend( c1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a null-terminated string of \c wchar_t \a t2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, const wchar_t* t2 ) { String s = s1; s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated string of \c wchar_t \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, const wchar_t* t2 ) { String s = std::move( s1 ); s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated string of \c wchar_t \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, const wchar_t* t2 ) { s1.Append( t2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a null-terminated string * of \c wchar_t \a t1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( const wchar_t* t1, const String::string_base& s2 ) { String s = s2; s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated string * of \c wchar_t \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const wchar_t* t1, String::string_base&& s2 ) { String s = std::move( s2 ); s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated string * of \c wchar_t \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const wchar_t* t1, String&& s2 ) { s2.Prepend( t1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a single \c wchar_t character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, wchar_t c2 ) { String s = s1; s.Append( c2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single \c wchar_t character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, wchar_t c2 ) { String s = std::move( s1 ); s.Append( c2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single \c wchar_t character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, wchar_t c2 ) { s1.Append( c2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a single \c wchar_t * character \a c1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( wchar_t c1, const String::string_base& s2 ) { String s = s2; s.Prepend( c1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a single \c wchar_t * character \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( wchar_t c1, String::string_base&& s2 ) { String s = std::move( s2 ); s.Prepend( c1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a single \c wchar_t * character \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( wchar_t c1, String&& s2 ) { s2.Prepend( c1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * an 8-bit string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, const String::string8_base& s2 ) { String s = s1; s.Append( s2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and an 8-bit string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, const String::string8_base& s2 ) { String s = std::move( s1 ); s.Append( s2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and an 8-bit string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, const String::string8_base& s2 ) { s1.Append( s2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of an 8-bit string \a s1 and * a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string8_base& s1, const String::string_base& s2 ) { String s = s2; s.Prepend( s1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of an 8-bit string \a s1 and * a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const String::string8_base& s1, String::string_base&& s2 ) { String s = std::move( s2 ); s.Prepend( s1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of an 8-bit string \a s1 and * a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( const String::string8_base& s1, String&& s2 ) { s2.Prepend( s1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a null-terminated 8-bit string \a t2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, String::const_c_string8 t2 ) { String s = s1; s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated 8-bit string \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, String::const_c_string8 t2 ) { String s = std::move( s1 ); s.Append( t2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a null-terminated 8-bit string \a t2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, String::const_c_string8 t2 ) { s1.Append( t2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a null-terminated 8-bit * string \a t1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String::const_c_string8 t1, const String::string_base& s2 ) { String s = s2; s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated 8-bit * string \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::const_c_string8 t1, String::string_base&& s2 ) { String s = std::move( s2 ); s.Prepend( t1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a null-terminated 8-bit * string \a t1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::const_c_string8 t1, String&& s2 ) { s2.Prepend( t1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 and * a single 8-bit character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( const String::string_base& s1, String::char8_type c2 ) { String s = s1; s.Append( c2 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single 8-bit character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String::string_base&& s1, String::char8_type c2 ) { s1.Append( String::char_type( c2 ) ); return String( std::move( s1 ) ); } /*! * Returns a UTF-16 string with the concatenation of a UTF-16 string \a s1 * (rvalue reference) and a single 8-bit character \a c2. * \ingroup string_concatenation_ops */ inline String operator +( String&& s1, String::char8_type c2 ) { s1.Append( c2 ); return std::move( s1 ); } /*! * Returns a UTF-16 string with the concatenation of a single 8-bit character * \a c1 and a UTF-16 string \a s2. * \ingroup string_concatenation_ops */ inline String operator +( String::char8_type c1, const String::string_base& s2 ) { String s = s2; s.Prepend( c1 ); return s; } /*! * Returns a UTF-16 string with the concatenation of a single 8-bit character * \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::char8_type c1, String::string_base&& s2 ) { s2.Prepend( String::char_type( c1 ) ); return String( std::move( s2 ) ); } /*! * Returns a UTF-16 string with the concatenation of a single 8-bit character * \a c1 and a UTF-16 string \a s2 (rvalue reference). * \ingroup string_concatenation_ops */ inline String operator +( String::char8_type c1, String&& s2 ) { s2.Prepend( c1 ); return std::move( s2 ); } // ---------------------------------------------------------------------------- /*! * Appends a UTF-16 string \a s2 to a UTF-16 string \a s1. Returns a reference * to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, const String::string_base& s2 ) { s1.Append( s2 ); return s1; } /*! * Appends a UTF-16 string \a s2 to a UTF-16 string \a s1. Returns a reference * to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, const String::string_base& s2 ) { s1.Append( s2 ); return s1; } /*! * Appends a null-terminated UTF-16 string \a t2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, String::const_iterator& t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a null-terminated UTF-16 string \a t2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, String::const_iterator& t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a single UTF-16 character \a c2 to a UTF-16 string \a s1. Returns a * reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, String::char_type c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a single UTF-16 character \a c2 to a UTF-16 string \a s1. Returns a * reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, String::char_type c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a null-terminated string \a t2 of \c char16_t to a UTF-16 string * \a s1. Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, const char16_t* t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a null-terminated string \a t2 of \c char16_t to a UTF-16 string * \a s1. Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, const char16_t* t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a single \c char16_t character \a c2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, char16_t c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a single \c char16_t character \a c2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, char16_t c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a null-terminated string \a t2 of \c wchar_t to a UTF-16 string * \a s1. Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, const wchar_t* t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a null-terminated string \a t2 of \c wchar_t to a UTF-16 string * \a s1. Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, const wchar_t* t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a single \c wchar_t character \a c2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, wchar_t c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a single \c wchar_t character \a c2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, wchar_t c2 ) { s1.Append( c2 ); return s1; } /*! * Appends an 8-bit string \a s2 to a UTF-16 string \a s1. Returns a reference * to the left-hand operand Unicode string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, const String::string8_base& s2 ) { s1.Append( s2 ); return s1; } /*! * Appends an 8-bit string \a s2 to a UTF-16 string \a s1. Returns a reference * to the left-hand operand Unicode string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, const String::string8_base& s2 ) { s1.Append( s2 ); return s1; } /*! * Appends a null-terminated 8-bit string \a t2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand Unicode string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, String::const_c_string8 t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a null-terminated 8-bit string \a t2 to a UTF-16 string \a s1. * Returns a reference to the left-hand operand Unicode string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, String::const_c_string8 t2 ) { s1.Append( t2 ); return s1; } /*! * Appends a single 8-bit character \a c2 to a UTF-16 string \a s1. Returns a * reference to the left-hand operand Unicode string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String& s1, String::char8_type c2 ) { s1.Append( c2 ); return s1; } /*! * Appends a single 8-bit character \a c2 to a UTF-16 string \a s1. Returns a * reference to the left-hand operand Unicode string \a s1. * \ingroup string_concatenation_ops */ inline String& operator <<( String&& s1, String::char8_type c2 ) { s1.Append( c2 ); return s1; } // ---------------------------------------------------------------------------- /*! * \defgroup string_relational_ops String Relational Operators */ /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const String& s1, const char16_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const String& s1, const char16_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) < 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const String& s1, const char16_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) <= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const String& s1, const char16_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) > 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const String& s1, const char16_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const char16_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const char16_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) > 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const char16_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) >= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const char16_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) < 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const char16_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const String& s1, char16_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const String& s1, char16_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) < 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const String& s1, char16_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) <= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const String& s1, char16_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) > 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const String& s1, char16_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( char16_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( char16_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) > 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( char16_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) >= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( char16_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) < 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( char16_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const String& s1, const wchar_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const String& s1, const wchar_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) < 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const String& s1, const wchar_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) <= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const String& s1, const wchar_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) > 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const String& s1, const wchar_t* t2 ) noexcept { return s1.CompareCodePoints( t2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const wchar_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const wchar_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) > 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const wchar_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) >= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const wchar_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) < 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const wchar_t* t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const String& s1, wchar_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const String& s1, wchar_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) < 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const String& s1, wchar_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) <= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const String& s1, wchar_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) > 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const String& s1, wchar_t c2 ) noexcept { return s1.CompareCodePoints( c2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( wchar_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( wchar_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) > 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( wchar_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) >= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( wchar_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) < 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( wchar_t c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const String& s1, String::const_c_string8 t2 ) noexcept { return s1.CompareCodePoints( t2 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const String& s1, String::const_c_string8 t2 ) noexcept { return s1.CompareCodePoints( t2 ) < 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const String& s1, String::const_c_string8 t2 ) noexcept { return s1.CompareCodePoints( t2 ) <= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const String& s1, String::const_c_string8 t2 ) noexcept { return s1.CompareCodePoints( t2 ) > 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const String& s1, String::const_c_string8 t2 ) noexcept { return s1.CompareCodePoints( t2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( String::const_c_string8 t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( String::const_c_string8 t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) > 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( String::const_c_string8 t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) >= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( String::const_c_string8 t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) < 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( String::const_c_string8 t1, const String& s2 ) noexcept { return s2.CompareCodePoints( t1 ) <= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( const String& s1, String::char8_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( const String& s1, String::char8_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) < 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( const String& s1, String::char8_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) <= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( const String& s1, String::char8_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) > 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( const String& s1, String::char8_type c2 ) noexcept { return s1.CompareCodePoints( c2 ) >= 0; } // ---------------------------------------------------------------------------- /*! * Equality operator. * \ingroup string_relational_ops */ inline bool operator ==( String::char8_type c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) == 0; } /*! * Less than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <( String::char8_type c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) > 0; } /*! * Less than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator <=( String::char8_type c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) >= 0; } /*! * Greater than operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >( String::char8_type c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) < 0; } /*! * Greater than or equal operator. This function performs a * character-to-character, locale-unaware comparison of numeric character * values. See GenericString<>::CompareCodePoints() for more information. * \ingroup string_relational_ops */ inline bool operator >=( String::char8_type c1, const String& s2 ) noexcept { return s2.CompareCodePoints( c1 ) <= 0; } // ---------------------------------------------------------------------------- #ifndef __PCL_NO_STRING_OSTREAM inline std::wostream& operator <<( std::wostream& o, const String& s ) { #ifdef __PCL_WINDOWS return o << reinterpret_cast( s.c_str() ); #else Array w = s.ToWCharArray(); return o << w.Begin(); #endif } inline std::ostream& operator <<( std::ostream& o, const String& s ) { return o << s.ToUTF8(); } #endif // __PCL_NO_STRING_OSTREAM // ---------------------------------------------------------------------------- } // pcl #endif // __PCL_String_h // ---------------------------------------------------------------------------- // EOF pcl/String.h - Released 2022-03-12T18:59:29Z