1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sal/config.h"
23 #pragma warning(disable:4738) // storing 32-bit float result in memory, possible loss of performance
29 #include <osl/interlck.h>
30 #include <rtl/alloc.h>
31 #include <osl/diagnose.h>
32 #include <rtl/tencinfo.h>
35 #include "surrogates.hxx"
36 #include <rtl/string.h>
39 #include "rtl/tencinfo.h"
41 /* ======================================================================= */
43 /* static data to be referenced by all empty strings
44 * the refCount is predefined to 1 and must never become 0 !
46 static rtl_String
const aImplEmpty_rtl_String
=
48 SAL_STRING_STATIC_FLAG
|1,
49 /* sal_Int32 refCount; */
50 0, /* sal_Int32 length; */
51 { 0 } /* sal_Char buffer[1]; */
54 /* ======================================================================= */
56 #define IMPL_RTL_STRCODE sal_Char
57 #define IMPL_RTL_USTRCODE( c ) ((unsigned char)c)
58 #define IMPL_RTL_STRNAME( n ) rtl_str_ ## n
60 #define IMPL_RTL_STRINGNAME( n ) rtl_string_ ## n
61 #define IMPL_RTL_STRINGDATA rtl_String
62 #define IMPL_RTL_EMPTYSTRING aImplEmpty_rtl_String
64 #undef RTL_LOG_STRING_NEW
65 #define RTL_LOG_STRING_NEW(s)
66 #undef RTL_LOG_STRING_DELETE
67 #define RTL_LOG_STRING_DELETE(s)
69 /* ======================================================================= */
71 /* Include String/UString template code */
73 #include "strtmpl.cxx"
75 sal_Int32 SAL_CALL
rtl_str_valueOfFloat(sal_Char
* pStr
, float f
)
78 rtl_String
* pResult
= NULL
;
80 rtl_math_doubleToString(
81 &pResult
, 0, 0, f
, rtl_math_StringFormat_G
,
82 RTL_STR_MAX_VALUEOFFLOAT
- RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0, 0,
84 nLen
= pResult
->length
;
85 OSL_ASSERT(nLen
< RTL_STR_MAX_VALUEOFFLOAT
);
86 memcpy(pStr
, pResult
->buffer
, (nLen
+ 1) * sizeof(sal_Char
));
87 rtl_string_release(pResult
);
91 sal_Int32 SAL_CALL
rtl_str_valueOfDouble(sal_Char
* pStr
, double d
)
94 rtl_String
* pResult
= NULL
;
96 rtl_math_doubleToString(
97 &pResult
, 0, 0, d
, rtl_math_StringFormat_G
,
98 RTL_STR_MAX_VALUEOFDOUBLE
- RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
100 nLen
= pResult
->length
;
101 OSL_ASSERT(nLen
< RTL_STR_MAX_VALUEOFDOUBLE
);
102 memcpy(pStr
, pResult
->buffer
, (nLen
+ 1) * sizeof(sal_Char
));
103 rtl_string_release(pResult
);
107 float SAL_CALL
rtl_str_toFloat(sal_Char
const * pStr
) SAL_THROW_EXTERN_C()
109 return (float) rtl_math_stringToDouble(pStr
, pStr
+ rtl_str_getLength(pStr
),
113 double SAL_CALL
rtl_str_toDouble(sal_Char
const * pStr
) SAL_THROW_EXTERN_C()
115 return rtl_math_stringToDouble(pStr
, pStr
+ rtl_str_getLength(pStr
), '.', 0,
119 /* ======================================================================= */
121 static int rtl_ImplGetFastUTF8ByteLen( const sal_Unicode
* pStr
, sal_Int32 nLen
)
125 sal_uInt32 nUCS4Char
;
126 const sal_Unicode
* pEndStr
;
130 while ( pStr
< pEndStr
)
136 else if ( c
< 0x800 )
140 if ( !SAL_RTL_IS_HIGH_SURROGATE(c
) )
146 if ( pStr
+1 < pEndStr
)
149 if ( SAL_RTL_IS_LOW_SURROGATE(c
) )
151 nUCS4Char
= SAL_RTL_COMBINE_SURROGATES(nUCS4Char
, c
);
156 if ( nUCS4Char
< 0x10000 )
158 else if ( nUCS4Char
< 0x200000 )
160 else if ( nUCS4Char
< 0x4000000 )
173 /* ----------------------------------------------------------------------- */
175 sal_Bool SAL_CALL
rtl_impl_convertUStringToString(rtl_String
** pTarget
,
176 sal_Unicode
const * pSource
,
178 rtl_TextEncoding nEncoding
,
180 sal_Bool bCheckErrors
)
182 OSL_ASSERT(pTarget
!= NULL
183 && (pSource
!= NULL
|| nLength
== 0)
185 && (nLength
== 0 || rtl_isOctetTextEncoding(nEncoding
)));
188 rtl_string_new( pTarget
);
192 rtl_UnicodeToTextConverter hConverter
;
197 sal_Size nNotConvertedChars
;
198 sal_Size nMaxCharLen
;
200 /* Optimization for UTF-8 - we try to calculate the exact length */
201 /* For all other encoding we try an good estimation */
202 if ( nEncoding
== RTL_TEXTENCODING_UTF8
)
204 nNewLen
= rtl_ImplGetFastUTF8ByteLen( pSource
, nLength
);
205 /* Includes the string only ASCII, then we could copy
207 if ( nNewLen
== (sal_Size
)nLength
)
209 IMPL_RTL_STRCODE
* pBuffer
;
211 IMPL_RTL_STRINGNAME( release
)( *pTarget
);
212 *pTarget
= IMPL_RTL_STRINGNAME( ImplAlloc
)( nLength
);
213 OSL_ASSERT(*pTarget
!= NULL
);
214 pBuffer
= (*pTarget
)->buffer
;
217 /* Check ASCII range */
218 OSL_ENSURE( *pSource
<= 127,
219 "rtl_uString2String() - UTF8 test is encoding is wrong" );
221 *pBuffer
= (IMPL_RTL_STRCODE
)(unsigned char)*pSource
;
234 rtl_TextEncodingInfo aTextEncInfo
;
235 aTextEncInfo
.StructSize
= sizeof( aTextEncInfo
);
236 if ( !rtl_getTextEncodingInfo( nEncoding
, &aTextEncInfo
) )
238 aTextEncInfo
.AverageCharSize
= 1;
239 aTextEncInfo
.MaximumCharSize
= 8;
242 nNewLen
= nLength
*aTextEncInfo
.AverageCharSize
;
243 nMaxCharLen
= aTextEncInfo
.MaximumCharSize
;
246 nFlags
|= RTL_UNICODETOTEXT_FLAGS_FLUSH
;
247 hConverter
= rtl_createUnicodeToTextConverter( nEncoding
);
251 pTemp
= IMPL_RTL_STRINGNAME( ImplAlloc
)( nNewLen
);
252 OSL_ASSERT(pTemp
!= NULL
);
253 nDestBytes
= rtl_convertUnicodeToText( hConverter
, 0,
255 pTemp
->buffer
, nNewLen
,
257 &nInfo
, &nSrcChars
);
258 if (bCheckErrors
&& (nInfo
& RTL_UNICODETOTEXT_INFO_ERROR
) != 0)
260 rtl_freeMemory(pTemp
);
261 rtl_destroyUnicodeToTextConverter(hConverter
);
265 if ((nInfo
& RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
) == 0)
268 /* Buffer not big enough, try again with enough space */
269 rtl_freeMemory( pTemp
);
271 /* Try with the max. count of characters with
272 additional overhead for replacing functionality */
273 nNotConvertedChars
= nLength
-nSrcChars
;
274 nNewLen
= nDestBytes
+(nNotConvertedChars
*nMaxCharLen
)+nNotConvertedChars
+4;
277 /* Set the buffer to the correct size or is there to
278 much overhead, reallocate to the correct size */
279 if ( nNewLen
> nDestBytes
+8 )
281 rtl_String
* pTemp2
= IMPL_RTL_STRINGNAME( ImplAlloc
)( nDestBytes
);
282 OSL_ASSERT(pTemp2
!= NULL
);
283 rtl_str_ImplCopy( pTemp2
->buffer
, pTemp
->buffer
, nDestBytes
);
284 rtl_freeMemory( pTemp
);
289 pTemp
->length
= nDestBytes
;
290 pTemp
->buffer
[nDestBytes
] = 0;
293 rtl_destroyUnicodeToTextConverter( hConverter
);
295 IMPL_RTL_STRINGNAME( release
)( *pTarget
);
298 /* Results the conversion in an empty buffer -
299 create an empty string */
300 if ( pTemp
&& !nDestBytes
)
301 rtl_string_new( pTarget
);
306 void SAL_CALL
rtl_uString2String( rtl_String
** ppThis
,
307 const sal_Unicode
* pUStr
,
309 rtl_TextEncoding eTextEncoding
,
310 sal_uInt32 nCvtFlags
)
313 rtl_impl_convertUStringToString(ppThis
, pUStr
, nULen
, eTextEncoding
,
314 nCvtFlags
, sal_False
);
317 sal_Bool SAL_CALL
rtl_convertUStringToString(rtl_String
** pTarget
,
318 sal_Unicode
const * pSource
,
320 rtl_TextEncoding nEncoding
,
324 return rtl_impl_convertUStringToString(pTarget
, pSource
, nLength
, nEncoding
,
328 void rtl_string_newReplaceFirst(
329 rtl_String
** newStr
, rtl_String
* str
, char const * from
,
330 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
,
331 sal_Int32
* index
) SAL_THROW_EXTERN_C()
335 assert(*index
>= 0 && *index
<= str
->length
);
336 assert(fromLength
>= 0);
337 assert(toLength
>= 0);
338 sal_Int32 i
= rtl_str_indexOfStr_WithLength(
339 str
->buffer
+ *index
, str
->length
- *index
, from
, fromLength
);
341 rtl_string_assign(newStr
, str
);
343 assert(i
<= str
->length
- *index
);
345 assert(fromLength
<= str
->length
);
346 if (str
->length
- fromLength
> SAL_MAX_INT32
- toLength
) {
349 sal_Int32 n
= str
->length
- fromLength
+ toLength
;
350 rtl_string_acquire(str
); // in case *newStr == str
351 rtl_string_new_WithLength(newStr
, n
);
353 (*newStr
)->length
= n
;
354 assert(i
>= 0 && i
< str
->length
);
355 memcpy((*newStr
)->buffer
, str
->buffer
, i
);
356 memcpy((*newStr
)->buffer
+ i
, to
, toLength
);
358 (*newStr
)->buffer
+ i
+ toLength
, str
->buffer
+ i
+ fromLength
,
359 str
->length
- i
- fromLength
);
361 rtl_string_release(str
);
366 void rtl_string_newReplaceAll(
367 rtl_String
** newStr
, rtl_String
* str
, char const * from
,
368 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
)
371 rtl_string_assign(newStr
, str
);
372 for (sal_Int32 i
= 0;; i
+= toLength
) {
373 rtl_string_newReplaceFirst(
374 newStr
, *newStr
, from
, fromLength
, to
, toLength
, &i
);
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */