LibreOffice
LibreOffice 4.4 SDK 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 INCLUDED_RTL_USTRBUF_HXX
21 #define INCLUDED_RTL_USTRBUF_HXX
22 
23 #include <sal/config.h>
24 
25 #include <cassert>
26 #include <string.h>
27 
28 #include <rtl/ustrbuf.h>
29 #include <rtl/ustring.hxx>
30 #include <rtl/stringutils.hxx>
31 #include <sal/types.h>
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 
141  OUStringBuffer(const OUString& value)
142  : pData(NULL)
143  , nCapacity( value.getLength() + 16 )
144  {
145  rtl_uStringbuffer_newFromStr_WithLength( &pData, value.getStr(), value.getLength() );
146  }
147 
148  template< typename T >
150  : pData(NULL)
151  , nCapacity( libreoffice_internal::ConstCharArrayDetector< T, void >::size - 1 + 16 )
152  {
153  assert( strlen( literal ) == libreoffice_internal::ConstCharArrayDetector< T >::size - 1 );
155 #ifdef RTL_STRING_UNITTEST
156  rtl_string_unittest_const_literal = true;
157 #endif
158  }
159 
160 #ifdef RTL_STRING_UNITTEST
161 
165  template< typename T >
167  {
168  pData = 0;
169  nCapacity = 10;
170  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
171  rtl_string_unittest_invalid_conversion = true;
172  }
177  template< typename T >
178  OUStringBuffer( const T&, typename libreoffice_internal::ExceptCharArrayDetector< T >::Type = libreoffice_internal::Dummy() )
179  {
180  pData = 0;
181  nCapacity = 10;
182  rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
183  rtl_string_unittest_invalid_conversion = true;
184  }
185 #endif
186 
187 #ifdef RTL_FAST_STRING
188 
192  template< typename T1, typename T2 >
193  OUStringBuffer( const OUStringConcat< T1, T2 >& c )
194  {
195  const sal_Int32 l = c.length();
196  nCapacity = l + 16;
197  pData = rtl_uString_alloc( nCapacity );
198  sal_Unicode* end = c.addData( pData->buffer );
199  *end = '\0';
200  pData->length = end - pData->buffer;
201  // TODO realloc in case pData->>length is noticeably smaller than l ?
202  }
203 #endif
204 
206  OUStringBuffer& operator = ( const OUStringBuffer& value )
207  {
208  if (this != &value)
209  {
211  value.nCapacity,
212  value.pData);
213  nCapacity = value.nCapacity;
214  }
215  return *this;
216  }
217 
222  {
223  rtl_uString_release( pData );
224  }
225 
235  {
236  return OUString(
237  rtl_uStringBuffer_makeStringAndClear( &pData, &nCapacity ),
238  SAL_NO_ACQUIRE );
239  }
240 
246  sal_Int32 getLength() const
247  {
248  return pData->length;
249  }
250 
259  bool isEmpty() const
260  {
261  return pData->length == 0;
262  }
263 
274  sal_Int32 getCapacity() const
275  {
276  return nCapacity;
277  }
278 
290  void ensureCapacity(sal_Int32 minimumCapacity)
291  {
292  rtl_uStringbuffer_ensureCapacity( &pData, &nCapacity, minimumCapacity );
293  }
294 
313  void setLength(sal_Int32 newLength)
314  {
315  assert(newLength >= 0);
316  // Avoid modifications if pData points to const empty string:
317  if( newLength != pData->length )
318  {
319  if( newLength > nCapacity )
320  rtl_uStringbuffer_ensureCapacity(&pData, &nCapacity, newLength);
321  else
322  pData->buffer[newLength] = 0;
323  pData->length = newLength;
324  }
325  }
326 
340  SAL_DEPRECATED("use rtl::OUStringBuffer::operator [] instead")
341  sal_Unicode charAt( sal_Int32 index ) const
342  {
343  assert(index >= 0 && index < pData->length);
344  return pData->buffer[ index ];
345  }
346 
357  SAL_DEPRECATED("use rtl::OUStringBuffer::operator [] instead")
358  OUStringBuffer & setCharAt(sal_Int32 index, sal_Unicode ch)
359  {
360  assert(index >= 0 && index < pData->length);
361  pData->buffer[ index ] = ch;
362  return *this;
363  }
364 
368  const sal_Unicode* getStr() const { return pData->buffer; }
369 
379  sal_Unicode & operator [](sal_Int32 index)
380  {
381  assert(index >= 0 && index < pData->length);
382  return pData->buffer[index];
383  }
384 
394  const sal_Unicode & operator [](sal_Int32 index) const
395  {
396  assert(index >= 0 && index < pData->length);
397  return pData->buffer[index];
398  }
399 
404  const OUString toString() const
405  {
406  return OUString(pData->buffer, pData->length);
407  }
408 
420  {
421  return append( str.getStr(), str.getLength() );
422  }
423 
437  {
438  if(!str.isEmpty())
439  {
440  append( str.getStr(), str.getLength() );
441  }
442  return *this;
443  }
444 
457  {
458  return append( str, rtl_ustr_getLength( str ) );
459  }
460 
474  OUStringBuffer & append( const sal_Unicode * str, sal_Int32 len)
475  {
476  assert( len >= 0 );
477  assert( len == 0 || str != 0 );
478  rtl_uStringbuffer_insert( &pData, &nCapacity, getLength(), str, len );
479  return *this;
480  }
481 
487  template< typename T >
489  {
490  assert( strlen( literal ) == libreoffice_internal::ConstCharArrayDetector< T >::size - 1 );
491  rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), literal,
493  return *this;
494  }
495 
496 #ifdef RTL_FAST_STRING
497 
501  template< typename T1, typename T2 >
502  OUStringBuffer& append( const OUStringConcat< T1, T2 >& c )
503  {
504  const int l = c.length();
505  if( l == 0 )
506  return *this;
507  rtl_uStringbuffer_ensureCapacity( &pData, &nCapacity, pData->length + l );
508  sal_Unicode* end = c.addData( pData->buffer + pData->length );
509  *end = '\0';
510  pData->length = end - pData->buffer;
511  return *this;
512  }
513 #endif
514 
532  {
533  return appendAscii( str, rtl_str_getLength( str ) );
534  }
535 
554  OUStringBuffer & appendAscii( const sal_Char * str, sal_Int32 len)
555  {
556  assert( len >= 0 );
557  rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, getLength(), str, len );
558  return *this;
559  }
560 
575  {
577  return append( sz, rtl_ustr_valueOfBoolean( sz, b ) );
578  }
579 
581  // Pointer can be automatically converted to bool, which is unwanted here.
582  // Explicitly delete all pointer append() overloads to prevent this
583  // (except for char* and sal_Unicode* overloads, which are handled elsewhere).
584  template< typename T >
585  typename libreoffice_internal::Enable< void,
587  append( T* ) SAL_DELETED_FUNCTION;
589 
590  // This overload is needed because OUString has a ctor from rtl_uString*, but
591  // the bool overload above would be preferred to the conversion.
595  OUStringBuffer & append(rtl_uString* str)
596  {
597  return append( OUString( str ));
598  }
599 
612  {
614  return append( sz, rtl_ustr_valueOfBoolean( sz, b ) );
615  }
616 
630  {
631  assert(static_cast< unsigned char >(c) <= 0x7F);
632  return append(sal_Unicode(c));
633  }
634 
646  {
647  return append( &c, 1 );
648  }
649 
662  OUStringBuffer & append(sal_Int32 i, sal_Int16 radix = 10 )
663  {
665  return append( sz, rtl_ustr_valueOfInt32( sz, i, radix ) );
666  }
667 
680  OUStringBuffer & append(sal_Int64 l, sal_Int16 radix = 10 )
681  {
683  return append( sz, rtl_ustr_valueOfInt64( sz, l, radix ) );
684  }
685 
698  {
700  return append( sz, rtl_ustr_valueOfFloat( sz, f ) );
701  }
702 
714  OUStringBuffer & append(double d)
715  {
717  return append( sz, rtl_ustr_valueOfDouble( sz, d ) );
718  }
719 
733  OUStringBuffer & appendUtf32(sal_uInt32 c) {
734  return insertUtf32(getLength(), c);
735  }
736 
752  sal_Unicode * appendUninitialized(sal_Int32 length) {
753  assert(length >= 0);
754  sal_Int32 n = getLength();
755  rtl_uStringbuffer_insert(&pData, &nCapacity, n, 0, length);
756  return pData->buffer + n;
757  }
758 
774  OUStringBuffer & insert(sal_Int32 offset, const OUString & str)
775  {
776  return insert( offset, str.getStr(), str.getLength() );
777  }
778 
796  OUStringBuffer & insert( sal_Int32 offset, const sal_Unicode * str )
797  {
798  return insert( offset, str, rtl_ustr_getLength( str ) );
799  }
800 
819  OUStringBuffer & insert( sal_Int32 offset, const sal_Unicode * str, sal_Int32 len)
820  {
821  assert( offset >= 0 && offset <= pData->length );
822  assert( len >= 0 );
823  assert( len == 0 || str != 0 );
824  rtl_uStringbuffer_insert( &pData, &nCapacity, offset, str, len );
825  return *this;
826  }
827 
833  template< typename T >
835  {
836  assert( strlen( literal ) == libreoffice_internal::ConstCharArrayDetector< T >::size - 1 );
837  rtl_uStringbuffer_insert_ascii( &pData, &nCapacity, offset, literal,
839  return *this;
840  }
841 
859  OUStringBuffer & insert(sal_Int32 offset, sal_Bool b)
860  {
862  return insert( offset, sz, rtl_ustr_valueOfBoolean( sz, b ) );
863  }
864 
884  OUStringBuffer & insert(sal_Int32 offset, bool b)
885  {
887  return insert( offset, sz, rtl_ustr_valueOfBoolean( sz, b ) );
888  }
889 
908  OUStringBuffer & insert(sal_Int32 offset, char c)
909  {
910  sal_Unicode u = c;
911  return insert( offset, &u, 1 );
912  }
913 
930  OUStringBuffer & insert(sal_Int32 offset, sal_Unicode c)
931  {
932  return insert( offset, &c, 1 );
933  }
934 
954  OUStringBuffer & insert(sal_Int32 offset, sal_Int32 i, sal_Int16 radix = 10 )
955  {
957  return insert( offset, sz, rtl_ustr_valueOfInt32( sz, i, radix ) );
958  }
959 
979  OUStringBuffer & insert(sal_Int32 offset, sal_Int64 l, sal_Int16 radix = 10 )
980  {
982  return insert( offset, sz, rtl_ustr_valueOfInt64( sz, l, radix ) );
983  }
984 
1003  OUStringBuffer insert(sal_Int32 offset, float f)
1004  {
1006  return insert( offset, sz, rtl_ustr_valueOfFloat( sz, f ) );
1007  }
1008 
1027  OUStringBuffer & insert(sal_Int32 offset, double d)
1028  {
1030  return insert( offset, sz, rtl_ustr_valueOfDouble( sz, d ) );
1031  }
1032 
1048  OUStringBuffer & insertUtf32(sal_Int32 offset, sal_uInt32 c) {
1049  rtl_uStringbuffer_insertUtf32(&pData, &nCapacity, offset, c);
1050  return *this;
1051  }
1052 
1065  OUStringBuffer & remove( sal_Int32 start, sal_Int32 len )
1066  {
1067  assert( start >= 0 && start <= pData->length );
1068  assert( len >= 0 );
1069  rtl_uStringbuffer_remove( &pData, start, len );
1070  return *this;
1071  }
1072 
1083  OUStringBuffer & truncate( sal_Int32 start = 0 )
1084  {
1085  assert( start >= 0 && start <= pData->length );
1086  rtl_uStringbuffer_remove( &pData, start, getLength() - start );
1087  return *this;
1088  }
1089 
1101  {
1102  sal_Int32 index = 0;
1103  while((index = indexOf(oldChar, index)) >= 0)
1104  {
1105  pData->buffer[ index ] = newChar;
1106  }
1107  return *this;
1108  }
1109 
1125  inline void accessInternals(rtl_uString *** pInternalData,
1126  sal_Int32 ** pInternalCapacity)
1127  {
1128  *pInternalData = &pData;
1129  *pInternalCapacity = &nCapacity;
1130  }
1131 
1132 
1148  sal_Int32 indexOf( sal_Unicode ch, sal_Int32 fromIndex = 0 ) const
1149  {
1150  assert( fromIndex >= 0 && fromIndex <= pData->length );
1151  sal_Int32 ret = rtl_ustr_indexOfChar_WithLength( pData->buffer+fromIndex, pData->length-fromIndex, ch );
1152  return (ret < 0 ? ret : ret+fromIndex);
1153  }
1154 
1166  sal_Int32 lastIndexOf( sal_Unicode ch ) const
1167  {
1168  return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, pData->length, ch );
1169  }
1170 
1185  sal_Int32 lastIndexOf( sal_Unicode ch, sal_Int32 fromIndex ) const
1186  {
1187  assert( fromIndex >= 0 && fromIndex <= pData->length );
1188  return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, fromIndex, ch );
1189  }
1190 
1208  sal_Int32 indexOf( const OUString & str, sal_Int32 fromIndex = 0 ) const
1209  {
1210  assert( fromIndex >= 0 && fromIndex <= pData->length );
1211  sal_Int32 ret = rtl_ustr_indexOfStr_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1212  str.pData->buffer, str.pData->length );
1213  return (ret < 0 ? ret : ret+fromIndex);
1214  }
1215 
1222  template< typename T >
1223  typename libreoffice_internal::ConstCharArrayDetector< T, sal_Int32 >::Type indexOf( T& literal, sal_Int32 fromIndex = 0 ) const
1224  {
1225  assert( strlen( literal ) == libreoffice_internal::ConstCharArrayDetector< T >::size - 1 );
1226  sal_Int32 ret = rtl_ustr_indexOfAscii_WithLength(
1227  pData->buffer + fromIndex, pData->length - fromIndex, literal,
1229  return ret < 0 ? ret : ret + fromIndex;
1230  }
1231 
1249  sal_Int32 lastIndexOf( const OUString & str ) const
1250  {
1251  return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, pData->length,
1252  str.pData->buffer, str.pData->length );
1253  }
1254 
1274  sal_Int32 lastIndexOf( const OUString & str, sal_Int32 fromIndex ) const
1275  {
1276  assert( fromIndex >= 0 && fromIndex <= pData->length );
1277  return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, fromIndex,
1278  str.pData->buffer, str.pData->length );
1279  }
1280 
1286  template< typename T >
1288  {
1289  assert( strlen( literal ) == libreoffice_internal::ConstCharArrayDetector< T >::size - 1 );
1291  pData->buffer, pData->length, literal, libreoffice_internal::ConstCharArrayDetector< T, void >::size - 1);
1292  }
1293 
1303  sal_Int32 stripStart(sal_Unicode c = (sal_Unicode)' ')
1304  {
1305  sal_Int32 index;
1306  for(index = 0; index < getLength() ; index++)
1307  {
1308  if(pData->buffer[ index ] != c)
1309  {
1310  break;
1311  }
1312  }
1313  if(index)
1314  {
1315  remove(0, index);
1316  }
1317  return index;
1318  }
1319 
1329  sal_Int32 stripEnd(sal_Unicode c = (sal_Unicode)' ')
1330  {
1331  sal_Int32 result = getLength();
1332  sal_Int32 index;
1333  for(index = getLength(); index > 0 ; index--)
1334  {
1335  if(pData->buffer[ index - 1 ] != c)
1336  {
1337  break;
1338  }
1339  }
1340  if(index < getLength())
1341  {
1342  truncate(index);
1343  }
1344  return result - getLength();
1345  }
1355  sal_Int32 strip(sal_Unicode c = (sal_Unicode)' ')
1356  {
1357  return stripStart(c) + stripEnd(c);
1358  }
1370  OUStringBuffer copy( sal_Int32 beginIndex ) const
1371  {
1372  assert(beginIndex >= 0 && beginIndex <= getLength());
1373  return copy( beginIndex, getLength() - beginIndex );
1374  }
1375 
1389  OUStringBuffer copy( sal_Int32 beginIndex, sal_Int32 count ) const
1390  {
1391  assert(beginIndex >= 0 && beginIndex <= getLength());
1392  assert(count >= 0 && count <= getLength() - beginIndex);
1393  rtl_uString *pNew = 0;
1394  rtl_uStringbuffer_newFromStr_WithLength( &pNew, getStr() + beginIndex, count );
1395  return OUStringBuffer( pNew, count + 16 );
1396  }
1397 
1398 #ifdef LIBO_INTERNAL_ONLY
1399  // This is to complement the RTL_FAST_STRING operator+, which allows any combination of valid operands,
1400  // even two buffers. It's intentional it returns OUString, just like the operator+ would in the fast variant.
1401 #ifndef RTL_FAST_STRING
1402 
1406  friend OUString operator+( const OUStringBuffer& str1, const OUStringBuffer& str2 )
1407  {
1408  return OUString( str1.pData ).concat( str2.pData );
1409  }
1410 #endif
1411 #endif
1412 
1413 private:
1414  OUStringBuffer( rtl_uString * value, const sal_Int32 capacity )
1415  {
1416  pData = value;
1417  nCapacity = capacity;
1418  }
1419 
1423  rtl_uString * pData;
1424 
1428  sal_Int32 nCapacity;
1429 };
1430 
1431 #ifdef RTL_FAST_STRING
1432 
1435 template<>
1436 struct ToStringHelper< OUStringBuffer >
1437  {
1438  static int length( const OUStringBuffer& s ) { return s.getLength(); }
1439  static sal_Unicode* addData( sal_Unicode* buffer, const OUStringBuffer& s ) { return addDataHelper( buffer, s.getStr(), s.getLength()); }
1440  static const bool allowOStringConcat = false;
1441  static const bool allowOUStringConcat = true;
1442  };
1443 #endif
1444 
1445 }
1446 
1447 #ifdef RTL_STRING_UNITTEST
1448 namespace rtl
1449 {
1450 typedef rtlunittest::OUStringBuffer OUStringBuffer;
1451 }
1452 #endif
1453 
1454 #ifdef RTL_USING
1455 using ::rtl::OUStringBuffer;
1456 #endif
1457 
1458 #endif // INCLUDED_RTL_USTRBUF_HXX
1459 
1460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */