1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: string.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
31 #pragma warning(disable:4738) // storing 32-bit float result in memory, possible loss of performance
34 #include <rtl/memory.h>
35 #include <osl/interlck.h>
36 #include <rtl/alloc.h>
37 #include <osl/diagnose.h>
38 #include <rtl/tencinfo.h>
41 #include "surrogates.h"
42 #include <rtl/string.h>
45 #include "rtl/tencinfo.h"
47 /* ======================================================================= */
49 /* static data to be referenced by all empty strings
50 * the refCount is predefined to 1 and must never become 0 !
52 static rtl_String
const aImplEmpty_rtl_String
=
54 SAL_STRING_STATIC_FLAG
|1,
55 /* sal_Int32 refCount; */
56 0, /* sal_Int32 length; */
57 { 0 } /* sal_Char buffer[1]; */
60 /* ======================================================================= */
62 #define IMPL_RTL_STRCODE sal_Char
63 #define IMPL_RTL_USTRCODE( c ) ((unsigned char)c)
64 #define IMPL_RTL_STRNAME( n ) rtl_str_ ## n
66 #define IMPL_RTL_STRINGNAME( n ) rtl_string_ ## n
67 #define IMPL_RTL_STRINGDATA rtl_String
68 #define IMPL_RTL_EMPTYSTRING aImplEmpty_rtl_String
70 /* ======================================================================= */
72 /* Include String/UString template code */
76 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 rtl_copyMemory(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
)
93 rtl_String
* pResult
= NULL
;
95 rtl_math_doubleToString(
96 &pResult
, 0, 0, d
, rtl_math_StringFormat_G
,
97 RTL_STR_MAX_VALUEOFDOUBLE
- RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
99 nLen
= pResult
->length
;
100 OSL_ASSERT(nLen
< RTL_STR_MAX_VALUEOFDOUBLE
);
101 rtl_copyMemory(pStr
, pResult
->buffer
, (nLen
+ 1) * sizeof(sal_Char
));
102 rtl_string_release(pResult
);
106 float SAL_CALL
rtl_str_toFloat(sal_Char
const * pStr
)
108 return (float) rtl_math_stringToDouble(pStr
, pStr
+ rtl_str_getLength(pStr
),
112 double SAL_CALL
rtl_str_toDouble(sal_Char
const * pStr
)
114 return rtl_math_stringToDouble(pStr
, pStr
+ rtl_str_getLength(pStr
), '.', 0,
118 /* ======================================================================= */
120 static int rtl_ImplGetFastUTF8ByteLen( const sal_Unicode
* pStr
, sal_Int32 nLen
)
124 sal_uInt32 nUCS4Char
;
125 const sal_Unicode
* pEndStr
;
129 while ( pStr
< pEndStr
)
135 else if ( c
< 0x800 )
139 if ( !SAL_RTL_IS_HIGH_SURROGATE(c
) )
145 if ( pStr
+1 < pEndStr
)
148 if ( SAL_RTL_IS_LOW_SURROGATE(c
) )
150 nUCS4Char
= SAL_RTL_COMBINE_SURROGATES(nUCS4Char
, c
);
155 if ( nUCS4Char
< 0x10000 )
157 else if ( nUCS4Char
< 0x200000 )
159 else if ( nUCS4Char
< 0x4000000 )
172 /* ----------------------------------------------------------------------- */
174 sal_Bool SAL_CALL
rtl_impl_convertUStringToString(rtl_String
** pTarget
,
175 sal_Unicode
const * pSource
,
177 rtl_TextEncoding nEncoding
,
179 sal_Bool bCheckErrors
)
181 OSL_ASSERT(pTarget
!= NULL
182 && (pSource
!= NULL
|| nLength
== 0)
184 && rtl_isOctetTextEncoding(nEncoding
));
187 rtl_string_new( pTarget
);
191 rtl_UnicodeToTextConverter hConverter
;
196 sal_Size nNotConvertedChars
;
197 sal_Size nMaxCharLen
;
199 /* Optimization for UTF-8 - we try to calculate the exact length */
200 /* For all other encoding we try an good estimation */
201 if ( nEncoding
== RTL_TEXTENCODING_UTF8
)
203 nNewLen
= rtl_ImplGetFastUTF8ByteLen( pSource
, nLength
);
204 /* Includes the string only ASCII, then we could copy
206 if ( nNewLen
== (sal_Size
)nLength
)
208 IMPL_RTL_STRCODE
* pBuffer
;
210 IMPL_RTL_STRINGNAME( release
)( *pTarget
);
211 *pTarget
= IMPL_RTL_STRINGNAME( ImplAlloc
)( nLength
);
212 OSL_ASSERT(*pTarget
!= NULL
);
213 pBuffer
= (*pTarget
)->buffer
;
216 /* Check ASCII range */
217 OSL_ENSURE( *pSource
<= 127,
218 "rtl_uString2String() - UTF8 test is encoding is wrong" );
220 *pBuffer
= (IMPL_RTL_STRCODE
)(unsigned char)*pSource
;
233 rtl_TextEncodingInfo aTextEncInfo
;
234 aTextEncInfo
.StructSize
= sizeof( aTextEncInfo
);
235 if ( !rtl_getTextEncodingInfo( nEncoding
, &aTextEncInfo
) )
237 aTextEncInfo
.AverageCharSize
= 1;
238 aTextEncInfo
.MaximumCharSize
= 8;
241 nNewLen
= nLength
*aTextEncInfo
.AverageCharSize
;
242 nMaxCharLen
= aTextEncInfo
.MaximumCharSize
;
245 nFlags
|= RTL_UNICODETOTEXT_FLAGS_FLUSH
;
246 hConverter
= rtl_createUnicodeToTextConverter( nEncoding
);
250 pTemp
= IMPL_RTL_STRINGNAME( ImplAlloc
)( nNewLen
);
251 OSL_ASSERT(pTemp
!= NULL
);
252 nDestBytes
= rtl_convertUnicodeToText( hConverter
, 0,
254 pTemp
->buffer
, nNewLen
,
256 &nInfo
, &nSrcChars
);
257 if (bCheckErrors
&& (nInfo
& RTL_UNICODETOTEXT_INFO_ERROR
) != 0)
259 rtl_freeMemory(pTemp
);
260 rtl_destroyUnicodeToTextConverter(hConverter
);
264 if ((nInfo
& RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
) == 0)
267 /* Buffer not big enough, try again with enough space */
268 rtl_freeMemory( pTemp
);
270 /* Try with the max. count of characters with
271 additional overhead for replacing functionality */
272 nNotConvertedChars
= nLength
-nSrcChars
;
273 nNewLen
= nDestBytes
+(nNotConvertedChars
*nMaxCharLen
)+nNotConvertedChars
+4;
276 /* Set the buffer to the correct size or is there to
277 much overhead, reallocate to the correct size */
278 if ( nNewLen
> nDestBytes
+8 )
280 rtl_String
* pTemp2
= IMPL_RTL_STRINGNAME( ImplAlloc
)( nDestBytes
);
281 OSL_ASSERT(pTemp2
!= NULL
);
282 rtl_str_ImplCopy( pTemp2
->buffer
, pTemp
->buffer
, nDestBytes
);
283 rtl_freeMemory( pTemp
);
288 pTemp
->length
= nDestBytes
;
289 pTemp
->buffer
[nDestBytes
] = 0;
292 rtl_destroyUnicodeToTextConverter( hConverter
);
294 IMPL_RTL_STRINGNAME( release
)( *pTarget
);
297 /* Results the conversion in an empty buffer -
298 create an empty string */
299 if ( pTemp
&& !nDestBytes
)
300 rtl_string_new( pTarget
);
305 void SAL_CALL
rtl_uString2String( rtl_String
** ppThis
,
306 const sal_Unicode
* pUStr
,
308 rtl_TextEncoding eTextEncoding
,
309 sal_uInt32 nCvtFlags
)
311 rtl_impl_convertUStringToString(ppThis
, pUStr
, nULen
, eTextEncoding
,
312 nCvtFlags
, sal_False
);
315 sal_Bool SAL_CALL
rtl_convertUStringToString(rtl_String
** pTarget
,
316 sal_Unicode
const * pSource
,
318 rtl_TextEncoding nEncoding
,
321 return rtl_impl_convertUStringToString(pTarget
, pSource
, nLength
, nEncoding
,