My Project
UDK 3.2.7 C/C++ API Reference
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ustrbuf.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_USTRBUF_HXX_
21 #define _RTL_USTRBUF_HXX_
22 
23 #include "sal/config.h"
24 
25 #include <cassert>
26 #include <string.h>
27 
28 #include <osl/diagnose.h>
29 #include <rtl/ustrbuf.h>
30 #include <rtl/ustring.hxx>
31 #include <rtl/stringutils.hxx>
32 
33 #ifdef RTL_FAST_STRING
34 #include <rtl/stringconcat.hxx>
35 #endif
36 
37 // The unittest uses slightly different code to help check that the proper
38 // calls are made. The class is put into a different namespace to make
39 // sure the compiler generates a different (if generating also non-inline)
40 // copy of the function and does not merge them together. The class
41 // is "brought" into the proper rtl namespace by a typedef below.
42 #ifdef RTL_STRING_UNITTEST
43 #define rtl rtlunittest
44 #endif
45 
46 namespace rtl
47 {
48 
49 #ifdef RTL_STRING_UNITTEST
50 #undef rtl
51 #endif
52 
92 {
93 public:
99  : pData(NULL)
100  , nCapacity( 16 )
101  {
102  rtl_uString_new_WithLength( &pData, nCapacity );
103  }
104 
112  : pData(NULL)
113  , nCapacity( value.nCapacity )
114  {
115  rtl_uStringbuffer_newFromStringBuffer( &pData, value.nCapacity, value.pData );
116  }
117 
124  explicit OUStringBuffer(int length)
125  : pData(NULL)
126  , nCapacity( length )
127  {
128  rtl_uString_new_WithLength( &pData, length );
129  }
130 
142  : pData(NULL)
143  , nCapacity( value.getLength() + 16 )
144  {
145  rtl_uStringbuffer_newFromStr_WithLength( &pData, value.getStr(), value.getLength() );
146  }
147 
148 #ifdef HAVE_SFINAE_ANONYMOUS_BROKEN // see OUString ctors
149  template< int N >
150  OUStringBuffer( const char (&literal)[ N ] )
151  : pData(NULL)
152  , nCapacity( N - 1 + 16 )
153  {
154  assert( strlen( literal ) == N - 1 );
155  rtl_uString_newFromLiteral( &pData, literal, N - 1, 16 );
156 #ifdef RTL_STRING_UNITTEST
157  rtl_string_unittest_const_literal = true;
158 #endif
159  }
160 
165  template< int N >
166  OUStringBuffer( char (&value)[ N ] )
167 #ifndef RTL_STRING_UNITTEST
168  ; // intentionally not implemented
169 #else
170  {
171  (void) value; // unused
172  pData = 0;
173  nCapacity = 10;
174  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
175  rtl_string_unittest_invalid_conversion = true;
176  }
177 #endif
178 #else // HAVE_SFINAE_ANONYMOUS_BROKEN
179  template< typename T >
181  : pData(NULL)
182  , nCapacity( internal::ConstCharArrayDetector< T, void >::size - 1 + 16 )
183  {
184  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
186 #ifdef RTL_STRING_UNITTEST
187  rtl_string_unittest_const_literal = true;
188 #endif
189  }
190 #endif // HAVE_SFINAE_ANONYMOUS_BROKEN
191 
192 #ifdef RTL_STRING_UNITTEST
193 
197  template< typename T >
198  OUStringBuffer( T&, typename internal::ExceptConstCharArrayDetector< T >::Type = internal::Dummy() )
199  {
200  pData = 0;
201  nCapacity = 10;
202  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
203  rtl_string_unittest_invalid_conversion = true;
204  }
209  template< typename T >
210  OUStringBuffer( const T&, typename internal::ExceptCharArrayDetector< T >::Type = internal::Dummy() )
211  {
212  pData = 0;
213  nCapacity = 10;
214  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
215  rtl_string_unittest_invalid_conversion = true;
216  }
217 #endif
218 
219 #ifdef RTL_FAST_STRING
220  template< typename T1, typename T2 >
221  OUStringBuffer( const OUStringConcat< T1, T2 >& c )
222  {
223  const sal_Int32 l = c.length();
224  rtl_uString* buffer = NULL;
225  nCapacity = l + 16;
226  rtl_uString_new_WithLength( &buffer, nCapacity ); // TODO this clears, not necessary
227  sal_Unicode* end = c.addData( buffer->buffer );
228  *end = '\0';
229  buffer->length = end - buffer->buffer;
230  // TODO realloc in case buffer->length is noticeably smaller than l ?
231  pData = buffer;
232  }
233 #endif
234 
236  OUStringBuffer& operator = ( const OUStringBuffer& value )
237  {
238  if (this != &value)
239  {
241  value.nCapacity,
242  value.pData);
243  nCapacity = value.nCapacity;
244  }
245  return *this;
246  }
247 
251  ~OUStringBuffer()
252  {
253  rtl_uString_release( pData );
254  }
255 
264  OUString makeStringAndClear()
265  {
266  return OUString(
267  rtl_uStringBuffer_makeStringAndClear( &pData, &nCapacity ),
268  SAL_NO_ACQUIRE );
269  }
270 
276  sal_Int32 getLength() const
277  {
278  return pData->length;
279  }
280 
291  sal_Int32 getCapacity() const
292  {
293  return nCapacity;
294  }
295 
307  void ensureCapacity(sal_Int32 minimumCapacity)
308  {
309  rtl_uStringbuffer_ensureCapacity( &pData, &nCapacity, minimumCapacity );
310  }
311 
330  void setLength(sal_Int32 newLength)
331  {
332  assert(newLength >= 0);
333  // Avoid modifications if pData points to const empty string:
334  if( newLength != pData->length )
335  {
336  if( newLength > nCapacity )
337  rtl_uStringbuffer_ensureCapacity(&pData, &nCapacity, newLength);
338  else
339  pData->buffer[newLength] = 0;
340  pData->length = newLength;
341  }
342  }
343 
357  SAL_DEPRECATED("use rtl::OUStringBuffer::operator [] instead")
358  sal_Unicode charAt( sal_Int32 index ) const
359  {
360  assert(index >= 0 && index < pData->length);
361  return pData->buffer[ index ];
362  }
363 
374  SAL_DEPRECATED("use rtl::OUStringBuffer::operator [] instead")
375  OUStringBuffer & setCharAt(sal_Int32 index, sal_Unicode ch)
376  {
377  assert(index >= 0 && index < pData->length);
378  pData->buffer[ index ] = ch;
379  return *this;
380  }
381 
385  const sal_Unicode* getStr() const { return pData->buffer; }
386 
396  sal_Unicode & operator [](sal_Int32 index) { return pData->buffer[index]; }
397 
402  const OUString toString() const
403  {
404  return OUString(pData->buffer, pData->length);
405  }
406 
417  OUStringBuffer & append(const OUString &str)
418  {
419  return append( str.getStr(), str.getLength() );
420  }
421 
434  OUStringBuffer & append(const OUStringBuffer &str)
435  {
436  if(str.getLength() > 0)
437  {
438  append( str.getStr(), str.getLength() );
439  }
440  return *this;
441  }
442 
454  OUStringBuffer & append( const sal_Unicode * str )
455  {
456  return append( str, rtl_ustr_getLength( str ) );
457  }
458 
472  OUStringBuffer & append( const sal_Unicode * str, sal_Int32 len)
473  {
474  // insert behind the last character
475  rtl_uStringbuffer_insert( &pData, &nCapacity, getLength(), str, len );
476  return *this;
477  }
478 
484  template< typename T >
486  {
487  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
488  rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), literal,
490  return *this;
491  }
492 
509  OUStringBuffer & appendAscii( const sal_Char * str )
510  {
511  return appendAscii( str, rtl_str_getLength( str ) );
512  }
513 
532  OUStringBuffer & appendAscii( const sal_Char * str, sal_Int32 len)
533  {
534  rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), str, len );
535  return *this;
536  }
537 
549  OUStringBuffer & append(sal_Bool b)
550  {
552  return append( sz, rtl_ustr_valueOfBoolean( sz, b ) );
553  }
554 
567  OUStringBuffer & append(char c)
568  {
569  assert(static_cast< unsigned char >(c) <= 0x7F);
570  return append(sal_Unicode(c));
571  }
572 
583  OUStringBuffer & append(sal_Unicode c)
584  {
585  return append( &c, 1 );
586  }
587 
599  OUStringBuffer & append(sal_Int32 i, sal_Int16 radix = 10 )
600  {
602  return append( sz, rtl_ustr_valueOfInt32( sz, i, radix ) );
603  }
604 
616  OUStringBuffer & append(sal_Int64 l, sal_Int16 radix = 10 )
617  {
619  return append( sz, rtl_ustr_valueOfInt64( sz, l, radix ) );
620  }
621 
633  OUStringBuffer & append(float f)
634  {
636  return append( sz, rtl_ustr_valueOfFloat( sz, f ) );
637  }
638 
650  OUStringBuffer & append(double d)
651  {
653  return append( sz, rtl_ustr_valueOfDouble( sz, d ) );
654  }
655 
669  OUStringBuffer & appendUtf32(sal_uInt32 c) {
670  return insertUtf32(getLength(), c);
671  }
672 
688  OUStringBuffer & insert(sal_Int32 offset, const OUString & str)
689  {
690  return insert( offset, str.getStr(), str.getLength() );
691  }
692 
710  OUStringBuffer & insert( sal_Int32 offset, const sal_Unicode * str )
711  {
712  return insert( offset, str, rtl_ustr_getLength( str ) );
713  }
714 
733  OUStringBuffer & insert( sal_Int32 offset, const sal_Unicode * str, sal_Int32 len)
734  {
735  // insert behind the last character
736  rtl_uStringbuffer_insert( &pData, &nCapacity, offset, str, len );
737  return *this;
738  }
739 
745  template< typename T >
746  typename internal::ConstCharArrayDetector< T, OUStringBuffer& >::Type insert( sal_Int32 offset, T& literal )
747  {
748  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
749  rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, offset, literal,
751  return *this;
752  }
753 
771  OUStringBuffer & insert(sal_Int32 offset, sal_Bool b)
772  {
774  return insert( offset, sz, rtl_ustr_valueOfBoolean( sz, b ) );
775  }
776 
795  OUStringBuffer & insert(sal_Int32 offset, char c)
796  {
797  sal_Unicode u = c;
798  return insert( offset, &u, 1 );
799  }
800 
817  OUStringBuffer & insert(sal_Int32 offset, sal_Unicode c)
818  {
819  return insert( offset, &c, 1 );
820  }
821 
841  OUStringBuffer & insert(sal_Int32 offset, sal_Int32 i, sal_Int16 radix = 10 )
842  {
844  return insert( offset, sz, rtl_ustr_valueOfInt32( sz, i, radix ) );
845  }
846 
866  OUStringBuffer & insert(sal_Int32 offset, sal_Int64 l, sal_Int16 radix = 10 )
867  {
869  return insert( offset, sz, rtl_ustr_valueOfInt64( sz, l, radix ) );
870  }
871 
890  OUStringBuffer insert(sal_Int32 offset, float f)
891  {
893  return insert( offset, sz, rtl_ustr_valueOfFloat( sz, f ) );
894  }
895 
914  OUStringBuffer & insert(sal_Int32 offset, double d)
915  {
917  return insert( offset, sz, rtl_ustr_valueOfDouble( sz, d ) );
918  }
919 
935  OUStringBuffer & insertUtf32(sal_Int32 offset, sal_uInt32 c) {
936  rtl_uStringbuffer_insertUtf32(&pData, &nCapacity, offset, c);
937  return *this;
938  }
939 
952  OUStringBuffer & remove( sal_Int32 start, sal_Int32 len )
953  {
954  rtl_uStringbuffer_remove( &pData, start, len );
955  return *this;
956  }
957 
968  OUStringBuffer & truncate( sal_Int32 start = 0 )
969  {
970  rtl_uStringbuffer_remove( &pData, start, getLength() - start );
971  return *this;
972  }
973 
984  OUStringBuffer& replace( sal_Unicode oldChar, sal_Unicode newChar )
985  {
986  sal_Int32 index = 0;
987  while((index = indexOf(oldChar, index)) >= 0)
988  {
989  pData->buffer[ index ] = newChar;
990  }
991  return *this;
992  }
993 
1009  inline void accessInternals(rtl_uString *** pInternalData,
1010  sal_Int32 ** pInternalCapacity)
1011  {
1012  *pInternalData = &pData;
1013  *pInternalCapacity = &nCapacity;
1014  }
1015 
1016 
1032  sal_Int32 indexOf( sal_Unicode ch, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
1033  {
1034  sal_Int32 ret = rtl_ustr_indexOfChar_WithLength( pData->buffer+fromIndex, pData->length-fromIndex, ch );
1035  return (ret < 0 ? ret : ret+fromIndex);
1036  }
1037 
1049  sal_Int32 lastIndexOf( sal_Unicode ch ) const SAL_THROW(())
1050  {
1051  return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, pData->length, ch );
1052  }
1053 
1068  sal_Int32 lastIndexOf( sal_Unicode ch, sal_Int32 fromIndex ) const SAL_THROW(())
1069  {
1070  return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, fromIndex, ch );
1071  }
1072 
1090  sal_Int32 indexOf( const OUString & str, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
1091  {
1092  sal_Int32 ret = rtl_ustr_indexOfStr_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1093  str.pData->buffer, str.pData->length );
1094  return (ret < 0 ? ret : ret+fromIndex);
1095  }
1096 
1103  template< typename T >
1104  typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type indexOf( T& literal, sal_Int32 fromIndex = 0 ) const SAL_THROW(())
1105  {
1106  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1107  sal_Int32 ret = rtl_ustr_indexOfAscii_WithLength(
1108  pData->buffer + fromIndex, pData->length - fromIndex, literal,
1110  return ret < 0 ? ret : ret + fromIndex;
1111  }
1112 
1130  sal_Int32 lastIndexOf( const OUString & str ) const SAL_THROW(())
1131  {
1132  return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, pData->length,
1133  str.pData->buffer, str.pData->length );
1134  }
1135 
1155  sal_Int32 lastIndexOf( const OUString & str, sal_Int32 fromIndex ) const SAL_THROW(())
1156  {
1157  return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, fromIndex,
1158  str.pData->buffer, str.pData->length );
1159  }
1160 
1166  template< typename T >
1167  typename internal::ConstCharArrayDetector< T, sal_Int32 >::Type lastIndexOf( T& literal ) const SAL_THROW(())
1168  {
1169  assert( strlen( literal ) == internal::ConstCharArrayDetector< T >::size - 1 );
1171  pData->buffer, pData->length, literal, internal::ConstCharArrayDetector< T, void >::size - 1);
1172  }
1173 
1183  sal_Int32 stripStart(sal_Unicode c = (sal_Unicode)' ')
1184  {
1185  sal_Int32 index;
1186  for(index = 0; index < getLength() ; index++)
1187  {
1188  if(pData->buffer[ index ] != c)
1189  {
1190  break;
1191  }
1192  }
1193  if(index)
1194  {
1195  remove(0, index);
1196  }
1197  return index;
1198  }
1199 
1209  sal_Int32 stripEnd(sal_Unicode c = (sal_Unicode)' ')
1210  {
1211  sal_Int32 result = getLength();
1212  sal_Int32 index;
1213  for(index = getLength(); index > 0 ; index--)
1214  {
1215  if(pData->buffer[ index - 1 ] != c)
1216  {
1217  break;
1218  }
1219  }
1220  if(index < getLength())
1221  {
1222  truncate(index);
1223  }
1224  return result - getLength();
1225  }
1235  sal_Int32 strip(sal_Unicode c = (sal_Unicode)' ')
1236  {
1237  return stripStart(c) + stripEnd(c);
1238  }
1239 
1240 private:
1244  rtl_uString * pData;
1245 
1249  sal_Int32 nCapacity;
1250 };
1251 
1252 #ifdef RTL_FAST_STRING
1253 template<>
1254 struct ToStringHelper< OUStringBuffer >
1255  {
1256  static int length( const OUStringBuffer& s ) { return s.getLength(); }
1257  static sal_Unicode* addData( sal_Unicode* buffer, const OUStringBuffer& s ) { return addDataHelper( buffer, s.getStr(), s.getLength()); }
1258  static const bool allowOStringConcat = false;
1259  static const bool allowOUStringConcat = true;
1260  };
1261 #endif
1262 
1263 }
1264 
1265 #ifdef RTL_STRING_UNITTEST
1266 namespace rtl
1267 {
1268 typedef rtlunittest::OUStringBuffer OUStringBuffer;
1269 }
1270 #endif
1271 
1272 #ifdef RTL_USING
1273 using ::rtl::OUStringBuffer;
1274 #endif
1275 
1276 #endif /* _RTL_USTRBUF_HXX_ */
1277 
1278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */