LibreOffice
LibreOffice 4.1 SDK C/C++ API Reference
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ustring.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef _RTL_USTRING_HXX_
21 #define _RTL_USTRING_HXX_
22 
23 #include "sal/config.h"
24 
25 #include <cassert>
26 #include <ostream>
27 #include <string.h>
28 
29 #include "osl/diagnose.h"
30 #include <rtl/ustring.h>
31 #include <rtl/string.hxx>
32 #include <rtl/stringutils.hxx>
33 #include <rtl/textenc.h>
34 #include "sal/log.hxx"
35 
36 #ifdef RTL_FAST_STRING
37 #include <rtl/stringconcat.hxx>
38 #endif
39 
40 #if defined EXCEPTIONS_OFF
41 #include <stdlib.h>
42 #else
43 #include <new>
44 #endif
45 
46 // The unittest uses slightly different code to help check that the proper
47 // calls are made. The class is put into a different namespace to make
48 // sure the compiler generates a different (if generating also non-inline)
49 // copy of the function and does not merge them together. The class
50 // is "brought" into the proper rtl namespace by a typedef below.
51 #ifdef RTL_STRING_UNITTEST
52 #define rtl rtlunittest
53 #endif
54 
55 namespace rtl
56 {
57 
58 #ifdef RTL_STRING_UNITTEST
59 #undef rtl
60 #endif
61 
62 /* ======================================================================= */
63 
88 {
89 public:
91  rtl_uString * pData;
93 
94 private:
95  class DO_NOT_ACQUIRE{};
96 
97  OUString( rtl_uString * value, SAL_UNUSED_PARAMETER DO_NOT_ACQUIRE * )
98  {
99  pData = value;
100  }
101 
102 public:
107  {
108  pData = 0;
109  rtl_uString_new( &pData );
110  }
111 
117  OUString( const OUString & str ) SAL_THROW(())
118  {
119  pData = str.pData;
120  rtl_uString_acquire( pData );
121  }
122 
128  OUString( rtl_uString * str ) SAL_THROW(())
129  {
130  pData = str;
131  rtl_uString_acquire( pData );
132  }
133 
142  inline OUString( rtl_uString * str, __sal_NoAcquire ) SAL_THROW(())
143  { pData = str; }
144 
150  explicit OUString( sal_Unicode value ) SAL_THROW(())
151  : pData (0)
152  {
153  rtl_uString_newFromStr_WithLength( &pData, &value, 1 );
154  }
155 
161  OUString( const sal_Unicode * value ) SAL_THROW(())
162  {
163  pData = 0;
164  rtl_uString_newFromStr( &pData, value );
165  }
166 
175  OUString( const sal_Unicode * value, sal_Int32 length ) SAL_THROW(())
176  {
177  pData = 0;
178  rtl_uString_newFromStr_WithLength( &pData, value, length );
179  }
180 
196  template< typename T >
198  {
199  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
200  pData = 0;
201  if( internal::ConstCharArrayDetector< T, void >::size - 1 == 0 ) // empty string
202  rtl_uString_new( &pData );
203  else
205 #ifdef RTL_STRING_UNITTEST
206  rtl_string_unittest_const_literal = true;
207 #endif
208  }
209 
210 #ifdef RTL_STRING_UNITTEST
211 
215  template< typename T >
217  {
218  pData = 0;
219  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
220  rtl_string_unittest_invalid_conversion = true;
221  }
226  template< typename T >
227  OUString( const T&, typename internal::ExceptCharArrayDetector< T >::Type = internal::Dummy() )
228  {
229  pData = 0;
230  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
231  rtl_string_unittest_invalid_conversion = true;
232  }
233 #endif
234 
249  OUString( const sal_Char * value, sal_Int32 length,
250  rtl_TextEncoding encoding,
251  sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS )
252  {
253  pData = 0;
254  rtl_string2UString( &pData, value, length, encoding, convertFlags );
255  if (pData == 0) {
256 #if defined EXCEPTIONS_OFF
257  abort();
258 #else
259  throw std::bad_alloc();
260 #endif
261  }
262  }
263 
280  inline explicit OUString(
281  sal_uInt32 const * codePoints, sal_Int32 codePointCount):
282  pData(NULL)
283  {
284  rtl_uString_newFromCodePoints(&pData, codePoints, codePointCount);
285  if (pData == NULL) {
286 #if defined EXCEPTIONS_OFF
287  abort();
288 #else
289  throw std::bad_alloc();
290 #endif
291  }
292  }
293 
294 #ifdef RTL_FAST_STRING
295 
299  template< typename T1, typename T2 >
300  OUString( const OUStringConcat< T1, T2 >& c )
301  {
302  const sal_Int32 l = c.length();
303  pData = rtl_uString_alloc( l );
304  if (l != 0)
305  {
306  sal_Unicode* end = c.addData( pData->buffer );
307  pData->length = end - pData->buffer;
308  *end = '\0';
309  // TODO realloc in case pData->length is noticeably smaller than l?
310  }
311  }
312 #endif
313 
318  {
319  rtl_uString_release( pData );
320  }
321 
333  static inline OUString const & unacquired( rtl_uString * const * ppHandle )
334  { return * reinterpret_cast< OUString const * >( ppHandle ); }
335 
341  OUString & operator=( const OUString & str ) SAL_THROW(())
342  {
343  rtl_uString_assign( &pData, str.pData );
344  return *this;
345  }
346 
359  template< typename T >
361  {
362  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
363  if( internal::ConstCharArrayDetector< T, void >::size - 1 == 0 ) // empty string
364  rtl_uString_new( &pData );
365  else
367  return *this;
368  }
369 
375  OUString & operator+=( const OUString & str ) SAL_THROW(())
376  {
377  rtl_uString_newConcat( &pData, pData, str.pData );
378  return *this;
379  }
380 
381 #ifdef RTL_FAST_STRING
382 
386  template< typename T1, typename T2 >
387  OUString& operator+=( const OUStringConcat< T1, T2 >& c )
388  {
389  const int l = c.length();
390  if( l == 0 )
391  return *this;
392  rtl_uString_ensureCapacity( &pData, pData->length + l );
393  sal_Unicode* end = c.addData( pData->buffer + pData->length );
394  *end = '\0';
395  pData->length = end - pData->buffer;
396  return *this;
397  }
398 #endif
399 
408  sal_Int32 getLength() const SAL_THROW(()) { return pData->length; }
409 
418  bool isEmpty() const SAL_THROW(())
419  {
420  return pData->length == 0;
421  }
422 
430  const sal_Unicode * getStr() const SAL_THROW(()) { return pData->buffer; }
431 
441  sal_Unicode operator [](sal_Int32 index) const {
442  assert(index >= 0 && index <= getLength());
443  //TODO: should really check for < getLength(), but there is quite
444  // some clever code out there that violates this function's
445  // documented precondition and relies on s[s.getLength()] == 0 and
446  // that would need to be fixed first
447  return getStr()[index];
448  }
449 
462  sal_Int32 compareTo( const OUString & str ) const SAL_THROW(())
463  {
464  return rtl_ustr_compare_WithLength( pData->buffer, pData->length,
465  str.pData->buffer, str.pData->length );
466  }
467 
483  sal_Int32 compareTo( const OUString & str, sal_Int32 maxLength ) const SAL_THROW(())
484  {
485  return rtl_ustr_shortenedCompare_WithLength( pData->buffer, pData->length,
486  str.pData->buffer, str.pData->length, maxLength );
487  }
488 
501  sal_Int32 reverseCompareTo( const OUString & str ) const SAL_THROW(())
502  {
503  return rtl_ustr_reverseCompare_WithLength( pData->buffer, pData->length,
504  str.pData->buffer, str.pData->length );
505  }
506 
512  template< typename T >
513  typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type reverseCompareTo( T& literal ) const SAL_THROW(())
514  {
515  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
516  return rtl_ustr_asciil_reverseCompare_WithLength( pData->buffer, pData->length,
518  }
519 
531  sal_Bool equals( const OUString & str ) const SAL_THROW(())
532  {
533  if ( pData->length != str.pData->length )
534  return sal_False;
535  if ( pData == str.pData )
536  return sal_True;
537  return rtl_ustr_reverseCompare_WithLength( pData->buffer, pData->length,
538  str.pData->buffer, str.pData->length ) == 0;
539  }
540 
555  sal_Bool equalsIgnoreAsciiCase( const OUString & str ) const SAL_THROW(())
556  {
557  if ( pData->length != str.pData->length )
558  return sal_False;
559  if ( pData == str.pData )
560  return sal_True;
561  return rtl_ustr_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length,
562  str.pData->buffer, str.pData->length ) == 0;
563  }
564 
580  sal_Int32 compareToIgnoreAsciiCase( const OUString & str ) const SAL_THROW(())
581  {
582  return rtl_ustr_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length,
583  str.pData->buffer, str.pData->length );
584  }
585 
586 
592  template< typename T >
593  typename internal::ConstCharArrayDetector< T, bool >::Type equalsIgnoreAsciiCase( T& literal ) const SAL_THROW(())
594  {
595  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
596  if ( pData->length != internal::ConstCharArrayDetector< T, void >::size - 1 )
597  return sal_False;
598 
599  return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, literal ) == 0;
600  }
601 
617  sal_Bool match( const OUString & str, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
618  {
619  return rtl_ustr_shortenedCompare_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
620  str.pData->buffer, str.pData->length, str.pData->length ) == 0;
621  }
622 
628  template< typename T >
629  typename internal::ConstCharArrayDetector< T, bool >::Type match( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
630  {
631  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
632  return rtl_ustr_ascii_shortenedCompare_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
634  }
635 
654  sal_Bool matchIgnoreAsciiCase( const OUString & str, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
655  {
656  return rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
657  str.pData->buffer, str.pData->length,
658  str.pData->length ) == 0;
659  }
660 
666  template< typename T >
667  typename internal::ConstCharArrayDetector< T, bool >::Type matchIgnoreAsciiCase( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
668  {
669  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
670  return rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
672  }
673 
690  sal_Int32 compareToAscii( const sal_Char* asciiStr ) const SAL_THROW(())
691  {
692  return rtl_ustr_ascii_compare_WithLength( pData->buffer, pData->length, asciiStr );
693  }
694 
718  "replace s1.compareToAscii(s2, strlen(s2)) == 0 with s1.startsWith(s2)")
719  sal_Int32 compareToAscii( const sal_Char * asciiStr, sal_Int32 maxLength ) const SAL_THROW(())
720  {
721  return rtl_ustr_ascii_shortenedCompare_WithLength( pData->buffer, pData->length,
722  asciiStr, maxLength );
723  }
724 
744  sal_Int32 reverseCompareToAsciiL( const sal_Char * asciiStr, sal_Int32 asciiStrLength ) const SAL_THROW(())
745  {
746  return rtl_ustr_asciil_reverseCompare_WithLength( pData->buffer, pData->length,
747  asciiStr, asciiStrLength );
748  }
749 
765  sal_Bool equalsAscii( const sal_Char* asciiStr ) const SAL_THROW(())
766  {
767  return rtl_ustr_ascii_compare_WithLength( pData->buffer, pData->length,
768  asciiStr ) == 0;
769  }
770 
788  sal_Bool equalsAsciiL( const sal_Char* asciiStr, sal_Int32 asciiStrLength ) const SAL_THROW(())
789  {
790  if ( pData->length != asciiStrLength )
791  return sal_False;
792 
794  pData->buffer, asciiStr, asciiStrLength );
795  }
796 
815  sal_Bool equalsIgnoreAsciiCaseAscii( const sal_Char * asciiStr ) const SAL_THROW(())
816  {
817  return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, asciiStr ) == 0;
818  }
819 
838  sal_Int32 compareToIgnoreAsciiCaseAscii( const sal_Char * asciiStr ) const SAL_THROW(())
839  {
840  return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, asciiStr );
841  }
842 
863  sal_Bool equalsIgnoreAsciiCaseAsciiL( const sal_Char * asciiStr, sal_Int32 asciiStrLength ) const SAL_THROW(())
864  {
865  if ( pData->length != asciiStrLength )
866  return sal_False;
867 
868  return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, asciiStr ) == 0;
869  }
870 
892  sal_Bool matchAsciiL( const sal_Char* asciiStr, sal_Int32 asciiStrLength, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
893  {
894  return rtl_ustr_ascii_shortenedCompare_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
895  asciiStr, asciiStrLength ) == 0;
896  }
897 
898  // This overload is left undefined, to detect calls of matchAsciiL that
899  // erroneously use RTL_CONSTASCII_USTRINGPARAM instead of
900  // RTL_CONSTASCII_STRINGPARAM (but would lead to ambiguities on 32 bit
901  // platforms):
902 #if SAL_TYPES_SIZEOFLONG == 8
903  void matchAsciiL(char const *, sal_Int32, rtl_TextEncoding) const;
904 #endif
905 
930  sal_Bool matchIgnoreAsciiCaseAsciiL( const sal_Char* asciiStr, sal_Int32 asciiStrLength, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
931  {
932  return rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
933  asciiStr, asciiStrLength ) == 0;
934  }
935 
936  // This overload is left undefined, to detect calls of
937  // matchIgnoreAsciiCaseAsciiL that erroneously use
938  // RTL_CONSTASCII_USTRINGPARAM instead of RTL_CONSTASCII_STRINGPARAM (but
939  // would lead to ambiguities on 32 bit platforms):
940 #if SAL_TYPES_SIZEOFLONG == 8
941  void matchIgnoreAsciiCaseAsciiL(char const *, sal_Int32, rtl_TextEncoding)
942  const;
943 #endif
944 
955  bool startsWith(OUString const & str) const {
956  return match(str, 0);
957  }
958 
964  template< typename T >
965  typename internal::ConstCharArrayDetector< T, bool >::Type startsWith( T& literal ) const
966  {
967  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
968  return internal::ConstCharArrayDetector< T, void >::size - 1 <= pData->length
969  && rtl_ustr_asciil_reverseEquals_WithLength( pData->buffer, literal,
970  internal::ConstCharArrayDetector< T, void >::size - 1);
971  }
972 
986  sal_Bool startsWithIgnoreAsciiCase( const OUString & str ) const SAL_THROW(())
987  {
988  return matchIgnoreAsciiCase(str, 0);
989  }
990 
996  template< typename T >
997  typename internal::ConstCharArrayDetector< T, bool >::Type startsWithIgnoreAsciiCase( T& literal ) const SAL_THROW(())
998  {
999  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1001  pData->buffer,
1002  internal::ConstCharArrayDetector< T, void >::size - 1, literal,
1003  internal::ConstCharArrayDetector< T, void >::size - 1)
1004  == 0);
1005  }
1006 
1017  bool endsWith(OUString const & str) const {
1018  return str.getLength() <= getLength()
1019  && match(str, getLength() - str.getLength());
1020  }
1021 
1027  template< typename T >
1028  typename internal::ConstCharArrayDetector< T, bool >::Type endsWith( T& literal ) const
1029  {
1030  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1031  return internal::ConstCharArrayDetector< T, void >::size - 1 <= pData->length
1033  pData->buffer + pData->length - ( internal::ConstCharArrayDetector< T, void >::size - 1 ), literal,
1034  internal::ConstCharArrayDetector< T, void >::size - 1);
1035  }
1036 
1048  inline bool endsWithAsciiL(char const * asciiStr, sal_Int32 asciiStrLength)
1049  const
1050  {
1051  return asciiStrLength <= pData->length
1053  pData->buffer + pData->length - asciiStrLength, asciiStr,
1054  asciiStrLength);
1055  }
1056 
1070  sal_Bool endsWithIgnoreAsciiCase( const OUString & str ) const SAL_THROW(())
1071  {
1072  return str.getLength() <= getLength()
1073  && matchIgnoreAsciiCase(str, getLength() - str.getLength());
1074  }
1075 
1081  template< typename T >
1082  typename internal::ConstCharArrayDetector< T, bool >::Type endsWithIgnoreAsciiCase( T& literal ) const SAL_THROW(())
1083  {
1084  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1085  return internal::ConstCharArrayDetector< T, void >::size - 1 <= pData->length
1087  pData->buffer + pData->length - ( internal::ConstCharArrayDetector< T, void >::size - 1 ),
1088  internal::ConstCharArrayDetector< T, void >::size - 1, literal,
1089  internal::ConstCharArrayDetector< T, void >::size - 1)
1090  == 0);
1091  }
1092 
1103  inline bool endsWithIgnoreAsciiCaseAsciiL(
1104  char const * asciiStr, sal_Int32 asciiStrLength) const
1105  {
1106  return asciiStrLength <= pData->length
1108  pData->buffer + pData->length - asciiStrLength,
1109  asciiStrLength, asciiStr, asciiStrLength)
1110  == 0);
1111  }
1112 
1113  friend sal_Bool operator == ( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1114  { return rStr1.equals(rStr2); }
1115  friend sal_Bool operator == ( const OUString& rStr1, const sal_Unicode * pStr2 ) SAL_THROW(())
1116  { return rStr1.compareTo( pStr2 ) == 0; }
1117  friend sal_Bool operator == ( const sal_Unicode * pStr1, const OUString& rStr2 ) SAL_THROW(())
1118  { return OUString( pStr1 ).compareTo( rStr2 ) == 0; }
1119 
1120  friend sal_Bool operator != ( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1121  { return !(operator == ( rStr1, rStr2 )); }
1122  friend sal_Bool operator != ( const OUString& rStr1, const sal_Unicode * pStr2 ) SAL_THROW(())
1123  { return !(operator == ( rStr1, pStr2 )); }
1124  friend sal_Bool operator != ( const sal_Unicode * pStr1, const OUString& rStr2 ) SAL_THROW(())
1125  { return !(operator == ( pStr1, rStr2 )); }
1126 
1127  friend sal_Bool operator < ( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1128  { return rStr1.compareTo( rStr2 ) < 0; }
1129  friend sal_Bool operator > ( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1130  { return rStr1.compareTo( rStr2 ) > 0; }
1131  friend sal_Bool operator <= ( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1132  { return rStr1.compareTo( rStr2 ) <= 0; }
1133  friend sal_Bool operator >= ( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1134  { return rStr1.compareTo( rStr2 ) >= 0; }
1135 
1143  template< typename T >
1144  friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator==( const OUString& string, T& literal )
1145  {
1146  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1147  return string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
1148  }
1156  template< typename T >
1157  friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator==( T& literal, const OUString& string )
1158  {
1159  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1160  return string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
1161  }
1169  template< typename T >
1170  friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator!=( const OUString& string, T& literal )
1171  {
1172  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1173  return !string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
1174  }
1182  template< typename T >
1183  friend inline typename internal::ConstCharArrayDetector< T, bool >::Type operator!=( T& literal, const OUString& string )
1184  {
1185  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1186  return !string.equalsAsciiL( literal, internal::ConstCharArrayDetector< T, void >::size - 1 );
1187  }
1188 
1196  sal_Int32 hashCode() const SAL_THROW(())
1197  {
1198  return rtl_ustr_hashCode_WithLength( pData->buffer, pData->length );
1199  }
1200 
1214  sal_Int32 indexOf( sal_Unicode ch, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
1215  {
1216  sal_Int32 ret = rtl_ustr_indexOfChar_WithLength( pData->buffer+fromIndex, pData->length-fromIndex, ch );
1217  return (ret < 0 ? ret : ret+fromIndex);
1218  }
1219 
1229  sal_Int32 lastIndexOf( sal_Unicode ch ) const SAL_THROW(())
1230  {
1231  return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, pData->length, ch );
1232  }
1233 
1246  sal_Int32 lastIndexOf( sal_Unicode ch, sal_Int32 fromIndex ) const SAL_THROW(())
1247  {
1248  return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, fromIndex, ch );
1249  }
1250 
1266  sal_Int32 indexOf( const OUString & str, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
1267  {
1268  sal_Int32 ret = rtl_ustr_indexOfStr_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1269  str.pData->buffer, str.pData->length );
1270  return (ret < 0 ? ret : ret+fromIndex);
1271  }
1272 
1278  template< typename T >
1279  typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type indexOf( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
1280  {
1281  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1282  sal_Int32 ret = rtl_ustr_indexOfAscii_WithLength(
1283  pData->buffer + fromIndex, pData->length - fromIndex, literal,
1284  internal::ConstCharArrayDetector< T, void >::size - 1);
1285  return ret < 0 ? ret : ret + fromIndex;
1286  }
1287 
1311  sal_Int32 indexOfAsciiL(
1312  char const * str, sal_Int32 len, sal_Int32 fromIndex = 0) const
1313  SAL_THROW(())
1314  {
1315  sal_Int32 ret = rtl_ustr_indexOfAscii_WithLength(
1316  pData->buffer + fromIndex, pData->length - fromIndex, str, len);
1317  return ret < 0 ? ret : ret + fromIndex;
1318  }
1319 
1320  // This overload is left undefined, to detect calls of indexOfAsciiL that
1321  // erroneously use RTL_CONSTASCII_USTRINGPARAM instead of
1322  // RTL_CONSTASCII_STRINGPARAM (but would lead to ambiguities on 32 bit
1323  // platforms):
1324 #if SAL_TYPES_SIZEOFLONG == 8
1325  void indexOfAsciiL(char const *, sal_Int32 len, rtl_TextEncoding) const;
1326 #endif
1327 
1343  sal_Int32 lastIndexOf( const OUString & str ) const SAL_THROW(())
1344  {
1345  return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, pData->length,
1346  str.pData->buffer, str.pData->length );
1347  }
1348 
1366  sal_Int32 lastIndexOf( const OUString & str, sal_Int32 fromIndex ) const SAL_THROW(())
1367  {
1368  return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, fromIndex,
1369  str.pData->buffer, str.pData->length );
1370  }
1371 
1377  template< typename T >
1378  typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type lastIndexOf( T& literal ) const SAL_THROW(())
1379  {
1380  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1382  pData->buffer, pData->length, literal, internal::ConstCharArrayDetector< T, void >::size - 1);
1383  }
1384 
1404  sal_Int32 lastIndexOfAsciiL(char const * str, sal_Int32 len) const
1405  SAL_THROW(())
1406  {
1408  pData->buffer, pData->length, str, len);
1409  }
1410 
1421  SAL_WARN_UNUSED_RESULT OUString copy( sal_Int32 beginIndex ) const SAL_THROW(())
1422  {
1423  rtl_uString *pNew = 0;
1424  rtl_uString_newFromSubString( &pNew, pData, beginIndex, getLength() - beginIndex );
1425  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1426  }
1427 
1440  SAL_WARN_UNUSED_RESULT OUString copy( sal_Int32 beginIndex, sal_Int32 count ) const SAL_THROW(())
1441  {
1442  rtl_uString *pNew = 0;
1443  rtl_uString_newFromSubString( &pNew, pData, beginIndex, count );
1444  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1445  }
1446 
1455  SAL_WARN_UNUSED_RESULT OUString concat( const OUString & str ) const SAL_THROW(())
1456  {
1457  rtl_uString* pNew = 0;
1458  rtl_uString_newConcat( &pNew, pData, str.pData );
1459  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1460  }
1461 
1462 #ifndef RTL_FAST_STRING
1463  friend OUString operator+( const OUString& rStr1, const OUString& rStr2 ) SAL_THROW(())
1464  {
1465  return rStr1.concat( rStr2 );
1466  }
1467 #endif
1468 
1482  SAL_WARN_UNUSED_RESULT OUString replaceAt( sal_Int32 index, sal_Int32 count, const OUString& newStr ) const SAL_THROW(())
1483  {
1484  rtl_uString* pNew = 0;
1485  rtl_uString_newReplaceStrAt( &pNew, pData, index, count, newStr.pData );
1486  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1487  }
1488 
1502  SAL_WARN_UNUSED_RESULT OUString replace( sal_Unicode oldChar, sal_Unicode newChar ) const SAL_THROW(())
1503  {
1504  rtl_uString* pNew = 0;
1505  rtl_uString_newReplace( &pNew, pData, oldChar, newChar );
1506  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1507  }
1508 
1527  SAL_WARN_UNUSED_RESULT OUString replaceFirst(
1528  OUString const & from, OUString const & to, sal_Int32 * index = 0) const
1529  {
1530  rtl_uString * s = 0;
1531  sal_Int32 i = 0;
1533  &s, pData, from.pData, to.pData, index == 0 ? &i : index);
1534  return OUString(s, SAL_NO_ACQUIRE);
1535  }
1536 
1555  template< typename T >
1556  SAL_WARN_UNUSED_RESULT typename internal::ConstCharArrayDetector< T, OUString >::Type replaceFirst( T& from, OUString const & to,
1557  sal_Int32 * index = 0) const
1558  {
1559  rtl_uString * s = 0;
1560  sal_Int32 i = 0;
1561  assert( strlen( from ) == internal::ConstCharArrayDetector< T >::size - 1 );
1563  &s, pData, from, internal::ConstCharArrayDetector< T, void >::size - 1, to.pData, index == 0 ? &i : index);
1564  return OUString(s, SAL_NO_ACQUIRE);
1565  }
1566 
1585  template< typename T1, typename T2 >
1586  SAL_WARN_UNUSED_RESULT typename internal::ConstCharArrayDetector< T1, typename internal::ConstCharArrayDetector< T2, OUString >::Type >::Type
1587  replaceFirst( T1& from, T2& to, sal_Int32 * index = 0) const
1588  {
1589  rtl_uString * s = 0;
1590  sal_Int32 i = 0;
1591  assert( strlen( from ) == internal::ConstCharArrayDetector< T1 >::size - 1 );
1592  assert( strlen( to ) == internal::ConstCharArrayDetector< T2 >::size - 1 );
1594  &s, pData, from, internal::ConstCharArrayDetector< T1, void >::size - 1, to,
1595  internal::ConstCharArrayDetector< T2, void >::size - 1, index == 0 ? &i : index);
1596  return OUString(s, SAL_NO_ACQUIRE);
1597  }
1598 
1614  SAL_WARN_UNUSED_RESULT OUString replaceAll(
1615  OUString const & from, OUString const & to, sal_Int32 fromIndex = 0) const
1616  {
1617  rtl_uString * s = 0;
1618  rtl_uString_newReplaceAllFromIndex(&s, pData, from.pData, to.pData, fromIndex);
1619  return OUString(s, SAL_NO_ACQUIRE);
1620  }
1621 
1635  template< typename T >
1636  SAL_WARN_UNUSED_RESULT typename internal::ConstCharArrayDetector< T, OUString >::Type replaceAll( T& from, OUString const & to) const
1637  {
1638  rtl_uString * s = 0;
1639  assert( strlen( from ) == internal::ConstCharArrayDetector< T >::size - 1 );
1640  rtl_uString_newReplaceAllAsciiL(&s, pData, from, internal::ConstCharArrayDetector< T, void >::size - 1, to.pData);
1641  return OUString(s, SAL_NO_ACQUIRE);
1642  }
1643 
1657  template< typename T1, typename T2 >
1658  SAL_WARN_UNUSED_RESULT typename internal::ConstCharArrayDetector< T1, typename internal::ConstCharArrayDetector< T2, OUString >::Type >::Type
1659  replaceAll( T1& from, T2& to ) const
1660  {
1661  rtl_uString * s = 0;
1662  assert( strlen( from ) == internal::ConstCharArrayDetector< T1 >::size - 1 );
1663  assert( strlen( to ) == internal::ConstCharArrayDetector< T2 >::size - 1 );
1665  &s, pData, from, internal::ConstCharArrayDetector< T1, void >::size - 1,
1666  to, internal::ConstCharArrayDetector< T2, void >::size - 1);
1667  return OUString(s, SAL_NO_ACQUIRE);
1668  }
1669 
1680  SAL_WARN_UNUSED_RESULT OUString toAsciiLowerCase() const SAL_THROW(())
1681  {
1682  rtl_uString* pNew = 0;
1683  rtl_uString_newToAsciiLowerCase( &pNew, pData );
1684  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1685  }
1686 
1697  SAL_WARN_UNUSED_RESULT OUString toAsciiUpperCase() const SAL_THROW(())
1698  {
1699  rtl_uString* pNew = 0;
1700  rtl_uString_newToAsciiUpperCase( &pNew, pData );
1701  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1702  }
1703 
1715  SAL_WARN_UNUSED_RESULT OUString trim() const SAL_THROW(())
1716  {
1717  rtl_uString* pNew = 0;
1718  rtl_uString_newTrim( &pNew, pData );
1719  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
1720  }
1721 
1746  OUString getToken( sal_Int32 token, sal_Unicode cTok, sal_Int32& index ) const SAL_THROW(())
1747  {
1748  rtl_uString * pNew = 0;
1749  index = rtl_uString_getToken( &pNew, pData, token, cTok, index );
1750  return OUString( pNew, (DO_NOT_ACQUIRE *)0 );
1751  }
1752 
1766  OUString getToken(sal_Int32 count, sal_Unicode separator) const {
1767  sal_Int32 n = 0;
1768  return getToken(count, separator, n);
1769  }
1770 
1779  sal_Bool toBoolean() const SAL_THROW(())
1780  {
1781  return rtl_ustr_toBoolean( pData->buffer );
1782  }
1783 
1790  sal_Unicode toChar() const SAL_THROW(())
1791  {
1792  return pData->buffer[0];
1793  }
1794 
1804  sal_Int32 toInt32( sal_Int16 radix = 10 ) const SAL_THROW(())
1805  {
1806  return rtl_ustr_toInt32( pData->buffer, radix );
1807  }
1808 
1818  sal_Int64 toInt64( sal_Int16 radix = 10 ) const SAL_THROW(())
1819  {
1820  return rtl_ustr_toInt64( pData->buffer, radix );
1821  }
1822 
1835  sal_uInt64 toUInt64( sal_Int16 radix = 10 ) const SAL_THROW(())
1836  {
1837  return rtl_ustr_toUInt64( pData->buffer, radix );
1838  }
1839 
1848  float toFloat() const SAL_THROW(())
1849  {
1850  return rtl_ustr_toFloat( pData->buffer );
1851  }
1852 
1861  double toDouble() const SAL_THROW(())
1862  {
1863  return rtl_ustr_toDouble( pData->buffer );
1864  }
1865 
1866 
1882  OUString intern() const
1883  {
1884  rtl_uString * pNew = 0;
1885  rtl_uString_intern( &pNew, pData );
1886  if (pNew == 0) {
1887 #if defined EXCEPTIONS_OFF
1888  abort();
1889 #else
1890  throw std::bad_alloc();
1891 #endif
1892  }
1893  return OUString( pNew, (DO_NOT_ACQUIRE *)0 );
1894  }
1895 
1921  static OUString intern( const sal_Char * value, sal_Int32 length,
1922  rtl_TextEncoding encoding,
1923  sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS,
1924  sal_uInt32 *pInfo = NULL )
1925  {
1926  rtl_uString * pNew = 0;
1927  rtl_uString_internConvert( &pNew, value, length, encoding,
1928  convertFlags, pInfo );
1929  if (pNew == 0) {
1930 #if defined EXCEPTIONS_OFF
1931  abort();
1932 #else
1933  throw std::bad_alloc();
1934 #endif
1935  }
1936  return OUString( pNew, (DO_NOT_ACQUIRE *)0 );
1937  }
1938 
1963  inline bool convertToString(OString * pTarget, rtl_TextEncoding nEncoding,
1964  sal_uInt32 nFlags) const
1965  {
1966  return rtl_convertUStringToString(&pTarget->pData, pData->buffer,
1967  pData->length, nEncoding, nFlags);
1968  }
1969 
2021  inline sal_uInt32 iterateCodePoints(
2022  sal_Int32 * indexUtf16, sal_Int32 incrementCodePoints = 1) const
2023  {
2025  pData, indexUtf16, incrementCodePoints);
2026  }
2027 
2038  static OUString number( int i, sal_Int16 radix = 10 )
2039  {
2041  rtl_uString* pNewData = 0;
2042  rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfInt32( aBuf, i, radix ) );
2043  return OUString( pNewData, (DO_NOT_ACQUIRE*)0 );
2044  }
2047  static OUString number( unsigned int i, sal_Int16 radix = 10 )
2048  {
2049  return number( static_cast< unsigned long long >( i ), radix );
2050  }
2053  static OUString number( long i, sal_Int16 radix = 10)
2054  {
2055  return number( static_cast< long long >( i ), radix );
2056  }
2059  static OUString number( unsigned long i, sal_Int16 radix = 10 )
2060  {
2061  return number( static_cast< unsigned long long >( i ), radix );
2062  }
2065  static OUString number( long long ll, sal_Int16 radix = 10 )
2066  {
2068  rtl_uString* pNewData = 0;
2069  rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfInt64( aBuf, ll, radix ) );
2070  return OUString( pNewData, (DO_NOT_ACQUIRE*)0 );
2071  }
2074  static OUString number( unsigned long long ll, sal_Int16 radix = 10 )
2075  {
2077  rtl_uString* pNewData = 0;
2078  rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfUInt64( aBuf, ll, radix ) );
2079  return OUString( pNewData, (DO_NOT_ACQUIRE*)0 );
2080  }
2081 
2091  static OUString number( float f )
2092  {
2094  rtl_uString* pNewData = 0;
2095  rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfFloat( aBuf, f ) );
2096  return OUString( pNewData, (DO_NOT_ACQUIRE*)0 );
2097  }
2098 
2108  static OUString number( double d )
2109  {
2111  rtl_uString* pNewData = 0;
2112  rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfDouble( aBuf, d ) );
2113  return OUString( pNewData, (DO_NOT_ACQUIRE*)0 );
2114  }
2115 
2127  SAL_DEPRECATED_INTERNAL("use boolean()") static OUString valueOf( sal_Bool b ) SAL_THROW(())
2128  {
2129  return boolean(b);
2130  }
2131 
2143  static OUString boolean( bool b ) SAL_THROW(())
2144  {
2146  rtl_uString* pNewData = 0;
2147  rtl_uString_newFromStr_WithLength( &pNewData, aBuf, rtl_ustr_valueOfBoolean( aBuf, b ) );
2148  return OUString( pNewData, (DO_NOT_ACQUIRE*)0 );
2149  }
2150 
2158  SAL_DEPRECATED_INTERNAL("convert to OUString or use directly") static OUString valueOf( sal_Unicode c ) SAL_THROW(())
2159  {
2160  return OUString( &c, 1 );
2161  }
2162 
2173  SAL_DEPRECATED_INTERNAL("use number()") static OUString valueOf( sal_Int32 i, sal_Int16 radix = 10 ) SAL_THROW(())
2174  {
2175  return number( i, radix );
2176  }
2177 
2188  SAL_DEPRECATED_INTERNAL("use number()") static OUString valueOf( sal_Int64 ll, sal_Int16 radix = 10 ) SAL_THROW(())
2189  {
2190  return number( ll, radix );
2191  }
2192 
2202  SAL_DEPRECATED_INTERNAL("use number()") static OUString valueOf( float f ) SAL_THROW(())
2203  {
2204  return number(f);
2205  }
2206 
2216  SAL_DEPRECATED_INTERNAL("use number()") static OUString valueOf( double d ) SAL_THROW(())
2217  {
2218  return number(d);
2219  }
2220 
2236  static OUString createFromAscii( const sal_Char * value ) SAL_THROW(())
2237  {
2238  rtl_uString* pNew = 0;
2239  rtl_uString_newFromAscii( &pNew, value );
2240  return OUString( pNew, (DO_NOT_ACQUIRE*)0 );
2241  }
2242 };
2243 
2244 /* ======================================================================= */
2245 
2246 #ifdef RTL_FAST_STRING
2247 
2256 {
2257  template< int N >
2258  OUStringLiteral( const char (&str)[ N ] ) : size( N - 1 ), data( str ) { assert( strlen( str ) == N - 1 ); }
2259  int size;
2260  const char* data;
2261 };
2262 
2266 template<>
2267 struct ToStringHelper< OUString >
2268  {
2269  static int length( const OUString& s ) { return s.getLength(); }
2270  static sal_Unicode* addData( sal_Unicode* buffer, const OUString& s ) { return addDataHelper( buffer, s.getStr(), s.getLength()); }
2271  static const bool allowOStringConcat = false;
2272  static const bool allowOUStringConcat = true;
2273  };
2274 
2278 template<>
2279 struct ToStringHelper< OUStringLiteral >
2280  {
2281  static int length( const OUStringLiteral& str ) { return str.size; }
2282  static sal_Unicode* addData( sal_Unicode* buffer, const OUStringLiteral& str ) { return addDataLiteral( buffer, str.data, str.size ); }
2283  static const bool allowOStringConcat = false;
2284  static const bool allowOUStringConcat = true;
2285  };
2286 
2290 template< typename charT, typename traits, typename T1, typename T2 >
2291 inline std::basic_ostream<charT, traits> & operator <<(
2292  std::basic_ostream<charT, traits> & stream, const OUStringConcat< T1, T2 >& concat)
2293 {
2294  return stream << OUString( concat );
2295 }
2296 #else
2297 // non-RTL_FAST_CODE needs this to compile
2299 #endif
2300 
2307 {
2317  size_t operator()(const OUString& rString) const
2318  { return (size_t)rString.hashCode(); }
2319 };
2320 
2321 /* ======================================================================= */
2322 
2340 inline OUString OStringToOUString( const OString & rStr,
2341  rtl_TextEncoding encoding,
2342  sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS )
2343 {
2344  return OUString( rStr.getStr(), rStr.getLength(), encoding, convertFlags );
2345 }
2346 
2364 inline OString OUStringToOString( const OUString & rUnicode,
2365  rtl_TextEncoding encoding,
2366  sal_uInt32 convertFlags = OUSTRING_TO_OSTRING_CVTFLAGS )
2367 {
2368  return OString( rUnicode.getStr(), rUnicode.getLength(), encoding, convertFlags );
2369 }
2370 
2371 /* ======================================================================= */
2372 
2381 template< typename charT, typename traits >
2382 inline std::basic_ostream<charT, traits> & operator <<(
2383  std::basic_ostream<charT, traits> & stream, OUString const & string)
2384 {
2385  return stream <<
2387  // best effort; potentially loses data due to conversion failures
2388  // (stray surrogate halves) and embedded null characters
2389 }
2390 
2391 } // namespace
2392 
2393 #ifdef RTL_STRING_UNITTEST
2394 namespace rtl
2395 {
2396 typedef rtlunittest::OUString OUString;
2397 }
2398 #endif
2399 
2400 // RTL_USING is defined by gbuild for all modules except those with stable public API
2401 // (as listed in ure/source/README). It allows to use classes like OUString without
2402 // having to explicitly refer to the rtl namespace, which is kind of superfluous
2403 // given that OUString itself is namespaced by its OU prefix.
2404 #ifdef RTL_USING
2405 using ::rtl::OUString;
2406 using ::rtl::OUStringHash;
2410 #endif
2411 
2412 #endif /* _RTL_USTRING_HXX */
2413 
2414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */