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 .
21 static sal_Bool
ImplDbgCheckAsciiStr( const sal_Char
* pAsciiStr
, sal_Int32 nLen
)
23 while ( nLen
&& *pAsciiStr
)
25 if ( ((unsigned char)*pAsciiStr
) > 127 )
35 static void ImplCopyAsciiStr( sal_Unicode
* pDest
, const sal_Char
* pSrc
,
38 DBG_ASSERT( ImplDbgCheckAsciiStr( pSrc
, nLen
),
39 "UniString::CopyAsciiStr() - pAsciiStr include characters > 127" );
43 *pDest
= (unsigned char)*pSrc
;
50 static sal_Int32
ImplStringCompareAscii( const sal_Unicode
* pStr1
, const sal_Char
* pStr2
)
53 while ( ((nRet
= ((sal_Int32
)*pStr1
)-((sal_Int32
)((unsigned char)*pStr2
))) == 0) &&
63 static sal_Int32
ImplStringCompareAscii( const sal_Unicode
* pStr1
, const sal_Char
* pStr2
,
68 ((nRet
= ((sal_Int32
)*pStr1
)-((sal_Int32
)((unsigned char)*pStr2
))) == 0) &&
79 static sal_Int32
ImplStringCompareWithoutZeroAscii( const sal_Unicode
* pStr1
, const sal_Char
* pStr2
,
84 ((nRet
= ((sal_Int32
)*pStr1
)-((sal_Int32
)((unsigned char)*pStr2
))) == 0) )
94 static sal_Int32
ImplStringICompareAscii( const sal_Unicode
* pStr1
, const sal_Char
* pStr2
)
101 // Convert if char is between 'A' and 'Z'
104 if ( (c1
>= 65) && (c1
<= 90) )
106 if ( (c2
>= 65) && (c2
<= 90) )
108 nRet
= ((sal_Int32
)c1
)-((sal_Int32
)((unsigned char)c2
));
120 static sal_Int32
ImplStringICompareAscii( const sal_Unicode
* pStr1
, const sal_Char
* pStr2
,
131 // Convert if char is between 'A' and 'Z'
134 if ( (c1
>= 65) && (c1
<= 90) )
136 if ( (c2
>= 65) && (c2
<= 90) )
138 nRet
= ((sal_Int32
)c1
)-((sal_Int32
)((unsigned char)c2
));
151 UniString
& UniString::AssignAscii( const sal_Char
* pAsciiStr
)
153 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
154 DBG_ASSERT( pAsciiStr
, "UniString::AssignAscii() - pAsciiStr is NULL" );
156 // Determine string length
157 xub_StrLen nLen
= ImplStringLen( pAsciiStr
);
161 STRING_NEW((STRING_TYPE
**)&mpData
);
165 // Replace string in-place if new size is equal
166 if ( (nLen
== mpData
->mnLen
) && (mpData
->mnRefCount
== 1) )
167 ImplCopyAsciiStr( mpData
->maStr
, pAsciiStr
, nLen
);
170 // release old string
171 STRING_RELEASE((STRING_TYPE
*)mpData
);
174 mpData
= ImplAllocData( nLen
);
175 ImplCopyAsciiStr( mpData
->maStr
, pAsciiStr
, nLen
);
182 UniString
& UniString::AssignAscii( const sal_Char
* pAsciiStr
, xub_StrLen nLen
)
184 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
185 DBG_ASSERT( pAsciiStr
, "UniString::AssignAscii() - pAsciiStr is NULL" );
187 if ( nLen
== STRING_LEN
)
188 nLen
= ImplStringLen( pAsciiStr
);
193 for ( xub_StrLen i
= 0; i
< nLen
; ++i
)
197 OSL_FAIL( "UniString::AssignAscii() : nLen is wrong" );
205 STRING_NEW((STRING_TYPE
**)&mpData
);
209 // Replace string in-place if new size is equal
210 if ( (nLen
== mpData
->mnLen
) && (mpData
->mnRefCount
== 1) )
211 ImplCopyAsciiStr( mpData
->maStr
, pAsciiStr
, nLen
);
214 // release old string
215 STRING_RELEASE((STRING_TYPE
*)mpData
);
218 mpData
= ImplAllocData( nLen
);
219 ImplCopyAsciiStr( mpData
->maStr
, pAsciiStr
, nLen
);
226 UniString
& UniString::AppendAscii( const sal_Char
* pAsciiStr
)
228 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
229 DBG_ASSERT( pAsciiStr
, "UniString::AppendAscii() - pAsciiStr is NULL" );
231 // determine string length
232 sal_Int32 nCopyLen
= ImplStringLen( pAsciiStr
);
235 nCopyLen
= ImplGetCopyLen( mpData
->mnLen
, nCopyLen
);
237 // If appended string is not empty
240 // Allocate new string
241 UniStringData
* pNewData
= ImplAllocData( mpData
->mnLen
+nCopyLen
);
244 memcpy( pNewData
->maStr
, mpData
->maStr
, mpData
->mnLen
*sizeof( sal_Unicode
) );
245 ImplCopyAsciiStr( pNewData
->maStr
+mpData
->mnLen
, pAsciiStr
, nCopyLen
);
247 // release old string
248 STRING_RELEASE((STRING_TYPE
*)mpData
);
255 UniString
& UniString::AppendAscii( const sal_Char
* pAsciiStr
, xub_StrLen nLen
)
257 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
258 DBG_ASSERT( pAsciiStr
, "UniString::AppendAscii() - pAsciiStr is NULL" );
260 if ( nLen
== STRING_LEN
)
261 nLen
= ImplStringLen( pAsciiStr
);
266 for ( xub_StrLen i
= 0; i
< nLen
; ++i
)
270 OSL_FAIL( "UniString::AppendAscii() : nLen is wrong" );
277 sal_Int32 nCopyLen
= ImplGetCopyLen( mpData
->mnLen
, nLen
);
279 // If appended string is not empty
282 // Allocate new string
283 UniStringData
* pNewData
= ImplAllocData( mpData
->mnLen
+nCopyLen
);
286 memcpy( pNewData
->maStr
, mpData
->maStr
, mpData
->mnLen
*sizeof( sal_Unicode
) );
287 ImplCopyAsciiStr( pNewData
->maStr
+mpData
->mnLen
, pAsciiStr
, nCopyLen
);
289 // release old string
290 STRING_RELEASE((STRING_TYPE
*)mpData
);
297 UniString
& UniString::InsertAscii( const char* pAsciiStr
, xub_StrLen nIndex
)
299 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
300 DBG_ASSERT( pAsciiStr
, "UniString::InsertAscii() - pAsciiStr is NULL" );
302 // Determine string length
303 sal_Int32 nCopyLen
= ImplStringLen( pAsciiStr
);
306 nCopyLen
= ImplGetCopyLen( mpData
->mnLen
, nCopyLen
);
308 // If appended string is not empty
312 // Adjust index if exceeds length
313 if ( nIndex
> mpData
->mnLen
)
314 nIndex
= static_cast< xub_StrLen
>(mpData
->mnLen
);
316 // Allocate new string
317 UniStringData
* pNewData
= ImplAllocData( mpData
->mnLen
+nCopyLen
);
320 memcpy( pNewData
->maStr
, mpData
->maStr
, nIndex
*sizeof( sal_Unicode
) );
321 ImplCopyAsciiStr( pNewData
->maStr
+nIndex
, pAsciiStr
, nCopyLen
);
322 memcpy( pNewData
->maStr
+nIndex
+nCopyLen
, mpData
->maStr
+nIndex
,
323 (mpData
->mnLen
-nIndex
)*sizeof( sal_Unicode
) );
325 // release old string
326 STRING_RELEASE((STRING_TYPE
*)mpData
);
332 UniString
& UniString::ReplaceAscii( xub_StrLen nIndex
, xub_StrLen nCount
,
333 const sal_Char
* pAsciiStr
, xub_StrLen nStrLen
)
335 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
336 DBG_ASSERT( pAsciiStr
, "UniString::ReplaceAscii() - pAsciiStr is NULL" );
338 // Use append if index >= length
339 if ( nIndex
>= mpData
->mnLen
)
341 AppendAscii( pAsciiStr
, nStrLen
);
345 // Use assign if index = 0 and count >= length
346 if ( (nIndex
== 0) && (nCount
>= mpData
->mnLen
) )
348 AssignAscii( pAsciiStr
, nStrLen
);
352 // Use erase if length is equal
353 if ( nStrLen
== STRING_LEN
)
354 nStrLen
= ImplStringLen( pAsciiStr
);
356 return Erase( nIndex
, nCount
);
358 // nCount must not exceed string length
359 if ( nCount
> mpData
->mnLen
- nIndex
)
360 nCount
= static_cast< xub_StrLen
>(mpData
->mnLen
-nIndex
);
362 // Use assign if length matches
363 if ( nCount
== nStrLen
)
366 ImplCopyAsciiStr( mpData
->maStr
+nIndex
, pAsciiStr
, nStrLen
);
371 sal_Int32 n
= ImplGetCopyLen( mpData
->mnLen
-nCount
, nStrLen
);
373 // allocate new string
374 STRINGDATA
* pNewData
= ImplAllocData( mpData
->mnLen
-nCount
+n
);
377 memcpy( pNewData
->maStr
, mpData
->maStr
, nIndex
*sizeof( STRCODE
) );
378 ImplCopyAsciiStr( pNewData
->maStr
+nIndex
, pAsciiStr
, n
);
379 memcpy( pNewData
->maStr
+nIndex
+n
, mpData
->maStr
+nIndex
+nCount
,
380 (mpData
->mnLen
-nIndex
-nCount
+1)*sizeof( STRCODE
) );
382 // release old string
383 STRING_RELEASE((STRING_TYPE
*)mpData
);
389 StringCompare
UniString::CompareToAscii( const sal_Char
* pAsciiStr
,
390 xub_StrLen nLen
) const
392 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
393 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, nLen
),
394 "UniString::CompareToAscii() - pAsciiStr include characters > 127" );
396 // String vergleichen
397 sal_Int32 nCompare
= ImplStringCompareAscii( mpData
->maStr
, pAsciiStr
, nLen
);
399 // Rueckgabewert anpassen
401 return COMPARE_EQUAL
;
402 else if ( nCompare
< 0 )
405 return COMPARE_GREATER
;
408 StringCompare
UniString::CompareIgnoreCaseToAscii( const sal_Char
* pAsciiStr
,
409 xub_StrLen nLen
) const
411 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
412 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, nLen
),
413 "UniString::CompareIgnoreCaseToAscii() - pAsciiStr include characters > 127" );
416 sal_Int32 nCompare
= ImplStringICompareAscii( mpData
->maStr
, pAsciiStr
, nLen
);
419 return COMPARE_EQUAL
;
420 else if ( nCompare
< 0 )
423 return COMPARE_GREATER
;
426 sal_Bool
UniString::EqualsAscii( const sal_Char
* pAsciiStr
) const
428 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
429 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, STRING_LEN
),
430 "UniString::EqualsAscii() - pAsciiStr include characters > 127" );
432 return (ImplStringCompareAscii( mpData
->maStr
, pAsciiStr
) == 0);
435 sal_Bool
UniString::EqualsIgnoreCaseAscii( const sal_Char
* pAsciiStr
) const
437 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
438 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, STRING_LEN
),
439 "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" );
441 return (ImplStringICompareAscii( mpData
->maStr
, pAsciiStr
) == 0);
444 sal_Bool
UniString::EqualsAscii( const sal_Char
* pAsciiStr
,
445 xub_StrLen nIndex
, xub_StrLen nLen
) const
447 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
448 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, nLen
),
449 "UniString::EqualsAscii() - pAsciiStr include characters > 127" );
451 // Are there enough codes for comparing?
452 if ( nIndex
> mpData
->mnLen
)
453 return (*pAsciiStr
== 0);
455 return (ImplStringCompareAscii( mpData
->maStr
+nIndex
, pAsciiStr
, nLen
) == 0);
458 sal_Bool
UniString::EqualsIgnoreCaseAscii( const sal_Char
* pAsciiStr
,
459 xub_StrLen nIndex
, xub_StrLen nLen
) const
461 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
462 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, nLen
),
463 "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" );
465 // Are there enough codes for comparing?
466 if ( nIndex
> mpData
->mnLen
)
467 return (*pAsciiStr
== 0);
469 return (ImplStringICompareAscii( mpData
->maStr
+nIndex
, pAsciiStr
, nLen
) == 0);
472 xub_StrLen
UniString::SearchAscii( const sal_Char
* pAsciiStr
, xub_StrLen nIndex
) const
474 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
475 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, STRING_LEN
),
476 "UniString::SearchAscii() - pAsciiStr include characters > 127" );
478 sal_Int32 nLen
= mpData
->mnLen
;
479 xub_StrLen nStrLen
= ImplStringLen( pAsciiStr
);
481 // If length of pAsciiStr is 0 or index exceeds length, it was not found
482 if ( !nStrLen
|| (nIndex
>= nLen
) )
483 return STRING_NOTFOUND
;
485 const sal_Unicode
* pStr
= mpData
->maStr
;
490 sal_Unicode cSearch
= (unsigned char)*pAsciiStr
;
491 while ( nIndex
< nLen
)
493 if ( *pStr
== cSearch
)
501 // Only search within string
502 while ( nLen
- nIndex
>= nStrLen
)
504 // Check if string matches
505 if ( ImplStringCompareWithoutZeroAscii( pStr
, pAsciiStr
, nStrLen
) == 0 )
512 return STRING_NOTFOUND
;
515 xub_StrLen
UniString::SearchAndReplaceAscii( const sal_Char
* pAsciiStr
, const UniString
& rRepStr
,
518 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
519 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, STRING_LEN
),
520 "UniString::SearchAndReplaceAscii() - pAsciiStr include characters > 127" );
522 xub_StrLen nSPos
= SearchAscii( pAsciiStr
, nIndex
);
523 if ( nSPos
!= STRING_NOTFOUND
)
524 Replace( nSPos
, ImplStringLen( pAsciiStr
), rRepStr
);
529 void UniString::SearchAndReplaceAllAscii( const sal_Char
* pAsciiStr
, const UniString
& rRepStr
)
531 DBG_CHKTHIS( UniString
, DbgCheckUniString
);
532 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr
, STRING_LEN
),
533 "UniString::SearchAndReplaceAllAscii() - pAsciiStr include characters > 127" );
535 xub_StrLen nCharLen
= ImplStringLen( pAsciiStr
);
536 xub_StrLen nSPos
= SearchAscii( pAsciiStr
, 0 );
537 while ( nSPos
!= STRING_NOTFOUND
)
539 Replace( nSPos
, nCharLen
, rRepStr
);
540 nSPos
= nSPos
+ rRepStr
.Len();
541 nSPos
= SearchAscii( pAsciiStr
, nSPos
);
545 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */