PCL
String.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.4.9
6 // ----------------------------------------------------------------------------
7 // pcl/String.h - Released 2021-04-09T19:40:59Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2021 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_String_h
53 #define __PCL_String_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
60 #include <pcl/Allocator.h>
61 #include <pcl/Atomic.h>
62 #include <pcl/ByteArray.h>
63 #include <pcl/CharTraits.h>
64 #include <pcl/Container.h>
65 #include <pcl/Flags.h>
66 #include <pcl/Iterator.h>
67 #include <pcl/Math.h>
68 #include <pcl/ReferenceCounter.h>
69 #include <pcl/Sort.h>
70 #include <pcl/Utility.h>
71 
72 #include <stdarg.h>
73 
74 #ifdef __PCL_ALIGNED_STRING_ALLOCATION
75 # include <pcl/AlignedAllocator.h>
76 # define PCL_STRING_ALLOCATOR AlignedAllocator
77 #else
78 # include <pcl/StandardAllocator.h>
79 # define PCL_STRING_ALLOCATOR StandardAllocator
80 #endif
81 
82 #ifndef __PCL_NO_STRING_COMPLEX
83 # include <pcl/Complex.h>
84 #endif
85 
86 #ifndef __PCL_NO_STRING_OSTREAM
87 # ifndef _MSC_VER
88 # define _GLIBCXX_USE_WCHAR_T 1
89 # endif
90 # include <ostream>
91 #endif
92 
93 #ifdef __PCL_QT_INTERFACE
94 # include <QtCore/QByteArray>
95 # include <QtCore/QDateTime>
96 # include <QtCore/QString>
97 # define PCL_GET_CHARPTR_FROM_QSTRING( qs ) (qs.toLatin1().data())
98 # define PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ((char16_type*)( qs.utf16() ))
99 # define PCL_GET_QSTRING_FROM_CHAR16PTR( s ) (QString::fromUtf16( (const ushort*)(s) ))
100 # define PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) (qb.data())
101 # define PCL_QDATE_FMT_STR "yyyy/MM/dd"
102 # define PCL_QDATETIME_FMT_STR "yyyy/MM/dd hh:mm:ss"
103 #endif
104 
105 namespace pcl
106 {
107 
108 // ----------------------------------------------------------------------------
109 
126 namespace RandomizationOption
127 {
128  enum mask_type
129  {
130  Lowercase = 0x00000001, // Generate random lowercase alphabetic characters: a..z
131  Uppercase = 0x00000002, // Generate random uppercase alphabetic characters: A..Z
132  Alpha = Lowercase|Uppercase, // Generate random alphabetic characters: a..zA..Z
133  Digits = 0x00000004, // Generate random decimal digits: 0..9
134  Symbols = 0x00000008, // Generate random symbol characters: .#/[]() etc
135  HexDigits = 0x00000010, // Generate hexadecimal digits: 0..9a..f or 0..9A..F
136  BinDigits = 0x00000020, // Generate binary digits: 0 and 1
137  FullRange = 0x80000000, // Generate random characters in the whole range of code points except zero
138  Default = Alpha|Digits
139  };
140 };
141 
147 
148 // ----------------------------------------------------------------------------
149 
164 {
171  unsigned items : 2;
172 
177  unsigned precision : 4;
178 
183  bool sign : 1;
184 
192  unsigned width : 4;
193 
198  char separator;
199 
205  char padding;
206 
210  constexpr SexagesimalConversionOptions( unsigned items_ = 3,
211  unsigned precision_ = 2,
212  bool sign_ = false,
213  unsigned width_ = 0,
214  char separator_ = ':',
215  char padding_ = ' ' )
216  : items( items_ )
217  , precision( precision_ )
218  , sign( sign_ )
219  , width( width_ )
220  , separator( separator_ )
221  , padding( padding_ )
222  {
223  }
224 
229 
233  SexagesimalConversionOptions& operator =( const SexagesimalConversionOptions& ) = default;
234 };
235 
236 // ----------------------------------------------------------------------------
237 
251 {
259  constexpr AngleConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' )
260  : SexagesimalConversionOptions( 3/*items*/, precision, false/*sign*/, width, ' '/*separator*/, padding )
261  {}
262 };
263 
264 // ----------------------------------------------------------------------------
265 
280 {
289  constexpr LongitudeConversionOptions( unsigned precision = 2, unsigned width = 4, char padding = ' ' )
290  : SexagesimalConversionOptions( 3/*items*/, precision, true/*sign*/, width, ' '/*separator*/, padding )
291  {}
292 };
293 
294 // ----------------------------------------------------------------------------
295 
311 {
319  constexpr RAConversionOptions( unsigned precision = 3, unsigned width = 2, char padding = ' ' )
320  : SexagesimalConversionOptions( 3/*items*/, precision, false/*sign*/, width, ' '/*separator*/, padding )
321  {}
322 };
323 
324 // ----------------------------------------------------------------------------
325 
340 {
349  constexpr LatitudeConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' )
350  : SexagesimalConversionOptions( 3/*items*/, precision, true/*sign*/, width, ' '/*separator*/, padding )
351  {}
352 };
353 
354 // ----------------------------------------------------------------------------
355 
369 {
378  constexpr DecConversionOptions( unsigned precision = 2, unsigned width = 3, char padding = ' ' )
379  : LatitudeConversionOptions( precision, width, padding )
380  {}
381 };
382 
383 // ----------------------------------------------------------------------------
384 
392 struct PCL_CLASS ISO8601ConversionOptions
393 {
400  unsigned timeItems : 2;
401 
406  unsigned precision : 4;
407 
412  bool timeZone : 1;
413 
418  bool zuluTime : 1;
419 
423  constexpr ISO8601ConversionOptions( unsigned timeItems_ = 3,
424  unsigned precision_ = 3,
425  bool timeZone_ = true,
426  bool zuluTime_ = true )
427  : timeItems( timeItems_ )
428  , precision( precision_ )
429  , timeZone( timeZone_ )
430  , zuluTime( zuluTime_ )
431  {
432  }
433 
438 
442  ISO8601ConversionOptions& operator =( const ISO8601ConversionOptions& ) = default;
443 };
444 
445 // ----------------------------------------------------------------------------
446 
466 template <class T, class R, class A = PCL_STRING_ALLOCATOR>
467 class PCL_CLASS GenericString : public DirectContainer<T>
468 {
469 public:
470 
474  typedef T char_type;
475 
479  typedef R char_traits;
480 
484  typedef A block_allocator;
485 
490 
494  typedef T* c_string;
495 
499  typedef const T* const_c_string;
500 
504  typedef T* iterator;
505 
509  typedef const T* const_iterator;
510 
516 
522 
523  // -------------------------------------------------------------------------
524 
528  static const size_type notFound = ~size_type( 0 );
529 
533  static const size_type maxPos = ~size_type( 0 );
534 
535  // -------------------------------------------------------------------------
536 
541  {
542  m_data = Data::New();
543  }
544 
549  : m_data( s.m_data )
550  {
551  m_data->Attach();
552  }
553 
558  : m_data( s.m_data )
559  {
560  s.m_data = nullptr;
561  }
562 
567  GenericString( const_c_string t )
568  {
569  size_type len = R::Length( t );
570  if ( len > 0 )
571  {
572  m_data = Data::New( len );
573  R::Copy( m_data->string, t, len );
574  }
575  else
576  m_data = Data::New();
577  }
578 
596  GenericString( const_iterator i, const_iterator j )
597  {
598  if ( i < j )
599  {
600  size_type len = j - i;
601  m_data = Data::New( len );
602  R::Copy( m_data->string, i, len );
603  }
604  else
605  m_data = Data::New();
606  }
607 
616  GenericString( std::initializer_list<char_type> l )
617  : GenericString( l.begin(), l.end() )
618  {
619  }
620 
625  GenericString( const_c_string t, size_type i, size_type n )
626  {
627  size_type len = R::Length( t );
628  if ( i < len && (n = pcl::Min( n, len-i )) > 0 )
629  {
630  m_data = Data::New( n );
631  R::Copy( m_data->string, t+i, n );
632  }
633  else
634  m_data = Data::New();
635  }
636 
640  GenericString( char_type c, size_type n = 1 )
641  {
642  if ( n > 0 )
643  {
644  m_data = Data::New( n );
645  R::Fill( m_data->string, c, n );
646  }
647  else
648  m_data = Data::New();
649  }
650 
656  {
657  if ( m_data != nullptr )
658  {
659  DetachFromData();
660  m_data = nullptr;
661  }
662  }
663 
669  bool IsUnique() const noexcept
670  {
671  return m_data->IsUnique();
672  }
673 
681  bool IsAliasOf( const GenericString& s ) const noexcept
682  {
683  return m_data == s.m_data;
684  }
685 
696  {
697  if ( !IsUnique() )
698  {
699  size_type len = Length();
700  Data* newData = Data::New( len );
701  if ( len > 0 )
702  R::Copy( newData->string, m_data->string, len );
703  DetachFromData();
704  m_data = newData;
705  }
706  }
707 
715  static size_type BytesPerChar() noexcept
716  {
717  return R::BytesPerChar();
718  }
719 
726  size_type Size() const noexcept
727  {
728  return Length()*BytesPerChar();
729  }
730 
737  size_type Length() const noexcept
738  {
739  return m_data->end - m_data->string;
740  }
741 
750  size_type Capacity() const noexcept
751  {
752  return m_data->capacity - m_data->string;
753  }
754 
762  size_type Available() const noexcept
763  {
764  return m_data->capacity - m_data->end;
765  }
766 
783  bool IsValid() const noexcept
784  {
785  return m_data != nullptr;
786  }
787 
795  bool IsEmpty() const noexcept
796  {
797  return m_data->string == m_data->end;
798  }
799 
808  size_type LowerBound() const noexcept
809  {
810  return 0;
811  }
812 
821  size_type UpperBound() const noexcept
822  {
823  PCL_PRECONDITION( !IsEmpty() )
824  return Length()-1;
825  }
826 
832  const allocator& Allocator() const noexcept
833  {
834  return m_data->alloc;
835  }
836 
846  void SetAllocator( const allocator& a )
847  {
848  EnsureUnique();
849  m_data->alloc = a;
850  }
851 
864  iterator At( size_type i )
865  {
866  PCL_PRECONDITION( i < Length() )
867  EnsureUnique();
868  return m_data->string + i;
869  }
870 
880  const_iterator At( size_type i ) const noexcept
881  {
882  PCL_PRECONDITION( i < Length() )
883  return m_data->string + i;
884  }
885 
898  char_type& operator []( size_type i )
899  {
900  return *At( i );
901  }
902 
912  char_type operator []( size_type i ) const noexcept
913  {
914  return *At( i );
915  }
916 
924  char_type& operator *()
925  {
926  EnsureUnique();
927  return *m_data->string;
928  }
929 
937  char_type operator *() const noexcept
938  {
939  return *m_data->string;
940  }
941 
953  iterator Begin()
954  {
955  EnsureUnique();
956  return m_data->string;
957  }
958 
967  const_iterator Begin() const noexcept
968  {
969  return m_data->string;
970  }
971 
983  iterator End()
984  {
985  EnsureUnique();
986  return m_data->end;
987  }
988 
997  const_iterator End() const noexcept
998  {
999  return m_data->end;
1000  }
1001 
1016  {
1017  EnsureUnique();
1018  return (m_data->string < m_data->end) ? m_data->end-1 : nullptr;
1019  }
1020 
1032  {
1033  return (m_data->string < m_data->end) ? m_data->end-1 : nullptr;
1034  }
1035 
1050  {
1051  EnsureUnique();
1052  return (m_data->string < m_data->end) ? m_data->string-1 : nullptr;
1053  }
1054 
1066  {
1067  return (m_data->string < m_data->end) ? m_data->string-1 : nullptr;
1068  }
1069 
1080  size_type IndexAt( const_iterator i ) const noexcept
1081  {
1082  PCL_PRECONDITION( i >= m_data->string )
1083  return i - m_data->string;
1084  }
1085 
1086 #ifndef __PCL_NO_STL_COMPATIBLE_ITERATORS
1087 
1090  iterator begin()
1091  {
1092  return Begin();
1093  }
1094 
1098  const_iterator begin() const noexcept
1099  {
1100  return Begin();
1101  }
1102 
1106  iterator end()
1107  {
1108  return End();
1109  }
1110 
1114  const_iterator end() const noexcept
1115  {
1116  return End();
1117  }
1118 #endif // !__PCL_NO_STL_COMPATIBLE_ITERATORS
1119 
1127  const_c_string c_str() const noexcept
1128  {
1129  static const char_type theNullChar = char_traits::Null();
1130  return IsEmpty() ? &theNullChar : Begin();
1131  }
1132 
1138  GenericString& operator =( const GenericString& s )
1139  {
1140  Assign( s );
1141  return *this;
1142  }
1143 
1158  void Assign( const GenericString& s )
1159  {
1160  s.m_data->Attach();
1161  DetachFromData();
1162  m_data = s.m_data;
1163  }
1164 
1170  GenericString& operator =( GenericString&& s )
1171  {
1172  Transfer( s );
1173  return *this;
1174  }
1175 
1190  {
1191  DetachFromData();
1192  m_data = s.m_data;
1193  s.m_data = nullptr;
1194  }
1195 
1202  {
1203  DetachFromData();
1204  m_data = s.m_data;
1205  s.m_data = nullptr;
1206  }
1207 
1212  GenericString& operator =( const_c_string t )
1213  {
1214  Assign( t );
1215  return *this;
1216  }
1217 
1222  GenericString& operator =( char_type c )
1223  {
1224  Assign( c, 1 );
1225  return *this;
1226  }
1227 
1232  void Assign( const GenericString& s, size_type i, size_type n )
1233  {
1234  Transfer( s.Substring( i, n ) );
1235  }
1236 
1244  void Assign( const_c_string t )
1245  {
1246  size_type len = R::Length( t );
1247  if ( len > 0 )
1248  {
1249  MaybeReallocate( len );
1250  R::Copy( m_data->string, t, len );
1251  }
1252  else
1253  Clear();
1254  }
1255 
1276  void Assign( const_iterator i, const_iterator j )
1277  {
1278  if ( i < j )
1279  {
1280  size_type len = j - i;
1281  MaybeReallocate( len );
1282  R::Copy( m_data->string, i, len );
1283  }
1284  else
1285  Clear();
1286  }
1287 
1294  void Assign( std::initializer_list<char_type> l )
1295  {
1296  Assign( l.begin(), l.end() );
1297  }
1298 
1312  void Assign( const_c_string t, size_type i, size_type n )
1313  {
1314  size_type len = R::Length( t );
1315  if ( i < len && (n = pcl::Min( n, len-i )) > 0 )
1316  {
1317  MaybeReallocate( n );
1318  R::Copy( m_data->string, t+i, n );
1319  }
1320  else
1321  Clear();
1322  }
1323 
1329  void Assign( char_type c, size_type n = 1 )
1330  {
1331  if ( !R::IsNull( c ) && n > 0 )
1332  {
1333  MaybeReallocate( n );
1334  R::Fill( m_data->string, c, n );
1335  }
1336  else
1337  Clear();
1338  }
1339 
1343  void Swap( GenericString& s ) noexcept
1344  {
1345  pcl::Swap( m_data, s.m_data );
1346  }
1347 
1357  void Fill( char_type c )
1358  {
1359  size_type len = Length();
1360  if ( len > 0 )
1361  {
1362  if ( !IsUnique() )
1363  {
1364  Data* newData = Data::New( len );
1365  DetachFromData();
1366  m_data = newData;
1367  }
1368  R::Fill( m_data->string, c, len );
1369  }
1370  }
1371 
1386  void Fill( char_type c, size_type i, size_type n = maxPos )
1387  {
1388  size_type len = Length();
1389  if ( i < len )
1390  {
1391  n = pcl::Min( n, len-i );
1392  if ( n < len )
1393  EnsureUnique();
1394  else if ( !IsUnique() )
1395  {
1396  Data* newData = Data::New( len );
1397  DetachFromData();
1398  m_data = newData;
1399  }
1400  R::Fill( m_data->string+i, c, n );
1401  }
1402  }
1403 
1425  void SecureFill( char c = '\0' ) noexcept
1426  {
1427  volatile char* s = reinterpret_cast<volatile char*>( m_data->string );
1428  for ( size_type n = Capacity()*sizeof( char_type ); n > 0; --n )
1429  *s++ = c;
1430  }
1431 
1439  void Reserve( size_type n )
1440  {
1441  if ( n > 0 )
1442  if ( IsUnique() )
1443  {
1444  if ( Capacity() < n+1 )
1445  {
1446  iterator old = m_data->string;
1447  size_type len = Length();
1448  m_data->Reserve( len, n );
1449  if ( old != nullptr )
1450  {
1451  if ( len > 0 )
1452  R::Copy( m_data->string, old, len );
1453  m_data->alloc.Deallocate( old );
1454  }
1455  }
1456  }
1457  else
1458  {
1459  size_type len = Length();
1460  Data* newData = Data::New(); // ### FIXME: unlikely, but this is a potential leak
1461  newData->Reserve( len, pcl::Max( len, n ) );
1462  if ( len > 0 )
1463  R::Copy( newData->string, m_data->string, len );
1464  DetachFromData();
1465  m_data = newData;
1466  }
1467  }
1468 
1483  {
1484  if ( n != Length() )
1485  {
1486  if ( n > 0 )
1487  {
1488  if ( !IsUnique() || m_data->ShouldReallocate( n ) )
1489  {
1490  Data* newData = Data::New( n );
1491  size_type m = Capacity();
1492  if ( m > 0 )
1493  R::Copy( newData->string, m_data->string, pcl::Min( n, m ) );
1494  DetachFromData();
1495  m_data = newData;
1496  }
1497  else
1498  m_data->SetLength( n );
1499  }
1500  else
1501  Clear();
1502  }
1503  else
1504  EnsureUnique();
1505  }
1506 
1513  {
1514  // NB: This can be done more efficiently if this string is unique.
1515  GenericString s( *this );
1516  s.SetLength( n );
1517  return s;
1518  }
1519 
1529  {
1530  SetLength( R::Length( m_data->string ) );
1531  }
1532 
1538  {
1539  GenericString s( *this );
1541  return s;
1542  }
1543 
1556  void Squeeze()
1557  {
1558  if ( Available() > 0 )
1559  {
1560  size_type len = Length();
1561  if ( len > 0 )
1562  {
1563  if ( IsUnique() )
1564  {
1565  iterator old = m_data->string;
1566  m_data->Allocate( len, 0 );
1567  R::Copy( m_data->string, old, len );
1568  m_data->alloc.Deallocate( old );
1569  }
1570  else
1571  {
1572  Data* newData = Data::New( len, 0 );
1573  R::Copy( newData->string, m_data->string, len );
1574  DetachFromData();
1575  m_data = newData;
1576  }
1577  }
1578  else
1579  Clear();
1580  }
1581  }
1582 
1588  {
1589  // NB: This can be done more efficiently if this string is unique.
1590  GenericString s( *this );
1591  s.Squeeze();
1592  return s;
1593  }
1594 
1607  c_string Release()
1608  {
1609  EnsureUnique();
1610  iterator string = m_data->string;
1611  m_data->Reset();
1612  return string;
1613  }
1614 
1631  void c_copy( iterator dst, size_type maxCharsToCopy, size_type i = 0 ) const noexcept
1632  {
1633  if ( dst != nullptr )
1634  if ( maxCharsToCopy > 0 )
1635  {
1636  if ( --maxCharsToCopy > 0 )
1637  {
1638  size_type len = Length();
1639  if ( i < len )
1640  {
1641  size_type n = pcl::Min( maxCharsToCopy, len-i );
1642  R::Copy( dst, m_data->string+i, n );
1643  dst += n;
1644  }
1645  }
1646 
1647  *dst = R::Null();
1648  }
1649  }
1650 
1654  template <class R1, class A1>
1656  {
1657  size_type n = s.Length();
1658  if ( n > 0 )
1659  {
1660  UninitializedGrow( i, n ); // -> 0 <= i <= len
1661  R::Copy( m_data->string+i, s.m_data->string, n );
1662  }
1663  }
1664 
1672  void Insert( size_type i, const_iterator p, const_iterator q )
1673  {
1674  if ( p < q )
1675  {
1676  size_type n = q - p;
1677  UninitializedGrow( i, n ); // -> 0 <= i <= len
1678  R::Copy( m_data->string+i, p, n );
1679  }
1680  }
1681 
1686  void Insert( size_type i, const_c_string t )
1687  {
1688  size_type n = R::Length( t );
1689  if ( n > 0 )
1690  {
1691  UninitializedGrow( i, n ); // -> 0 <= i <= len
1692  R::Copy( m_data->string+i, t, n );
1693  }
1694  }
1695 
1700  void Insert( size_type i, const_c_string t, size_type n )
1701  {
1702  if ( (n = pcl::Min( n, R::Length( t ) )) > 0 )
1703  {
1704  UninitializedGrow( i, n ); // -> 0 <= i <= len
1705  R::Copy( m_data->string+i, t, n );
1706  }
1707  }
1708 
1712  void Insert( size_type i, char_type c, size_type n = 1 )
1713  {
1714  if ( n > 0 )
1715  {
1716  UninitializedGrow( i, n ); // -> 0 <= i <= len
1717  R::Fill( m_data->string+i, c, n );
1718  }
1719  }
1720 
1724  template <class R1, class A1>
1726  {
1727  Insert( maxPos, s );
1728  }
1729 
1734  template <class R1, class A1>
1735  GenericString& operator +=( const GenericString<T,R1,A1>& s )
1736  {
1737  Append( s );
1738  return *this;
1739  }
1740 
1748  void Append( const_iterator i, const_iterator j )
1749  {
1750  Insert( maxPos, i, j );
1751  }
1752 
1757  void Append( const_c_string t, size_type n )
1758  {
1759  Insert( maxPos, t, n );
1760  }
1761 
1765  void Append( const_c_string t )
1766  {
1767  Insert( maxPos, t );
1768  }
1769 
1774  GenericString& operator +=( const_c_string t )
1775  {
1776  Append( t );
1777  return *this;
1778  }
1779 
1783  void Append( char_type c, size_type n = 1 )
1784  {
1785  Insert( maxPos, c, n );
1786  }
1787 
1792  template <class R1, class A1>
1793  void Add( const GenericString<T,R1,A1>& s )
1794  {
1795  Append( s );
1796  }
1797 
1802  void Add( const_iterator i, const_iterator j )
1803  {
1804  Append( i, j );
1805  }
1806 
1811  void Add( const_c_string t, size_type n )
1812  {
1813  Append( t, n );
1814  }
1815 
1820  void Add( const_c_string t )
1821  {
1822  Append( t );
1823  }
1824 
1829  void Add( char_type c, size_type n = 1 )
1830  {
1831  Append( c, n );
1832  }
1833 
1838  GenericString& operator +=( char_type c )
1839  {
1840  Append( c );
1841  return *this;
1842  }
1843 
1848  template <class R1, class A1>
1850  {
1851  Insert( 0, s );
1852  }
1853 
1858  template <class R1, class A1>
1859  GenericString& operator -=( const GenericString<T,R1,A1>& s )
1860  {
1861  Prepend( s );
1862  return *this;
1863  }
1864 
1872  void Prepend( const_iterator i, const_iterator j )
1873  {
1874  Insert( 0, i, j );
1875  }
1876 
1881  void Prepend( const_c_string t, size_type n )
1882  {
1883  Insert( 0, t, n );
1884  }
1885 
1890  void Prepend( const_c_string t )
1891  {
1892  Insert( 0, t );
1893  }
1894 
1899  GenericString& operator -=( const_c_string t )
1900  {
1901  Prepend( t );
1902  return *this;
1903  }
1904 
1908  void Prepend( char_type c, size_type n = 1 )
1909  {
1910  Insert( 0, c, n );
1911  }
1912 
1917  GenericString& operator -=( char_type c )
1918  {
1919  Prepend( c );
1920  return *this;
1921  }
1922 
1927  template <class R1, class A1>
1929  {
1930  if ( n > 0 )
1931  {
1932  size_type len = Length();
1933  if ( i < len )
1934  {
1935  n = pcl::Min( n, len-i );
1936  if ( n != len )
1937  {
1938  size_type ns = s.Length();
1939  if ( ns > 0 )
1940  {
1941  if ( n < ns )
1942  UninitializedGrow( i, ns-n );
1943  else if ( ns < n )
1944  Delete( i, n-ns );
1945  else
1946  EnsureUnique();
1947 
1948  R::Copy( m_data->string+i, s.m_data->string, ns );
1949  }
1950  else
1951  Delete( i, n );
1952  }
1953  else
1954  Assign( s );
1955  }
1956  }
1957  }
1958 
1967  void Replace( size_type i, size_type n, const_c_string t )
1968  {
1969  if ( n > 0 )
1970  {
1971  size_type len = Length();
1972  if ( i < len )
1973  {
1974  n = pcl::Min( n, len-i );
1975  if ( n != len )
1976  {
1977  size_type nt = R::Length( t );
1978  if ( nt > 0 )
1979  {
1980  if ( n < nt )
1981  UninitializedGrow( i, nt-n );
1982  else if ( nt < n )
1983  Delete( i, n-nt );
1984  else
1985  EnsureUnique();
1986 
1987  R::Copy( m_data->string+i, t, nt );
1988  }
1989  else
1990  Delete( i, n );
1991  }
1992  else
1993  Assign( t );
1994  }
1995  }
1996  }
1997 
2002  void Replace( size_type i, size_type n, char_type c, size_type nc = 1 )
2003  {
2004  if ( n > 0 )
2005  {
2006  size_type len = Length();
2007  if ( i < len )
2008  {
2009  n = pcl::Min( n, len-i );
2010  if ( n != len )
2011  {
2012  if ( nc > 0 )
2013  {
2014  if ( n < nc )
2015  UninitializedGrow( i, nc-n );
2016  else if ( nc < n )
2017  Delete( i, n-nc );
2018  else
2019  EnsureUnique();
2020 
2021  R::Fill( m_data->string+i, c, nc );
2022  }
2023  else
2024  Delete( i, n );
2025  }
2026  else
2027  Assign( c, nc );
2028  }
2029  }
2030  }
2031 
2037  void ReplaceChar( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos )
2038  {
2039  ReplaceChar( c1, c2, i, n, true/*case*/ );
2040  }
2041 
2049  void ReplaceCharIC( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos )
2050  {
2051  ReplaceChar( c1, c2, i, n, false/*case*/ );
2052  }
2053 
2059  template <class R1, class A1, class R2, class A2>
2061  const GenericString<T,R2,A2>& s2, size_type i = 0 )
2062  {
2063  ReplaceString( s1.m_data->string, s1.Length(), s2.m_data->string, s2.Length(), i, true/*case*/ );
2064  }
2065 
2071  void ReplaceString( const_c_string t1, const_c_string t2, size_type i = 0 )
2072  {
2073  ReplaceString( t1, R::Length( t1 ), t2, R::Length( t2 ), i, true/*case*/ );
2074  }
2075 
2083  template <class R1, class A1, class R2, class A2>
2085  const GenericString<T,R2,A2>& s2, size_type i = 0 )
2086  {
2087  ReplaceString( s1.m_data->string, s1.Length(), s2.m_data->string, s2.Length(), i, false/*case*/ );
2088  }
2089 
2097  void ReplaceStringIC( const_c_string t1, const_c_string t2, size_type i = 0 )
2098  {
2099  ReplaceString( t1, R::Length( t1 ), t2, R::Length( t2 ), i, false/*case*/ );
2100  }
2101 
2106  void Delete( size_type i, size_type n = 1 )
2107  {
2108  if ( n > 0 )
2109  {
2110  size_type len = Length();
2111  if ( i < len )
2112  {
2113  n = pcl::Min( n, len-i );
2114  if ( n < len )
2115  {
2116  size_type newLen = len-n;
2117  if ( !IsUnique() || m_data->ShouldReallocate( newLen ) )
2118  {
2119  Data* newData = Data::New( newLen );
2120  if ( i > 0 )
2121  R::Copy( newData->string, m_data->string, i );
2122  if ( i < newLen )
2123  R::Copy( newData->string+i, m_data->string+i+n, newLen-i );
2124  DetachFromData();
2125  m_data = newData;
2126  }
2127  else
2128  {
2129  if ( i < newLen )
2130  R::CopyOverlapped( m_data->string+i, m_data->string+i+n, newLen-i );
2131  m_data->SetLength( newLen );
2132  }
2133  }
2134  else
2135  Clear();
2136  }
2137  }
2138  }
2139 
2145  {
2146  Delete( i, maxPos );
2147  }
2148 
2154  {
2155  Delete( 0, i );
2156  }
2157 
2163  void DeleteChar( char_type c, size_type i = 0 )
2164  {
2165  ReplaceString( &c, 1, nullptr, 0, i, true/*case*/ );
2166  }
2167 
2175  void DeleteCharIC( char_type c, size_type i = 0 )
2176  {
2177  ReplaceString( &c, 1, nullptr, 0, i, false/*case*/ );
2178  }
2179 
2185  template <class R1, class A1>
2187  {
2188  ReplaceString( s.m_data->string, s.Length(), nullptr, 0, i, true/*case*/ );
2189  }
2190 
2196  void DeleteString( const_c_string t, size_type i = 0 )
2197  {
2198  ReplaceString( t, R::Length( t ), nullptr, 0, i, true/*case*/ );
2199  }
2200 
2208  template <class R1, class A1>
2210  {
2211  ReplaceString( s.m_data->string, s.Length(), nullptr, 0, i, false/*case*/ );
2212  }
2213 
2221  void DeleteStringIC( const_c_string t, size_type i = 0 )
2222  {
2223  ReplaceString( t, R::Length( t ), nullptr, 0, i, false/*case*/ );
2224  }
2225 
2235  void Clear()
2236  {
2237  if ( !IsEmpty() )
2238  if ( IsUnique() )
2239  m_data->Deallocate();
2240  else
2241  {
2242  Data* newData = Data::New();
2243  DetachFromData();
2244  m_data = newData;
2245  }
2246  }
2247 
2253  {
2254  size_type len = Length();
2255  if ( i < len )
2256  {
2257  n = pcl::Min( n, len-i );
2258  if ( n > 0 )
2259  {
2260  if ( n < len )
2261  {
2262  GenericString t;
2263  t.m_data->Allocate( n );
2264  R::Copy( t.m_data->string, m_data->string+i, n );
2265  return t;
2266  }
2267  return *this;
2268  }
2269  }
2270  return GenericString();
2271  }
2272 
2278  {
2279  size_type len = Length();
2280  n = pcl::Min( n, len );
2281  if ( n > 0 )
2282  {
2283  if ( n < len )
2284  {
2285  GenericString t;
2286  t.m_data->Allocate( n );
2287  R::Copy( t.m_data->string, m_data->string, n );
2288  return t;
2289  }
2290  return *this;
2291  }
2292  return GenericString();
2293  }
2294 
2300  {
2301  size_type len = Length();
2302  n = pcl::Min( n, len );
2303  if ( n > 0 )
2304  {
2305  if ( n < len )
2306  {
2307  GenericString t;
2308  t.m_data->Allocate( n );
2309  R::Copy( t.m_data->string, m_data->string+len-n, n );
2310  return t;
2311  }
2312  return *this;
2313  }
2314  return GenericString();
2315  }
2316 
2324  {
2325  return Substring( i );
2326  }
2327 
2335  {
2336  return Left( (i > 0) ? i-1 : 0 );
2337  }
2338 
2356  template <class C, class R1, class A1>
2357  size_type Break( C& list, const GenericString<T,R1,A1>& s, bool trim = false, size_type i = 0 ) const
2358  {
2359  size_type count = 0;
2360  size_type len = Length();
2361  if ( i < len )
2362  {
2363  size_type n = s.Length();
2364  if ( n > 0 )
2365  for ( SearchEngine S( s.m_data->string, n, true/*case*/ ); ; )
2366  {
2367  size_type j = S( m_data->string, i, len );
2368 
2369  GenericString t;
2370  if ( i < j )
2371  {
2372  const_iterator l = m_data->string + i;
2373  size_type m = j - i;
2374  if ( trim )
2375  {
2376  const_iterator r = l + m;
2377  l = R::SearchTrimLeft( l, r );
2378  m = R::SearchTrimRight( l, r ) - l;
2379  }
2380  if ( m > 0 )
2381  {
2382  t.m_data->Allocate( m );
2383  R::Copy( t.m_data->string, l, m );
2384  }
2385  }
2386  list.Add( t );
2387  ++count;
2388 
2389  if ( j == len )
2390  break;
2391 
2392  i = j + n;
2393  }
2394  }
2395  return count;
2396  }
2397 
2416  template <class C>
2417  size_type Break( C& list, const_c_string s, bool trim = false, size_type i = 0 ) const
2418  {
2419  size_type count = 0;
2420  size_type len = Length();
2421  if ( i < len )
2422  {
2423  size_type n = R::Length( s );
2424  if ( n > 0 )
2425  for ( SearchEngine S( s, n, true/*case*/ ); ; )
2426  {
2427  size_type j = S( m_data->string, i, len );
2428 
2429  GenericString t;
2430  if ( i < j )
2431  {
2432  const_iterator l = m_data->string + i;
2433  size_type m = j - i;
2434  if ( trim )
2435  {
2436  const_iterator r = l + m;
2437  l = R::SearchTrimLeft( l, r );
2438  m = R::SearchTrimRight( l, r ) - l;
2439  }
2440  if ( m > 0 )
2441  {
2442  t.m_data->Allocate( m );
2443  R::Copy( t.m_data->string, l, m );
2444  }
2445  }
2446  list.Add( t );
2447  ++count;
2448 
2449  if ( j == len )
2450  break;
2451 
2452  i = j + n;
2453  }
2454  }
2455  return count;
2456  }
2457 
2476  template <class C>
2477  size_type Break( C& list, char_type c, bool trim = false, size_type i = 0 ) const
2478  {
2479  size_type count = 0;
2480  size_type len = Length();
2481  if ( i < len )
2482  {
2483  for ( ;; )
2484  {
2485  size_type j = i;
2486  for ( const_iterator p = m_data->string + i; j < len; ++j, ++p )
2487  if ( *p == c )
2488  break;
2489 
2490  GenericString t;
2491  if ( i < j )
2492  {
2493  const_iterator l = m_data->string + i;
2494  size_type m = j - i;
2495  if ( trim )
2496  {
2497  const_iterator r = l + m;
2498  l = R::SearchTrimLeft( l, r );
2499  m = R::SearchTrimRight( l, r ) - l;
2500  }
2501  if ( m > 0 )
2502  {
2503  t.m_data->Allocate( m );
2504  R::Copy( t.m_data->string, l, m );
2505  }
2506  }
2507  list.Add( t );
2508  ++count;
2509 
2510  if ( j == len )
2511  break;
2512 
2513  i = j + 1;
2514  }
2515  }
2516  return count;
2517  }
2518 
2541  template <class C, typename S>
2542  size_type Break( C& list, const Array<S>& ca, bool trim = false, size_type i = 0 ) const
2543  {
2544  size_type count = 0;
2545  if ( !ca.IsEmpty() )
2546  {
2547  size_type len = Length();
2548  if ( i < len )
2549  {
2550  for ( ;; )
2551  {
2552  size_type j = i;
2553  for ( const_iterator p = m_data->string + i; j < len; ++j, ++p )
2554  for ( auto c : ca )
2555  if ( *p == char_type( c ) )
2556  goto __Break_1;
2557 __Break_1:
2558  GenericString t;
2559  if ( i < j )
2560  {
2561  const_iterator l = m_data->string + i;
2562  size_type m = j - i;
2563  if ( trim )
2564  {
2565  const_iterator r = l + m;
2566  l = R::SearchTrimLeft( l, r );
2567  m = R::SearchTrimRight( l, r ) - l;
2568  }
2569  if ( m > 0 )
2570  {
2571  t.m_data->Allocate( m );
2572  R::Copy( t.m_data->string, l, m );
2573  }
2574  }
2575  list.Add( t );
2576  ++count;
2577 
2578  if ( j == len )
2579  break;
2580 
2581  i = j + 1;
2582  }
2583  }
2584  }
2585  return count;
2586  }
2587 
2608  template <class C, class R1, class A1>
2609  size_type BreakIC( C& list, const GenericString<T,R1,A1>& s, bool trim = false, size_type i = 0 ) const
2610  {
2611  size_type count = 0;
2612  size_type len = Length();
2613  if ( i < len )
2614  {
2615  size_type n = s.Length();
2616  if ( n > 0 )
2617  {
2618  for ( SearchEngine S( s.m_data->string, n, false/*case*/ ); ; )
2619  {
2620  size_type j = S( m_data->string, i, len );
2621 
2622  GenericString t;
2623  if ( i < j )
2624  {
2625  const_iterator l = m_data->string + i;
2626  size_type m = j - i;
2627  if ( trim )
2628  {
2629  const_iterator r = l + m;
2630  l = R::SearchTrimLeft( l, r );
2631  m = R::SearchTrimRight( l, r ) - l;
2632  }
2633  if ( m > 0 )
2634  {
2635  t.m_data->Allocate( m );
2636  R::Copy( t.m_data->string, l, m );
2637  }
2638  }
2639  list.Add( t );
2640  ++count;
2641 
2642  if ( j == len )
2643  break;
2644 
2645  i = j + n;
2646  }
2647  }
2648  }
2649  return count;
2650  }
2651 
2674  template <class C>
2675  size_type BreakIC( C& list, const_c_string s, bool trim = false, size_type i = 0 ) const
2676  {
2677  size_type count = 0;
2678  size_type len = Length();
2679  if ( i < len )
2680  {
2681  size_type n = R::Length( s );
2682  if ( n > 0 )
2683  {
2684  for ( SearchEngine S( s, n, false/*case*/ ); ; )
2685  {
2686  size_type j = S( m_data->string, i, len );
2687 
2688  GenericString t;
2689  if ( i < j )
2690  {
2691  const_iterator l = m_data->string + i;
2692  size_type m = j - i;
2693  if ( trim )
2694  {
2695  const_iterator r = l + m;
2696  l = R::SearchTrimLeft( l, r );
2697  m = R::SearchTrimRight( l, r ) - l;
2698  }
2699  if ( m > 0 )
2700  {
2701  t.m_data->Allocate( m );
2702  R::Copy( t.m_data->string, l, m );
2703  }
2704  }
2705  list.Add( t );
2706  ++count;
2707 
2708  if ( j == len )
2709  break;
2710 
2711  i = j + n;
2712  }
2713  }
2714  }
2715  return count;
2716  }
2717 
2739  template <class C>
2740  size_type BreakIC( C& list, char_type c, bool trim = false, size_type i = 0 ) const
2741  {
2742  size_type count = 0;
2743  size_type len = Length();
2744  if ( i < len )
2745  {
2746  c = R::ToCaseFolded( c );
2747  for ( ;; )
2748  {
2749  size_type j = i;
2750  for ( const_iterator p = m_data->string + i; j < len; ++j, ++p )
2751  if ( R::ToCaseFolded( *p ) == c )
2752  break;
2753 
2754  GenericString t;
2755  if ( i < j )
2756  {
2757  const_iterator l = m_data->string + i;
2758  size_type m = j - i;
2759  if ( trim )
2760  {
2761  const_iterator r = l + m;
2762  l = R::SearchTrimLeft( l, r );
2763  m = R::SearchTrimRight( l, r ) - l;
2764  }
2765  if ( m > 0 )
2766  {
2767  t.m_data->Allocate( m );
2768  R::Copy( t.m_data->string, l, m );
2769  }
2770  }
2771  list.Add( t );
2772  ++count;
2773 
2774  if ( j == len )
2775  break;
2776 
2777  i = j + 1;
2778  }
2779  }
2780  return count;
2781  }
2782 
2787  char_type FirstChar() const noexcept
2788  {
2789  return (m_data->string != nullptr) ? *m_data->string : R::Null();
2790  }
2791 
2796  char_type LastChar() const noexcept
2797  {
2798  return (m_data->string < m_data->end) ? *(m_data->end-1) : R::Null();
2799  }
2800 
2804  template <class R1, class A1>
2805  bool StartsWith( const GenericString<T,R1,A1>& s ) const noexcept
2806  {
2807  if ( s.IsEmpty() || Length() < s.Length() )
2808  return false;
2809  for ( const_iterator p = m_data->string, q = s.m_data->string; q < s.m_data->end; ++p, ++q )
2810  if ( *p != *q )
2811  return false;
2812  return true;
2813  }
2814 
2819  bool StartsWith( const_c_string t ) const noexcept
2820  {
2821  size_type n = R::Length( t );
2822  if ( n == 0 || Length() < n )
2823  return false;
2824  for ( const_iterator p = m_data->string, e = p+n; p < e; ++p, ++t )
2825  if ( *p != *t )
2826  return false;
2827  return true;
2828  }
2829 
2833  bool StartsWith( char_type c ) const noexcept
2834  {
2835  return m_data->string < m_data->end && *m_data->string == c;
2836  }
2837 
2842  template <class R1, class A1>
2843  bool StartsWithIC( const GenericString<T,R1,A1>& s ) const noexcept
2844  {
2845  if ( s.IsEmpty() || Length() < s.Length() )
2846  return false;
2847  for ( const_iterator p = m_data->string, q = s.m_data->string; q < s.m_data->end; ++p, ++q )
2848  if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *q ) )
2849  return false;
2850  return true;
2851  }
2852 
2857  bool StartsWithIC( const_c_string t ) const noexcept
2858  {
2859  size_type n = R::Length( t );
2860  if ( n == 0 || Length() < n )
2861  return false;
2862  for ( const_iterator p = m_data->string, e = p+n; p < e; ++p, ++t )
2863  if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *t ) )
2864  return false;
2865  return true;
2866  }
2867 
2872  bool StartsWithIC( char_type c ) const noexcept
2873  {
2874  return m_data->string < m_data->end && R::ToCaseFolded( *m_data->string ) == R::ToCaseFolded( c );
2875  }
2876 
2880  template <class R1, class A1>
2881  bool EndsWith( const GenericString<T,R1,A1>& s ) const noexcept
2882  {
2883  size_type n = s.Length();
2884  if ( n == 0 || Length() < n )
2885  return false;
2886  for ( const_iterator p = m_data->end-n, q = s.m_data->string; p < m_data->end; ++p, ++q )
2887  if ( *p != *q )
2888  return false;
2889  return true;
2890  }
2891 
2896  bool EndsWith( const_c_string t ) const noexcept
2897  {
2898  size_type n = R::Length( t );
2899  if ( n == 0 || Length() < n )
2900  return false;
2901  for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t )
2902  if ( *p != *t )
2903  return false;
2904  return true;
2905  }
2906 
2910  bool EndsWith( char_type c ) const noexcept
2911  {
2912  return m_data->string < m_data->end && *(m_data->end-1) == c;
2913  }
2914 
2919  template <class R1, class A1>
2920  bool EndsWithIC( const GenericString<T,R1,A1>& s ) const noexcept
2921  {
2922  size_type n = s.Length();
2923  if ( n == 0 || Length() < n )
2924  return false;
2925  for ( const_iterator p = m_data->end-n, q = s.m_data->string; p < m_data->end; ++p, ++q )
2926  if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *q ) )
2927  return false;
2928  return true;
2929  }
2930 
2935  bool EndsWithIC( const_c_string t ) const noexcept
2936  {
2937  size_type n = R::Length( t );
2938  if ( n == 0 || Length() < n )
2939  return false;
2940  for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t )
2941  if ( R::ToCaseFolded( *p ) != R::ToCaseFolded( *t ) )
2942  return false;
2943  return true;
2944  }
2945 
2950  bool EndsWithIC( char_type c ) const noexcept
2951  {
2952  return m_data->string < m_data->end && R::ToCaseFolded( *(m_data->end-1) ) == R::ToCaseFolded( c );
2953  }
2954 
2960  template <class R1, class A1>
2961  size_type FindFirst( const GenericString<T,R1,A1>& s, size_type i = 0 ) const noexcept
2962  {
2963  size_type len = Length();
2964  i = SearchEngine( s.m_data->string, s.Length(), true/*case*/ )( m_data->string, i, len );
2965  return (i < len) ? i : notFound;
2966  }
2967 
2973  size_type FindFirst( const_c_string t, size_type i = 0 ) const noexcept
2974  {
2975  size_type len = Length();
2976  i = SearchEngine( t, R::Length( t ), true/*case*/ )( m_data->string, i, len );
2977  return (i < len) ? i : notFound;
2978  }
2979 
2985  size_type FindFirst( char_type c, size_type i = 0 ) const noexcept
2986  {
2987  for ( const_iterator p = m_data->string+i; p < m_data->end; ++p )
2988  if ( *p == c )
2989  return p - m_data->string;
2990  return notFound;
2991  }
2992 
3001  template <class R1, class A1>
3002  size_type FindFirstIC( const GenericString<T,R1,A1>& s, size_type i = 0 ) const noexcept
3003  {
3004  size_type len = Length();
3005  i = SearchEngine( s.m_data->string, s.Length(), false/*case*/ )( m_data->string, i, len );
3006  return (i < len) ? i : notFound;
3007  }
3008 
3017  size_type FindFirstIC( const_c_string t, size_type i = 0 ) const noexcept
3018  {
3019  size_type len = Length();
3020  i = SearchEngine( t, R::Length( t ), false/*case*/ )( m_data->string, i, len );
3021  return (i < len) ? i : notFound;
3022  }
3023 
3032  size_type FindFirstIC( char_type c, size_type i = 0 ) const noexcept
3033  {
3034  c = R::ToCaseFolded( c );
3035  for ( const_iterator p = m_data->string+i; p < m_data->end; ++p )
3036  if ( R::ToCaseFolded( *p ) == c )
3037  return p - m_data->string;
3038  return notFound;
3039  }
3040 
3044  template <class R1, class A1>
3045  size_type Find( const GenericString<T,R1,A1>& s, size_type i = 0 ) const noexcept
3046  {
3047  return FindFirst( s, i );
3048  }
3049 
3053  size_type Find( const_c_string t, size_type i = 0 ) const noexcept
3054  {
3055  return FindFirst( t, i );
3056  }
3057 
3061  size_type Find( char_type c, size_type i = 0 ) const noexcept
3062  {
3063  return FindFirst( c, i );
3064  }
3065 
3069  template <class R1, class A1>
3070  size_type FindIC( const GenericString<T,R1,A1>& s, size_type i = 0 ) const noexcept
3071  {
3072  return FindFirstIC( s, i );
3073  }
3074 
3078  size_type FindIC( const_c_string t, size_type i = 0 ) const noexcept
3079  {
3080  return FindFirstIC( t, i );
3081  }
3082 
3086  size_type FindIC( char_type c, size_type i = 0 ) const noexcept
3087  {
3088  return FindFirstIC( c, i );
3089  }
3090 
3100  template <class R1, class A1>
3101  size_type FindLast( const GenericString<T,R1,A1>& s, size_type r = maxPos ) const noexcept
3102  {
3103  r = pcl::Min( r, Length() );
3104  size_type i = SearchEngine( s.m_data->string, s.Length(), true/*case*/, true/*last*/ )( m_data->string, 0, r );
3105  return (i < r) ? i : notFound;
3106  }
3107 
3117  size_type FindLast( const_c_string t, size_type r = maxPos ) const noexcept
3118  {
3119  r = pcl::Min( r, Length() );
3120  size_type i = SearchEngine( t, R::Length( t ), true/*case*/, true/*last*/ )( m_data->string, 0, r );
3121  return (i < r) ? i : notFound;
3122  }
3123 
3129  size_type FindLast( char_type c, size_type r = maxPos ) const noexcept
3130  {
3131  r = pcl::Min( r, Length() );
3132  for ( const_iterator p = m_data->string+r; r > 0; --r )
3133  if ( *--p == c )
3134  return r - 1;
3135  return notFound;
3136  }
3137 
3150  template <class R1, class A1>
3151  size_type FindLastIC( const GenericString<T,R1,A1>& s, size_type r = maxPos ) const noexcept
3152  {
3153  r = pcl::Min( r, Length() );
3154  size_type i = SearchEngine( s.m_data->string, s.Length(), false/*case*/, true/*last*/ )( m_data->string, 0, r );
3155  return (i < r) ? i : notFound;
3156  }
3157 
3170  size_type FindLastIC( const_c_string t, size_type r = maxPos ) const noexcept
3171  {
3172  r = pcl::Min( r, Length() );
3173  size_type i = SearchEngine( t, R::Length( t ), false/*case*/, true/*last*/ )( m_data->string, 0, r );
3174  return (i < r) ? i : notFound;
3175  }
3176 
3185  size_type FindLastIC( char_type c, size_type r = maxPos ) const noexcept
3186  {
3187  c = R::ToCaseFolded( c );
3188  r = pcl::Min( r, Length() );
3189  for ( const_iterator p = m_data->string+r; r > 0; --r )
3190  if ( R::ToCaseFolded( *--p ) == c )
3191  return r - 1;
3192  return notFound;
3193  }
3194 
3198  template <class R1, class A1>
3199  bool Contains( const GenericString<T,R1,A1>& s ) const noexcept
3200  {
3201  return Find( s ) != notFound;
3202  }
3203 
3207  bool Contains( const_c_string t ) const noexcept
3208  {
3209  return Find( t ) != notFound;
3210  }
3211 
3215  bool Contains( char_type c ) const noexcept
3216  {
3217  return Find( c ) != notFound;
3218  }
3219 
3226  template <class R1, class A1>
3227  bool ContainsIC( const GenericString<T,R1,A1>& s ) const noexcept
3228  {
3229  return FindIC( s ) != notFound;
3230  }
3231 
3238  bool ContainsIC( const_c_string t ) const noexcept
3239  {
3240  return FindIC( t ) != notFound;
3241  }
3242 
3249  bool ContainsIC( char_type c ) const noexcept
3250  {
3251  return FindIC( c ) != notFound;
3252  }
3253 
3263  void Trim()
3264  {
3265  const_iterator l = R::SearchTrimLeft( m_data->string, m_data->end );
3266  const_iterator r = R::SearchTrimRight( l, m_data->end );
3267  if ( m_data->string < l || r < m_data->end )
3268  Trim( l, r - l );
3269  }
3270 
3280  void TrimLeft()
3281  {
3282  const_iterator l = R::SearchTrimLeft( m_data->string, m_data->end );
3283  if ( m_data->string < l )
3284  Trim( l, m_data->end - l );
3285  }
3286 
3296  void TrimRight()
3297  {
3298  const_iterator r = R::SearchTrimRight( m_data->string, m_data->end );
3299  if ( r < m_data->end )
3300  Trim( m_data->string, r - m_data->string );
3301  }
3302 
3309  {
3310  GenericString s( *this );
3311  s.Trim();
3312  return s;
3313  }
3314 
3321  {
3322  GenericString s( *this );
3323  s.TrimLeft();
3324  return s;
3325  }
3326 
3333  {
3334  GenericString s( *this );
3335  s.TrimRight();
3336  return s;
3337  }
3338 
3345  void EnsureEnclosed( char_type c )
3346  {
3347  int encloseLeft = 1;
3348  int encloseRight = 1;
3349  size_type len = Length();
3350  if ( len > 0 )
3351  {
3352  if ( *m_data->string == c )
3353  encloseLeft = 0;
3354  if ( *(m_data->end-1) == c )
3355  if ( len > 1 )
3356  encloseRight = 0;
3357  else
3358  encloseLeft = 0;
3359  }
3360  size_type n = len + encloseLeft + encloseRight;
3361  if ( n > len )
3362  {
3363  if ( !IsUnique() || m_data->ShouldReallocate( n ) )
3364  {
3365  Data* newData = Data::New( n );
3366  R::Copy( newData->string + encloseLeft, m_data->string, len );
3367  DetachFromData();
3368  m_data = newData;
3369  }
3370  else
3371  {
3372  m_data->SetLength( n );
3373  R::CopyOverlapped( m_data->string + encloseLeft, m_data->string, len );
3374  }
3375 
3376  if ( encloseLeft )
3377  *m_data->string = c;
3378  if ( encloseRight )
3379  *(m_data->end-1) = c;
3380  }
3381  }
3382 
3389  GenericString Enclosed( char_type c ) const
3390  {
3391  GenericString s( *this );
3392  s.EnsureEnclosed( c );
3393  return s;
3394  }
3395 
3403  {
3404  EnsureEnclosed( R::SingleQuote() );
3405  }
3406 
3414  {
3415  GenericString s( *this );
3416  s.EnsureSingleQuoted();
3417  return s;
3418  }
3419 
3427  {
3428  EnsureEnclosed( R::DoubleQuote() );
3429  }
3430 
3438  {
3439  GenericString s( *this );
3440  s.EnsureDoubleQuoted();
3441  return s;
3442  }
3443 
3457  void Unquote()
3458  {
3459  size_type len = Length();
3460  if ( len > 1 )
3461  if ( *m_data->string == R::SingleQuote() && *(m_data->end-1) == R::SingleQuote() ||
3462  *m_data->string == R::DoubleQuote() && *(m_data->end-1) == R::DoubleQuote() )
3463  if ( IsUnique() )
3464  {
3465  R::CopyOverlapped( m_data->string, m_data->string+1, len-2 );
3466  m_data->SetLength( len-2 );
3467  }
3468  else
3469  {
3470  Data* newData = Data::New( len-2 );
3471  R::Copy( newData->string, m_data->string+1, len-2 );
3472  DetachFromData();
3473  m_data = newData;
3474  }
3475  }
3476 
3482  {
3483  GenericString s( *this );
3484  s.Unquote();
3485  return s;
3486  }
3487 
3499  void JustifyLeft( size_type width, char_type fill = R::Blank() )
3500  {
3501  size_type len = Length();
3502  if ( len < width )
3503  Append( fill, width-len );
3504  }
3505 
3517  void JustifyRight( size_type width, char_type fill = R::Blank() )
3518  {
3519  size_type len = Length();
3520  if ( len < width )
3521  Prepend( fill, width-len );
3522  }
3523 
3536  void JustifyCenter( size_type width, char_type fill = R::Blank() )
3537  {
3538  size_type len = Length();
3539  if ( len < width )
3540  {
3541  size_type n = width-len;
3542  size_type n2 = n >> 1;
3543  Prepend( fill, n2 );
3544  Append( fill, n-n2 );
3545  }
3546  }
3547 
3554  GenericString LeftJustified( size_type width, char_type fill = R::Blank() ) const
3555  {
3556  GenericString s( *this );
3557  s.JustifyLeft( width, fill );
3558  return s;
3559  }
3560 
3567  GenericString RightJustified( size_type width, char_type fill = R::Blank() ) const
3568  {
3569  GenericString s( *this );
3570  s.JustifyRight( width, fill );
3571  return s;
3572  }
3573 
3580  GenericString CenterJustified( size_type width, char_type fill = R::Blank() ) const
3581  {
3582  GenericString s( *this );
3583  s.JustifyCenter( width, fill );
3584  return s;
3585  }
3586 
3610  template <class R1, class A1>
3611  int CompareCodePoints( const GenericString<T,R1,A1>& s, bool caseSensitive = true ) const noexcept
3612  {
3613  return R::CompareCodePoints( m_data->string, Length(), s.m_data->string, s.Length(), caseSensitive );
3614  }
3615 
3640  int CompareCodePoints( const_c_string t, bool caseSensitive = true ) const noexcept
3641  {
3642  return R::CompareCodePoints( m_data->string, Length(), t, R::Length( t ), caseSensitive );
3643  }
3644 
3672  int CompareCodePoints( char_type c, bool caseSensitive = true ) const noexcept
3673  {
3674  return R::CompareCodePoints( m_data->string, Length(), &c, 1, caseSensitive );
3675  }
3676 
3703  template <class R1, class A1>
3705  bool caseSensitive = true, bool localeAware = true ) const noexcept
3706  {
3707  return R::Compare( m_data->string, Length(), s.m_data->string, s.Length(), caseSensitive, localeAware );
3708  }
3709 
3737  int Compare( const_c_string t, bool caseSensitive = true, bool localeAware = true ) const noexcept
3738  {
3739  return R::Compare( m_data->string, Length(), t, R::Length( t ), caseSensitive, localeAware );
3740  }
3741 
3771  int Compare( char_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept
3772  {
3773  return R::Compare( m_data->string, Length(), &c, 1, caseSensitive, localeAware );
3774  }
3775 
3796  template <class R1, class A1>
3797  int CompareIC( const GenericString<T,R1,A1>& s, bool localeAware = true ) const noexcept
3798  {
3799  return R::Compare( m_data->string, Length(), s.m_data->string, s.Length(), false/*caseSensitive*/, localeAware );
3800  }
3801 
3823  int CompareIC( const_c_string t, bool localeAware = true ) const noexcept
3824  {
3825  return R::Compare( m_data->string, Length(), t, R::Length( t ), false/*caseSensitive*/, localeAware );
3826  }
3827 
3852  int CompareIC( char_type c, bool localeAware = true ) const noexcept
3853  {
3854  return R::Compare( m_data->string, Length(), &c, 1, false/*caseSensitive*/, localeAware );
3855  }
3856 
3872  template <class R1, class A1>
3873  bool WildMatch( const GenericString<T,R1,A1>& pattern, bool caseSensitive = true ) const noexcept
3874  {
3875  return R::WildMatch( m_data->string, Length(), pattern.m_data->string, pattern.Length(), caseSensitive );
3876  }
3877 
3891  template <class R1, class A1>
3892  bool WildMatchIC( const GenericString<T,R1,A1>& pattern ) const noexcept
3893  {
3894  return R::WildMatch( m_data->string, Length(), pattern.m_data->string, pattern.Length(), false/*caseSensitive*/ );
3895  }
3896 
3912  bool WildMatch( const_c_string pattern, bool caseSensitive = true ) const noexcept
3913  {
3914  return R::WildMatch( m_data->string, Length(), pattern, R::Length( pattern ), caseSensitive );
3915  }
3916 
3931  bool WildMatchIC( const_c_string pattern ) const noexcept
3932  {
3933  return R::WildMatch( m_data->string, Length(), pattern, R::Length( pattern ), false/*caseSensitive*/ );
3934  }
3935 
3940  bool HasWildcards() const noexcept
3941  {
3942  for ( iterator i = m_data->string; i < m_data->end; ++i )
3943  if ( R::IsWildcard( *i ) )
3944  return true;
3945  return false;
3946  }
3947 
3953  {
3954  size_type len = Length();
3955  if ( len > 0 )
3956  {
3957  EnsureUnique();
3958  R::ToCaseFolded( m_data->string, len );
3959  }
3960  }
3961 
3967  {
3968  size_type len = Length();
3969  if ( len > 0 )
3970  {
3971  EnsureUnique();
3972  R::ToLowercase( m_data->string, len );
3973  }
3974  }
3975 
3981  {
3982  size_type len = Length();
3983  if ( len > 0 )
3984  {
3985  EnsureUnique();
3986  R::ToUppercase( m_data->string, len );
3987  }
3988  }
3989 
3995  {
3996  GenericString s( *this );
3997  s.ToCaseFolded();
3998  return s;
3999  }
4000 
4006  {
4007  GenericString s( *this );
4008  s.ToLowercase();
4009  return s;
4010  }
4011 
4017  {
4018  GenericString s( *this );
4019  s.ToUppercase();
4020  return s;
4021  }
4022 
4028  void Reverse()
4029  {
4030  if ( !IsEmpty() )
4031  {
4032  EnsureUnique();
4033  for ( iterator i = m_data->string, j = m_data->end; i < --j; ++i )
4034  pcl::Swap( *i, *j );
4035  }
4036  }
4037 
4042  {
4043  GenericString s( *this );
4044  s.Reverse();
4045  return s;
4046  }
4047 
4051  void Sort()
4052  {
4053  if ( !IsEmpty() )
4054  {
4055  EnsureUnique();
4056  pcl::Sort( m_data->string, m_data->end );
4057  }
4058  }
4059 
4065  {
4066  GenericString s( *this );
4067  s.Sort();
4068  return s;
4069  }
4070 
4076  template <class BP>
4077  void Sort( BP p )
4078  {
4079  if ( !IsEmpty() )
4080  {
4081  EnsureUnique();
4082  pcl::Sort( m_data->string, m_data->end, p );
4083  }
4084  }
4085 
4090  template <class BP>
4091  GenericString Sorted( BP p ) const
4092  {
4093  GenericString s( *this );
4094  s.Sort( p );
4095  return s;
4096  }
4097 
4112  bool IsNumeral() const noexcept
4113  {
4114  if ( IsEmpty() )
4115  return false;
4116  char_type c = *R::SearchTrimLeft( m_data->string, m_data->end );
4117  return R::IsDigit( c ) || R::IsSign( c ) || R::IsDecimalSeparator( c );
4118  }
4119 
4134  bool IsSymbol() const noexcept
4135  {
4136  if ( IsEmpty() )
4137  return false;
4138  char_type c = *R::SearchTrimLeft( m_data->string, m_data->end );
4139  return R::IsSymbolDigit( c );
4140  }
4141 
4157  bool IsValidIdentifier( distance_type& pos ) const noexcept
4158  {
4159  if ( IsEmpty() )
4160  {
4161  pos = 0;
4162  return false;
4163  }
4164  const_iterator i = m_data->string;
4165  if ( R::IsStartingSymbolDigit( *i ) )
4166  for ( ;; )
4167  {
4168  if ( ++i == m_data->end )
4169  return true;
4170  if ( !R::IsSymbolDigit( *i ) )
4171  break;
4172  }
4173  pos = i - m_data->string;
4174  return false;
4175  }
4176 
4188  bool IsValidIdentifier() const noexcept
4189  {
4190  if ( !IsEmpty() )
4191  if ( R::IsStartingSymbolDigit( *m_data->string ) )
4192  {
4193  for ( const_iterator i = m_data->string; ++i < m_data->end; )
4194  if ( !R::IsSymbolDigit( *i ) )
4195  return false;
4196  return true;
4197  }
4198  return false;
4199  }
4200 
4209  uint64 Hash64( uint64 seed = 0 ) const noexcept
4210  {
4211  return pcl::Hash64( m_data->string, Size(), seed );
4212  }
4213 
4222  uint32 Hash32( uint32 seed = 0 ) const noexcept
4223  {
4224  return pcl::Hash32( m_data->string, Size(), seed );
4225  }
4226 
4231  uint64 Hash( uint64 seed = 0 ) const noexcept
4232  {
4233  return Hash64( seed );
4234  }
4235 
4244  {
4245  return Data::DeleteFreeList();
4246  }
4247 
4248  // -------------------------------------------------------------------------
4249 
4250 protected:
4251 
4256  void DetachFromData()
4257  {
4258  if ( !m_data->Detach() )
4259  Data::Dispose( m_data );
4260  }
4261 
4273  void MaybeReallocate( size_type len )
4274  {
4275  if ( IsUnique() )
4276  {
4277  if ( m_data->ShouldReallocate( len ) )
4278  {
4279  m_data->Deallocate();
4280  m_data->Allocate( len );
4281  }
4282  else
4283  m_data->SetLength( len );
4284  }
4285  else
4286  {
4287  Data* newData = Data::New( len );
4288  DetachFromData();
4289  m_data = newData;
4290  }
4291  }
4292 
4301  void UninitializedGrow( size_type& i, size_type n )
4302  {
4303  size_type len = Length();
4304  size_type newLen = len+n;
4305  if ( newLen > len )
4306  {
4307  if ( i > len )
4308  i = len;
4309  if ( IsUnique() )
4310  {
4311  if ( size_type( m_data->capacity - m_data->string ) < newLen+1 )
4312  {
4313  iterator old = m_data->string;
4314  m_data->Allocate( newLen );
4315  if ( old != nullptr )
4316  {
4317  if ( i > 0 )
4318  R::Copy( m_data->string, old, i );
4319  if ( i < len )
4320  R::Copy( m_data->string+i+n, old+i, len-i );
4321  m_data->alloc.Deallocate( old );
4322  }
4323  }
4324  else
4325  {
4326  if ( i < len )
4327  R::CopyOverlapped( m_data->string+i+n, m_data->string+i, len-i );
4328  m_data->SetLength( newLen );
4329  }
4330  }
4331  else
4332  {
4333  Data* newData = Data::New( newLen );
4334  if ( i > 0 )
4335  R::Copy( newData->string, m_data->string, i );
4336  if ( i < len )
4337  R::Copy( newData->string+i+n, m_data->string+i, len-i );
4338  DetachFromData();
4339  m_data = newData;
4340  }
4341  }
4342  }
4343 
4348  void Trim( const_iterator left, size_type len )
4349  {
4350  if ( len > 0 )
4351  {
4352  if ( IsUnique() )
4353  {
4354  if ( m_data->ShouldReallocate( len ) )
4355  {
4356  iterator old = m_data->string;
4357  m_data->Allocate( len );
4358  R::Copy( m_data->string, left, len );
4359  if ( old != nullptr )
4360  m_data->alloc.Deallocate( old );
4361  }
4362  else
4363  {
4364  if ( left != m_data->string ) // trim left
4365  R::CopyOverlapped( m_data->string, left, len );
4366  m_data->SetLength( len ); // trim right
4367  }
4368  }
4369  else
4370  {
4371  Data* newData = Data::New( len );
4372  R::Copy( newData->string, left, len );
4373  DetachFromData();
4374  m_data = newData;
4375  }
4376  }
4377  else
4378  Clear();
4379  }
4380 
4385  void ReplaceChar( char_type c1, char_type c2, size_type i, size_type n, bool caseSensitive )
4386  {
4387  if ( n > 0 )
4388  {
4389  size_type len = Length();
4390  if ( i < len )
4391  {
4392  n = pcl::Min( n, len-i );
4393  if ( caseSensitive )
4394  {
4395  for ( iterator p = m_data->string + i, p1 = p + n; p < p1; ++p )
4396  if ( *p == c1 )
4397  {
4398  EnsureUnique();
4399  *p = c2;
4400  for ( ; ++p < p1; )
4401  if ( *p == c1 )
4402  *p = c2;
4403  break;
4404  }
4405  }
4406  else
4407  {
4408  c1 = R::ToCaseFolded( c1 );
4409  for ( iterator p = m_data->string + i, p1 = p + n; p < p1; ++p )
4410  if ( R::ToCaseFolded( *p ) == c1 )
4411  {
4412  EnsureUnique();
4413  *p = c2;
4414  for ( ; ++p < p1; )
4415  if ( R::ToCaseFolded( *p ) == c1 )
4416  *p = c2;
4417  break;
4418  }
4419  }
4420  }
4421  }
4422  }
4423 
4428  void ReplaceString( const_iterator t1, size_type n1, const_iterator t2, size_type n2, size_type i, bool caseSensitive )
4429  {
4430  if ( n1 > 0 )
4431  {
4432  size_type len = Length();
4433  if ( i < len )
4434  {
4435  SearchEngine S( t1, n1, caseSensitive );
4436  if ( n1 == n2 )
4437  {
4438  EnsureUnique();
4439  for ( size_type p = i; (p = S( m_data->string, p, len )) < len; p += n1 )
4440  R::Copy( m_data->string + p, t2, n2 );
4441  }
4442  else
4443  {
4444  Array<size_type> P;
4445  for ( size_type p = i; (p = S( m_data->string, p, len )) < len; p += n1 )
4446  P.Add( p );
4447  if ( !P.IsEmpty() )
4448  {
4449  size_type newLen = len;
4450  if ( n1 < n2 )
4451  newLen += P.Length()*(n2 - n1);
4452  else
4453  newLen -= P.Length()*(n1 - n2);
4454 
4455  if ( newLen > 0 )
4456  {
4457  Data* newData = Data::New( newLen );
4458  size_type targetIndex = 0;
4459  size_type sourceIndex = 0;
4460  for ( size_type p : P )
4461  {
4462  size_type n = p - sourceIndex;
4463  if ( n > 0 )
4464  R::Copy( newData->string+targetIndex, m_data->string+sourceIndex, n );
4465  R::Copy( newData->string+targetIndex+n, t2, n2 );
4466  targetIndex += n + n2;
4467  sourceIndex = p + n1;
4468  }
4469  if ( sourceIndex < len )
4470  R::Copy( newData->string+targetIndex, m_data->string+sourceIndex, len-sourceIndex );
4471  DetachFromData();
4472  m_data = newData;
4473  }
4474  else
4475  Clear();
4476  }
4477  }
4478  }
4479  }
4480  }
4481 
4499  class PCL_CLASS SearchEngine
4500  {
4501  public:
4502 
4513  SearchEngine( const_iterator pattern, size_type patternLength,
4514  bool caseSensitive = true, bool searchLast = false, bool useBoyerMoore = true )
4515  : m_pattern( pattern )
4516  , m_patternLength( int( patternLength ) )
4517  , m_caseSensitive( caseSensitive )
4518  , m_searchLast( searchLast )
4519  , m_useBoyerMoore( useBoyerMoore && m_patternLength > 3 )
4520  {
4521  if ( m_useBoyerMoore )
4522  InitSkipList();
4523  }
4524 
4537  size_type operator()( const_iterator text, size_type startIndex, size_type endIndex ) const noexcept
4538  {
4539  if ( endIndex <= startIndex
4540  || m_patternLength <= 0
4541  || endIndex-startIndex < size_type( m_patternLength )
4542  || text == nullptr
4543  || m_pattern == nullptr )
4544  return endIndex;
4545 
4546  if ( m_caseSensitive )
4547  {
4548  if ( m_useBoyerMoore )
4549  {
4550  if ( m_searchLast )
4551  {
4552  for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; )
4553  {
4554  int skip = 0;
4555  const_iterator t = text + r - i;
4556  const_iterator p = m_pattern;
4557  for ( int j = m_patternLength; --j >= 0; )
4558  {
4559  char_type c = *t++;
4560  if ( c != *p++ )
4561  {
4562  skip = j - m_skipList[uint8( c )];
4563  if ( skip < 1 )
4564  skip = 1;
4565  break;
4566  }
4567  }
4568  if ( skip == 0 )
4569  return r - i;
4570  i += skip;
4571  }
4572  }
4573  else
4574  {
4575  for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; )
4576  {
4577  int skip = 0;
4578  const_iterator t = text + i + m_patternLength;
4579  const_iterator p = m_pattern + m_patternLength;
4580  for ( int j = m_patternLength; --j >= 0; )
4581  {
4582  char_type c = *--t;
4583  if ( c != *--p )
4584  {
4585  // ### N.B.: Could do better with a precomputed pattern mismatch table.
4586  skip = j - m_skipList[uint8( c )];
4587  if ( skip < 1 )
4588  skip = 1;
4589  break;
4590  }
4591  }
4592  if ( skip == 0 )
4593  return i;
4594  i += skip;
4595  }
4596  }
4597  }
4598  else
4599  {
4600  // Use a brute force search for very small patterns.
4601  if ( m_searchLast )
4602  {
4603  for ( size_type i = endIndex-m_patternLength; ; --i )
4604  {
4605  const_iterator t = text + i;
4606  const_iterator p = m_pattern;
4607  for ( int j = m_patternLength; ; ++t, ++p )
4608  {
4609  if ( *t != *p )
4610  break;
4611  if ( --j == 0 )
4612  return i;
4613  }
4614  if ( i == startIndex )
4615  break;
4616  }
4617  }
4618  else
4619  {
4620  for ( size_type i = startIndex, r = endIndex-m_patternLength; ; ++i )
4621  {
4622  const_iterator t = text + i;
4623  const_iterator p = m_pattern;
4624  for ( int j = m_patternLength; ; ++t, ++p )
4625  {
4626  if ( *t != *p )
4627  break;
4628  if ( --j == 0 )
4629  return i;
4630  }
4631  if ( i == r )
4632  break;
4633  }
4634  }
4635  }
4636  }
4637  else
4638  {
4639  if ( m_useBoyerMoore )
4640  {
4641  if ( m_searchLast )
4642  {
4643  for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; )
4644  {
4645  int skip = 0;
4646  const_iterator t = text + r - i;
4647  const_iterator p = m_pattern;
4648  for ( int j = m_patternLength; --j >= 0; )
4649  {
4650  char_type c = R::ToCaseFolded( *t++ );
4651  if ( c != R::ToCaseFolded( *p++ ) )
4652  {
4653  skip = j - m_skipList[uint8( c )];
4654  if ( skip < 1 )
4655  skip = 1;
4656  break;
4657  }
4658  }
4659  if ( skip == 0 )
4660  return r - i;
4661  i += skip;
4662  }
4663  }
4664  else
4665  {
4666  for ( size_type i = startIndex, r = endIndex-m_patternLength; i <= r; )
4667  {
4668  int skip = 0;
4669  const_iterator t = text + i + m_patternLength;
4670  const_iterator p = m_pattern + m_patternLength;
4671  for ( int j = m_patternLength; --j >= 0; )
4672  {
4673  char_type c = R::ToCaseFolded( *--t );
4674  if ( c != R::ToCaseFolded( *--p ) )
4675  {
4676  // ### N.B.: Could do better with a precomputed pattern mismatch table.
4677  skip = j - m_skipList[uint8( c )];
4678  if ( skip < 1 )
4679  skip = 1;
4680  break;
4681  }
4682  }
4683  if ( skip == 0 )
4684  return i;
4685  i += skip;
4686  }
4687  }
4688  }
4689  else
4690  {
4691  // Use a brute force search for very small patterns.
4692  if ( m_searchLast )
4693  {
4694  for ( size_type i = endIndex-m_patternLength; ; --i )
4695  {
4696  const_iterator t = text + i;
4697  const_iterator p = m_pattern;
4698  for ( int j = m_patternLength; ; ++t, ++p )
4699  {
4700  if ( R::ToCaseFolded( *t ) != R::ToCaseFolded( *p ) )
4701  break;
4702  if ( --j == 0 )
4703  return i;
4704  }
4705  if ( i == startIndex )
4706  break;
4707  }
4708  }
4709  else
4710  {
4711  for ( size_type i = startIndex, r = endIndex-m_patternLength; ; ++i )
4712  {
4713  const_iterator t = text + i;
4714  const_iterator p = m_pattern;
4715  for ( int j = m_patternLength; ; ++t, ++p )
4716  {
4717  if ( R::ToCaseFolded( *t ) != R::ToCaseFolded( *p ) )
4718  break;
4719  if ( --j == 0 )
4720  return i;
4721  }
4722  if ( i == r )
4723  break;
4724  }
4725  }
4726  }
4727  }
4728  return endIndex;
4729  }
4730 
4731  private:
4732 
4733  int m_skipList[ 256 ];
4734  const_iterator m_pattern;
4735  int m_patternLength;
4736  bool m_caseSensitive : 1;
4737  bool m_searchLast : 1;
4738  bool m_useBoyerMoore : 1;
4739 
4740  void InitSkipList() noexcept
4741  {
4742  ::memset( m_skipList, 0xff, sizeof( m_skipList ) ); // fill with -1
4743  if ( m_searchLast )
4744  {
4745  const_iterator p = m_pattern + m_patternLength;
4746  if ( m_caseSensitive )
4747  for ( int i = 0; i < m_patternLength; ++i )
4748  m_skipList[uint8( *--p )] = i;
4749  else
4750  for ( int i = 0; i < m_patternLength; ++i )
4751  m_skipList[uint8( R::ToCaseFolded( *--p ) )] = i;
4752  }
4753  else
4754  {
4755  const_iterator p = m_pattern;
4756  if ( m_caseSensitive )
4757  for ( int i = 0; i < m_patternLength; ++i )
4758  m_skipList[uint8( *p++ )] = i;
4759  else
4760  for ( int i = 0; i < m_patternLength; ++i )
4761  m_skipList[uint8( R::ToCaseFolded( *p++ ) )] = i;
4762  }
4763  }
4764  };
4765 
4766  // -------------------------------------------------------------------------
4767 
4773  class PCL_CLASS Data : public ReferenceCounter
4774  {
4775  private:
4776 
4777 #ifndef __PCL_NO_STRING_FREE_LIST
4778  static Data* freeList;
4779  static AtomicInt freeLock;
4780 #endif
4781 
4782  public:
4783 
4784  iterator string = nullptr;
4785  iterator end = nullptr;
4786  iterator capacity = nullptr;
4787  allocator alloc;
4788 
4792  Data() = default;
4793 
4797  Data( size_type len )
4798  {
4799  Allocate( len );
4800  }
4801 
4806  Data( size_type len, size_type total )
4807  {
4808  Allocate( len, total );
4809  }
4810 
4814  ~Data()
4815  {
4816  Deallocate();
4817  }
4818 
4829  void Allocate( size_type len, size_type total )
4830  {
4831  total = (len <= total) ? alloc.PagedLength( total+1 ) : len+1; // +1 is room for a null terminating character
4832  string = alloc.Allocate( total );
4833  capacity = string + total;
4834  SetLength( len );
4835  }
4836 
4841  void Allocate( size_type len )
4842  {
4843  Allocate( len, len );
4844  }
4845 
4854  void Reserve( size_type len, size_type total )
4855  {
4856  PCL_PRECONDITION( len <= total )
4857  string = alloc.Allocate( total+1 );
4858  capacity = string + total+1;
4859  SetLength( pcl::Min( len, total ) );
4860  }
4861 
4865  void Deallocate()
4866  {
4867  PCL_CHECK( (string == nullptr) ? end == nullptr : string < end )
4868  if ( string != nullptr )
4869  {
4870  alloc.Deallocate( string );
4871  Reset();
4872  }
4873  }
4874 
4879  bool ShouldReallocate( size_type len ) const noexcept
4880  {
4881  size_type m = capacity - string;
4882  return m <= len || alloc.ReallocatedLength( m, len+1 ) < (m >> 1);
4883  }
4884 
4889  void SetLength( size_type len ) noexcept
4890  {
4891  *(end = (string + len)) = R::Null();
4892  }
4893 
4897  void Reset() noexcept
4898  {
4899  string = end = capacity = nullptr;
4900  }
4901 
4908 #ifndef __PCL_NO_STRING_FREE_LIST
4909  static Data* NextFree() noexcept
4910  {
4911  if ( freeLock.TestAndSet( 0, 1 ) )
4912  {
4913  Data* data = freeList;
4914  if ( data != nullptr )
4915  freeList = reinterpret_cast<Data*>( data->string );
4916  freeLock.Store( 0 );
4917  return data;
4918  }
4919  return nullptr;
4920  }
4921 #endif // !__PCL_NO_STRING_FREE_LIST
4922 
4930  static Data* New()
4931  {
4932 #ifndef __PCL_NO_STRING_FREE_LIST
4933  Data* data = NextFree();
4934  if ( data != nullptr )
4935  {
4936  data->string = nullptr;
4937  return data;
4938  }
4939 #endif // !__PCL_NO_STRING_FREE_LIST
4940  return new Data;
4941  }
4942 
4950  static Data* New( size_type len )
4951  {
4952 #ifndef __PCL_NO_STRING_FREE_LIST
4953  Data* data = NextFree();
4954  if ( data != nullptr )
4955  {
4956  data->Allocate( len ); // ### FIXME: If allocation fails, data is a leak.
4957  return data;
4958  }
4959 #endif // !__PCL_NO_STRING_FREE_LIST
4960  return new Data( len );
4961  }
4962 
4970  static Data* New( size_type len, size_type total )
4971  {
4972 #ifndef __PCL_NO_STRING_FREE_LIST
4973  Data* data = NextFree();
4974  if ( data != nullptr )
4975  {
4976  data->Allocate( len, total ); // ### FIXME: If allocation fails, data is a leak.
4977  return data;
4978  }
4979 #endif // !__PCL_NO_STRING_FREE_LIST
4980  return new Data( len, total );
4981  }
4982 
4990  static void Dispose( Data* data )
4991  {
4992  PCL_PRECONDITION( data != nullptr )
4993  PCL_CHECK( data->RefCount() == 0 )
4994 #ifndef __PCL_NO_STRING_FREE_LIST
4995  if ( freeLock.TestAndSet( 0, 1 ) )
4996  {
4997  data->Attach();
4998  data->Deallocate();
4999  data->string = reinterpret_cast<iterator>( freeList );
5000  freeList = data;
5001  freeLock.Store( 0 );
5002  }
5003  else
5004 #endif // !__PCL_NO_STRING_FREE_LIST
5005  delete data;
5006  }
5007 
5015  static size_type DeleteFreeList()
5016  {
5017  size_type count = 0;
5018 #ifndef __PCL_NO_STRING_FREE_LIST
5019  while ( freeList != nullptr )
5020  {
5021  Data* data = freeList;
5022  freeList = reinterpret_cast<Data*>( data->string );
5023  data->string = nullptr;
5024  delete data;
5025  ++count;
5026  }
5027 #endif // !__PCL_NO_STRING_FREE_LIST
5028  return count;
5029  }
5030  };
5031 
5032  /*
5033  * The reference-counted string data.
5034  */
5035  Data* m_data = nullptr;
5036 };
5037 
5038 #ifndef __PCL_NO_STRING_FREE_LIST
5039 
5040 template <class T, class R, class A>
5042 
5043 template <class T, class R, class A>
5045 
5046 #endif // !__PCL_NO_STRING_FREE_LIST
5047 
5051 template <class T, class R, class A> inline
5053 {
5054  s1.Swap( s2 );
5055 }
5056 
5057 // ----------------------------------------------------------------------------
5058 
5063 // ----------------------------------------------------------------------------
5064 
5069 template <class T, class R1, class A1, class R2, class A2> inline
5070 bool operator ==( const GenericString<T,R1,A1>& s1, const GenericString<T,R2,A2>& s2 ) noexcept
5071 {
5072  return s1.CompareCodePoints( s2 ) == 0;
5073 }
5074 
5082 template <class T, class R1, class A1, class R2, class A2> inline
5083 bool operator <( const GenericString<T,R1,A1>& s1, const GenericString<T,R2,A2>& s2 ) noexcept
5084 {
5085  return s1.CompareCodePoints( s2 ) < 0;
5086 }
5087 
5095 template <class T, class R1, class A1, class R2, class A2> inline
5096 bool operator <=( const GenericString<T,R1,A1>& s1, const GenericString<T,R2,A2>& s2 ) noexcept
5097 {
5098  return s1.CompareCodePoints( s2 ) <= 0;
5099 }
5100 
5108 template <class T, class R1, class A1, class R2, class A2> inline
5109 bool operator >( const GenericString<T,R1,A1>& s1, const GenericString<T,R2,A2>& s2 ) noexcept
5110 {
5111  return s1.CompareCodePoints( s2 ) > 0;
5112 }
5113 
5121 template <class T, class R1, class A1, class R2, class A2> inline
5122 bool operator >=( const GenericString<T,R1,A1>& s1, const GenericString<T,R2,A2>& s2 ) noexcept
5123 {
5124  return s1.CompareCodePoints( s2 ) >= 0;
5125 }
5126 
5127 // ----------------------------------------------------------------------------
5128 
5133 template <class T, class R, class A> inline
5135 {
5136  return s1.CompareCodePoints( t2 ) == 0;
5137 }
5138 
5146 template <class T, class R, class A> inline
5147 bool operator <( const GenericString<T,R,A>& s1, typename GenericString<T,R,A>::const_c_string t2 ) noexcept
5148 {
5149  return s1.CompareCodePoints( t2 ) < 0;
5150 }
5151 
5159 template <class T, class R, class A> inline
5160 bool operator <=( const GenericString<T,R,A>& s1, typename GenericString<T,R,A>::const_c_string t2 ) noexcept
5161 {
5162  return s1.CompareCodePoints( t2 ) <= 0;
5163 }
5164 
5172 template <class T, class R, class A> inline
5174 {
5175  return s1.CompareCodePoints( t2 ) > 0;
5176 }
5177 
5185 template <class T, class R, class A> inline
5187 {
5188  return s1.CompareCodePoints( t2 ) >= 0;
5189 }
5190 
5191 // ----------------------------------------------------------------------------
5192 
5197 template <class T, class R, class A> inline
5199 {
5200  return s2.CompareCodePoints( t1 ) == 0;
5201 }
5202 
5210 template <class T, class R, class A> inline
5211 bool operator <( typename GenericString<T,R,A>::const_c_string t1, const GenericString<T,R,A>& s2 ) noexcept
5212 {
5213  return s2.CompareCodePoints( t1 ) > 0;
5214 }
5215 
5223 template <class T, class R, class A> inline
5224 bool operator <=( typename GenericString<T,R,A>::const_c_string t1, const GenericString<T,R,A>& s2 ) noexcept
5225 {
5226  return s2.CompareCodePoints( t1 ) >= 0;
5227 }
5228 
5236 template <class T, class R, class A> inline
5238 {
5239  return s2.CompareCodePoints( t1 ) < 0;
5240 }
5241 
5249 template <class T, class R, class A> inline
5251 {
5252  return s2.CompareCodePoints( t1 ) <= 0;
5253 }
5254 
5255 // ----------------------------------------------------------------------------
5256 
5261 template <class T, class R, class A> inline
5263 {
5264  return s1.CompareCodePoints( c2 ) == 0;
5265 }
5266 
5274 template <class T, class R, class A> inline
5275 bool operator <( const GenericString<T,R,A>& s1, typename GenericString<T,R,A>::char_type c2 ) noexcept
5276 {
5277  return s1.CompareCodePoints( c2 ) < 0;
5278 }
5279 
5287 template <class T, class R, class A> inline
5288 bool operator <=( const GenericString<T,R,A>& s1, typename GenericString<T,R,A>::char_type c2 ) noexcept
5289 {
5290  return s1.CompareCodePoints( c2 ) <= 0;
5291 }
5292 
5300 template <class T, class R, class A> inline
5301 bool operator >( const GenericString<T,R,A>& s1, typename GenericString<T,R,A>::char_type c2 ) noexcept
5302 {
5303  return s1.CompareCodePoints( c2 ) > 0;
5304 }
5305 
5313 template <class T, class R, class A> inline
5315 {
5316  return s1.CompareCodePoints( c2 ) >= 0;
5317 }
5318 
5319 // ----------------------------------------------------------------------------
5320 
5325 template <class T, class R, class A> inline
5327 {
5328  return s2.CompareCodePoints( c1 ) == 0;
5329 }
5330 
5338 template <class T, class R, class A> inline
5339 bool operator <( typename GenericString<T,R,A>::char_type c1, const GenericString<T,R,A>& s2 ) noexcept
5340 {
5341  return s2.CompareCodePoints( c1 ) > 0;
5342 }
5343 
5351 template <class T, class R, class A> inline
5352 bool operator <=( typename GenericString<T,R,A>::char_type c1, const GenericString<T,R,A>& s2 ) noexcept
5353 {
5354  return s2.CompareCodePoints( c1 ) >= 0;
5355 }
5356 
5364 template <class T, class R, class A> inline
5365 bool operator >( typename GenericString<T,R,A>::char_type c1, const GenericString<T,R,A>& s2 ) noexcept
5366 {
5367  return s2.CompareCodePoints( c1 ) < 0;
5368 }
5369 
5377 template <class T, class R, class A> inline
5379 {
5380  return s2.CompareCodePoints( c1 ) <= 0;
5381 }
5382 
5383 // ----------------------------------------------------------------------------
5384 
5397 class PCL_CLASS IsoString : public GenericString<char, IsoCharTraits, PCL_STRING_ALLOCATOR>
5398 {
5399 public:
5400 
5406 
5411 
5416 
5421 
5426 
5431 
5436 
5441 
5446 
5451 
5456 
5464 
5469 
5474 
5479 
5483  typedef ustring_base::const_c_string const_c_ustring;
5484 
5489 
5494 
5495  // -------------------------------------------------------------------------
5496 
5500  IsoString() = default;
5501 
5507  : string_base( s )
5508  {
5509  }
5510 
5514  IsoString( const IsoString& ) = default;
5515 
5521  : string_base( std::move( s ) )
5522  {
5523  }
5524 
5528  IsoString( IsoString&& ) = default;
5529 
5537  explicit
5539  {
5540  (void)operator =( s );
5541  }
5542 
5546  IsoString( const_c_string t )
5547  : string_base( t )
5548  {
5549  }
5550 
5555  IsoString( const_c_string t, size_type i, size_type n )
5556  : string_base( t, i, n )
5557  {
5558  }
5559 
5563  IsoString( char_type c, size_type n = 1 )
5564  : string_base( c, n )
5565  {
5566  }
5567 
5572  IsoString( const_iterator i, const_iterator j )
5573  : string_base( i, j )
5574  {
5575  }
5576 
5585  IsoString( std::initializer_list<char_type> l )
5586  : IsoString( l.begin(), l.end() )
5587  {
5588  }
5589 
5599  explicit
5600  IsoString( const_c_ustring t )
5601  {
5602  (void)operator =( t );
5603  }
5604 
5615  IsoString( const_c_ustring t, size_type i, size_type n );
5616 
5624  explicit
5625  IsoString( const ByteArray& B )
5626  : IsoString( const_iterator( B.Begin() ), const_iterator( B.End() ) )
5627  {
5628  }
5629 
5633  explicit
5634  IsoString( bool x )
5635  : string_base( x ? "true" : "false" )
5636  {
5637  }
5638 
5643  explicit
5644  IsoString( short x )
5645  {
5646  (void)Format( "%hd", x );
5647  }
5648 
5653  explicit
5654  IsoString( unsigned short x )
5655  {
5656  (void)Format( "%hu", x );
5657  }
5658 
5663  explicit
5664  IsoString( int x )
5665  {
5666  (void)Format( "%i", x );
5667  }
5668 
5673  explicit
5674  IsoString( unsigned int x )
5675  {
5676  (void)Format( "%u", x );
5677  }
5678 
5683  explicit
5684  IsoString( long x )
5685  {
5686  (void)Format( "%ld", x );
5687  }
5688 
5693  explicit
5694  IsoString( unsigned long x )
5695  {
5696  (void)Format( "%lu", x );
5697  }
5698 
5703  explicit
5704  IsoString( long long x )
5705  {
5706  (void)Format( "%lli", x );
5707  }
5708 
5713  explicit
5714  IsoString( unsigned long long x )
5715  {
5716  (void)Format( "%llu", x );
5717  }
5718 
5723  explicit
5724  IsoString( float x )
5725  {
5726  (void)Format( "%.7g", x );
5727  }
5728 
5733  explicit
5734  IsoString( double x )
5735  {
5736  (void)Format( "%.16g", x );
5737  }
5738 
5743  explicit
5744  IsoString( long double x )
5745  {
5746 #ifdef _MSC_VER
5747  (void)Format( "%.16Lg", x );
5748 #else
5749  (void)Format( "%.18Lg", x );
5750 #endif
5751  }
5752 
5753 #ifndef __PCL_NO_STRING_COMPLEX
5754 
5759  explicit
5761  {
5762  (void)Format( "{%.7g,%.7g}", x.Real(), x.Imag() );
5763  }
5764 
5769  explicit
5771  {
5772  (void)Format( "{%.16g,%.16g}", x.Real(), x.Imag() );
5773  }
5774 
5779  explicit
5781  {
5782 #ifdef _MSC_VER
5783  (void)Format( "{%.16Lg,%.16Lg}", x.Real(), x.Imag() );
5784 #else
5785  (void)Format( "{%.18Lg,%.18Lg}", x.Real(), x.Imag() );
5786 #endif
5787  }
5788 
5789 #endif // !__PCL_NO_STRING_COMPLEX
5790 
5791 #ifdef __PCL_QT_INTERFACE
5792 
5793  explicit
5794  IsoString( const QString& qs )
5795  : string_base( qs.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHARPTR_FROM_QSTRING( qs ) ) )
5796  {
5797  }
5798 
5799  explicit
5800  IsoString( const QByteArray& qb )
5801  : string_base( qb.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) ) )
5802  {
5803  }
5804 
5805  explicit
5806  IsoString( const QDate& qd )
5807  : string_base( iterator( PCL_GET_CHARPTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ) )
5808  {
5809  }
5810 
5811  explicit
5812  IsoString( const QDateTime& qdt )
5813  : string_base( iterator( PCL_GET_CHARPTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ) )
5814  {
5815  }
5816 
5817 #endif
5818 
5819  // -------------------------------------------------------------------------
5820 
5824  IsoString& operator =( const IsoString& s )
5825  {
5826  Assign( s );
5827  return *this;
5828  }
5829 
5833  IsoString& operator =( IsoString&& s )
5834  {
5835  Transfer( s );
5836  return *this;
5837  }
5838 
5843  IsoString& operator =( const string_base& s )
5844  {
5845  Assign( s );
5846  return *this;
5847  }
5848 
5853  IsoString& operator =( string_base&& s )
5854  {
5855  Transfer( s );
5856  return *this;
5857  }
5858 
5869  IsoString& operator =( const ustring_base& s )
5870  {
5871  return operator =( s.Begin() );
5872  }
5873 
5878  IsoString& operator =( const_c_string t )
5879  {
5880  Assign( t );
5881  return *this;
5882  }
5883 
5888  IsoString& operator =( char_type c )
5889  {
5890  Assign( c, 1 );
5891  return *this;
5892  }
5893 
5904  IsoString& operator =( const_c_ustring t );
5905 
5906 #ifdef __PCL_QT_INTERFACE
5907 
5908  IsoString& operator =( const QString& qs )
5909  {
5910  if ( qs.isEmpty() )
5911  Clear();
5912  else
5913  Assign( PCL_GET_CHARPTR_FROM_QSTRING( qs ) );
5914  return *this;
5915  }
5916 
5917  IsoString& operator =( const QByteArray& qb )
5918  {
5919  if ( qb.isEmpty() )
5920  Clear();
5921  else
5922  Assign( PCL_GET_CHARPTR_FROM_QBYTEARRAY( qb ) );
5923  return *this;
5924  }
5925 
5926  IsoString& operator =( const QDate& qd )
5927  {
5928  Assign( PCL_GET_CHARPTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) );
5929  return *this;
5930  }
5931 
5932  IsoString& operator =( const QDateTime& qdt )
5933  {
5934  Assign( PCL_GET_CHARPTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) );
5935  return *this;
5936  }
5937 
5938 #endif
5939 
5940  // -------------------------------------------------------------------------
5941 
5942  IsoString SetToLength( size_type n ) const
5943  {
5944  return string_base::SetToLength( n );
5945  }
5946 
5947  IsoString ResizedToNullTerminated() const
5948  {
5949  return string_base::ResizedToNullTerminated();
5950  }
5951 
5952  IsoString Squeezed() const
5953  {
5954  return string_base::Squeezed();
5955  }
5956 
5957  // -------------------------------------------------------------------------
5958 
5959  IsoString Substring( size_type i, size_type n = maxPos ) const
5960  {
5961  return string_base::Substring( i, n );
5962  }
5963 
5964  IsoString Left( size_type n ) const
5965  {
5966  return string_base::Left( n );
5967  }
5968 
5969  IsoString Right( size_type n ) const
5970  {
5971  return string_base::Right( n );
5972  }
5973 
5974  IsoString Suffix( size_type i ) const
5975  {
5976  return string_base::Suffix( i );
5977  }
5978 
5979  IsoString Prefix( size_type i ) const
5980  {
5981  return string_base::Prefix( i );
5982  }
5983 
5984  // -------------------------------------------------------------------------
5985 
5986  IsoString Trimmed() const
5987  {
5988  return string_base::Trimmed();
5989  }
5990 
5991  IsoString TrimmedLeft() const
5992  {
5993  return string_base::TrimmedLeft();
5994  }
5995 
5996  IsoString TrimmedRight() const
5997  {
5998  return string_base::TrimmedRight();
5999  }
6000 
6001  // -------------------------------------------------------------------------
6002 
6003  IsoString LeftJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const
6004  {
6005  return string_base::LeftJustified( width, fill );
6006  }
6007 
6008  IsoString RightJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const
6009  {
6010  return string_base::RightJustified( width, fill );
6011  }
6012 
6013  IsoString CenterJustified( size_type width, char_type fill = IsoCharTraits::Blank() ) const
6014  {
6015  return string_base::CenterJustified( width, fill );
6016  }
6017 
6018  // -------------------------------------------------------------------------
6019 
6020  IsoString Enclosed( char_type c ) const
6021  {
6022  return string_base::Enclosed( c );
6023  }
6024 
6025  IsoString SingleQuoted() const
6026  {
6027  return string_base::SingleQuoted();
6028  }
6029 
6030  IsoString DoubleQuoted() const
6031  {
6032  return string_base::DoubleQuoted();
6033  }
6034 
6035  IsoString Unquoted() const
6036  {
6037  return string_base::Unquoted();
6038  }
6039 
6040  // -------------------------------------------------------------------------
6041 
6042  IsoString CaseFolded() const
6043  {
6044  return string_base::CaseFolded();
6045  }
6046 
6047  IsoString Lowercase() const
6048  {
6049  return string_base::Lowercase();
6050  }
6051 
6052  IsoString Uppercase() const
6053  {
6054  return string_base::Uppercase();
6055  }
6056 
6057  // -------------------------------------------------------------------------
6058 
6059  IsoString Reversed() const
6060  {
6061  return string_base::Reversed();
6062  }
6063 
6064  IsoString Sorted() const
6065  {
6066  return string_base::Sorted();
6067  }
6068 
6069  template <class BP>
6070  IsoString Sorted( BP p ) const
6071  {
6072  return string_base::Sorted( p );
6073  }
6074 
6075  // -------------------------------------------------------------------------
6076 
6086  template <class C>
6087  IsoString& ToSeparated( const C& c, char_type separator )
6088  {
6089  Clear();
6090  return c.ToSeparated( *this, separator );
6091  }
6092 
6109  template <class C, class AF>
6110  IsoString& ToSeparated( const C& c, char_type separator, AF append )
6111  {
6112  Clear();
6113  return c.ToSeparated( *this, separator, append );
6114  }
6115 
6125  template <class C>
6126  IsoString& ToSeparated( const C& c, const IsoString& separator )
6127  {
6128  Clear();
6129  return c.ToSeparated( *this, separator );
6130  }
6131 
6148  template <class C, class AF>
6149  IsoString& ToSeparated( const C& c, const IsoString& separator, AF append )
6150  {
6151  Clear();
6152  return c.ToSeparated( *this, separator, append );
6153  }
6154 
6164  template <class C>
6165  IsoString& ToSeparated( const C& c, const_c_string separator )
6166  {
6167  return ToSeparated( c, IsoString( separator ) );
6168  }
6169 
6186  template <class C, class AF>
6187  IsoString& ToSeparated( const C& c, const_c_string separator, AF append )
6188  {
6189  return ToSeparated( c, IsoString( separator ), append );
6190  }
6191 
6201  template <class C>
6203  {
6204  return ToSeparated( c, IsoCharTraits::Comma() );
6205  }
6206 
6216  template <class C>
6218  {
6219  return ToSeparated( c, IsoCharTraits::Colon() );
6220  }
6221 
6231  template <class C>
6233  {
6234  return ToSeparated( c, IsoCharTraits::Blank() );
6235  }
6236 
6246  template <class C>
6247  IsoString& ToTabSeparated( const C& c )
6248  {
6249  return ToSeparated( c, IsoCharTraits::Tab() );
6250  }
6251 
6261  template <class C>
6263  {
6264  return ToSeparated( c, IsoCharTraits::LF() );
6265  }
6266 
6276  template <class C>
6278  {
6279  return ToSeparated( c, IsoCharTraits::Null() );
6280  }
6281 
6290  template <class C>
6291  IsoString& ToHyphenated( const C& c )
6292  {
6293  return ToSeparated( c, IsoCharTraits::Hyphen() );
6294  }
6295 
6296  // -------------------------------------------------------------------------
6297 
6312  IsoString& ToEncodedHTMLSpecialChars();
6313 
6321  {
6322  return IsoString( *this ).ToEncodedHTMLSpecialChars();
6323  }
6324 
6341  IsoString& ToDecodedHTMLSpecialChars();
6342 
6351  {
6352  return IsoString( *this ).ToDecodedHTMLSpecialChars();
6353  }
6354 
6366  static IsoString ToURLEncoded( const void* data, size_type length );
6367 
6380  template <class C>
6381  static IsoString ToURLEncoded( const C& c )
6382  {
6383  return ToURLEncoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) );
6384  }
6385 
6395  IsoString& ToURLEncoded();
6396 
6404  {
6405  return IsoString( *this ).ToURLEncoded();
6406  }
6407 
6419  static ByteArray FromURLEncoded( const void* data, size_type length );
6420 
6428  template <class C>
6429  static ByteArray FromURLEncoded( const C& c )
6430  {
6431  return FromURLEncoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) );
6432  }
6433 
6446  {
6447  return FromURLEncoded( Begin(), Length() );
6448  }
6449 
6461  static IsoString ToURLDecoded( const void* data, size_type length );
6462 
6469  template <class C>
6470  static IsoString ToURLDecoded( const C& c )
6471  {
6472  return ToURLDecoded( c.Begin(), c.Length()*sizeof( *c.Begin() ) );
6473  }
6474 
6484  IsoString& ToURLDecoded();
6485 
6493  {
6494  return IsoString( *this ).ToURLDecoded();
6495  }
6496 
6497  // -------------------------------------------------------------------------
6498 
6499 #ifdef __PCL_QT_INTERFACE
6500 
6501  operator QString() const
6502  {
6503  return QString( c_str() );
6504  }
6505 
6506  operator QByteArray() const
6507  {
6508  return QByteArray( c_str() );
6509  }
6510 
6511  operator QDate() const
6512  {
6513  return QDate::fromString( c_str(), PCL_QDATE_FMT_STR );
6514  }
6515 
6516  operator QDateTime() const
6517  {
6518  return QDateTime::fromString( c_str(), PCL_QDATETIME_FMT_STR );
6519  }
6520 
6521 #endif
6522 
6534  IsoString& Format( const_c_string fmt, ... )
6535  {
6536  va_list paramList;
6537  va_start( paramList, fmt );
6538 
6539  (void)VFormat( fmt, paramList );
6540 
6541  va_end( paramList );
6542  return *this;
6543  }
6544 
6556  IsoString& AppendFormat( const_c_string fmt, ... )
6557  {
6558  va_list paramList;
6559  va_start( paramList, fmt );
6560 
6561  (void)AppendVFormat( fmt, paramList );
6562 
6563  va_end( paramList );
6564  return *this;
6565  }
6566 
6579  int VFormat( const_c_string fmt, va_list paramList );
6580 
6593  int AppendVFormat( const_c_string fmt, va_list paramList );
6594 
6595  // -------------------------------------------------------------------------
6596 
6607  {
6608  ustring_base s;
6609  s.SetLength( Length() );
6610  uchar_iterator p = s.Begin();
6611  for ( const_iterator i = m_data->string; i < m_data->end; ++p, ++i )
6612  *p = uchar_type( *i );
6613  return s;
6614  }
6615 
6623  ustring_base UTF8ToUTF16( size_type i = 0, size_type n = maxPos ) const; // implemented inline after String
6624 
6640  ustring_base MBSToWCS() const;
6641 
6642 #ifdef __PCL_QT_INTERFACE
6643 
6644  QString ToQString() const
6645  {
6646  return operator QString();
6647  }
6648 
6649  QByteArray ToQByteArray() const
6650  {
6651  return operator QByteArray();
6652  }
6653 
6654  QDate ToQDate() const
6655  {
6656  return operator QDate();
6657  }
6658 
6659  QDateTime ToQDateTime() const
6660  {
6661  return operator QDateTime();
6662  }
6663 
6664 #endif
6665 
6676  bool ToBool() const;
6677 
6692  bool TryToBool( bool& value ) const noexcept;
6693 
6707  float ToFloat() const;
6708 
6723  bool TryToFloat( float& value ) const noexcept;
6724 
6748  double ToDouble() const;
6749 
6764  bool TryToDouble( double& value ) const noexcept;
6765 
6783  long ToInt() const
6784  {
6785  return ToInt( 0 );
6786  }
6787 
6811  bool TryToInt( int& value ) const noexcept
6812  {
6813  return TryToInt( value, 0 );
6814  }
6815 
6842  long ToInt( int base ) const;
6843 
6861  bool TryToInt( int& value, int base ) const noexcept;
6862 
6880  unsigned long ToUInt() const
6881  {
6882  return ToUInt( 0 );
6883  }
6884 
6908  bool TryToUInt( unsigned& value ) const noexcept
6909  {
6910  return TryToUInt( value, 0 );
6911  }
6912 
6929  unsigned long ToUInt( int base ) const;
6930 
6948  bool TryToUInt( unsigned& value, int base ) const noexcept;
6949 
6964  long long ToInt64() const
6965  {
6966  return ToInt64( 0 );
6967  }
6968 
6993  bool TryToInt64( long long& value ) const noexcept
6994  {
6995  return TryToInt64( value, 0 );
6996  }
6997 
7012  long long ToInt64( int base ) const;
7013 
7031  bool TryToInt64( long long& value, int base ) const noexcept;
7032 
7047  unsigned long long ToUInt64() const
7048  {
7049  return ToUInt64( 0 );
7050  }
7051 
7076  bool TryToUInt64( unsigned long long& value ) const noexcept
7077  {
7078  return TryToUInt64( value, 0 );
7079  }
7080 
7095  unsigned long long ToUInt64( int base ) const;
7096 
7114  bool TryToUInt64( unsigned long long& value, int base ) const noexcept;
7115 
7143  double SexagesimalToDouble( const IsoString& separator = ':' ) const
7144  {
7145  int sign, s1, s2; double s3;
7146  ParseSexagesimal( sign, s1, s2, s3, separator );
7147  return sign*(s1 + (s2 + s3/60)/60);
7148  }
7149 
7150  double SexagesimalToDouble( char separator ) const
7151  {
7152  return SexagesimalToDouble( IsoString( separator ) );
7153  }
7154 
7155  double SexagesimalToDouble( const ustring_base& separator ) const
7156  {
7157  return SexagesimalToDouble( IsoString( separator ) );
7158  }
7159 
7173  double SexagesimalToDouble( const Array<char_type>& separators ) const
7174  {
7175  int sign, s1, s2; double s3;
7176  ParseSexagesimal( sign, s1, s2, s3, separators );
7177  return sign*(s1 + (s2 + s3/60)/60);
7178  }
7179 
7197  bool TrySexagesimalToDouble( double& value, const IsoString& separator = ':' ) const noexcept
7198  {
7199  int sign, s1, s2; double s3;
7200  if ( TryParseSexagesimal( sign, s1, s2, s3, separator ) )
7201  {
7202  value = sign*(s1 + (s2 + s3/60)/60);
7203  return true;
7204  }
7205  return false;
7206  }
7207 
7208  bool TrySexagesimalToDouble( double& value, char separator ) const noexcept
7209  {
7210  return TrySexagesimalToDouble( value, IsoString( separator ) );
7211  }
7212 
7213  bool TrySexagesimalToDouble( double& value, const ustring_base& separator ) const noexcept
7214  {
7215  return TrySexagesimalToDouble( value, IsoString( separator ) );
7216  }
7217 
7230  bool TrySexagesimalToDouble( double& value, const Array<char_type>& separators ) const noexcept
7231  {
7232  int sign, s1, s2; double s3;
7233  if ( TryParseSexagesimal( sign, s1, s2, s3, separators ) )
7234  {
7235  value = sign*(s1 + (s2 + s3/60)/60);
7236  return true;
7237  }
7238  return false;
7239  }
7240 
7267  void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const IsoString& separator = ':' ) const;
7268 
7269  void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, char separator ) const
7270  {
7271  ParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) );
7272  }
7273 
7274  void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const ustring_base& separator ) const
7275  {
7276  ParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) );
7277  }
7278 
7293  void ParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array<char_type>& separators ) const;
7294 
7309  bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const IsoString& separator = ':' ) const noexcept;
7310 
7311  bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, char separator ) const noexcept
7312  {
7313  return TryParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) );
7314  }
7315 
7316  bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const ustring_base& separator ) const noexcept
7317  {
7318  return TryParseSexagesimal( sign, s1, s2, s3, IsoString( separator ) );
7319  }
7320 
7334  bool TryParseSexagesimal( int& sign, int& s1, int& s2, double& s3, const Array<char_type>& separators ) const noexcept;
7335 
7360  static IsoString ToSexagesimal( int sign, double s1, double s2, double s3,
7362 
7374  {
7375  return ToSexagesimal( (d < 0) ? -1 : +1, Abs( d ), 0, 0, options );
7376  }
7377 
7401  void ParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const;
7402 
7416  bool TryParseISO8601DateTime( int& year, int& month, int& day, double& dayf, double& tz ) const noexcept;
7417 
7441  static IsoString ToISO8601DateTime( int year, int month, int day, double dayf, double tz = 0,
7443 
7454  static IsoString CurrentUTCISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() );
7455 
7466  static IsoString CurrentLocalISO8601DateTime( const ISO8601ConversionOptions& options = ISO8601ConversionOptions() );
7467 
7475  static IsoString ToHex( const void* data, size_type length );
7476 
7489  template <class C>
7490  static IsoString ToHex( const C& c )
7491  {
7492  return ToHex( c.Begin(), c.Length()*sizeof( *c.Begin() ) );
7493  }
7494 
7505  static IsoString ToBase64( const void* data, size_type length );
7506 
7519  template <class C>
7520  static IsoString ToBase64( const C& c )
7521  {
7522  return ToBase64( c.Begin(), c.Length()*sizeof( *c.Begin() ) );
7523  }
7524 
7533  {
7534  return ByteArray( Begin(), End() );
7535  }
7536 
7549  ByteArray FromHex() const;
7550 
7563  ByteArray FromBase64() const;
7564 
7571  static IsoString Random( size_type n, RandomizationOptions options = RandomizationOption::Default );
7572 
7584  static IsoString UUID();
7585 };
7586 
7587 // ----------------------------------------------------------------------------
7588 
7598 {
7599  IsoString s( s1 );
7600  s.Append( s2 );
7601  return s;
7602 }
7603 
7610 {
7611  s1.Append( s2 );
7612  return IsoString( std::move( s1 ) );
7613 }
7614 
7621 {
7622  s1.Append( s2 );
7623  return std::move( s1 );
7624 }
7625 
7632 {
7633  s2.Prepend( s1 );
7634  return IsoString( std::move( s2 ) );
7635 }
7636 
7643 {
7644  s2.Prepend( s1 );
7645  return std::move( s2 );
7646 }
7647 
7654 {
7655  s1.Append( s2 );
7656  return IsoString( std::move( s1 ) );
7657 }
7658 
7665 {
7666  s1.Append( s2 );
7667  return std::move( s1 );
7668 }
7669 
7676 {
7677  s1.Append( s2 );
7678  return IsoString( std::move( s1 ) );
7679 }
7680 
7687 {
7688  s1.Append( s2 );
7689  return std::move( s1 );
7690 }
7691 
7692 // ----------------------------------------------------------------------------
7693 
7700 {
7701  IsoString s = s1;
7702  s.Append( t2 );
7703  return s;
7704 }
7705 
7712 {
7713  s1.Append( t2 );
7714  return IsoString( std::move( s1 ) );
7715 }
7716 
7723 {
7724  s1.Append( t2 );
7725  return std::move( s1 );
7726 }
7727 
7734 {
7735  IsoString s = s2;
7736  s.Prepend( t1 );
7737  return s;
7738 }
7739 
7746 {
7747  s2.Prepend( t1 );
7748  return IsoString( std::move( s2 ) );
7749 }
7750 
7757 {
7758  s2.Prepend( t1 );
7759  return std::move( s2 );
7760 }
7761 
7762 // ----------------------------------------------------------------------------
7763 
7770 {
7771  IsoString s = s1;
7772  s.Append( c2 );
7773  return s;
7774 }
7775 
7782 {
7783  s1.Append( c2 );
7784  return IsoString( std::move( s1 ) );
7785 }
7786 
7793 {
7794  s1.Append( c2 );
7795  return std::move( s1 );
7796 }
7797 
7804 {
7805  IsoString s = s2;
7806  s.Prepend( c1 );
7807  return s;
7808 }
7809 
7816 {
7817  s2.Prepend( c1 );
7818  return IsoString( std::move( s2 ) );
7819 }
7820 
7827 {
7828  s2.Prepend( c1 );
7829  return std::move( s2 );
7830 }
7831 
7832 // ----------------------------------------------------------------------------
7833 
7840 {
7841  s1.Append( s2 );
7842  return s1;
7843 }
7844 
7851 {
7852  s1.Append( s2 );
7853  return s1;
7854 }
7855 
7862 {
7863  s1.Append( t2 );
7864  return s1;
7865 }
7866 
7873 {
7874  s1.Append( t2 );
7875  return s1;
7876 }
7877 
7884 {
7885  s1.Append( c2 );
7886  return s1;
7887 }
7888 
7895 {
7896  s1.Append( c2 );
7897  return s1;
7898 }
7899 
7900 // ----------------------------------------------------------------------------
7901 
7902 #ifndef __PCL_NO_STRING_OSTREAM
7903 
7904 inline std::ostream& operator <<( std::ostream& o, const IsoString& s )
7905 {
7906  return o << s.c_str();
7907 }
7908 
7909 #endif
7910 
7911 // ----------------------------------------------------------------------------
7912 
7923 class PCL_CLASS String : public GenericString<char16_type, CharTraits, PCL_STRING_ALLOCATOR>
7924 {
7925 public:
7926 
7932 
7937 
7942 
7947 
7952 
7957 
7962 
7963  /*
7964  * Null-terminated UTF-16 string - C++11 compatibility.
7965  */
7966  typedef char16_t* c16_string;
7967 
7968  /*
7969  * Immutable null-terminated UTF-16 string - C++11 compatibility.
7970  */
7971  typedef const char16_t* const_c16_string;
7972 
7977 
7982 
7987 
7992 
8002 
8007 
8012 
8017 
8022 
8027 
8032 
8033  // -------------------------------------------------------------------------
8034 
8038  String() = default;
8039 
8044  String( const string_base& s )
8045  : string_base( s )
8046  {
8047  }
8048 
8052  String( const String& ) = default;
8053 
8059  : string_base( std::move( s ) )
8060  {
8061  }
8062 
8066  String( String&& ) = default;
8067 
8072  String( const string8_base& s )
8073  {
8074  Assign( s );
8075  }
8076 
8080  String( const_iterator t )
8081  : string_base( t )
8082  {
8083  }
8084 
8089  String( const_iterator t, size_type i, size_type n )
8090  : string_base( t, i, n )
8091  {
8092  }
8093 
8097  String( char_type c, size_type n )
8098  : string_base( c, n )
8099  {
8100  }
8101 
8106  String( const_iterator i, const_iterator j )
8107  : string_base( i, j )
8108  {
8109  }
8110 
8119  String( std::initializer_list<char_type> l )
8120  : String( l.begin(), l.end() )
8121  {
8122  }
8123 
8128  String( const char16_t* t )
8129  : string_base( reinterpret_cast<const_iterator>( t ) )
8130  {
8131  }
8132 
8138  String( const char16_t* t, size_type i, size_type n )
8139  : string_base( reinterpret_cast<const_iterator>( t ), i, n )
8140  {
8141  }
8142 
8146  String( char16_t c, size_type n )
8147  : string_base( char_type( c ), n )
8148  {
8149  }
8150 
8155  String( const wchar_t* t )
8156  {
8157  Assign( t );
8158  }
8159 
8165  String( const wchar_t* t, size_type i, size_type n )
8166  {
8167  Assign( t, i, n );
8168  }
8169 
8173  String( wchar_t c, size_type n )
8174  : string_base( char_type( c ), n )
8175  {
8176  }
8177 
8182  String( const_c_string8 t )
8183  {
8184  Assign( t );
8185  }
8186 
8192  String( const_c_string8 t, size_type i, size_type n )
8193  {
8194  Assign( t, i, n );
8195  }
8196 
8201  String( const_char8_iterator i, const_char8_iterator j )
8202  {
8203  Assign( i, j );
8204  }
8205 
8214  String( std::initializer_list<char8_type> l )
8215  : String( l.begin(), l.end() )
8216  {
8217  }
8218 
8223  String( char8_type c, size_type n = 1 )
8224  : string_base( char_type( c ), n )
8225  {
8226  }
8227 
8231  explicit
8232  String( bool x )
8233  {
8234  Assign( x ? "true" : "false" );
8235  }
8236 
8241  explicit
8242  String( short x )
8243  {
8244  (void)Format( L"%hd", x );
8245  }
8246 
8251  explicit
8252  String( unsigned short x )
8253  {
8254  (void)Format( L"%hu", x );
8255  }
8256 
8261  explicit
8262  String( int x )
8263  {
8264  (void)Format( L"%i", x );
8265  }
8266 
8271  explicit
8272  String( unsigned int x )
8273  {
8274  (void)Format( L"%u", x );
8275  }
8276 
8281  explicit
8282  String( long x )
8283  {
8284  (void)Format( L"%ld", x );
8285  }
8286 
8291  explicit
8292  String( unsigned long x )
8293  {
8294  (void)Format( L"%lu", x );
8295  }
8296 
8301  explicit
8302  String( long long x )
8303  {
8304  (void)Format( L"%lli", x );
8305  }
8306 
8311  explicit
8312  String( unsigned long long x )
8313  {
8314  (void)Format( L"%llu", x );
8315  }
8316 
8321  explicit
8322  String( float x )
8323  {
8324  (void)Format( L"%.7g", x );
8325  }
8326 
8331  explicit
8332  String( double x )
8333  {
8334  (void)Format( L"%.16g", x );
8335  }
8336 
8341  explicit
8342  String( long double x )
8343  {
8344 #ifdef _MSC_VER
8345  (void)Format( L"%.16Lg", x );
8346 #else
8347  (void)Format( L"%.18Lg", x );
8348 #endif
8349  }
8350 
8351 #ifndef __PCL_NO_STRING_COMPLEX
8352 
8356  explicit
8358  {
8359  (void)Format( L"{%.7g,%.7g}", x.Real(), x.Imag() );
8360  }
8361 
8365  explicit
8367  {
8368  (void)Format( L"{%.16g,%.16g}", x.Real(), x.Imag() );
8369  }
8370 
8374  explicit
8376  {
8377 #ifdef _MSC_VER
8378  (void)Format( L"{%.16Lg,%.16Lg}", x.Real(), x.Imag() );
8379 #else
8380  (void)Format( L"{%.18Lg,%.18Lg}", x.Real(), x.Imag() );
8381 #endif
8382  }
8383 
8384 #endif // !__PCL_NO_STRING_COMPLEX
8385 
8386 #ifdef __PCL_QT_INTERFACE
8387 
8388  explicit
8389  String( const QString& qs )
8390  : string_base( qs.isEmpty() ? iterator( nullptr ) : iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) ) )
8391  {
8392  }
8393 
8394  explicit
8395  String( const QDate& qd )
8396  : string_base( iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) ) )
8397  {
8398  }
8399 
8400  explicit
8401  String( const QDateTime& qdt )
8402  : string_base( iterator( PCL_GET_CHAR16PTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) ) )
8403  {
8404  }
8405 
8406 #endif
8407 
8408  // -------------------------------------------------------------------------
8409 
8413  String& operator =( const String& s )
8414  {
8415  string_base::Assign( s );
8416  return *this;
8417  }
8418 
8422  String& operator =( String&& s )
8423  {
8424  string_base::Transfer( s );
8425  return *this;
8426  }
8427 
8432  String& operator =( const string_base& s )
8433  {
8434  string_base::Assign( s );
8435  return *this;
8436  }
8437 
8442  String& operator =( string_base&& s )
8443  {
8444  string_base::Transfer( s );
8445  return *this;
8446  }
8447 
8452  String& operator =( const string8_base& s )
8453  {
8454  Assign( s );
8455  return *this;
8456  }
8457 
8462  String& operator =( const_iterator t )
8463  {
8464  string_base::Assign( t );
8465  return *this;
8466  }
8467 
8472  String& operator =( char_type c )
8473  {
8474  string_base::Assign( c );
8475  return *this;
8476  }
8477 
8482  String& operator =( const char16_t* t )
8483  {
8484  string_base::Assign( reinterpret_cast<const_iterator>( t ) );
8485  return *this;
8486  }
8487 
8492  String& operator =( char16_t c )
8493  {
8494  string_base::Assign( char_type( c ) );
8495  return *this;
8496  }
8497 
8502  String& operator =( const wchar_t* t )
8503  {
8504  Assign( t );
8505  return *this;
8506  }
8507 
8512  String& operator =( wchar_t c )
8513  {
8514  Assign( c );
8515  return *this;
8516  }
8517 
8522  String& operator =( const_c_string8 t )
8523  {
8524  Assign( t );
8525  return *this;
8526  }
8527 
8532  String& operator =( char8_type c )
8533  {
8534  Assign( c );
8535  return *this;
8536  }
8537 
8538 #ifdef __PCL_QT_INTERFACE
8539 
8540  String& operator =( const QString& qs )
8541  {
8542  if ( qs.isEmpty() )
8543  Clear();
8544  else
8545  string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qs ) );
8546  return *this;
8547  }
8548 
8549  String& operator =( const QDate& qd )
8550  {
8551  string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qd.toString( PCL_QDATE_FMT_STR ) ) );
8552  return *this;
8553  }
8554 
8555  String& operator =( const QDateTime& qdt )
8556  {
8557  string_base::Assign( PCL_GET_CHAR16PTR_FROM_QSTRING( qdt.toString( PCL_QDATETIME_FMT_STR ) ) );
8558  return *this;
8559  }
8560 
8561 #endif
8562 
8563  // -------------------------------------------------------------------------
8564 
8568  void Assign( const String& s )
8569  {
8570  string_base::Assign( s );
8571  }
8572 
8577  void Assign( const String& s, size_type i, size_type n )
8578  {
8579  string_base::Assign( s, i, n );
8580  }
8581 
8585  void Assign( const_iterator t )
8586  {
8587  string_base::Assign( t );
8588  }
8589 
8594  void Assign( const_iterator i, const_iterator j )
8595  {
8596  string_base::Assign( i, j );
8597  }
8598 
8605  void Assign( std::initializer_list<char_type> l )
8606  {
8607  Assign( l.begin(), l.end() );
8608  }
8609 
8615  void Assign( const_iterator t, size_type i, size_type n )
8616  {
8617  string_base::Assign( t, i, n );
8618  }
8619 
8623  void Assign( char_type c, size_type n = 1 )
8624  {
8625  string_base::Assign( c, n );
8626  }
8627 
8631  void Assign( const char16_t* t )
8632  {
8633  string_base::Assign( reinterpret_cast<const_iterator>( t ) );
8634  }
8635 
8641  void Assign( const char16_t* t, size_type i, size_type n )
8642  {
8643  string_base::Assign( reinterpret_cast<const_iterator>( t ), i, n );
8644  }
8645 
8649  void Assign( char16_t c, size_type n = 1 )
8650  {
8651  string_base::Assign( char_type( c ), n );
8652  }
8653 
8657  void Assign( const wchar_t* t );
8658 
8664  void Assign( const wchar_t* t, size_type i, size_type n );
8665 
8669  void Assign( wchar_t c, size_type n = 1 )
8670  {
8671  string_base::Assign( char_type( c ), n );
8672  }
8673 
8677  void Assign( const string8_base& s )
8678  {
8679  size_type n = s.Length();
8680  if ( n > 0 )
8681  {
8682  MaybeReallocate( n );
8683  const_char8_iterator t = s.Begin();
8684  PCL_IVDEP
8685  for ( iterator i = m_data->string; i < m_data->end; ++i, ++t )
8686  *i = char_type( uint8( *t ) );
8687  }
8688  else
8689  Clear();
8690  }
8691 
8696  void Assign( const_c_string8 t )
8697  {
8698  size_type n = char8_traits::Length( t );
8699  if ( n > 0 )
8700  {
8701  MaybeReallocate( n );
8702  PCL_IVDEP
8703  for ( iterator i = m_data->string; i < m_data->end; ++i, ++t )
8704  *i = char_type( uint8( *t ) );
8705  }
8706  else
8707  Clear();
8708  }
8709 
8715  void Assign( const_c_string8 t, size_type i, size_type n )
8716  {
8717  size_type len = char8_traits::Length( t );
8718  if ( i < len )
8719  {
8720  n = pcl::Min( n, len-i );
8721  MaybeReallocate( n );
8722  t += i;
8723  PCL_IVDEP
8724  for ( iterator i = m_data->string; i < m_data->end; ++i, ++t )
8725  *i = char_type( uint8( *t ) );
8726  }
8727  else
8728  Clear();
8729  }
8730 
8735  void Assign( const_char8_iterator p, const_char8_iterator q )
8736  {
8737  if ( p < q )
8738  {
8739  MaybeReallocate( q - p );
8740  PCL_IVDEP
8741  for ( iterator i = m_data->string; i < m_data->end; ++i, ++p )
8742  *i = char_type( uint8( *p ) );
8743  }
8744  else
8745  Clear();
8746  }
8747 
8755  void Assign( std::initializer_list<char8_type> l )
8756  {
8757  Assign( l.begin(), l.end() );
8758  }
8759 
8763  void Assign( char8_type c, size_type n = 1 )
8764  {
8765  string_base::Assign( char_type( c ), n );
8766  }
8767 
8768  // -------------------------------------------------------------------------
8769 
8770  void Insert( size_type i, const String& s )
8771  {
8772  string_base::Insert( i, s );
8773  }
8774 
8775  void Insert( size_type i, const_iterator p, const_iterator q )
8776  {
8777  string_base::Insert( i, p, q );
8778  }
8779 
8780  void Insert( size_type i, const_iterator t )
8781  {
8782  string_base::Insert( i, t );
8783  }
8784 
8785  void Insert( size_type i, const_iterator t, size_type n )
8786  {
8787  string_base::Insert( i, t, n );
8788  }
8789 
8790  void Insert( size_type i, char_type c, size_type n = 1 )
8791  {
8792  string_base::Insert( i, c, n );
8793  }
8794 
8795  void Insert( size_type i, const char16_t* t )
8796  {
8797  string_base::Insert( i, reinterpret_cast<const_iterator>( t ) );
8798  }
8799 
8800  void Insert( size_type i, char16_t c, size_type n = 1 )
8801  {
8802  string_base::Insert( i, String( c, n ) );
8803  }
8804 
8805  void Insert( size_type i, const wchar_t* t )
8806  {
8807 #ifdef __PCL_WINDOWS
8808  string_base::Insert( i, reinterpret_cast<const_iterator>( t ) );
8809 #else
8810  string_base::Insert( i, String( t ) );
8811 #endif
8812  }
8813 
8814  void Insert( size_type i, wchar_t c, size_type n = 1 )
8815  {
8816  string_base::Insert( i, String( c, n ) );
8817  }
8818 
8819  void Insert( size_type i, const string8_base& s, size_type n )
8820  {
8821  n = pcl::Min( n, s.Length() );
8822  if ( n > 0 )
8823  {
8824  UninitializedGrow( i, n ); // -> 0 <= i <= len
8825  const_char8_iterator t = s.Begin();
8826  PCL_IVDEP
8827  for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t )
8828  *p = char_type( uint8( *t ) );
8829  }
8830  }
8831 
8832  void Insert( size_type i, const string8_base& s )
8833  {
8834  size_type n = s.Length();
8835  if ( n > 0 )
8836  {
8837  UninitializedGrow( i, n ); // -> 0 <= i <= len
8838  const_char8_iterator t = s.Begin();
8839  PCL_IVDEP
8840  for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t )
8841  *p = char_type( uint8( *t ) );
8842  }
8843  }
8844 
8845  void Insert( size_type i, const_c_string8 t )
8846  {
8847  size_type n = char8_traits::Length( t );
8848  if ( n > 0 )
8849  {
8850  UninitializedGrow( i, n ); // -> 0 <= i <= len
8851  PCL_IVDEP
8852  for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t )
8853  *p = char_type( uint8( *t ) );
8854  }
8855  }
8856 
8857  void Insert( size_type i, const_c_string8 t, size_type n )
8858  {
8859  n = pcl::Min( n, char8_traits::Length( t ) );
8860  if ( n > 0 )
8861  {
8862  UninitializedGrow( i, n ); // -> 0 <= i <= len
8863  PCL_IVDEP
8864  for ( iterator p = m_data->string+i, q = p+n; p < q; ++p, ++t )
8865  *p = char_type( uint8( *t ) );
8866  }
8867  }
8868 
8869  void Insert( size_type i, const_char8_iterator p, const_char8_iterator q )
8870  {
8871  if ( p < q )
8872  {
8873  size_type n = q - p;
8874  UninitializedGrow( i, n ); // -> 0 <= i <= len
8875  PCL_IVDEP
8876  for ( iterator r = m_data->string+i, s = r+n; r < s; ++r, ++p )
8877  *r = char_type( uint8( *p ) );
8878  }
8879  }
8880 
8881  void Insert( size_type i, char8_type c, size_type n = 1 )
8882  {
8883  string_base::Insert( i, char_type( c ), n );
8884  }
8885 
8886  // -------------------------------------------------------------------------
8887 
8888  void Append( const String& s )
8889  {
8890  string_base::Append( s );
8891  }
8892 
8893  String& operator +=( const String& s )
8894  {
8895  Append( s );
8896  return *this;
8897  }
8898 
8899  void Append( const_iterator i, const_iterator j )
8900  {
8901  string_base::Append( i, j );
8902  }
8903 
8904  void Append( const_iterator t )
8905  {
8906  string_base::Append( t );
8907  }
8908 
8909  String& operator +=( const_iterator t )
8910  {
8911  Append( t );
8912  return *this;
8913  }
8914 
8915  void Append( const_iterator t, size_type n )
8916  {
8917  string_base::Append( t, n );
8918  }
8919 
8920  void Append( char_type c, size_type n = 1 )
8921  {
8922  string_base::Append( c, n );
8923  }
8924 
8925  String& operator +=( char_type c )
8926  {
8927  Append( c );
8928  return *this;
8929  }
8930 
8931  void Append( const char16_t* t )
8932  {
8933  string_base::Append( reinterpret_cast<const_iterator>( t ) );
8934  }
8935 
8936  String& operator +=( const char16_t* t )
8937  {
8938  Append( t );
8939  return *this;
8940  }
8941 
8942  void Append( char16_t c, size_type n = 1 )
8943  {
8944  string_base::Append( char_type( c ), n );
8945  }
8946 
8947  String& operator +=( char16_t c )
8948  {
8949  Append( c );
8950  return *this;
8951  }
8952 
8953  void Append( const wchar_t* t )
8954  {
8955 #ifdef __PCL_WINDOWS
8956  string_base::Append( reinterpret_cast<const_iterator>( t ) );
8957 #else
8958  string_base::Append( String( t ) );
8959 #endif
8960  }
8961 
8962  String& operator +=( const wchar_t* t )
8963  {
8964  Append( t );
8965  return *this;
8966  }
8967 
8968  void Append( wchar_t c, size_type n = 1 )
8969  {
8970  string_base::Append( char_type( c ), n );
8971  }
8972 
8973  String& operator +=( wchar_t c )
8974  {
8975  Append( c );
8976  return *this;
8977  }
8978 
8979  void Append( const string8_base& s )
8980  {
8981  Insert( maxPos, s );
8982  }
8983 
8984  String& operator +=( const string8_base& s )
8985  {
8986  Append( s );
8987  return *this;
8988  }
8989 
8990  void Append( const string8_base& s, size_type n )
8991  {
8992  Insert( maxPos, s, n );
8993  }
8994 
8995  void Append( const_c_string8 t )
8996  {
8997  Insert( maxPos, t );
8998  }
8999 
9000  String& operator +=( const_c_string8 t )
9001  {
9002  Append( t );
9003  return *this;
9004  }
9005 
9006  void Append( const_c_string8 t, size_type n )
9007  {
9008  Insert( maxPos, t, n );
9009  }
9010 
9011  void Append( const_char8_iterator p, const_char8_iterator q )
9012  {
9013  Insert( maxPos, p, q );
9014  }
9015 
9016  void Append( char8_type c, size_type n = 1 )
9017  {
9018  string_base::Append( char_type( c ), n );
9019  }
9020 
9021  String& operator +=( char8_type c )
9022  {
9023  Append( c );
9024  return *this;
9025  }
9026 
9027  void Add( const String& s )
9028  {
9029  Append( s );
9030  }
9031 
9032  void Add( const_iterator i, const_iterator j )
9033  {
9034  Append( i, j );
9035  }
9036 
9037  void Add( const_iterator t )
9038  {
9039  Append( t );
9040  }
9041 
9042  void Add( const_iterator t, size_type n )
9043  {
9044  Append( t, n );
9045  }
9046 
9047  void Add( char_type c, size_type n = 1 )
9048  {
9049  Append( c, n );
9050  }
9051 
9052  void Add( const char16_t* t )
9053  {
9054  Append( t );
9055  }
9056 
9057  void Add( char16_t c, size_type n = 1 )
9058  {
9059  Append( c, n );
9060  }
9061 
9062  void Add( const wchar_t* t )
9063  {
9064  Append( t );
9065  }
9066 
9067  void Add( wchar_t c, size_type n = 1 )
9068  {
9069  Append( c, n );
9070  }
9071 
9072  void Add( const string8_base& s )
9073  {
9074  Append( s );
9075  }
9076 
9077  void Add( const string8_base& s, size_type n )
9078  {
9079  Append( s, n );
9080  }
9081 
9082  void Add( const_c_string8 t )
9083  {
9084  Append( t );
9085  }
9086 
9087  void Add( const_c_string8 t, size_type n )
9088  {
9089  Append( t, n );
9090  }
9091 
9092  void Add( const_char8_iterator p, const_char8_iterator q )
9093  {
9094  Append( p, q );
9095  }
9096 
9097  void Add( char8_type c, size_type n = 1 )
9098  {
9099  Append( c, n );
9100  }
9101 
9102  // -------------------------------------------------------------------------
9103 
9104  void Prepend( const String& s )
9105  {
9106  string_base::Prepend( s );
9107  }
9108 
9109  String& operator -=( const String& s )
9110  {
9111  Prepend( s );
9112  return *this;
9113  }
9114 
9115  void Prepend( const_iterator i, const_iterator j )
9116  {
9117  string_base::Prepend( i, j );
9118  }
9119 
9120  void Prepend( const_iterator t )
9121  {
9122  string_base::Prepend( t );
9123  }
9124 
9125  String& operator -=( const_iterator t )
9126  {
9127  Prepend( t );
9128  return *this;
9129  }
9130 
9131  void Prepend( const_iterator t, size_type n )
9132  {
9133  string_base::Prepend( t, n );
9134  }
9135 
9136  void Prepend( char_type c, size_type n = 1 )
9137  {
9138  string_base::Prepend( c, n );
9139  }
9140 
9141  String& operator -=( char_type c )
9142  {
9143  Prepend( c );
9144  return *this;
9145  }
9146 
9147  void Prepend( const char16_t* t )
9148  {
9149  string_base::Prepend( reinterpret_cast<const_iterator>( t ) );
9150  }
9151 
9152  String& operator -=( const char16_t* t )
9153  {
9154  Prepend( t );
9155  return *this;
9156  }
9157 
9158  void Prepend( char16_t c, size_type n = 1 )
9159  {
9160  string_base::Prepend( char_type( c ), n );
9161  }
9162 
9163  String& operator -=( char16_t c )
9164  {
9165  Prepend( c );
9166  return *this;
9167  }
9168 
9169  void Prepend( const wchar_t* t )
9170  {
9171 #ifdef __PCL_WINDOWS
9172  string_base::Prepend( reinterpret_cast<const_iterator>( t ) );
9173 #else
9174  string_base::Prepend( String( t ) );
9175 #endif
9176  }
9177 
9178  String& operator -=( const wchar_t* t )
9179  {
9180  Prepend( t );
9181  return *this;
9182  }
9183 
9184  void Prepend( wchar_t c, size_type n = 1 )
9185  {
9186  string_base::Prepend( char_type( c ), n );
9187  }
9188 
9189  String& operator -=( wchar_t c )
9190  {
9191  Prepend( c );
9192  return *this;
9193  }
9194 
9195  void Prepend( const string8_base& s )
9196  {
9197  Insert( 0, s );
9198  }
9199 
9200  String& operator -=( const string8_base& s )
9201  {
9202  Prepend( s );
9203  return *this;
9204  }
9205 
9206  void Prepend( const string8_base& s, size_type n )
9207  {
9208  Insert( 0, s, n );
9209  }
9210 
9211  void Prepend( const_c_string8 t )
9212  {
9213  Insert( 0, t );
9214  }
9215 
9216  String& operator -=( const_c_string8 t )
9217  {
9218  Prepend( t );
9219  return *this;
9220  }
9221 
9222  void Prepend( const_c_string8 t, size_type n )
9223  {
9224  Insert( 0, t, n );
9225  }
9226 
9227  void Prepend( const_char8_iterator p, const_char8_iterator q )
9228  {
9229  Insert( 0, p, q );
9230  }
9231 
9232  void Prepend( char8_type c, size_type n = 1 )
9233  {
9234  string_base::Prepend( String( c, n ) );
9235  }
9236 
9237  String& operator -=( char8_type c )
9238  {
9239  Prepend( c );
9240  return *this;
9241  }
9242 
9243  // -------------------------------------------------------------------------
9244 
9245  void Replace( size_type i, size_type n, const String& s )
9246  {
9247  string_base::Replace( i, n, s );
9248  }
9249 
9250  void Replace( size_type i, size_type n, const_iterator t )
9251  {
9252  string_base::Replace( i, n, t );
9253  }
9254 
9255  void Replace( size_type i, size_type n, char_type c, size_type nc = 1 )
9256  {
9257  string_base::Replace( i, n, c, nc );
9258  }
9259 
9260  void Replace( size_type i, size_type n, const char16_t* t )
9261  {
9262  string_base::Replace( i, n, reinterpret_cast<const_iterator>( t ) );
9263  }
9264 
9265  void Replace( size_type i, size_type n, char16_t c, size_type nc = 1 )
9266  {
9267  string_base::Replace( i, n, char_type( c ), nc );
9268  }
9269 
9270  void Replace( size_type i, size_type n, const wchar_t* t )
9271  {
9272 #ifdef __PCL_WINDOWS
9273  string_base::Replace( i, n, reinterpret_cast<const_iterator>( t ) );
9274 #else
9275  string_base::Replace( i, n, String( t ) );
9276 #endif
9277  }
9278 
9279  void Replace( size_type i, size_type n, wchar_t c, size_type nc = 1 )
9280  {
9281  string_base::Replace( i, n, char_type( c ), nc );
9282  }
9283 
9284  void Replace( size_type i, size_type n, const_c_string8 t )
9285  {
9286  if ( n > 0 )
9287  {
9288  size_type len = Length();
9289  if ( i < len )
9290  {
9291  n = pcl::Min( n, len-i );
9292  if ( n == len )
9293  Assign( t );
9294  else
9295  {
9296  size_type nt = char8_traits::Length( t );
9297  if ( nt > 0 )
9298  {
9299  if ( n < nt )
9300  UninitializedGrow( i, nt-n );
9301  else if ( nt < n )
9302  Delete( i, n-nt );
9303  else
9304  EnsureUnique();
9305 
9306  PCL_IVDEP
9307  for ( iterator p = m_data->string+i, q = p+nt; p < q; ++p, ++t )
9308  *p = char_type( *t );
9309  }
9310  else
9311  Delete( i, n );
9312  }
9313  }
9314  }
9315  }
9316 
9317  void Replace( size_type i, size_type n, char8_type c, size_type nc = 1 )
9318  {
9319  string_base::Replace( i, n, char_type( c ), nc );
9320  }
9321 
9322  // -------------------------------------------------------------------------
9323 
9324  void ReplaceChar( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos )
9325  {
9326  string_base::ReplaceChar( c1, c2, i, n );
9327  }
9328 
9329  void ReplaceCharIC( char_type c1, char_type c2, size_type i = 0, size_type n = maxPos )
9330  {
9331  string_base::ReplaceCharIC( c1, c2, i, n );
9332  }
9333 
9334  void ReplaceChar( char16_t c1, char16_t c2, size_type i = 0, size_type n = maxPos )
9335  {
9336  string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n );
9337  }
9338 
9339  void ReplaceCharIC( char16_t c1, char16_t c2, size_type i = 0, size_type n = maxPos )
9340  {
9341  string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n );
9342  }
9343 
9344  void ReplaceChar( wchar_t c1, wchar_t c2, size_type i = 0, size_type n = maxPos )
9345  {
9346  string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n );
9347  }
9348 
9349  void ReplaceCharIC( wchar_t c1, wchar_t c2, size_type i = 0, size_type n = maxPos )
9350  {
9351  string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n );
9352  }
9353 
9354  void ReplaceChar( char8_type c1, char8_type c2, size_type i = 0, size_type n = maxPos )
9355  {
9356  string_base::ReplaceChar( char_type( c1 ), char_type( c2 ), i, n );
9357  }
9358 
9359  void ReplaceCharIC( char8_type c1, char8_type c2, size_type i = 0, size_type n = maxPos )
9360  {
9361  string_base::ReplaceCharIC( char_type( c1 ), char_type( c2 ), i, n );
9362  }
9363 
9364  // -------------------------------------------------------------------------
9365 
9366  void ReplaceString( const String& s1, const String& s2, size_type i = 0 )
9367  {
9368  string_base::ReplaceString( s1, s2, i );
9369  }
9370 
9371  void ReplaceStringIC( const String& s1, const String& s2, size_type i = 0 )
9372  {
9373  string_base::ReplaceStringIC( s1, s2, i );
9374  }
9375 
9376  void ReplaceString( const_iterator t1, const_iterator t2, size_type i = 0 )
9377  {
9378  string_base::ReplaceString( t1, t2, i );
9379  }
9380 
9381  void ReplaceStringIC( const_iterator t1, const_iterator t2, size_type i = 0 )
9382  {
9383  string_base::ReplaceStringIC( t1, t2, i );
9384  }
9385 
9386  void ReplaceString( const char16_t* t1, const char16_t* t2, size_type i = 0 )
9387  {
9388  string_base::ReplaceString( reinterpret_cast<const_iterator>( t1 ),
9389  reinterpret_cast<const_iterator>( t2 ), i );
9390  }
9391 
9392  void ReplaceStringIC( const char16_t* t1, const char16_t* t2, size_type i = 0 )
9393  {
9394  string_base::ReplaceStringIC( reinterpret_cast<const_iterator>( t1 ),
9395  reinterpret_cast<const_iterator>( t2 ), i );
9396  }
9397 
9398  void ReplaceString( const wchar_t* t1, const wchar_t* t2, size_type i = 0 )
9399  {
9400 #ifdef __PCL_WINDOWS
9401  string_base::ReplaceString( reinterpret_cast<const_iterator>( t1 ),
9402  reinterpret_cast<const_iterator>( t2 ), i );
9403 #else
9404  string_base::ReplaceString( String( t1 ), String( t2 ), i );
9405 #endif
9406  }
9407 
9408  void ReplaceStringIC( const wchar_t* t1, const wchar_t* t2, size_type i = 0 )
9409  {
9410 #ifdef __PCL_WINDOWS
9411  string_base::ReplaceStringIC( reinterpret_cast<const_iterator>( t1 ),
9412  reinterpret_cast<const_iterator>( t2 ), i );
9413 #else
9414  string_base::ReplaceStringIC( String( t1 ), String( t2 ), i );
9415 #endif
9416  }
9417 
9418  void ReplaceString( const_c_string8 t1, const_c_string8 t2, size_type i = 0 )
9419  {
9420  string_base::ReplaceString( String( t1 ), String( t2 ), i );
9421  }
9422 
9423  void ReplaceStringIC( const_c_string8 t1, const_c_string8 t2, size_type i = 0 )
9424  {
9425  string_base::ReplaceStringIC( String( t1 ), String( t2 ), i );
9426  }
9427 
9428  // -------------------------------------------------------------------------
9429 
9430  void DeleteChar( char_type c, size_type i = 0 )
9431  {
9432  string_base::DeleteChar( c, i );
9433  }
9434 
9435  void DeleteCharIC( char_type c, size_type i = 0 )
9436  {
9437  string_base::DeleteCharIC( c, i );
9438  }
9439 
9440  void DeleteChar( char16_t c, size_type i = 0 )
9441  {
9442  string_base::DeleteChar( char_type( c ), i );
9443  }
9444 
9445  void DeleteCharIC( char16_t c, size_type i = 0 )
9446  {
9447  string_base::DeleteCharIC( char_type( c ), i );
9448  }
9449 
9450  void DeleteChar( wchar_t c, size_type i = 0 )
9451  {
9452  string_base::DeleteChar( char_type( c ), i );
9453  }
9454 
9455  void DeleteCharIC( wchar_t c, size_type i = 0 )
9456  {
9457  string_base::DeleteCharIC( char_type( c ), i );
9458  }
9459 
9460  void DeleteChar( char8_type c, size_type i = 0 )
9461  {
9462  string_base::DeleteChar( char_type( c ), i );
9463  }
9464 
9465  void DeleteCharIC( char8_type c, size_type i = 0 )
9466  {
9467  string_base::DeleteCharIC( char_type( c ), i );
9468  }
9469 
9470  // -------------------------------------------------------------------------
9471 
9472  void DeleteString( const String& s, size_type i = 0 )
9473  {
9474  string_base::DeleteString( s, i );
9475  }
9476 
9477  void DeleteStringIC( const String& s, size_type i = 0 )
9478  {
9479  string_base::DeleteStringIC( s, i );
9480  }
9481 
9482  void DeleteString( const_iterator t, size_type i = 0 )
9483  {
9484  string_base::DeleteString( t, i );
9485  }
9486 
9487  void DeleteStringIC( const_iterator t, size_type i = 0 )
9488  {
9489  string_base::DeleteStringIC( t, i );
9490  }
9491 
9492  void DeleteString( const char16_t* t, size_type i = 0 )
9493  {
9494  string_base::DeleteString( reinterpret_cast<const_iterator>( t ), i );
9495  }
9496 
9497  void DeleteStringIC( const char16_t* t, size_type i = 0 )
9498  {
9499  string_base::DeleteStringIC( reinterpret_cast<const_iterator>( t ), i );
9500  }
9501 
9502  void DeleteString( const wchar_t* t, size_type i = 0 )
9503  {
9504 #ifdef __PCL_WINDOWS
9505  string_base::DeleteString( reinterpret_cast<const_iterator>( t ), i );
9506 #else
9507  string_base::DeleteString( String( t ), i );
9508 #endif
9509  }
9510 
9511  void DeleteStringIC( const wchar_t* t, size_type i = 0 )
9512  {
9513 #ifdef __PCL_WINDOWS
9514  string_base::DeleteStringIC( reinterpret_cast<const_iterator>( t ), i );
9515 #else
9516  string_base::DeleteStringIC( String( t ), i );
9517 #endif
9518  }
9519 
9520  void DeleteString( const_c_string8 t, size_type i = 0 )
9521  {
9522  string_base::DeleteString( String( t ), i );
9523  }
9524 
9525  void DeleteStringIC( const_c_string8 t, size_type i = 0 )
9526  {
9527  string_base::DeleteStringIC( String( t ), i );
9528  }
9529 
9530  // -------------------------------------------------------------------------
9531 
9532  bool StartsWith( const String& s ) const noexcept
9533  {
9534  return string_base::StartsWith( s );
9535  }
9536 
9537  bool StartsWith( const_iterator t ) const noexcept
9538  {
9539  return string_base::StartsWith( t );
9540  }
9541 
9542  bool StartsWith( char_type c ) const noexcept
9543  {
9544  return string_base::StartsWith( c );
9545  }
9546 
9547  bool StartsWithIC( const String& s ) const noexcept
9548  {
9549  return string_base::StartsWithIC( s );
9550  }
9551 
9552  bool StartsWithIC( const_iterator t ) const noexcept
9553  {
9554  return string_base::StartsWithIC( t );
9555  }
9556 
9557  bool StartsWithIC( char_type c ) const noexcept
9558  {
9559  return string_base::StartsWithIC( c );
9560  }
9561 
9562  bool StartsWith( const char16_t* t ) const noexcept
9563  {
9564  return string_base::StartsWith( reinterpret_cast<const_iterator>( t ) );
9565  }
9566 
9567  bool StartsWith( char16_t c ) const noexcept
9568  {
9569  return string_base::StartsWith( char_type( c ) );
9570  }
9571 
9572  bool StartsWithIC( const char16_t* t ) const noexcept
9573  {
9574  return string_base::StartsWithIC( reinterpret_cast<const_iterator>( t ) );
9575  }
9576 
9577  bool StartsWithIC( char16_t c ) const noexcept
9578  {
9579  return string_base::StartsWithIC( char_type( c ) );
9580  }
9581 
9582  bool StartsWith( const wchar_t* t ) const noexcept
9583  {
9584 #ifdef __PCL_WINDOWS
9585  return string_base::StartsWith( reinterpret_cast<const_iterator>( t ) );
9586 #else
9587  return string_base::StartsWith( String( t ) );
9588 #endif
9589  }
9590 
9591  bool StartsWith( wchar_t c ) const noexcept
9592  {
9593  return string_base::StartsWith( char_type( c ) );
9594  }
9595 
9596  bool StartsWithIC( const wchar_t* t ) const noexcept
9597  {
9598 #ifdef __PCL_WINDOWS
9599  return string_base::StartsWithIC( reinterpret_cast<const_iterator>( t ) );
9600 #else
9601  return string_base::StartsWithIC( String( t ) );
9602 #endif
9603  }
9604 
9605  bool StartsWithIC( wchar_t c ) const noexcept
9606  {
9607  return string_base::StartsWithIC( char_type( c ) );
9608  }
9609 
9610  bool StartsWith( const_c_string8 t ) const noexcept
9611  {
9612  size_type n = char8_traits::Length( t );
9613  if ( n == 0 || Length() < n )
9614  return false;
9615  for ( const_iterator p = m_data->string, q = p+n; p < q; ++p, ++t )
9616  if ( *p != char_type( *t ) )
9617  return false;
9618  return true;
9619  }
9620 
9621  bool StartsWith( char8_type c ) const noexcept
9622  {
9623  return string_base::StartsWith( char_type( c ) );
9624  }
9625 
9626  bool StartsWithIC( const_c_string8 t ) const noexcept
9627  {
9628  size_type n = char8_traits::Length( t );
9629  if ( n == 0 || Length() < n )
9630  return false;
9631  for ( const_iterator p = m_data->string, q = p+n; p < q; ++p, ++t )
9632  if ( char_traits::ToCaseFolded( *p ) != char_type( char8_traits::ToCaseFolded( *t ) ) )
9633  return false;
9634  return true;
9635  }
9636 
9637  bool StartsWithIC( char8_type c ) const noexcept
9638  {
9639  return string_base::StartsWithIC( char_type( c ) );
9640  }
9641 
9642  // -------------------------------------------------------------------------
9643 
9644  bool EndsWith( const String& s ) const noexcept
9645  {
9646  return string_base::EndsWith( s );
9647  }
9648 
9649  bool EndsWith( const_iterator t ) const noexcept
9650  {
9651  return string_base::EndsWith( t );
9652  }
9653 
9654  bool EndsWith( char_type c ) const noexcept
9655  {
9656  return string_base::EndsWith( c );
9657  }
9658 
9659  bool EndsWithIC( const String& s ) const noexcept
9660  {
9661  return string_base::EndsWithIC( s );
9662  }
9663 
9664  bool EndsWithIC( const_iterator t ) const noexcept
9665  {
9666  return string_base::EndsWithIC( t );
9667  }
9668 
9669  bool EndsWithIC( char_type c ) const noexcept
9670  {
9671  return string_base::EndsWithIC( c );
9672  }
9673 
9674  bool EndsWith( const char16_t* t ) const noexcept
9675  {
9676  return string_base::EndsWith( reinterpret_cast<const_iterator>( t ) );
9677  }
9678 
9679  bool EndsWith( char16_t c ) const noexcept
9680  {
9681  return string_base::EndsWith( char_type( c ) );
9682  }
9683 
9684  bool EndsWithIC( const char16_t* t ) const noexcept
9685  {
9686  return string_base::EndsWithIC( reinterpret_cast<const_iterator>( t ) );
9687  }
9688 
9689  bool EndsWithIC( char16_t c ) const noexcept
9690  {
9691  return string_base::EndsWithIC( char_type( c ) );
9692  }
9693 
9694  bool EndsWith( const wchar_t* t ) const noexcept
9695  {
9696 #ifdef __PCL_WINDOWS
9697  return string_base::EndsWith( reinterpret_cast<const_iterator>( t ) );
9698 #else
9699  return string_base::EndsWith( String( t ) );
9700 #endif
9701  }
9702 
9703  bool EndsWith( wchar_t c ) const noexcept
9704  {
9705  return string_base::EndsWith( char_type( c ) );
9706  }
9707 
9708  bool EndsWithIC( const wchar_t* t ) const noexcept
9709  {
9710 #ifdef __PCL_WINDOWS
9711  return string_base::EndsWithIC( reinterpret_cast<const_iterator>( t ) );
9712 #else
9713  return string_base::EndsWithIC( String( t ) );
9714 #endif
9715  }
9716 
9717  bool EndsWithIC( wchar_t c ) const noexcept
9718  {
9719  return string_base::EndsWithIC( char_type( c ) );
9720  }
9721 
9722  bool EndsWith( const_c_string8 t ) const noexcept
9723  {
9724  size_type n = char8_traits::Length( t );
9725  if ( n == 0 || Length() < n )
9726  return false;
9727  for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t )
9728  if ( *p != char_type( *t ) )
9729  return false;
9730  return true;
9731  }
9732 
9733  bool EndsWith( char8_type c ) const noexcept
9734  {
9735  return string_base::EndsWith( char_type( c ) );
9736  }
9737 
9738  bool EndsWithIC( const_c_string8 t ) const noexcept
9739  {
9740  size_type n = char8_traits::Length( t );
9741  if ( n == 0 || Length() < n )
9742  return false;
9743  for ( const_iterator p = m_data->end-n; p < m_data->end; ++p, ++t )
9744  if ( char_traits::ToCaseFolded( *p ) != char_type( char8_traits::ToCaseFolded( *t ) ) )
9745  return false;
9746  return true;
9747  }
9748 
9749  bool EndsWithIC( char8_type c ) const noexcept
9750  {
9751  return string_base::EndsWithIC( char_type( c ) );
9752  }
9753 
9754  // -------------------------------------------------------------------------
9755 
9756  size_type FindFirst( const String& s, size_type i = 0 ) const noexcept
9757  {
9758  return string_base::FindFirst( s, i );
9759  }
9760 
9761  size_type FindFirst( const_iterator t, size_type i = 0 ) const noexcept
9762  {
9763  return string_base::FindFirst( t, i );
9764  }
9765 
9766  size_type FindFirst( char_type c, size_type i = 0 ) const noexcept
9767  {
9768  return string_base::FindFirst( c, i );
9769  }
9770 
9771  size_type FindFirstIC( const String& s, size_type i = 0 ) const noexcept
9772  {
9773  return string_base::FindFirstIC( s, i );
9774  }
9775 
9776  size_type FindFirstIC( const_iterator t, size_type i = 0 ) const noexcept
9777  {
9778  return string_base::FindFirstIC( t, i );
9779  }
9780 
9781  size_type FindFirstIC( char_type c, size_type i = 0 ) const noexcept
9782  {
9783  return string_base::FindFirstIC( c, i );
9784  }
9785 
9786  size_type FindFirst( const char16_t* t, size_type i = 0 ) const noexcept
9787  {
9788  return string_base::FindFirst( reinterpret_cast<const_iterator>( t ), i );
9789  }
9790 
9791  size_type FindFirst( char16_t c, size_type i = 0 ) const noexcept
9792  {
9793  return string_base::FindFirst( char_type( c ), i );
9794  }
9795 
9796  size_type FindFirstIC( const char16_t* t, size_type i = 0 ) const noexcept
9797  {
9798  return string_base::FindFirstIC( reinterpret_cast<const_iterator>( t ), i );
9799  }
9800 
9801  size_type FindFirstIC( char16_t c, size_type i = 0 ) const noexcept
9802  {
9803  return string_base::FindFirstIC( char_type( c ), i );
9804  }
9805 
9806  size_type FindFirst( const wchar_t* t, size_type i = 0 ) const noexcept
9807  {
9808 #ifdef __PCL_WINDOWS
9809  return string_base::FindFirst( reinterpret_cast<const_iterator>( t ), i );
9810 #else
9811  return string_base::FindFirst( String( t ), i );
9812 #endif
9813  }
9814 
9815  size_type FindFirst( wchar_t c, size_type i = 0 ) const noexcept
9816  {
9817  return string_base::FindFirst( char_type( c ), i );
9818  }
9819 
9820  size_type FindFirstIC( const wchar_t* t, size_type i = 0 ) const noexcept
9821  {
9822 #ifdef __PCL_WINDOWS
9823  return string_base::FindFirstIC( reinterpret_cast<const_iterator>( t ), i );
9824 #else
9825  return string_base::FindFirstIC( String( t ), i );
9826 #endif
9827  }
9828 
9829  size_type FindFirstIC( wchar_t c, size_type i = 0 ) const noexcept
9830  {
9831  return string_base::FindFirstIC( char_type( c ), i );
9832  }
9833 
9834  size_type FindFirst( const_c_string8 t, size_type i = 0 ) const noexcept
9835  {
9836  return string_base::FindFirst( String( t ), i );
9837  }
9838 
9839  size_type FindFirst( char8_type c, size_type i = 0 ) const noexcept
9840  {
9841  return string_base::FindFirst( char_type( c ), i );
9842  }
9843 
9844  size_type FindFirstIC( const_c_string8 t, size_type i = 0 ) const noexcept
9845  {
9846  return string_base::FindFirstIC( String( t ), i );
9847  }
9848 
9849  size_type FindFirstIC( char8_type c, size_type i = 0 ) const noexcept
9850  {
9851  return string_base::FindFirstIC( char_type( c ), i );
9852  }
9853 
9854  //
9855 
9856  size_type Find( const String& s, size_type i = 0 ) const noexcept
9857  {
9858  return FindFirst( s, i );
9859  }
9860 
9861  size_type Find( const_iterator t, size_type i = 0 ) const noexcept
9862  {
9863  return FindFirst( t, i );
9864  }
9865 
9866  size_type Find( char_type c, size_type i = 0 ) const noexcept
9867  {
9868  return FindFirst( c, i );
9869  }
9870 
9871  size_type Find( const char16_t* t, size_type i = 0 ) const noexcept
9872  {
9873  return FindFirst( t, i );
9874  }
9875 
9876  size_type Find( char16_t c, size_type i = 0 ) const noexcept
9877  {
9878  return FindFirst( c, i );
9879  }
9880 
9881  size_type Find( const wchar_t* t, size_type i = 0 ) const noexcept
9882  {
9883  return FindFirst( t, i );
9884  }
9885 
9886  size_type Find( wchar_t c, size_type i = 0 ) const noexcept
9887  {
9888  return FindFirst( c, i );
9889  }
9890 
9891  size_type Find( const_c_string8 t, size_type i = 0 ) const noexcept
9892  {
9893  return FindFirst( t, i );
9894  }
9895 
9896  size_type Find( char8_type c, size_type i = 0 ) const noexcept
9897  {
9898  return FindFirst( c, i );
9899  }
9900 
9901  size_type FindIC( const String& s, size_type i = 0 ) const noexcept
9902  {
9903  return FindFirstIC( s, i );
9904  }
9905 
9906  size_type FindIC( const_iterator t, size_type i = 0 ) const noexcept
9907  {
9908  return FindFirstIC( t, i );
9909  }
9910 
9911  size_type FindIC( char_type c, size_type i = 0 ) const noexcept
9912  {
9913  return FindFirstIC( c, i );
9914  }
9915 
9916  size_type FindIC( const char16_t* t, size_type i = 0 ) const noexcept
9917  {
9918  return FindFirstIC( t, i );
9919  }
9920 
9921  size_type FindIC( char16_t c, size_type i = 0 ) const noexcept
9922  {
9923  return FindFirstIC( c, i );
9924  }
9925 
9926  size_type FindIC( const wchar_t* t, size_type i = 0 ) const noexcept
9927  {
9928  return FindFirstIC( t, i );
9929  }
9930 
9931  size_type FindIC( wchar_t c, size_type i = 0 ) const noexcept
9932  {
9933  return FindFirstIC( c, i );
9934  }
9935 
9936  size_type FindIC( const_c_string8 t, size_type i = 0 ) const noexcept
9937  {
9938  return FindFirstIC( t, i );
9939  }
9940 
9941  size_type FindIC( char8_type c, size_type i = 0 ) const noexcept
9942  {
9943  return FindFirstIC( c, i );
9944  }
9945 
9946  // -------------------------------------------------------------------------
9947 
9948  size_type FindLast( const String& s, size_type r = maxPos ) const noexcept
9949  {
9950  return string_base::FindLast( s, r );
9951  }
9952 
9953  size_type FindLast( const_iterator t, size_type r = maxPos ) const noexcept
9954  {
9955  return string_base::FindLast( t, r );
9956  }
9957 
9958  size_type FindLast( char_type c, size_type r = maxPos ) const noexcept
9959  {
9960  return string_base::FindLast( c, r );
9961  }
9962 
9963  size_type FindLastIC( const String& s, size_type r = maxPos ) const noexcept
9964  {
9965  return string_base::FindLastIC( s, r );
9966  }
9967 
9968  size_type FindLastIC( const_iterator t, size_type r = maxPos ) const noexcept
9969  {
9970  return string_base::FindLastIC( t, r );
9971  }
9972 
9973  size_type FindLastIC( char_type c, size_type r = maxPos ) const noexcept
9974  {
9975  return string_base::FindLastIC( c, r );
9976  }
9977 
9978  size_type FindLast( const char16_t* t, size_type r = maxPos ) const noexcept
9979  {
9980  return string_base::FindLast( reinterpret_cast<const_iterator>( t ), r );
9981  }
9982 
9983  size_type FindLast( char16_t c, size_type r = maxPos ) const noexcept
9984  {
9985  return string_base::FindLast( char_type( c ), r );
9986  }
9987 
9988  size_type FindLastIC( const char16_t* t, size_type r = maxPos ) const noexcept
9989  {
9990  return string_base::FindLastIC( reinterpret_cast<const_iterator>( t ), r );
9991  }
9992 
9993  size_type FindLastIC( char16_t c, size_type r = maxPos ) const noexcept
9994  {
9995  return string_base::FindLastIC( char_type( c ), r );
9996  }
9997 
9998  size_type FindLast( const wchar_t* t, size_type r = maxPos ) const noexcept
9999  {
10000 #ifdef __PCL_WINDOWS
10001  return string_base::FindLast( reinterpret_cast<const_iterator>( t ), r );
10002 #else
10003  return string_base::FindLast( String( t ), r );
10004 #endif
10005  }
10006 
10007  size_type FindLast( wchar_t c, size_type r = maxPos ) const noexcept
10008  {
10009  return string_base::FindLast( char_type( c ), r );
10010  }
10011 
10012  size_type FindLastIC( const wchar_t* t, size_type r = maxPos ) const noexcept
10013  {
10014 #ifdef __PCL_WINDOWS
10015  return string_base::FindLastIC( reinterpret_cast<const_iterator>( t ), r );
10016 #else
10017  return string_base::FindLastIC( String( t ), r );
10018 #endif
10019  }
10020 
10021  size_type FindLastIC( wchar_t c, size_type r = maxPos ) const noexcept
10022  {
10023  return string_base::FindLastIC( char_type( c ), r );
10024  }
10025 
10026  size_type FindLast( const_c_string8 t, size_type r = maxPos ) const noexcept
10027  {
10028  return string_base::FindLast( String( t ), r );
10029  }
10030 
10031  size_type FindLast( char8_type c, size_type r = maxPos ) const noexcept
10032  {
10033  return string_base::FindLast( char_type( c ), r );
10034  }
10035 
10036  size_type FindLastIC( const_c_string8 t, size_type r = maxPos ) const noexcept
10037  {
10038  return string_base::FindLastIC( String( t ), r );
10039  }
10040 
10041  size_type FindLastIC( char8_type c, size_type r = maxPos ) const noexcept
10042  {
10043  return string_base::FindLastIC( char_type( c ), r );
10044  }
10045 
10046  // -------------------------------------------------------------------------
10047 
10048  bool Contains( const String& s ) const noexcept
10049  {
10050  return string_base::Contains( s );
10051  }
10052 
10053  bool Contains( const_iterator t ) const noexcept
10054  {
10055  return string_base::Contains( t );
10056  }
10057 
10058  bool Contains( char_type c ) const noexcept
10059  {
10060  return string_base::Contains( c );
10061  }
10062 
10063  bool ContainsIC( const String& s ) const noexcept
10064  {
10065  return string_base::ContainsIC( s );
10066  }
10067 
10068  bool ContainsIC( const_iterator t ) const noexcept
10069  {
10070  return string_base::ContainsIC( t );
10071  }
10072 
10073  bool ContainsIC( char_type c ) const noexcept
10074  {
10075  return string_base::ContainsIC( c );
10076  }
10077 
10078  bool Contains( const char16_t* t ) const noexcept
10079  {
10080  return string_base::Contains( reinterpret_cast<const_iterator>( t ) );
10081  }
10082 
10083  bool Contains( char16_t c ) const noexcept
10084  {
10085  return string_base::Contains( char_type( c ) );
10086  }
10087 
10088  bool ContainsIC( const char16_t* t ) const noexcept
10089  {
10090  return string_base::ContainsIC( reinterpret_cast<const_iterator>( t ) );
10091  }
10092 
10093  bool ContainsIC( char16_t c ) const noexcept
10094  {
10095  return string_base::ContainsIC( char_type( c ) );
10096  }
10097 
10098  bool Contains( const wchar_t* t ) const noexcept
10099  {
10100 #ifdef __PCL_WINDOWS
10101  return string_base::Contains( reinterpret_cast<const_iterator>( t ) );
10102 #else
10103  return string_base::Contains( String( t ) );
10104 #endif
10105  }
10106 
10107  bool Contains( wchar_t c ) const noexcept
10108  {
10109  return string_base::Contains( char_type( c ) );
10110  }
10111 
10112  bool ContainsIC( const wchar_t* t ) const noexcept
10113  {
10114 #ifdef __PCL_WINDOWS
10115  return string_base::ContainsIC( reinterpret_cast<const_iterator>( t ) );
10116 #else
10117  return string_base::ContainsIC( String( t ) );
10118 #endif
10119  }
10120 
10121  bool ContainsIC( wchar_t c ) const noexcept
10122  {
10123  return string_base::ContainsIC( char_type( c ) );
10124  }
10125 
10126  bool Contains( const_c_string8 t ) const noexcept
10127  {
10128  return string_base::Contains( String( t ) );
10129  }
10130 
10131  bool Contains( char8_type c ) const noexcept
10132  {
10133  return string_base::Contains( char_type( c ) );
10134  }
10135 
10136  bool ContainsIC( const_c_string8 t ) const noexcept
10137  {
10138  return string_base::ContainsIC( String( t ) );
10139  }
10140 
10141  bool ContainsIC( char8_type c ) const noexcept
10142  {
10143  return string_base::ContainsIC( char_type( c ) );
10144  }
10145 
10146  // -------------------------------------------------------------------------
10147 
10148  int CompareCodePoints( const String& s, bool caseSensitive = true ) const noexcept
10149  {
10150  return string_base::CompareCodePoints( s, caseSensitive );
10151  }
10152 
10153  int CompareCodePoints( const_iterator t, bool caseSensitive = true ) const noexcept
10154  {
10155  return string_base::CompareCodePoints( t, caseSensitive );
10156  }
10157 
10158  int CompareCodePoints( char_type c, bool caseSensitive = true ) const noexcept
10159  {
10160  return string_base::CompareCodePoints( c, caseSensitive );
10161  }
10162 
10163  int CompareCodePoints( const char16_t* t, bool caseSensitive = true ) const noexcept
10164  {
10165  return string_base::CompareCodePoints( reinterpret_cast<const_iterator>( t ), caseSensitive );
10166  }
10167 
10168  int CompareCodePoints( char16_t c, bool caseSensitive = true ) const noexcept
10169  {
10170  return string_base::CompareCodePoints( char_type( c ), caseSensitive );
10171  }
10172 
10173  int CompareCodePoints( const wchar_t* t, bool caseSensitive = true ) const noexcept
10174  {
10175 #ifdef __PCL_WINDOWS
10176  return string_base::CompareCodePoints( reinterpret_cast<const_iterator>( t ), caseSensitive );
10177 #else
10178  return string_base::CompareCodePoints( String( t ), caseSensitive );
10179 #endif
10180  }
10181 
10182  int CompareCodePoints( wchar_t c, bool caseSensitive = true ) const noexcept
10183  {
10184  return string_base::CompareCodePoints( char_type( c ), caseSensitive );
10185  }
10186 
10187  int CompareCodePoints( const_c_string8 t, bool caseSensitive = true ) const noexcept
10188  {
10189  return string_base::CompareCodePoints( String( t ), caseSensitive );
10190  }
10191 
10192  int CompareCodePoints( char8_type c, bool caseSensitive = true ) const noexcept
10193  {
10194  return string_base::CompareCodePoints( char_type( c ), caseSensitive );
10195  }
10196 
10197  // -------------------------------------------------------------------------
10198 
10199  int Compare( const String& s, bool caseSensitive = true, bool localeAware = true ) const noexcept
10200  {
10201  return string_base::Compare( s, caseSensitive, localeAware );
10202  }
10203 
10204  int Compare( const_iterator t, bool caseSensitive = true, bool localeAware = true ) const noexcept
10205  {
10206  return string_base::Compare( t, caseSensitive, localeAware );
10207  }
10208 
10209  int Compare( char_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept
10210  {
10211  return string_base::Compare( c, caseSensitive, localeAware );
10212  }
10213 
10214  int CompareIC( const String& s, bool localeAware = true ) const noexcept
10215  {
10216  return string_base::CompareIC( s, localeAware );
10217  }
10218 
10219  int CompareIC( const_iterator t, bool localeAware = true ) const noexcept
10220  {
10221  return string_base::CompareIC( t, localeAware );
10222  }
10223 
10224  int CompareIC( char_type c, bool localeAware = true ) const noexcept
10225  {
10226  return string_base::CompareIC( c, localeAware );
10227  }
10228 
10229  int Compare( const char16_t* t, bool caseSensitive = true, bool localeAware = true ) const noexcept
10230  {
10231  return string_base::Compare( reinterpret_cast<const_iterator>( t ), caseSensitive, localeAware );
10232  }
10233 
10234  int Compare( char16_t c, bool caseSensitive = true, bool localeAware = true ) const noexcept
10235  {
10236  return string_base::Compare( char_type( c ), caseSensitive, localeAware );
10237  }
10238 
10239  int CompareIC( const char16_t* t, bool localeAware = true ) const noexcept
10240  {
10241  return string_base::CompareIC( reinterpret_cast<const_iterator>( t ), localeAware );
10242  }
10243 
10244  int CompareIC( char16_t c, bool localeAware = true ) const noexcept
10245  {
10246  return string_base::CompareIC( char_type( c ), localeAware );
10247  }
10248 
10249  int Compare( const wchar_t* t, bool caseSensitive = true, bool localeAware = true ) const noexcept
10250  {
10251 #ifdef __PCL_WINDOWS
10252  return string_base::Compare( reinterpret_cast<const_iterator>( t ), caseSensitive, localeAware );
10253 #else
10254  return string_base::Compare( String( t ), caseSensitive, localeAware );
10255 #endif
10256  }
10257 
10258  int Compare( wchar_t c, bool caseSensitive = true, bool localeAware = true ) const noexcept
10259  {
10260  return string_base::Compare( char_type( c ), caseSensitive, localeAware );
10261  }
10262 
10263  int CompareIC( const wchar_t* t, bool localeAware = true ) const noexcept
10264  {
10265 #ifdef __PCL_WINDOWS
10266  return string_base::CompareIC( reinterpret_cast<const_iterator>( t ), localeAware );
10267 #else
10268  return string_base::CompareIC( String( t ), localeAware );
10269 #endif
10270  }
10271 
10272  int CompareIC( wchar_t c, bool localeAware = true ) const noexcept
10273  {
10274  return string_base::CompareIC( char_type( c ), localeAware );
10275  }
10276 
10277  int Compare( const_c_string8 t, bool caseSensitive = true, bool localeAware = true ) const noexcept
10278  {
10279  return string_base::Compare( String( t ), caseSensitive, localeAware );
10280  }
10281 
10282  int Compare( char8_type c, bool caseSensitive = true, bool localeAware = true ) const noexcept
10283  {
10284  return string_base::Compare( char_type( c ), caseSensitive, localeAware );
10285  }
10286 
10287  int CompareIC( const_c_string8 t, bool localeAware = true ) const noexcept
10288  {
10289  return string_base::CompareIC( String( t ), localeAware );
10290  }
10291 
10292  int CompareIC( char8_type c, bool localeAware = true ) const noexcept
10293  {
10294  return string_base::CompareIC( char_type( c ), localeAware );
10295  }
10296 
10297  // -------------------------------------------------------------------------
10298 
10299  bool WildMatch( const String& pattern, bool caseSensitive = true ) const noexcept
10300  {
10301  return string_base::WildMatch( pattern, caseSensitive );
10302  }
10303 
10304  bool WildMatchIC( const String& pattern ) const noexcept
10305  {
10306  return string_base::WildMatchIC( pattern );
10307  }
10308 
10309  bool WildMatch( const_iterator pattern, bool caseSensitive = true ) const noexcept
10310  {
10311  return string_base::WildMatch( pattern, caseSensitive );
10312  }
10313 
10314  bool WildMatchIC( const_iterator pattern ) const noexcept
10315  {
10316  return string_base::WildMatchIC( pattern );
10317  }
10318 
10319  bool WildMatch( const string8_base& pattern, bool caseSensitive = true ) const noexcept
10320  {
10321  return char_traits::WildMatch( m_data->string, Length(), pattern.Begin(), pattern.Length(), caseSensitive );
10322  }
10323 
10324  bool WildMatchIC( const string8_base& pattern ) const noexcept
10325  {
10326  return char_traits::WildMatch( m_data->string, Length(), pattern.Begin(), pattern.Length(), false/*caseSensitive*/ );
10327  }
10328 
10329  bool WildMatch( const_c_string8 pattern, bool caseSensitive = true ) const noexcept
10330  {
10331  return char_traits::WildMatch( m_data->string, Length(), pattern, char8_traits::Length( pattern ), caseSensitive );
10332  }
10333 
10334  bool WildMatchIC( const_c_string8 pattern ) const noexcept
10335  {
10336  return char_traits::WildMatch( m_data->string, Length(), pattern, char8_traits::Length( pattern ), false/*caseSensitive*/ );
10337  }
10338 
10339  // -------------------------------------------------------------------------
10340 
10341  String SetToLength( size_type n ) const
10342  {
10343  return string_base::SetToLength( n );
10344  }
10345 
10346  String ResizedToNullTerminated() const
10347  {
10348  return string_base::ResizedToNullTerminated();
10349  }
10350 
10351  String Squeezed() const
10352  {
10353  return string_base::Squeezed();
10354  }
10355 
10356  // -------------------------------------------------------------------------
10357 
10358  String Substring( size_type i, size_type n = maxPos ) const
10359  {
10360  return string_base::Substring( i, n );
10361  }
10362 
10363  String Left( size_type n ) const
10364  {
10365  return string_base::Left( n );
10366  }
10367 
10368  String Right( size_type n ) const
10369  {
10370  return string_base::Right( n );
10371  }
10372 
10373  String Suffix( size_type i ) const
10374  {
10375  return string_base::Suffix( i );
10376  }
10377 
10378  String Prefix( size_type i ) const
10379  {
10380  return string_base::Prefix( i );
10381  }
10382 
10383  // -------------------------------------------------------------------------
10384 
10385  template <class C>
10386  size_type Break( C& list, const String& s, bool trim = false, size_type i = 0 ) const
10387  {
10388  return string_base::Break( list, s, trim, i );
10389  }
10390 
10391  template <class C>
10392  size_type Break( C& list, const string8_base& s, bool trim = false, size_type i = 0 ) const
10393  {
10394  return string_base::Break( list, String( s ), trim, i );
10395  }
10396 
10397  template <class C>
10398  size_type Break( C& list, const_c_string8 s, bool trim = false, size_type i = 0 ) const
10399  {
10400  return string_base::Break( list, String( s ), trim, i );
10401  }
10402 
10403  template <class C>
10404  size_type Break( C& list, char_type c, bool trim = false, size_type i = 0 ) const
10405  {
10406  return string_base::Break( list, c, trim, i );
10407  }
10408 
10409  template <class C>
10410  size_type Break( C& list, char8_type c, bool trim = false, size_type i = 0 ) const
10411  {
10412  return string_base::Break( list, char_type( c ), trim, i );
10413  }
10414 
10415  template <class C, typename S>
10416  size_type Break( C& list, const Array<S>& ca, bool trim = false, size_type i = 0 ) const
10417  {
10418  return string_base::Break( list, ca, trim, i );
10419  }
10420 
10421  // -------------------------------------------------------------------------
10422 
10423  template <class C>
10424  size_type BreakIC( C& list, const String& s, bool trim = false, size_type i = 0 ) const
10425  {
10426  return string_base::BreakIC( list, s, trim, i );
10427  }
10428 
10429  template <class C>
10430  size_type BreakIC( C& list, const string8_base& s, bool trim = false, size_type i = 0 ) const
10431  {
10432  return string_base::BreakIC( list, String( s ), trim, i );
10433  }
10434 
10435  template <class C>
10436  size_type BreakIC( C& list, const_c_string8 s, bool trim = false, size_type i = 0 ) const
10437  {
10438  return string_base::BreakIC( list, String( s ), trim, i );
10439  }
10440 
10441  template <class C>
10442  size_type BreakIC( C& list, char_type c, bool trim = false, size_type i = 0 ) const
10443  {
10444  return string_base::BreakIC( list, c, trim, i );
10445  }
10446 
10447  template <class C>
10448  size_type BreakIC( C& list, char8_type c, bool trim = false, size_type i = 0 ) const
10449  {
10450  return string_base::BreakIC( list, char_type( c ), trim, i );
10451  }
10452 
10453  // -------------------------------------------------------------------------
10454 
10455  String Trimmed() const
10456  {
10457  return string_base::Trimmed();
10458  }
10459 
10460  String TrimmedLeft() const
10461  {
10462  return string_base::TrimmedLeft();
10463  }
10464 
10465  String TrimmedRight() const
10466  {
10467  return string_base::TrimmedRight();
10468  }
10469 
10470  // -------------------------------------------------------------------------
10471 
10472  String LeftJustified( size_type width, char_type fill = CharTraits::Blank() ) const
10473  {
10474  return string_base::LeftJustified( width, fill );
10475  }
10476 
10477  String RightJustified( size_type width, char_type fill = CharTraits::Blank() ) const
10478  {
10479  return string_base::RightJustified( width, fill );
10480  }
10481 
10482  String CenterJustified( size_type width, char_type fill = CharTraits::Blank() ) const
10483  {
10484  return string_base::CenterJustified( width, fill );
10485  }
10486 
10487  // -------------------------------------------------------------------------
10488 
10489  String Enclosed( char_type c ) const
10490  {
10491  return string_base::Enclosed( c );
10492  }
10493 
10494  String SingleQuoted() const
10495  {
10496  return string_base::SingleQuoted();
10497  }
10498 
10499  String DoubleQuoted() const
10500  {
10501  return string_base::DoubleQuoted();
10502  }
10503 
10504  String Unquoted() const
10505  {
10506  return string_base::Unquoted();
10507  }
10508 
10509  // -------------------------------------------------------------------------
10510 
10511  String CaseFolded() const
10512  {
10513  return string_base::CaseFolded();
10514  }
10515 
10516  String Lowercase() const
10517  {
10518  return string_base::Lowercase();
10519  }
10520 
10521  String Uppercase() const
10522  {
10523  return string_base::Uppercase();
10524  }
10525 
10526  // -------------------------------------------------------------------------
10527 
10528  String Reversed() const
10529  {
10530  return string_base::Reversed();
10531  }
10532 
10533  String Sorted() const
10534  {
10535  return string_base::Sorted();
10536  }
10537 
10538  template <class BP>
10539  String Sorted( BP p ) const
10540  {
10541  return string_base::Sorted( p );
10542  }
10543 
10544  // -------------------------------------------------------------------------
10545 
10555  template <class C>
10556  String& ToSeparated( const C& c, char_type separator )
10557  {
10558  Clear();
10559  return c.ToSeparated( *this, separator );
10560  }
10561 
10578  template <class C, class AF>
10579  String& ToSeparated( const C& c, char_type separator, AF append )
10580  {
10581  Clear();
10582  return c.ToSeparated( *this, separator, append );
10583  }
10584 
10594  template <class C>
10595  String& ToSeparated( const C& c, const String& separator )
10596  {
10597  Clear();
10598  return c.ToSeparated( *this, separator );
10599  }
10600 
10617  template <class C, class AF>
10618  String& ToSeparated( const C& c, const String& separator, AF append )
10619  {
10620  Clear();
10621  return c.ToSeparated( *this, separator, append );
10622  }
10623 
10633  template <class C>
10634  String& ToSeparated( const C& c, const_c_string separator )
10635  {
10636  return ToSeparated( c, String( separator ) );
10637  }
10638 
10655  template <class C, class AF>
10656  String& ToSeparated( const C& c, const_c_string separator, AF append )
10657  {
10658  return ToSeparated( c, String( separator ), append );
10659  }
10660 
10671  template <class C>
10672  String& ToSeparated( const C& c, const_c_string8 separator )
10673  {
10674  return ToSeparated( c, String( separator ) );
10675  }
10676 
10693  template <class C, class AF>
10694  String& ToSeparated( const C& c, const_c_string8 separator, AF append )
10695  {
10696  return ToSeparated( c, String( separator ), append );
10697  }
10698 
10708  template <class C>
10709  String& ToCommaSeparated( const C& c )
10710  {
10711  return ToSeparated( c, CharTraits::Comma() );
10712  }
10713 
10723  template <class C>
10724  String& ToColonSeparated( const C& c )
10725  {
10726  return ToSeparated( c, CharTraits::Colon() );
10727  }
10728 
10738  template <class C>
10739  String& ToSpaceSeparated( const C& c )
10740  {
10741  return ToSeparated( c, CharTraits::Blank() );
10742  }
10743 
10753  template <class C>
10754  String& ToTabSeparated( const C& c )
10755  {
10756  return ToSeparated( c, CharTraits::Tab() );
10757  }
10758 
10768  template <class C>
10770  {
10771  return ToSeparated( c, CharTraits::LF() );
10772  }
10773 
10783  template <class C>
10784  String& ToNullSeparated( const C& c )
10785  {
10786  return ToSeparated( c, CharTraits::Null() );
10787  }
10788 
10797  template <class C>
10798  String& ToHyphenated( const C& c )
10799  {
10800  return ToSeparated( c, CharTraits::Hyphen() );
10801  }
10802 
10803  // -------------------------------------------------------------------------
10804 
10819  String& ToEncodedHTMLSpecialChars();
10820 
10828  {
10829  return String( *this ).ToEncodedHTMLSpecialChars();
10830  }
10831 
10848  String& ToDecodedHTMLSpecialChars();
10849 
10858  {
10859  return String( *this ).ToDecodedHTMLSpecialChars();
10860  }
10861 
10862  // -------------------------------------------------------------------------
10863 
10864 #ifdef __PCL_QT_INTERFACE
10865 
10866  operator QString() const
10867  {
10868  return PCL_GET_QSTRING_FROM_CHAR16PTR( c_str() );
10869  }
10870 
10871  operator QDate() const
10872  {
10873  return QDate::fromString( operator QString(), PCL_QDATE_FMT_STR );
10874  }
10875 
10876  operator QDateTime() const
10877  {
10878  return QDateTime::fromString( operator QString(), PCL_QDATETIME_FMT_STR );
10879  }
10880 
10881 #endif
10882 
10894  String& Format( const_c_string8 fmt, ... )
10895  {
10896  va_list paramList;
10897  va_start( paramList, fmt );