Bug Summary

File:home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx
Warning:line 486, column 17
Forming reference to null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name stringresource.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/scripting/source/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx

/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx

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#include <memory>
21#include "stringresource.hxx"
22#include <com/sun/star/io/TempFile.hpp>
23#include <com/sun/star/io/TextInputStream.hpp>
24#include <com/sun/star/io/TextOutputStream.hpp>
25#include <com/sun/star/io/XStream.hpp>
26#include <com/sun/star/io/XSeekable.hpp>
27#include <com/sun/star/embed/ElementModes.hpp>
28#include <com/sun/star/lang/NoSupportException.hpp>
29#include <com/sun/star/resource/MissingResourceException.hpp>
30#include <cppuhelper/implementationentry.hxx>
31#include <cppuhelper/supportsservice.hxx>
32#include <com/sun/star/beans/XPropertySet.hpp>
33#include <com/sun/star/container/ElementExistException.hpp>
34#include <com/sun/star/ucb/SimpleFileAccess.hpp>
35
36#include <osl/diagnose.h>
37#include <rtl/tencinfo.h>
38#include <rtl/ustrbuf.hxx>
39#include <tools/urlobj.hxx>
40#include <i18nlangtag/languagetag.hxx>
41
42using namespace ::com::sun::star;
43using namespace ::com::sun::star::lang;
44using namespace ::com::sun::star::uno;
45using namespace ::com::sun::star::ucb;
46using namespace ::com::sun::star::util;
47using namespace ::com::sun::star::embed;
48using namespace ::com::sun::star::container;
49
50
51namespace stringresource
52{
53
54
55// mutex
56
57
58::osl::Mutex& getMutex()
59{
60 static ::osl::Mutex s_aMutex;
61
62 return s_aMutex;
63}
64
65
66// StringResourceImpl
67
68extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface*
69scripting_StringResourcePersistenceImpl_implementation(
70 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
71{
72 return cppu::acquire(new StringResourcePersistenceImpl(context));
73}
74
75
76StringResourceImpl::StringResourceImpl( const Reference< XComponentContext >& rxContext )
77 : m_xContext( rxContext )
78 , m_pCurrentLocaleItem( nullptr )
79 , m_pDefaultLocaleItem( nullptr )
80 , m_bDefaultModified( false )
81 , m_aListenerContainer( getMutex() )
82 , m_bModified( false )
83 , m_bReadOnly( false )
84 , m_nNextUniqueNumericId( UNIQUE_NUMBER_NEEDS_INITIALISATION )
85{
86}
87
88
89StringResourceImpl::~StringResourceImpl()
90{
91}
92
93
94// XServiceInfo
95
96OUString StringResourceImpl::getImplementationName( )
97{
98 return "com.sun.star.comp.scripting.StringResource";
99}
100
101sal_Bool StringResourceImpl::supportsService( const OUString& rServiceName )
102{
103 return cppu::supportsService(this, rServiceName);
104}
105
106Sequence< OUString > StringResourceImpl::getSupportedServiceNames( )
107{
108 return { "com.sun.star.resource.StringResource" };
109}
110
111
112// XModifyBroadcaster
113
114void StringResourceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
115{
116 if( !aListener.is() )
117 throw RuntimeException();
118
119 ::osl::MutexGuard aGuard( getMutex() );
120 m_aListenerContainer.addInterface( Reference<XInterface>( aListener, UNO_QUERY ) );
121}
122
123void StringResourceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
124{
125 if( !aListener.is() )
126 throw RuntimeException();
127
128 ::osl::MutexGuard aGuard( getMutex() );
129 m_aListenerContainer.removeInterface( Reference<XInterface>( aListener, UNO_QUERY ) );
130}
131
132
133// XStringResourceResolver
134
135OUString StringResourceImpl::implResolveString
136 ( const OUString& ResourceID, LocaleItem* pLocaleItem )
137{
138 OUString aRetStr;
139 bool bSuccess = false;
140 if( pLocaleItem != nullptr && loadLocale( pLocaleItem ) )
141 {
142 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
143 if( it != pLocaleItem->m_aIdToStringMap.end() )
144 {
145 aRetStr = (*it).second;
146 bSuccess = true;
147 }
148 }
149 if( !bSuccess )
150 {
151 throw css::resource::MissingResourceException( "StringResourceImpl: No entry for ResourceID: " + ResourceID );
152 }
153 return aRetStr;
154}
155
156OUString StringResourceImpl::resolveString( const OUString& ResourceID )
157{
158 ::osl::MutexGuard aGuard( getMutex() );
159 return implResolveString( ResourceID, m_pCurrentLocaleItem );
160}
161
162OUString StringResourceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
163{
164 ::osl::MutexGuard aGuard( getMutex() );
165 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
166 return implResolveString( ResourceID, pLocaleItem );
167}
168
169bool StringResourceImpl::implHasEntryForId( const OUString& ResourceID, LocaleItem* pLocaleItem )
170{
171 bool bSuccess = false;
172 if( pLocaleItem != nullptr && loadLocale( pLocaleItem ) )
173 {
174 IdToStringMap::iterator it = pLocaleItem->m_aIdToStringMap.find( ResourceID );
175 if( it != pLocaleItem->m_aIdToStringMap.end() )
176 bSuccess = true;
177 }
178 return bSuccess;
179}
180
181sal_Bool StringResourceImpl::hasEntryForId( const OUString& ResourceID )
182{
183 ::osl::MutexGuard aGuard( getMutex() );
184 return implHasEntryForId( ResourceID, m_pCurrentLocaleItem );
185}
186
187sal_Bool StringResourceImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
188 const Locale& locale )
189{
190 ::osl::MutexGuard aGuard( getMutex() );
191 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
192 return implHasEntryForId( ResourceID, pLocaleItem );
193}
194
195Sequence< OUString > StringResourceImpl::implGetResourceIDs( LocaleItem* pLocaleItem )
196{
197 Sequence< OUString > aIDSeq( 0 );
198 if( pLocaleItem && loadLocale( pLocaleItem ) )
199 {
200 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
201 sal_Int32 nResourceIDCount = rHashMap.size();
202 aIDSeq.realloc( nResourceIDCount );
203 OUString* pStrings = aIDSeq.getArray();
204
205 int iTarget = 0;
206 for( const auto& rEntry : rHashMap )
207 {
208 OUString aStr = rEntry.first;
209 pStrings[iTarget] = aStr;
210 iTarget++;
211 }
212 }
213 return aIDSeq;
214}
215
216Sequence< OUString > StringResourceImpl::getResourceIDsForLocale
217 ( const Locale& locale )
218{
219 ::osl::MutexGuard aGuard( getMutex() );
220 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
221 return implGetResourceIDs( pLocaleItem );
222}
223
224Sequence< OUString > StringResourceImpl::getResourceIDs( )
225{
226 ::osl::MutexGuard aGuard( getMutex() );
227 return implGetResourceIDs( m_pCurrentLocaleItem );
228}
229
230Locale StringResourceImpl::getCurrentLocale()
231{
232 ::osl::MutexGuard aGuard( getMutex() );
233
234 Locale aRetLocale;
235 if( m_pCurrentLocaleItem != nullptr )
236 aRetLocale = m_pCurrentLocaleItem->m_locale;
237 return aRetLocale;
238}
239
240Locale StringResourceImpl::getDefaultLocale( )
241{
242 ::osl::MutexGuard aGuard( getMutex() );
243
244 Locale aRetLocale;
245 if( m_pDefaultLocaleItem != nullptr )
246 aRetLocale = m_pDefaultLocaleItem->m_locale;
247 return aRetLocale;
248}
249
250Sequence< Locale > StringResourceImpl::getLocales( )
251{
252 ::osl::MutexGuard aGuard( getMutex() );
253
254 sal_Int32 nSize = m_aLocaleItemVector.size();
255 Sequence< Locale > aLocalSeq( nSize );
256 Locale* pLocales = aLocalSeq.getArray();
257 int iTarget = 0;
258 for( const auto& pLocaleItem : m_aLocaleItemVector )
259 {
260 pLocales[iTarget] = pLocaleItem->m_locale;
261 iTarget++;
262 }
263 return aLocalSeq;
264}
265
266
267// XStringResourceManager
268
269void StringResourceImpl::implCheckReadOnly( const char* pExceptionMsg )
270{
271 if( m_bReadOnly )
272 {
273 OUString errorMsg = OUString::createFromAscii( pExceptionMsg );
274 throw NoSupportException( errorMsg );
275 }
276}
277
278sal_Bool StringResourceImpl::isReadOnly()
279{
280 return m_bReadOnly;
281}
282
283void StringResourceImpl::implSetCurrentLocale( const Locale& locale,
284 bool FindClosestMatch, bool bUseDefaultIfNoMatch )
285{
286 ::osl::MutexGuard aGuard( getMutex() );
287
288 LocaleItem* pLocaleItem = nullptr;
289 if( FindClosestMatch )
290 pLocaleItem = getClosestMatchItemForLocale( locale );
291 else
292 pLocaleItem = getItemForLocale( locale, true );
293
294 if( pLocaleItem == nullptr && bUseDefaultIfNoMatch )
295 pLocaleItem = m_pDefaultLocaleItem;
296
297 if( pLocaleItem != nullptr )
298 {
299 (void)loadLocale( pLocaleItem );
300 m_pCurrentLocaleItem = pLocaleItem;
301
302 // Only notify without modifying
303 implNotifyListeners();
304 }
305}
306
307void StringResourceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
308{
309 implSetCurrentLocale( locale, FindClosestMatch, false/*bUseDefaultIfNoMatch*/ );
310}
311
312void StringResourceImpl::setDefaultLocale( const Locale& locale )
313{
314 ::osl::MutexGuard aGuard( getMutex() );
315 implCheckReadOnly( "StringResourceImpl::setDefaultLocale(): Read only" );
316
317 LocaleItem* pLocaleItem = getItemForLocale( locale, true );
318 if( pLocaleItem && pLocaleItem != m_pDefaultLocaleItem )
319 {
320 if( m_pDefaultLocaleItem )
321 {
322 m_aChangedDefaultLocaleVector.push_back(
323 std::make_unique<LocaleItem>( m_pDefaultLocaleItem->m_locale ) );
324 }
325
326 m_pDefaultLocaleItem = pLocaleItem;
327 m_bDefaultModified = true;
328 implModified();
329 }
330}
331
332void StringResourceImpl::implSetString( const OUString& ResourceID,
333 const OUString& Str, LocaleItem* pLocaleItem )
334{
335 if( !(pLocaleItem != nullptr && loadLocale( pLocaleItem )) )
336 return;
337
338 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
339
340 IdToStringMap::iterator it = rHashMap.find( ResourceID );
341 bool bNew = ( it == rHashMap.end() );
342 if( bNew )
343 {
344 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
345 rIndexMap[ ResourceID ] = pLocaleItem->m_nNextIndex++;
346 implScanIdForNumber( ResourceID );
347 }
348 rHashMap[ ResourceID ] = Str;
349 pLocaleItem->m_bModified = true;
350 implModified();
351}
352
353void StringResourceImpl::setString( const OUString& ResourceID, const OUString& Str )
354{
355 ::osl::MutexGuard aGuard( getMutex() );
356 implCheckReadOnly( "StringResourceImpl::setString(): Read only" );
357 implSetString( ResourceID, Str, m_pCurrentLocaleItem );
358}
359
360void StringResourceImpl::setStringForLocale
361 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
362{
363 ::osl::MutexGuard aGuard( getMutex() );
364 implCheckReadOnly( "StringResourceImpl::setStringForLocale(): Read only" );
365 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
366 implSetString( ResourceID, Str, pLocaleItem );
367}
368
369void StringResourceImpl::implRemoveId( const OUString& ResourceID, LocaleItem* pLocaleItem )
370{
371 if( pLocaleItem != nullptr && loadLocale( pLocaleItem ) )
372 {
373 IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
374 IdToStringMap::iterator it = rHashMap.find( ResourceID );
375 if( it == rHashMap.end() )
376 {
377 throw css::resource::MissingResourceException( "StringResourceImpl: No entries for ResourceID: " + ResourceID );
378 }
379 rHashMap.erase( it );
380 pLocaleItem->m_bModified = true;
381 implModified();
382 }
383}
384
385void StringResourceImpl::removeId( const OUString& ResourceID )
386{
387 ::osl::MutexGuard aGuard( getMutex() );
388 implCheckReadOnly( "StringResourceImpl::removeId(): Read only" );
389 implRemoveId( ResourceID, m_pCurrentLocaleItem );
390}
391
392void StringResourceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
393{
394 ::osl::MutexGuard aGuard( getMutex() );
395 implCheckReadOnly( "StringResourceImpl::removeIdForLocale(): Read only" );
396 LocaleItem* pLocaleItem = getItemForLocale( locale, false );
397 implRemoveId( ResourceID, pLocaleItem );
398}
399
400void StringResourceImpl::newLocale( const Locale& locale )
401{
402 ::osl::MutexGuard aGuard( getMutex() );
403 implCheckReadOnly( "StringResourceImpl::newLocale(): Read only" );
404
405 if( getItemForLocale( locale, false ) != nullptr )
406 {
407 throw ElementExistException( "StringResourceImpl: locale already exists" );
408 }
409
410 // TODO?: Check if locale is valid? How?
411 //if (!bValid)
412 //{
413 // OUString errorMsg("StringResourceImpl: Invalid locale");
414 // throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 0 );
415 //}
416
417 LocaleItem* pLocaleItem = new LocaleItem( locale );
418 m_aLocaleItemVector.emplace_back( pLocaleItem );
419 pLocaleItem->m_bModified = true;
420
421 // Copy strings from default locale
422 LocaleItem* pCopyFromItem = m_pDefaultLocaleItem;
423 if( pCopyFromItem == nullptr )
424 pCopyFromItem = m_pCurrentLocaleItem;
425 if( pCopyFromItem != nullptr && loadLocale( pCopyFromItem ) )
426 {
427 const IdToStringMap& rSourceMap = pCopyFromItem->m_aIdToStringMap;
428 IdToStringMap& rTargetMap = pLocaleItem->m_aIdToStringMap;
429 for( const auto& rEntry : rSourceMap )
430 {
431 OUString aId = rEntry.first;
432 OUString aStr = rEntry.second;
433 rTargetMap[ aId ] = aStr;
434 }
435
436 const IdToIndexMap& rSourceIndexMap = pCopyFromItem->m_aIdToIndexMap;
437 IdToIndexMap& rTargetIndexMap = pLocaleItem->m_aIdToIndexMap;
438 for( const auto& rIndex : rSourceIndexMap )
439 {
440 OUString aId = rIndex.first;
441 sal_Int32 nIndex = rIndex.second;
442 rTargetIndexMap[ aId ] = nIndex;
443 }
444 pLocaleItem->m_nNextIndex = pCopyFromItem->m_nNextIndex;
445 }
446
447 if( m_pCurrentLocaleItem == nullptr )
448 m_pCurrentLocaleItem = pLocaleItem;
449
450 if( m_pDefaultLocaleItem == nullptr )
451 {
452 m_pDefaultLocaleItem = pLocaleItem;
453 m_bDefaultModified = true;
454 }
455
456 implModified();
457}
458
459void StringResourceImpl::removeLocale( const Locale& locale )
460{
461 ::osl::MutexGuard aGuard( getMutex() );
462 implCheckReadOnly( "StringResourceImpl::removeLocale(): Read only" );
463
464 LocaleItem* pRemoveItem = getItemForLocale( locale, true );
6
Calling 'StringResourceImpl::getItemForLocale'
49
Returning from 'StringResourceImpl::getItemForLocale'
465 if( !pRemoveItem
49.1
'pRemoveItem' is non-null
49.1
'pRemoveItem' is non-null
49.1
'pRemoveItem' is non-null
)
50
Taking false branch
466 return;
467
468 // Last locale?
469 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
470 if( nLocaleCount > 1 )
51
Assuming 'nLocaleCount' is > 1
52
Taking true branch
471 {
472 if( m_pCurrentLocaleItem == pRemoveItem ||
53
Assuming 'pRemoveItem' is equal to field 'm_pCurrentLocaleItem'
473 m_pDefaultLocaleItem == pRemoveItem )
474 {
475 LocaleItem* pFallbackItem = nullptr;
54
'pFallbackItem' initialized to a null pointer value
476 for( const auto& pLocaleItem : m_aLocaleItemVector )
477 {
478 if( pLocaleItem.get() != pRemoveItem )
479 {
480 pFallbackItem = pLocaleItem.get();
481 break;
482 }
483 }
484 if( m_pCurrentLocaleItem == pRemoveItem )
55
Assuming 'pRemoveItem' is equal to field 'm_pCurrentLocaleItem'
56
Taking true branch
485 {
486 setCurrentLocale( pFallbackItem->m_locale, false/*FindClosestMatch*/ );
57
Forming reference to null pointer
487 }
488 if( m_pDefaultLocaleItem == pRemoveItem )
489 {
490 setDefaultLocale( pFallbackItem->m_locale );
491 }
492 }
493 }
494 auto it = std::find_if(m_aLocaleItemVector.begin(), m_aLocaleItemVector.end(),
495 [&pRemoveItem](const std::unique_ptr<LocaleItem>& rxItem) { return rxItem.get() == pRemoveItem; });
496 if (it == m_aLocaleItemVector.end())
497 return;
498
499 // Remember locale item to delete file while storing
500 m_aDeletedLocaleItemVector.push_back( std::move(*it) );
501
502 // Last locale?
503 if( nLocaleCount == 1 )
504 {
505 m_nNextUniqueNumericId = 0;
506 if( m_pDefaultLocaleItem )
507 {
508 m_aChangedDefaultLocaleVector.push_back(
509 std::make_unique<LocaleItem>( m_pDefaultLocaleItem->m_locale ) );
510 }
511 m_pCurrentLocaleItem = nullptr;
512 m_pDefaultLocaleItem = nullptr;
513 }
514
515 m_aLocaleItemVector.erase( it );
516
517 implModified();
518}
519
520void StringResourceImpl::implScanIdForNumber( const OUString& ResourceID )
521{
522 const sal_Unicode* pSrc = ResourceID.getStr();
523 sal_Int32 nLen = ResourceID.getLength();
524
525 sal_Int32 nNumber = 0;
526 for( sal_Int32 i = 0 ; i < nLen ; i++ )
527 {
528 sal_Unicode c = pSrc[i];
529 if( c >= '0' && c <= '9' )
530 {
531 sal_uInt16 nDigitVal = c - '0';
532 nNumber = 10*nNumber + nDigitVal;
533 }
534 else
535 break;
536 }
537
538 if( m_nNextUniqueNumericId < nNumber + 1 )
539 m_nNextUniqueNumericId = nNumber + 1;
540}
541
542sal_Int32 StringResourceImpl::getUniqueNumericId( )
543{
544 if( m_nNextUniqueNumericId == UNIQUE_NUMBER_NEEDS_INITIALISATION )
545 {
546 implLoadAllLocales();
547 m_nNextUniqueNumericId = 0;
548 }
549
550 if( m_nNextUniqueNumericId < UNIQUE_NUMBER_NEEDS_INITIALISATION )
551 {
552 throw NoSupportException( "getUniqueNumericId: Extended sal_Int32 range" );
553 }
554 return m_nNextUniqueNumericId;
555}
556
557
558// Private helper methods
559
560LocaleItem* StringResourceImpl::getItemForLocale
561 ( const Locale& locale, bool bException )
562{
563 LocaleItem* pRetItem = nullptr;
564
565 // Search for locale
566 for( auto& pLocaleItem : m_aLocaleItemVector )
567 {
568 if( pLocaleItem )
7
Calling 'unique_ptr::operator bool'
12
Returning from 'unique_ptr::operator bool'
13
Taking true branch
569 {
570 Locale& cmp_locale = pLocaleItem->m_locale;
571 if( cmp_locale.Language == locale.Language &&
14
Calling 'operator=='
24
Returning from 'operator=='
46
Taking true branch
572 cmp_locale.Country == locale.Country &&
25
Calling 'operator=='
35
Returning from 'operator=='
573 cmp_locale.Variant == locale.Variant )
36
Calling 'operator=='
45
Returning from 'operator=='
574 {
575 pRetItem = pLocaleItem.get();
576 break;
47
Execution continues on line 581
577 }
578 }
579 }
580
581 if( pRetItem == nullptr && bException )
582 {
583 throw IllegalArgumentException( "StringResourceImpl: Invalid locale", Reference< XInterface >(), 0 );
584 }
585 return pRetItem;
48
Returning pointer (loaded from 'pRetItem'), which participates in a condition later
586}
587
588// Returns the LocaleItem for a given locale, if it exists, otherwise NULL.
589// This method performs a closest match search, at least the language must match.
590LocaleItem* StringResourceImpl::getClosestMatchItemForLocale( const Locale& locale )
591{
592 LocaleItem* pRetItem = nullptr;
593
594 ::std::vector< Locale > aLocales( m_aLocaleItemVector.size());
595 size_t i = 0;
596 for( const auto& pLocaleItem : m_aLocaleItemVector )
597 {
598 aLocales[i] = (pLocaleItem ? pLocaleItem->m_locale : Locale());
599 ++i;
600 }
601 ::std::vector< Locale >::const_iterator iFound( LanguageTag::getMatchingFallback( aLocales, locale));
602 if (iFound != aLocales.end())
603 pRetItem = (m_aLocaleItemVector.begin() + (iFound - aLocales.begin()))->get();
604
605 return pRetItem;
606}
607
608void StringResourceImpl::implModified()
609{
610 m_bModified = true;
611 implNotifyListeners();
612}
613
614void StringResourceImpl::implNotifyListeners()
615{
616 EventObject aEvent;
617 aEvent.Source = static_cast< XInterface* >( static_cast<OWeakObject*>(this) );
618
619 ::comphelper::OInterfaceIteratorHelper2 it( m_aListenerContainer );
620 while( it.hasMoreElements() )
621 {
622 Reference< XInterface > xIface = it.next();
623 Reference< XModifyListener > xListener( xIface, UNO_QUERY );
624 try
625 {
626 xListener->modified( aEvent );
627 }
628 catch(RuntimeException&)
629 {
630 it.remove();
631 }
632 }
633}
634
635
636// Loading
637
638bool StringResourceImpl::loadLocale( LocaleItem* )
639{
640 // Base implementation has nothing to load
641 return true;
642}
643
644void StringResourceImpl::implLoadAllLocales()
645{
646 // Base implementation has nothing to load
647}
648
649
650// StringResourcePersistenceImpl
651
652
653StringResourcePersistenceImpl::StringResourcePersistenceImpl( const Reference< XComponentContext >& rxContext )
654 : StringResourcePersistenceImpl_BASE( rxContext )
655{
656}
657
658
659StringResourcePersistenceImpl::~StringResourcePersistenceImpl()
660{
661}
662
663
664// XServiceInfo
665
666
667OUString StringResourcePersistenceImpl::getImplementationName( )
668{
669 return "com.sun.star.comp.scripting.StringResource";
670}
671
672
673sal_Bool StringResourcePersistenceImpl::supportsService( const OUString& rServiceName )
674{
675 return cppu::supportsService( this, rServiceName );
676}
677
678
679Sequence< OUString > StringResourcePersistenceImpl::getSupportedServiceNames( )
680{
681 return StringResourceImpl::getSupportedServiceNames();
682}
683
684
685// XInitialization base functionality for derived classes
686
687
688const char aNameBaseDefaultStr[] = "strings";
689
690void StringResourcePersistenceImpl::implInitializeCommonParameters
691 ( const Sequence< Any >& aArguments )
692{
693 bool bReadOnlyOk = (aArguments[1] >>= m_bReadOnly);
694 if( !bReadOnlyOk )
695 {
696 throw IllegalArgumentException( "XInitialization::initialize: Expected ReadOnly flag", Reference< XInterface >(), 1 );
697 }
698
699 css::lang::Locale aCurrentLocale;
700 bool bLocaleOk = (aArguments[2] >>= aCurrentLocale);
701 if( !bLocaleOk )
702 {
703 throw IllegalArgumentException( "XInitialization::initialize: Expected Locale", Reference< XInterface >(), 2 );
704 }
705
706 bool bNameBaseOk = (aArguments[3] >>= m_aNameBase);
707 if( !bNameBaseOk )
708 {
709 throw IllegalArgumentException( "XInitialization::initialize: Expected NameBase string", Reference< XInterface >(), 3 );
710 }
711 if( m_aNameBase.isEmpty() )
712 m_aNameBase = aNameBaseDefaultStr;
713
714 bool bCommentOk = (aArguments[4] >>= m_aComment);
715 if( !bCommentOk )
716 {
717 throw IllegalArgumentException( "XInitialization::initialize: Expected Comment string", Reference< XInterface >(), 4 );
718 }
719
720 implScanLocales();
721
722 implSetCurrentLocale( aCurrentLocale, true/*FindClosestMatch*/, true/*bUseDefaultIfNoMatch*/ );
723}
724
725
726// Forwarding calls to base class
727
728// XModifyBroadcaster
729void StringResourcePersistenceImpl::addModifyListener( const Reference< XModifyListener >& aListener )
730{
731 StringResourceImpl::addModifyListener( aListener );
732}
733void StringResourcePersistenceImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
734{
735 StringResourceImpl::removeModifyListener( aListener );
736}
737
738// XStringResourceResolver
739OUString StringResourcePersistenceImpl::resolveString( const OUString& ResourceID )
740{
741 return StringResourceImpl::resolveString( ResourceID ) ;
742}
743OUString StringResourcePersistenceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
744{
745 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
746}
747sal_Bool StringResourcePersistenceImpl::hasEntryForId( const OUString& ResourceID )
748{
749 return StringResourceImpl::hasEntryForId( ResourceID ) ;
750}
751sal_Bool StringResourcePersistenceImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
752 const Locale& locale )
753{
754 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
755}
756Locale StringResourcePersistenceImpl::getCurrentLocale()
757{
758 return StringResourceImpl::getCurrentLocale();
759}
760Locale StringResourcePersistenceImpl::getDefaultLocale( )
761{
762 return StringResourceImpl::getDefaultLocale();
763}
764Sequence< Locale > StringResourcePersistenceImpl::getLocales( )
765{
766 return StringResourceImpl::getLocales();
767}
768
769// XStringResourceManager
770sal_Bool StringResourcePersistenceImpl::isReadOnly()
771{
772 return StringResourceImpl::isReadOnly();
773}
774void StringResourcePersistenceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
775{
776 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
777}
778void StringResourcePersistenceImpl::setDefaultLocale( const Locale& locale )
779{
780 StringResourceImpl::setDefaultLocale( locale );
781}
782Sequence< OUString > StringResourcePersistenceImpl::getResourceIDs( )
783{
784 return StringResourceImpl::getResourceIDs();
785}
786void StringResourcePersistenceImpl::setString( const OUString& ResourceID, const OUString& Str )
787{
788 StringResourceImpl::setString( ResourceID, Str );
789}
790void StringResourcePersistenceImpl::setStringForLocale
791 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
792{
793 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
794}
795Sequence< OUString > StringResourcePersistenceImpl::getResourceIDsForLocale
796 ( const Locale& locale )
797{
798 return StringResourceImpl::getResourceIDsForLocale( locale );
799}
800void StringResourcePersistenceImpl::removeId( const OUString& ResourceID )
801{
802 StringResourceImpl::removeId( ResourceID );
803}
804void StringResourcePersistenceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
805{
806 StringResourceImpl::removeIdForLocale( ResourceID, locale );
807}
808void StringResourcePersistenceImpl::newLocale( const Locale& locale )
809{
810 StringResourceImpl::newLocale( locale );
811}
812void StringResourcePersistenceImpl::removeLocale( const Locale& locale )
813{
814 StringResourceImpl::removeLocale( locale );
815}
816sal_Int32 StringResourcePersistenceImpl::getUniqueNumericId( )
817{
818 return StringResourceImpl::getUniqueNumericId();
819}
820
821
822// XStringResourcePersistence
823
824void StringResourcePersistenceImpl::store()
825{
826}
827
828sal_Bool StringResourcePersistenceImpl::isModified( )
829{
830 ::osl::MutexGuard aGuard( getMutex() );
831
832 return m_bModified;
833}
834
835void StringResourcePersistenceImpl::setComment( const OUString& Comment )
836{
837 m_aComment = Comment;
838}
839
840void StringResourcePersistenceImpl::storeToStorage( const Reference< XStorage >& Storage,
841 const OUString& NameBase, const OUString& Comment )
842{
843 ::osl::MutexGuard aGuard( getMutex() );
844
845 implStoreAtStorage( NameBase, Comment, Storage, false/*bUsedForStore*/, true/*bStoreAll*/ );
846}
847
848void StringResourcePersistenceImpl::implStoreAtStorage
849(
850 const OUString& aNameBase,
851 const OUString& aComment,
852 const Reference< css::embed::XStorage >& Storage,
853 bool bUsedForStore,
854 bool bStoreAll
855)
856{
857 // Delete files for deleted locales
858 if( bUsedForStore )
859 {
860 for( auto& pLocaleItem : m_aDeletedLocaleItemVector )
861 {
862 if( pLocaleItem )
863 {
864 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem.get(), m_aNameBase ) + ".properties";
865
866 try
867 {
868 Storage->removeElement( aStreamName );
869 }
870 catch( Exception& )
871 {}
872
873 pLocaleItem.reset();
874 }
875 }
876 m_aDeletedLocaleItemVector.clear();
877 }
878
879 for( auto& pLocaleItem : m_aLocaleItemVector )
880 {
881 if( pLocaleItem != nullptr && (bStoreAll || pLocaleItem->m_bModified) &&
882 loadLocale( pLocaleItem.get() ) )
883 {
884 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem.get(), aNameBase ) + ".properties";
885
886 Reference< io::XStream > xElementStream =
887 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
888
889 OUString aPropName("MediaType");
890
891 uno::Reference< beans::XPropertySet > xProps( xElementStream, uno::UNO_QUERY );
892 OSL_ENSURE( xProps.is(), "The StorageStream must implement XPropertySet interface!" )do { if (true && (!(xProps.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "892" ": "), "%s", "The StorageStream must implement XPropertySet interface!"
); } } while (false)
;
893 if ( xProps.is() )
894 {
895 xProps->setPropertyValue( aPropName, uno::makeAny( OUString("text/plain") ) );
896
897 aPropName = "UseCommonStoragePasswordEncryption";
898 xProps->setPropertyValue( aPropName, uno::makeAny( true ) );
899 }
900
901 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
902 if( xOutputStream.is() )
903 implWritePropertiesFile( pLocaleItem.get(), xOutputStream, aComment );
904 xOutputStream->closeOutput();
905
906 if( bUsedForStore )
907 pLocaleItem->m_bModified = false;
908 }
909 }
910
911 // Delete files for changed defaults
912 if( bUsedForStore )
913 {
914 for( auto& pLocaleItem : m_aChangedDefaultLocaleVector )
915 {
916 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem.get(), m_aNameBase ) + ".default";
917
918 try
919 {
920 Storage->removeElement( aStreamName );
921 }
922 catch( Exception& )
923 {}
924
925 pLocaleItem.reset();
926 }
927 m_aChangedDefaultLocaleVector.clear();
928 }
929
930 // Default locale
931 if( !(m_pDefaultLocaleItem != nullptr && (bStoreAll || m_bDefaultModified)) )
932 return;
933
934 OUString aStreamName = implGetFileNameForLocaleItem( m_pDefaultLocaleItem, aNameBase ) + ".default";
935
936 Reference< io::XStream > xElementStream =
937 Storage->openStreamElement( aStreamName, ElementModes::READWRITE );
938
939 // Only create stream without content
940 Reference< io::XOutputStream > xOutputStream = xElementStream->getOutputStream();
941 xOutputStream->closeOutput();
942
943 if( bUsedForStore )
944 m_bDefaultModified = false;
945}
946
947void StringResourcePersistenceImpl::storeToURL( const OUString& URL,
948 const OUString& NameBase, const OUString& Comment,
949 const Reference< css::task::XInteractionHandler >& Handler )
950{
951 ::osl::MutexGuard aGuard( getMutex() );
952
953 Reference< ucb::XSimpleFileAccess3 > xFileAccess = ucb::SimpleFileAccess::create(m_xContext);
954 if( xFileAccess.is() && Handler.is() )
955 xFileAccess->setInteractionHandler( Handler );
956
957 implStoreAtLocation( URL, NameBase, Comment, xFileAccess, false/*bUsedForStore*/, true/*bStoreAll*/ );
958}
959
960void StringResourcePersistenceImpl::implKillRemovedLocaleFiles
961(
962 const OUString& Location,
963 const OUString& aNameBase,
964 const css::uno::Reference< css::ucb::XSimpleFileAccess3 >& xFileAccess
965)
966{
967 // Delete files for deleted locales
968 for( auto& pLocaleItem : m_aDeletedLocaleItemVector )
969 {
970 if( pLocaleItem )
971 {
972 OUString aCompleteFileName =
973 implGetPathForLocaleItem( pLocaleItem.get(), aNameBase, Location );
974 if( xFileAccess->exists( aCompleteFileName ) )
975 xFileAccess->kill( aCompleteFileName );
976
977 pLocaleItem.reset();
978 }
979 }
980 m_aDeletedLocaleItemVector.clear();
981}
982
983void StringResourcePersistenceImpl::implKillChangedDefaultFiles
984(
985 const OUString& Location,
986 const OUString& aNameBase,
987 const css::uno::Reference< css::ucb::XSimpleFileAccess3 >& xFileAccess
988)
989{
990 // Delete files for changed defaults
991 for( auto& pLocaleItem : m_aChangedDefaultLocaleVector )
992 {
993 OUString aCompleteFileName =
994 implGetPathForLocaleItem( pLocaleItem.get(), aNameBase, Location, true );
995 if( xFileAccess->exists( aCompleteFileName ) )
996 xFileAccess->kill( aCompleteFileName );
997 pLocaleItem.reset();
998 }
999 m_aChangedDefaultLocaleVector.clear();
1000}
1001
1002void StringResourcePersistenceImpl::implStoreAtLocation
1003(
1004 const OUString& Location,
1005 const OUString& aNameBase,
1006 const OUString& aComment,
1007 const Reference< ucb::XSimpleFileAccess3 >& xFileAccess,
1008 bool bUsedForStore,
1009 bool bStoreAll,
1010 bool bKillAll
1011)
1012{
1013 // Delete files for deleted locales
1014 if( bUsedForStore || bKillAll )
1015 implKillRemovedLocaleFiles( Location, aNameBase, xFileAccess );
1016
1017 for( auto& pLocaleItem : m_aLocaleItemVector )
1018 {
1019 if( pLocaleItem != nullptr && (bStoreAll || bKillAll || pLocaleItem->m_bModified) &&
1020 loadLocale( pLocaleItem.get() ) )
1021 {
1022 OUString aCompleteFileName =
1023 implGetPathForLocaleItem( pLocaleItem.get(), aNameBase, Location );
1024 if( xFileAccess->exists( aCompleteFileName ) )
1025 xFileAccess->kill( aCompleteFileName );
1026
1027 if( !bKillAll )
1028 {
1029 // Create Output stream
1030 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1031 if( xOutputStream.is() )
1032 {
1033 implWritePropertiesFile( pLocaleItem.get(), xOutputStream, aComment );
1034 xOutputStream->closeOutput();
1035 }
1036 if( bUsedForStore )
1037 pLocaleItem->m_bModified = false;
1038 }
1039 }
1040 }
1041
1042 // Delete files for changed defaults
1043 if( bUsedForStore || bKillAll )
1044 implKillChangedDefaultFiles( Location, aNameBase, xFileAccess );
1045
1046 // Default locale
1047 if( !(m_pDefaultLocaleItem != nullptr && (bStoreAll || bKillAll || m_bDefaultModified)) )
1048 return;
1049
1050 OUString aCompleteFileName =
1051 implGetPathForLocaleItem( m_pDefaultLocaleItem, aNameBase, Location, true );
1052 if( xFileAccess->exists( aCompleteFileName ) )
1053 xFileAccess->kill( aCompleteFileName );
1054
1055 if( !bKillAll )
1056 {
1057 // Create Output stream
1058 Reference< io::XOutputStream > xOutputStream = xFileAccess->openFileWrite( aCompleteFileName );
1059 if( xOutputStream.is() )
1060 xOutputStream->closeOutput();
1061
1062 if( bUsedForStore )
1063 m_bDefaultModified = false;
1064 }
1065}
1066
1067
1068// BinaryOutput, helper class for exportBinary
1069
1070class BinaryOutput
1071{
1072 Reference< XComponentContext > m_xContext;
1073 Reference< XInterface > m_xTempFile;
1074 Reference< io::XOutputStream > m_xOutputStream;
1075
1076public:
1077 explicit BinaryOutput( Reference< XComponentContext > const & xContext );
1078
1079 const Reference< io::XOutputStream >& getOutputStream() const
1080 { return m_xOutputStream; }
1081
1082 Sequence< ::sal_Int8 > closeAndGetData();
1083
1084 // Template to be used with sal_Int16 and sal_Unicode
1085 template< class T >
1086 void write16BitInt( T n );
1087 void writeInt16( sal_Int16 n )
1088 { write16BitInt( n ); }
1089 void writeUnicodeChar( sal_Unicode n )
1090 { write16BitInt( n ); }
1091 void writeInt32( sal_Int32 n );
1092 void writeString( const OUString& aStr );
1093};
1094
1095BinaryOutput::BinaryOutput( Reference< XComponentContext > const & xContext )
1096 : m_xContext( xContext )
1097{
1098 m_xTempFile = io::TempFile::create( m_xContext );
1099 m_xOutputStream.set( m_xTempFile, UNO_QUERY_THROW );
1100}
1101
1102template< class T >
1103void BinaryOutput::write16BitInt( T n )
1104{
1105 if( !m_xOutputStream.is() )
1106 return;
1107
1108 Sequence< sal_Int8 > aSeq( 2 );
1109 sal_Int8* p = aSeq.getArray();
1110
1111 sal_Int8 nLow = sal_Int8( n & 0xff );
1112 sal_Int8 nHigh = sal_Int8( n >> 8 );
1113
1114 p[0] = nLow;
1115 p[1] = nHigh;
1116 m_xOutputStream->writeBytes( aSeq );
1117}
1118
1119void BinaryOutput::writeInt32( sal_Int32 n )
1120{
1121 if( !m_xOutputStream.is() )
1122 return;
1123
1124 Sequence< sal_Int8 > aSeq( 4 );
1125 sal_Int8* p = aSeq.getArray();
1126
1127 for( sal_Int16 i = 0 ; i < 4 ; i++ )
1128 {
1129 p[i] = sal_Int8( n & 0xff );
1130 n >>= 8;
1131 }
1132 m_xOutputStream->writeBytes( aSeq );
1133}
1134
1135void BinaryOutput::writeString( const OUString& aStr )
1136{
1137 sal_Int32 nLen = aStr.getLength();
1138 const sal_Unicode* pStr = aStr.getStr();
1139
1140 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1141 writeUnicodeChar( pStr[i] );
1142
1143 writeUnicodeChar( 0 );
1144}
1145
1146Sequence< ::sal_Int8 > BinaryOutput::closeAndGetData()
1147{
1148 Sequence< ::sal_Int8 > aRetSeq;
1149 if( !m_xOutputStream.is() )
1150 return aRetSeq;
1151
1152 m_xOutputStream->closeOutput();
1153
1154 Reference< io::XSeekable> xSeekable( m_xTempFile, UNO_QUERY );
1155 if( !xSeekable.is() )
1156 return aRetSeq;
1157
1158 sal_Int32 nSize = static_cast<sal_Int32>(xSeekable->getPosition());
1159
1160 Reference< io::XInputStream> xInputStream( m_xTempFile, UNO_QUERY );
1161 if( !xInputStream.is() )
1162 return aRetSeq;
1163
1164 xSeekable->seek( 0 );
1165 sal_Int32 nRead = xInputStream->readBytes( aRetSeq, nSize );
1166 OSL_ENSURE( nRead == nSize, "BinaryOutput::closeAndGetData: nRead != nSize" )do { if (true && (!(nRead == nSize))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1166" ": "), "%s", "BinaryOutput::closeAndGetData: nRead != nSize"
); } } while (false)
;
1167
1168 return aRetSeq;
1169}
1170
1171
1172// Binary format:
1173
1174// Header
1175// Byte Content
1176// 0 + 1 sal_Int16: Version, currently 0, low byte first
1177// 2 + 3 sal_Int16: Locale count = n, low byte first
1178// 4 + 5 sal_Int16: Default Locale position in Locale list, == n if none
1179// 6 - 7 sal_Int32: Start index locale block 0, lowest byte first
1180// (n-1) * sal_Int32: Start index locale block 1 to n, lowest byte first
1181// 6 + 4*n sal_Int32: "Start index" non existing locale block n+1,
1182// marks the first invalid index, kind of EOF
1183
1184// Locale block
1185// All strings are stored as 2-Byte-0 terminated sequence
1186// of 16 bit Unicode characters, each with low byte first
1187// Empty strings only contain the 2-Byte-0
1188
1189// Members of com.sun.star.lang.Locale
1190// with l1 = Locale.Language.getLength()
1191// with l2 = Locale.Country.getLength()
1192// with l3 = Locale.Variant.getLength()
1193// pos0 = 0 Locale.Language
1194// pos1 = 2 * (l1 + 1) Locale.Country
1195// pos2 = pos1 + 2 * (l2 + 1) Locale.Variant
1196// pos3 = pos2 + 2 * (l3 + 1)
1197// pos3 Properties file written by implWritePropertiesFile
1198
1199Sequence< sal_Int8 > StringResourcePersistenceImpl::exportBinary( )
1200{
1201 BinaryOutput aOut( m_xContext );
1202
1203 sal_Int32 nLocaleCount = m_aLocaleItemVector.size();
1204 std::vector<Sequence< sal_Int8 >> aLocaleDataSeq(nLocaleCount);
1205
1206 sal_Int32 iLocale = 0;
1207 sal_Int32 iDefault = 0;
1208 for( auto& pLocaleItem : m_aLocaleItemVector )
1209 {
1210 if( pLocaleItem != nullptr && loadLocale( pLocaleItem.get() ) )
1211 {
1212 if( m_pDefaultLocaleItem == pLocaleItem.get() )
1213 iDefault = iLocale;
1214
1215 BinaryOutput aLocaleOut( m_xContext );
1216 implWriteLocaleBinary( pLocaleItem.get(), aLocaleOut );
1217
1218 aLocaleDataSeq[iLocale] = aLocaleOut.closeAndGetData();
1219 }
1220 ++iLocale;
1221 }
1222
1223 // Write header
1224 sal_Int16 nLocaleCount16 = static_cast<sal_Int16>(nLocaleCount);
1225 sal_Int16 iDefault16 = static_cast<sal_Int16>(iDefault);
1226 aOut.writeInt16( 0 ); // nVersion
1227 aOut.writeInt16( nLocaleCount16 );
1228 aOut.writeInt16( iDefault16 );
1229
1230 // Write data positions
1231 sal_Int32 nDataPos = 6 + 4 * (nLocaleCount + 1);
1232 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1233 {
1234 aOut.writeInt32( nDataPos );
1235
1236 Sequence< sal_Int8 >& rSeq = aLocaleDataSeq[iLocale];
1237 sal_Int32 nSeqLen = rSeq.getLength();
1238 nDataPos += nSeqLen;
1239 }
1240 // Write final position
1241 aOut.writeInt32( nDataPos );
1242
1243 // Write data
1244 Reference< io::XOutputStream > xOutputStream = aOut.getOutputStream();
1245 if( xOutputStream.is() )
1246 {
1247 for( iLocale = 0; iLocale < nLocaleCount; iLocale++ )
1248 {
1249 Sequence< sal_Int8 >& rSeq = aLocaleDataSeq[iLocale];
1250 xOutputStream->writeBytes( rSeq );
1251 }
1252 }
1253
1254 Sequence< sal_Int8 > aRetSeq = aOut.closeAndGetData();
1255 return aRetSeq;
1256}
1257
1258void StringResourcePersistenceImpl::implWriteLocaleBinary
1259 ( LocaleItem* pLocaleItem, BinaryOutput& rOut )
1260{
1261 Reference< io::XOutputStream > xOutputStream = rOut.getOutputStream();
1262 if( !xOutputStream.is() )
1263 return;
1264
1265 Locale& rLocale = pLocaleItem->m_locale;
1266 rOut.writeString( rLocale.Language );
1267 rOut.writeString( rLocale.Country );
1268 rOut.writeString( rLocale.Variant );
1269 implWritePropertiesFile( pLocaleItem, xOutputStream, m_aComment );
1270}
1271
1272
1273// BinaryOutput, helper class for exportBinary
1274
1275namespace {
1276
1277class BinaryInput
1278{
1279 Sequence< sal_Int8 > m_aData;
1280 Reference< XComponentContext > m_xContext;
1281
1282 const sal_Int8* m_pData;
1283 sal_Int32 m_nCurPos;
1284 sal_Int32 m_nSize;
1285
1286public:
1287 BinaryInput( const Sequence< ::sal_Int8 >& aData, Reference< XComponentContext > const & xContext );
1288
1289 Reference< io::XInputStream > getInputStreamForSection( sal_Int32 nSize );
1290
1291 void seek( sal_Int32 nPos );
1292 sal_Int32 getPosition() const
1293 { return m_nCurPos; }
1294
1295 sal_Int16 readInt16();
1296 sal_Int32 readInt32();
1297 sal_Unicode readUnicodeChar();
1298 OUString readString();
1299};
1300
1301}
1302
1303BinaryInput::BinaryInput( const Sequence< ::sal_Int8 >& aData, Reference< XComponentContext > const & xContext )
1304 : m_aData( aData )
1305 , m_xContext( xContext )
1306{
1307 m_pData = m_aData.getConstArray();
1308 m_nCurPos = 0;
1309 m_nSize = m_aData.getLength();
1310}
1311
1312Reference< io::XInputStream > BinaryInput::getInputStreamForSection( sal_Int32 nSize )
1313{
1314 Reference< io::XInputStream > xIn;
1315 if( m_nCurPos + nSize <= m_nSize )
1316 {
1317 Reference< io::XOutputStream > xTempOut( io::TempFile::create(m_xContext), UNO_QUERY_THROW );
1318 Sequence< sal_Int8 > aSection( m_pData + m_nCurPos, nSize );
1319 xTempOut->writeBytes( aSection );
1320
1321 Reference< io::XSeekable> xSeekable( xTempOut, UNO_QUERY );
1322 if( xSeekable.is() )
1323 xSeekable->seek( 0 );
1324
1325 xIn.set( xTempOut, UNO_QUERY );
1326 }
1327 else
1328 OSL_FAIL( "BinaryInput::getInputStreamForSection(): Read past end" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1328" ": "), "%s", "BinaryInput::getInputStreamForSection(): Read past end"
); } } while (false)
;
1329
1330 return xIn;
1331}
1332
1333void BinaryInput::seek( sal_Int32 nPos )
1334{
1335 if( nPos <= m_nSize )
1336 m_nCurPos = nPos;
1337 else
1338 OSL_FAIL( "BinaryInput::seek(): Position past end" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1338" ": "), "%s", "BinaryInput::seek(): Position past end"
); } } while (false)
;
1339}
1340
1341
1342sal_Int16 BinaryInput::readInt16()
1343{
1344 sal_Int16 nRet = 0;
1345 if( m_nCurPos + 2 <= m_nSize )
1346 {
1347 nRet = nRet + sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1348 nRet += 256 * sal_Int16( sal_uInt8( m_pData[m_nCurPos++] ) );
1349 }
1350 else
1351 OSL_FAIL( "BinaryInput::readInt16(): Read past end" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1351" ": "), "%s", "BinaryInput::readInt16(): Read past end"
); } } while (false)
;
1352
1353 return nRet;
1354}
1355
1356sal_Int32 BinaryInput::readInt32()
1357{
1358 sal_Int32 nRet = 0;
1359 if( m_nCurPos + 4 <= m_nSize )
1360 {
1361 sal_Int32 nFactor = 1;
1362 for( sal_Int16 i = 0; i < 4; i++ )
1363 {
1364 nRet += sal_uInt8( m_pData[m_nCurPos++] ) * nFactor;
1365 nFactor *= 256;
1366 }
1367 }
1368 else
1369 OSL_FAIL( "BinaryInput::readInt32(): Read past end" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1369" ": "), "%s", "BinaryInput::readInt32(): Read past end"
); } } while (false)
;
1370
1371 return nRet;
1372}
1373
1374sal_Unicode BinaryInput::readUnicodeChar()
1375{
1376 sal_uInt16 nRet = 0;
1377 if( m_nCurPos + 2 <= m_nSize )
1378 {
1379 nRet = nRet + sal_uInt8( m_pData[m_nCurPos++] );
1380 nRet += 256 * sal_uInt8( m_pData[m_nCurPos++] );
1381 }
1382 else
1383 OSL_FAIL( "BinaryInput::readUnicodeChar(): Read past end" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1383" ": "), "%s", "BinaryInput::readUnicodeChar(): Read past end"
); } } while (false)
;
1384
1385 sal_Unicode cRet = nRet;
1386 return cRet;
1387}
1388
1389OUString BinaryInput::readString()
1390{
1391 OUStringBuffer aBuf;
1392 sal_Unicode c;
1393 do
1394 {
1395 c = readUnicodeChar();
1396 if( c != 0 )
1397 aBuf.append( c );
1398 }
1399 while( c != 0 );
1400
1401 OUString aRetStr = aBuf.makeStringAndClear();
1402 return aRetStr;
1403}
1404
1405void StringResourcePersistenceImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
1406{
1407 // Init: Remove all locales
1408 sal_Int32 nOldLocaleCount = 0;
1409 do
1410 {
1411 Sequence< Locale > aLocaleSeq = getLocales();
1412 nOldLocaleCount = aLocaleSeq.getLength();
1413 if( nOldLocaleCount > 0 )
2
Assuming 'nOldLocaleCount' is > 0
3
Taking true branch
1414 {
1415 Locale aLocale = aLocaleSeq[0];
1416 removeLocale( aLocale );
4
Calling 'StringResourceWithLocationImpl::removeLocale'
1417 }
1418 }
1419 while( nOldLocaleCount > 0 );
1420
1421 // Import data
1422 BinaryInput aIn( Data, m_xContext );
1423
1424 aIn.readInt16(); // version
1425 sal_Int32 nLocaleCount = aIn.readInt16();
1426 sal_Int32 iDefault = aIn.readInt16();
1427
1428 std::unique_ptr<sal_Int32[]> pPositions( new sal_Int32[nLocaleCount + 1] );
1429 for( sal_Int32 i = 0; i < nLocaleCount + 1; i++ )
1430 pPositions[i] = aIn.readInt32();
1431
1432 // Import locales
1433 LocaleItem* pUseAsDefaultItem = nullptr;
1434 for( sal_Int32 i = 0; i < nLocaleCount; i++ )
1435 {
1436 sal_Int32 nPos = pPositions[i];
1437 aIn.seek( nPos );
1438
1439 Locale aLocale;
1440 aLocale.Language = aIn.readString();
1441 aLocale.Country = aIn.readString();
1442 aLocale.Variant = aIn.readString();
1443
1444 sal_Int32 nAfterStringPos = aIn.getPosition();
1445 sal_Int32 nSize = pPositions[i+1] - nAfterStringPos;
1446 Reference< io::XInputStream > xInput = aIn.getInputStreamForSection( nSize );
1447 if( xInput.is() )
1448 {
1449 LocaleItem* pLocaleItem = new LocaleItem( aLocale );
1450 if( iDefault == i )
1451 pUseAsDefaultItem = pLocaleItem;
1452 m_aLocaleItemVector.emplace_back( pLocaleItem );
1453 implReadPropertiesFile( pLocaleItem, xInput );
1454 }
1455 }
1456
1457 if( pUseAsDefaultItem != nullptr )
1458 setDefaultLocale( pUseAsDefaultItem->m_locale );
1459}
1460
1461
1462// Private helper methods
1463
1464static bool checkNamingSceme( const OUString& aName, const OUString& aNameBase,
1465 Locale& aLocale )
1466{
1467 bool bSuccess = false;
1468
1469 sal_Int32 nNameLen = aName.getLength();
1470 sal_Int32 nNameBaseLen = aNameBase.getLength();
1471
1472 // Name has to start with NameBase followed
1473 // by a '_' and at least one more character
1474 if( aName.startsWith( aNameBase ) && nNameBaseLen < nNameLen-1 &&
1475 aName[nNameBaseLen] == '_' )
1476 {
1477 bSuccess = true;
1478
1479 /* FIXME-BCP47: this uses '_' underscore character as separator and
1480 * also appends Variant, which can't be blindly changed as it would
1481 * violate the naming scheme in use. */
1482
1483 sal_Int32 iStart = nNameBaseLen + 1;
1484 sal_Int32 iNext_ = aName.indexOf( '_', iStart );
1485 if( iNext_ != -1 && iNext_ < nNameLen-1 )
1486 {
1487 aLocale.Language = aName.copy( iStart, iNext_ - iStart );
1488
1489 iStart = iNext_ + 1;
1490 iNext_ = aName.indexOf( '_', iStart );
1491 if( iNext_ != -1 && iNext_ < nNameLen-1 )
1492 {
1493 aLocale.Country = aName.copy( iStart, iNext_ - iStart );
1494 aLocale.Variant = aName.copy( iNext_ + 1 );
1495 }
1496 else
1497 aLocale.Country = aName.copy( iStart );
1498 }
1499 else
1500 aLocale.Language = aName.copy( iStart );
1501 }
1502 return bSuccess;
1503}
1504
1505void StringResourcePersistenceImpl::implLoadAllLocales()
1506{
1507 for( auto& pLocaleItem : m_aLocaleItemVector )
1508 if( pLocaleItem )
1509 loadLocale( pLocaleItem.get() );
1510}
1511
1512// Scan locale properties files helper
1513void StringResourcePersistenceImpl::implScanLocaleNames( const Sequence< OUString >& aContentSeq )
1514{
1515 Locale aDefaultLocale;
1516 bool bDefaultFound = false;
1517
1518 for( const OUString& aCompleteName : aContentSeq )
1519 {
1520 OUString aPureName;
1521 OUString aExtension;
1522 sal_Int32 iDot = aCompleteName.lastIndexOf( '.' );
1523 sal_Int32 iSlash = aCompleteName.lastIndexOf( '/' );
1524 if( iDot != -1 && iDot > iSlash)
1525 {
1526 sal_Int32 iCopyFrom = (iSlash != -1) ? iSlash + 1 : 0;
1527 aPureName = aCompleteName.copy( iCopyFrom, iDot-iCopyFrom );
1528 aExtension = aCompleteName.copy( iDot + 1 );
1529 }
1530
1531 if ( aExtension == "properties" )
1532 {
1533 //OUString aName = aInetObj.getBase();
1534 Locale aLocale;
1535
1536 if( checkNamingSceme( aPureName, m_aNameBase, aLocale ) )
1537 {
1538 LocaleItem* pLocaleItem = new LocaleItem( aLocale, false );
1539 m_aLocaleItemVector.emplace_back( pLocaleItem );
1540
1541 if( m_pCurrentLocaleItem == nullptr )
1542 m_pCurrentLocaleItem = pLocaleItem;
1543
1544 if( m_pDefaultLocaleItem == nullptr )
1545 {
1546 m_pDefaultLocaleItem = pLocaleItem;
1547 m_bDefaultModified = true;
1548 }
1549 }
1550 }
1551 else if( !bDefaultFound && aExtension == "default" )
1552 {
1553 if( checkNamingSceme( aPureName, m_aNameBase, aDefaultLocale ) )
1554 bDefaultFound = true;
1555 }
1556 }
1557 if( bDefaultFound )
1558 {
1559 LocaleItem* pLocaleItem = getItemForLocale( aDefaultLocale, false );
1560 if( pLocaleItem )
1561 {
1562 m_pDefaultLocaleItem = pLocaleItem;
1563 m_bDefaultModified = false;
1564 }
1565 }
1566}
1567
1568// Scan locale properties files
1569void StringResourcePersistenceImpl::implScanLocales()
1570{
1571 // Dummy implementation, method not called for this
1572 // base class, but pure virtual not possible-
1573}
1574
1575bool StringResourcePersistenceImpl::loadLocale( LocaleItem* pLocaleItem )
1576{
1577 bool bSuccess = false;
1578
1579 OSL_ENSURE( pLocaleItem, "StringResourcePersistenceImpl::loadLocale(): pLocaleItem == NULL" )do { if (true && (!(pLocaleItem))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1579" ": "), "%s", "StringResourcePersistenceImpl::loadLocale(): pLocaleItem == NULL"
); } } while (false)
;
1580 if( pLocaleItem )
1581 {
1582 if( pLocaleItem->m_bLoaded )
1583 {
1584 bSuccess = true;
1585 }
1586 else
1587 {
1588 bSuccess = implLoadLocale( pLocaleItem );
1589 pLocaleItem->m_bLoaded = true; // = bSuccess??? -> leads to more tries
1590 }
1591 }
1592 return bSuccess;
1593}
1594
1595bool StringResourcePersistenceImpl::implLoadLocale( LocaleItem* )
1596{
1597 // Dummy implementation, method not called for this
1598 // base class, but pure virtual not possible-
1599 return false;
1600}
1601
1602static OUString implGetNameScemeForLocaleItem( const LocaleItem* pLocaleItem )
1603{
1604 /* FIXME-BCP47: this uses '_' underscore character as separator and
1605 * also appends Variant, which can't be blindly changed as it would
1606 * violate the naming scheme in use. */
1607
1608 static const char aUnder[] = "_";
1609
1610 OSL_ENSURE( pLocaleItem,do { if (true && (!(pLocaleItem))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1611" ": "), "%s", "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL"
); } } while (false)
1611 "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL" )do { if (true && (!(pLocaleItem))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx"
":" "1611" ": "), "%s", "StringResourcePersistenceImpl::implGetNameScemeForLocaleItem(): pLocaleItem == NULL"
); } } while (false)
;
1612 Locale aLocale = pLocaleItem->m_locale;
1613
1614 OUString aRetStr = aUnder + aLocale.Language;
1615
1616 OUString aCountry = aLocale.Country;
1617 if( !aCountry.isEmpty() )
1618 {
1619 aRetStr += aUnder + aCountry;
1620 }
1621
1622 OUString aVariant = aLocale.Variant;
1623 if( !aVariant.isEmpty() )
1624 {
1625 aRetStr += aUnder + aVariant;
1626 }
1627 return aRetStr;
1628}
1629
1630OUString StringResourcePersistenceImpl::implGetFileNameForLocaleItem
1631 ( LocaleItem const * pLocaleItem, const OUString& aNameBase )
1632{
1633 OUString aFileName = aNameBase;
1634 if( aFileName.isEmpty() )
1635 aFileName = aNameBaseDefaultStr;
1636
1637 aFileName += implGetNameScemeForLocaleItem( pLocaleItem );
1638 return aFileName;
1639}
1640
1641OUString StringResourcePersistenceImpl::implGetPathForLocaleItem
1642 ( LocaleItem const * pLocaleItem, const OUString& aNameBase,
1643 const OUString& aLocation, bool bDefaultFile )
1644{
1645 OUString aFileName = implGetFileNameForLocaleItem( pLocaleItem, aNameBase );
1646 INetURLObject aInetObj( aLocation );
1647 aInetObj.insertName( aFileName, true, INetURLObject::LAST_SEGMENT, INetURLObject::EncodeMechanism::All );
1648 if( bDefaultFile )
1649 aInetObj.setExtension( "default" );
1650 else
1651 aInetObj.setExtension( "properties" );
1652 OUString aCompleteFileName = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
1653 return aCompleteFileName;
1654}
1655
1656// White space according to Java property files specification in
1657// http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)
1658static bool isWhiteSpace( sal_Unicode c )
1659{
1660 bool bWhite = ( c == 0x0020 || // space
1661 c == 0x0009 || // tab
1662 c == 0x000a || // line feed, not always handled by TextInputStream
1663 c == 0x000d || // carriage return, not always handled by TextInputStream
1664 c == 0x000C ); // form feed
1665 return bWhite;
1666}
1667
1668static void skipWhites( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1669{
1670 while( ri < nLen )
1671 {
1672 if( !isWhiteSpace( pBuf[ri] ) )
1673 break;
1674 ri++;
1675 }
1676}
1677
1678static bool isHexDigit( sal_Unicode c, sal_uInt16& nDigitVal )
1679{
1680 bool bRet = true;
1681 if( c >= '0' && c <= '9' )
1682 nDigitVal = c - '0';
1683 else if( c >= 'a' && c <= 'f' )
1684 nDigitVal = c - 'a' + 10;
1685 else if( c >= 'A' && c <= 'F' )
1686 nDigitVal = c - 'A' + 10;
1687 else
1688 bRet = false;
1689 return bRet;
1690}
1691
1692static sal_Unicode getEscapeChar( const sal_Unicode* pBuf, sal_Int32 nLen, sal_Int32& ri )
1693{
1694 sal_Int32 i = ri;
1695
1696 sal_Unicode cRet = 0;
1697 sal_Unicode c = pBuf[i];
1698 switch( c )
1699 {
1700 case 't':
1701 cRet = 0x0009;
1702 break;
1703 case 'n':
1704 cRet = 0x000a;
1705 break;
1706 case 'f':
1707 cRet = 0x000c;
1708 break;
1709 case 'r':
1710 cRet = 0x000d;
1711 break;
1712 case '\\':
1713 cRet = '\\';
1714 break;
1715 case 'u':
1716 {
1717 // Skip multiple u
1718 i++;
1719 while( i < nLen && pBuf[i] == 'u' )
1720 i++;
1721
1722 // Process hex digits
1723 sal_Int32 nDigitCount = 0;
1724 sal_uInt16 nDigitVal;
1725 while( i < nLen && isHexDigit( pBuf[i], nDigitVal ) )
1726 {
1727 cRet = 16 * cRet + nDigitVal;
1728
1729 nDigitCount++;
1730 if( nDigitCount == 4 )
1731 {
1732 // Write back position
1733 ri = i;
1734 break;
1735 }
1736 i++;
1737 }
1738 break;
1739 }
1740 default:
1741 cRet = c;
1742 }
1743
1744 return cRet;
1745}
1746
1747static void CheckContinueInNextLine( const Reference< io::XTextInputStream2 >& xTextInputStream,
1748 OUString& aLine, bool& bEscapePending, const sal_Unicode*& pBuf,
1749 sal_Int32& nLen, sal_Int32& i )
1750{
1751 if( !(i == nLen && bEscapePending) )
1752 return;
1753
1754 bEscapePending = false;
1755
1756 if( !xTextInputStream->isEOF() )
1757 {
1758 aLine = xTextInputStream->readLine();
1759 nLen = aLine.getLength();
1760 pBuf = aLine.getStr();
1761 i = 0;
1762
1763 skipWhites( pBuf, nLen, i );
1764 }
1765}
1766
1767bool StringResourcePersistenceImpl::implReadPropertiesFile
1768 ( LocaleItem* pLocaleItem, const Reference< io::XInputStream >& xInputStream )
1769{
1770 if( !xInputStream.is() || pLocaleItem == nullptr )
1771 return false;
1772
1773 Reference< io::XTextInputStream2 > xTextInputStream = io::TextInputStream::create( m_xContext );
1774
1775 xTextInputStream->setInputStream( xInputStream );
1776
1777 OUString aEncodingStr = OUString::createFromAscii
1778 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1(((rtl_TextEncoding) 12)) ) );
1779 xTextInputStream->setEncoding( aEncodingStr );
1780
1781 OUString aLine;
1782 while( !xTextInputStream->isEOF() )
1783 {
1784 aLine = xTextInputStream->readLine();
1785
1786 sal_Int32 nLen = aLine.getLength();
1787 if( 0 == nLen )
1788 continue;
1789 const sal_Unicode* pBuf = aLine.getStr();
1790 OUStringBuffer aBuf;
1791 sal_Unicode c = 0;
1792 sal_Int32 i = 0;
1793
1794 skipWhites( pBuf, nLen, i );
1795 if( i == nLen )
1796 continue; // line contains only white spaces
1797
1798 // Comment?
1799 c = pBuf[i];
1800 if( c == '#' || c == '!' )
1801 continue;
1802
1803 // Scan key
1804 OUString aResourceID;
1805 bool bEscapePending = false;
1806 bool bStrComplete = false;
1807 while( i < nLen && !bStrComplete )
1808 {
1809 c = pBuf[i];
1810 if( bEscapePending )
1811 {
1812 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
1813 bEscapePending = false;
1814 }
1815 else
1816 {
1817 if( c == '\\' )
1818 {
1819 bEscapePending = true;
1820 }
1821 else
1822 {
1823 if( c == ':' || c == '=' || isWhiteSpace( c ) )
1824 bStrComplete = true;
1825 else
1826 aBuf.append( c );
1827 }
1828 }
1829 i++;
1830
1831 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
1832 if( i == nLen )
1833 bStrComplete = true;
1834
1835 if( bStrComplete )
1836 aResourceID = aBuf.makeStringAndClear();
1837 }
1838
1839 // Ignore lines with empty keys
1840 if( aResourceID.isEmpty() )
1841 continue;
1842
1843 // Scan value
1844 skipWhites( pBuf, nLen, i );
1845
1846 OUString aValueStr;
1847 bEscapePending = false;
1848 bStrComplete = false;
1849 while( i < nLen && !bStrComplete )
1850 {
1851 c = pBuf[i];
1852 if( c == 0x000a || c == 0x000d ) // line feed/carriage return, not always handled by TextInputStream
1853 {
1854 i++;
1855 }
1856 else
1857 {
1858 if( bEscapePending )
1859 {
1860 aBuf.append( getEscapeChar( pBuf, nLen, i ) );
1861 bEscapePending = false;
1862 }
1863 else if( c == '\\' )
1864 bEscapePending = true;
1865 else
1866 aBuf.append( c );
1867 i++;
1868
1869 CheckContinueInNextLine( xTextInputStream, aLine, bEscapePending, pBuf, nLen, i );
1870 }
1871 if( i == nLen )
1872 bStrComplete = true;
1873
1874 if( bStrComplete )
1875 aValueStr = aBuf.makeStringAndClear();
1876 }
1877
1878 // Push into table
1879 pLocaleItem->m_aIdToStringMap[ aResourceID ] = aValueStr;
1880 implScanIdForNumber( aResourceID );
1881 IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
1882 rIndexMap[ aResourceID ] = pLocaleItem->m_nNextIndex++;
1883 }
1884
1885 return true;
1886}
1887
1888
1889static sal_Unicode getHexCharForDigit( sal_uInt16 nDigitVal )
1890{
1891 sal_Unicode cRet = ( nDigitVal < 10 ) ? ('0' + nDigitVal) : ('a' + (nDigitVal-10));
1892 return cRet;
1893}
1894
1895static void implWriteCharToBuffer( OUStringBuffer& aBuf, sal_Unicode cu, bool bKey )
1896{
1897 if( cu == '\\' )
1898 {
1899 aBuf.append( '\\' );
1900 aBuf.append( '\\' );
1901 }
1902 else if( cu == 0x000a )
1903 {
1904 aBuf.append( '\\' );
1905 aBuf.append( 'n' );
1906 }
1907 else if( cu == 0x000d )
1908 {
1909 aBuf.append( '\\' );
1910 aBuf.append( 'r' );
1911 }
1912 else if( bKey && cu == '=' )
1913 {
1914 aBuf.append( '\\' );
1915 aBuf.append( '=' );
1916 }
1917 else if( bKey && cu == ':' )
1918 {
1919 aBuf.append( '\\' );
1920 aBuf.append( ':' );
1921 }
1922 // ISO/IEC 8859-1 range according to:
1923 // http://en.wikipedia.org/wiki/ISO/IEC_8859-1
1924 else if( cu >= 0x20 && cu <= 0x7e )
1925 //TODO: Check why (cu >= 0xa0 && cu <= 0xFF)
1926 //is encoded in sample properties files
1927 //else if( (cu >= 0x20 && cu <= 0x7e) ||
1928 // (cu >= 0xa0 && cu <= 0xFF) )
1929 {
1930 aBuf.append( cu );
1931 }
1932 else
1933 {
1934 // Unicode encoding
1935 aBuf.append( '\\' );
1936 aBuf.append( 'u' );
1937
1938 sal_uInt16 nVal = cu;
1939 for( sal_uInt16 i = 0 ; i < 4 ; i++ )
1940 {
1941 sal_uInt16 nDigit = nVal / 0x1000;
1942 nVal -= nDigit * 0x1000;
1943 nVal *= 0x10;
1944 aBuf.append( getHexCharForDigit( nDigit ) );
1945 }
1946 }
1947}
1948
1949static void implWriteStringWithEncoding( const OUString& aStr,
1950 Reference< io::XTextOutputStream2 > const & xTextOutputStream, bool bKey )
1951{
1952 static const sal_Unicode cLineFeed = 0xa;
1953
1954 OUStringBuffer aBuf;
1955 sal_Int32 nLen = aStr.getLength();
1956 const sal_Unicode* pSrc = aStr.getStr();
1957 for( sal_Int32 i = 0 ; i < nLen ; i++ )
1958 {
1959 sal_Unicode cu = pSrc[i];
1960 implWriteCharToBuffer( aBuf, cu, bKey );
1961 // TODO?: split long lines
1962 }
1963 if( !bKey )
1964 aBuf.append( cLineFeed );
1965
1966 OUString aWriteStr = aBuf.makeStringAndClear();
1967 xTextOutputStream->writeString( aWriteStr );
1968}
1969
1970bool StringResourcePersistenceImpl::implWritePropertiesFile( LocaleItem const * pLocaleItem,
1971 const Reference< io::XOutputStream >& xOutputStream, const OUString& aComment )
1972{
1973 if( !xOutputStream.is() || pLocaleItem == nullptr )
1974 return false;
1975
1976 bool bSuccess = false;
1977 Reference< io::XTextOutputStream2 > xTextOutputStream = io::TextOutputStream::create(m_xContext);
1978
1979 xTextOutputStream->setOutputStream( xOutputStream );
1980
1981 OUString aEncodingStr = OUString::createFromAscii
1982 ( rtl_getMimeCharsetFromTextEncoding( RTL_TEXTENCODING_ISO_8859_1(((rtl_TextEncoding) 12)) ) );
1983 xTextOutputStream->setEncoding( aEncodingStr );
1984
1985 xTextOutputStream->writeString( aComment );
1986 xTextOutputStream->writeString( "\n" );
1987
1988 const IdToStringMap& rHashMap = pLocaleItem->m_aIdToStringMap;
1989 if( !rHashMap.empty() )
1990 {
1991 // Sort ids according to read order
1992 const IdToIndexMap& rIndexMap = pLocaleItem->m_aIdToIndexMap;
1993
1994 // Find max/min index
1995 auto itMinMax = std::minmax_element(rIndexMap.begin(), rIndexMap.end(),
1996 [](const IdToIndexMap::value_type& a, const IdToIndexMap::value_type& b) { return a.second < b.second; });
1997 sal_Int32 nMinIndex = itMinMax.first->second;
1998 sal_Int32 nMaxIndex = itMinMax.second->second;
1999 sal_Int32 nTabSize = nMaxIndex - nMinIndex + 1;
2000
2001 // Create sorted array of pointers to the id strings
2002 std::unique_ptr<const OUString*[]> pIdPtrs( new const OUString*[nTabSize] );
2003 for(sal_Int32 i = 0 ; i < nTabSize ; i++ )
2004 pIdPtrs[i] = nullptr;
2005 for( const auto& rIndex : rIndexMap )
2006 {
2007 sal_Int32 nIndex = rIndex.second;
2008 pIdPtrs[nIndex - nMinIndex] = &(rIndex.first);
2009 }
2010
2011 // Write lines in correct order
2012 for(sal_Int32 i = 0 ; i < nTabSize ; i++ )
2013 {
2014 const OUString* pStr = pIdPtrs[i];
2015 if( pStr != nullptr )
2016 {
2017 OUString aResourceID = *pStr;
2018 IdToStringMap::const_iterator it = rHashMap.find( aResourceID );
2019 if( it != rHashMap.end() )
2020 {
2021 implWriteStringWithEncoding( aResourceID, xTextOutputStream, true );
2022 xTextOutputStream->writeString( "=" );
2023 OUString aValStr = (*it).second;
2024 implWriteStringWithEncoding( aValStr, xTextOutputStream, false );
2025 }
2026 }
2027 }
2028 }
2029
2030 bSuccess = true;
2031
2032 return bSuccess;
2033}
2034
2035
2036// StringResourceWithStorageImpl
2037
2038extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface*
2039scripting_StringResourceWithStorageImpl_get_implementation(
2040 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
2041{
2042 return cppu::acquire(new StringResourceWithStorageImpl(context));
2043}
2044
2045
2046StringResourceWithStorageImpl::StringResourceWithStorageImpl( const Reference< XComponentContext >& rxContext )
2047 : StringResourceWithStorageImpl_BASE( rxContext )
2048 , m_bStorageChanged( false )
2049{
2050}
2051
2052
2053StringResourceWithStorageImpl::~StringResourceWithStorageImpl()
2054{
2055}
2056
2057
2058// XServiceInfo
2059
2060
2061OUString StringResourceWithStorageImpl::getImplementationName( )
2062{
2063 return "com.sun.star.comp.scripting.StringResourceWithStorage";
2064}
2065
2066sal_Bool StringResourceWithStorageImpl::supportsService( const OUString& rServiceName )
2067{
2068 return cppu::supportsService(this, rServiceName);
2069}
2070
2071Sequence< OUString > StringResourceWithStorageImpl::getSupportedServiceNames( )
2072{
2073 return { "com.sun.star.resource.StringResourceWithStorage" };
2074}
2075
2076
2077// XInitialization
2078
2079
2080void StringResourceWithStorageImpl::initialize( const Sequence< Any >& aArguments )
2081{
2082 ::osl::MutexGuard aGuard( getMutex() );
2083
2084 if ( aArguments.getLength() != 5 )
2085 {
2086 throw RuntimeException(
2087 "StringResourceWithStorageImpl::initialize: invalid number of arguments!" );
2088 }
2089
2090 bool bOk = (aArguments[0] >>= m_xStorage);
2091 if( bOk && !m_xStorage.is() )
2092 bOk = false;
2093
2094 if( !bOk )
2095 {
2096 throw IllegalArgumentException( "StringResourceWithStorageImpl::initialize: invalid storage", Reference< XInterface >(), 0 );
2097 }
2098
2099 implInitializeCommonParameters( aArguments );
2100}
2101
2102
2103// Forwarding calls to base class
2104
2105// XModifyBroadcaster
2106void StringResourceWithStorageImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2107{
2108 StringResourceImpl::addModifyListener( aListener );
2109}
2110void StringResourceWithStorageImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2111{
2112 StringResourceImpl::removeModifyListener( aListener );
2113}
2114
2115// XStringResourceResolver
2116OUString StringResourceWithStorageImpl::resolveString( const OUString& ResourceID )
2117{
2118 return StringResourceImpl::resolveString( ResourceID ) ;
2119}
2120OUString StringResourceWithStorageImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
2121{
2122 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2123}
2124sal_Bool StringResourceWithStorageImpl::hasEntryForId( const OUString& ResourceID )
2125{
2126 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2127}
2128sal_Bool StringResourceWithStorageImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
2129 const Locale& locale )
2130{
2131 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2132}
2133Sequence< OUString > StringResourceWithStorageImpl::getResourceIDs( )
2134{
2135 return StringResourceImpl::getResourceIDs();
2136}
2137Sequence< OUString > StringResourceWithStorageImpl::getResourceIDsForLocale
2138 ( const Locale& locale )
2139{
2140 return StringResourceImpl::getResourceIDsForLocale( locale );
2141}
2142Locale StringResourceWithStorageImpl::getCurrentLocale()
2143{
2144 return StringResourceImpl::getCurrentLocale();
2145}
2146Locale StringResourceWithStorageImpl::getDefaultLocale( )
2147{
2148 return StringResourceImpl::getDefaultLocale();
2149}
2150Sequence< Locale > StringResourceWithStorageImpl::getLocales( )
2151{
2152 return StringResourceImpl::getLocales();
2153}
2154
2155// XStringResourceManager
2156sal_Bool StringResourceWithStorageImpl::isReadOnly()
2157{
2158 return StringResourceImpl::isReadOnly();
2159}
2160void StringResourceWithStorageImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2161{
2162 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2163}
2164void StringResourceWithStorageImpl::setDefaultLocale( const Locale& locale )
2165{
2166 StringResourceImpl::setDefaultLocale( locale );
2167}
2168void StringResourceWithStorageImpl::setString( const OUString& ResourceID, const OUString& Str )
2169{
2170 StringResourceImpl::setString( ResourceID, Str );
2171}
2172void StringResourceWithStorageImpl::setStringForLocale
2173 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
2174{
2175 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2176}
2177void StringResourceWithStorageImpl::removeId( const OUString& ResourceID )
2178{
2179 StringResourceImpl::removeId( ResourceID );
2180}
2181void StringResourceWithStorageImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
2182{
2183 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2184}
2185void StringResourceWithStorageImpl::newLocale( const Locale& locale )
2186{
2187 StringResourceImpl::newLocale( locale );
2188}
2189void StringResourceWithStorageImpl::removeLocale( const Locale& locale )
2190{
2191 StringResourceImpl::removeLocale( locale );
2192}
2193sal_Int32 StringResourceWithStorageImpl::getUniqueNumericId( )
2194{
2195 return StringResourceImpl::getUniqueNumericId();
2196}
2197
2198// XStringResourcePersistence
2199void StringResourceWithStorageImpl::store()
2200{
2201 ::osl::MutexGuard aGuard( getMutex() );
2202 implCheckReadOnly( "StringResourceWithStorageImpl::store(): Read only" );
2203
2204 bool bStoreAll = m_bStorageChanged;
2205 m_bStorageChanged = false;
2206 if( !m_bModified && !bStoreAll )
2207 return;
2208
2209 implStoreAtStorage( m_aNameBase, m_aComment, m_xStorage, true/*bUsedForStore*/, bStoreAll );
2210 m_bModified = false;
2211}
2212
2213sal_Bool StringResourceWithStorageImpl::isModified( )
2214{
2215 return StringResourcePersistenceImpl::isModified();
2216}
2217void StringResourceWithStorageImpl::setComment( const OUString& Comment )
2218{
2219 StringResourcePersistenceImpl::setComment( Comment );
2220}
2221void StringResourceWithStorageImpl::storeToStorage( const Reference< XStorage >& Storage,
2222 const OUString& NameBase, const OUString& Comment )
2223{
2224 StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment );
2225}
2226void StringResourceWithStorageImpl::storeToURL( const OUString& URL,
2227 const OUString& NameBase, const OUString& Comment,
2228 const Reference< css::task::XInteractionHandler >& Handler )
2229{
2230 StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler );
2231}
2232Sequence< ::sal_Int8 > StringResourceWithStorageImpl::exportBinary( )
2233{
2234 return StringResourcePersistenceImpl::exportBinary();
2235}
2236void StringResourceWithStorageImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2237{
2238 StringResourcePersistenceImpl::importBinary( Data );
2239}
2240
2241
2242// XStringResourceWithStorage
2243
2244void StringResourceWithStorageImpl::storeAsStorage( const Reference< XStorage >& Storage )
2245{
2246 setStorage( Storage );
2247 store();
2248}
2249
2250void StringResourceWithStorageImpl::setStorage( const Reference< XStorage >& Storage )
2251{
2252 ::osl::MutexGuard aGuard( getMutex() );
2253
2254 if( !Storage.is() )
2255 {
2256 throw IllegalArgumentException( "StringResourceWithStorageImpl::setStorage: invalid storage", Reference< XInterface >(), 0 );
2257 }
2258
2259 implLoadAllLocales();
2260
2261 m_xStorage = Storage;
2262 m_bStorageChanged = true;
2263}
2264
2265
2266// Private helper methods
2267
2268
2269// Scan locale properties files
2270void StringResourceWithStorageImpl::implScanLocales()
2271{
2272 if( m_xStorage.is() )
2273 {
2274 Sequence< OUString > aContentSeq = m_xStorage->getElementNames();
2275 implScanLocaleNames( aContentSeq );
2276 }
2277
2278 implLoadAllLocales();
2279}
2280
2281// Loading
2282bool StringResourceWithStorageImpl::implLoadLocale( LocaleItem* pLocaleItem )
2283{
2284 bool bSuccess = false;
2285 try
2286 {
2287 OUString aStreamName = implGetFileNameForLocaleItem( pLocaleItem, m_aNameBase ) + ".properties";
2288
2289 Reference< io::XStream > xElementStream =
2290 m_xStorage->openStreamElement( aStreamName, ElementModes::READ );
2291
2292 if( xElementStream.is() )
2293 {
2294 Reference< io::XInputStream > xInputStream = xElementStream->getInputStream();
2295 if( xInputStream.is() )
2296 {
2297 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2298 xInputStream->closeInput();
2299 }
2300 }
2301 }
2302 catch( uno::Exception& )
2303 {}
2304
2305 return bSuccess;
2306}
2307
2308
2309// StringResourceWithLocationImpl
2310
2311
2312extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface*
2313scripting_StringResourceWithLocationImpl_get_implementation(
2314 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
2315{
2316 return cppu::acquire(new StringResourceWithLocationImpl(context));
2317}
2318
2319
2320
2321StringResourceWithLocationImpl::StringResourceWithLocationImpl( const Reference< XComponentContext >& rxContext )
2322 : StringResourceWithLocationImpl_BASE( rxContext )
2323 , m_bLocationChanged( false )
2324{
2325}
2326
2327
2328StringResourceWithLocationImpl::~StringResourceWithLocationImpl()
2329{
2330}
2331
2332
2333// XServiceInfo
2334
2335
2336OUString StringResourceWithLocationImpl::getImplementationName( )
2337{
2338 return "com.sun.star.comp.scripting.StringResourceWithLocation";
2339}
2340
2341sal_Bool StringResourceWithLocationImpl::supportsService( const OUString& rServiceName )
2342{
2343 return cppu::supportsService(this, rServiceName);
2344}
2345
2346Sequence< OUString > StringResourceWithLocationImpl::getSupportedServiceNames( )
2347{
2348 return { "com.sun.star.resource.StringResourceWithLocation" };
2349}
2350
2351
2352// XInitialization
2353
2354
2355void StringResourceWithLocationImpl::initialize( const Sequence< Any >& aArguments )
2356{
2357 ::osl::MutexGuard aGuard( getMutex() );
2358
2359 if ( aArguments.getLength() != 6 )
2360 {
2361 throw RuntimeException(
2362 "XInitialization::initialize: invalid number of arguments!" );
2363 }
2364
2365 bool bOk = (aArguments[0] >>= m_aLocation);
2366 sal_Int32 nLen = m_aLocation.getLength();
2367 if( bOk && nLen == 0 )
2368 {
2369 bOk = false;
2370 }
2371 else
2372 {
2373 if( m_aLocation[nLen - 1] != '/' )
2374 m_aLocation += "/";
2375 }
2376
2377 if( !bOk )
2378 {
2379 throw IllegalArgumentException( "XInitialization::initialize: invalid URL", Reference< XInterface >(), 0 );
2380 }
2381
2382
2383 bOk = (aArguments[5] >>= m_xInteractionHandler);
2384 if( !bOk )
2385 {
2386 throw IllegalArgumentException( "StringResourceWithStorageImpl::initialize: invalid type", Reference< XInterface >(), 5 );
2387 }
2388
2389 implInitializeCommonParameters( aArguments );
2390}
2391
2392
2393// Forwarding calls to base class
2394
2395// XModifyBroadcaster
2396void StringResourceWithLocationImpl::addModifyListener( const Reference< XModifyListener >& aListener )
2397{
2398 StringResourceImpl::addModifyListener( aListener );
2399}
2400void StringResourceWithLocationImpl::removeModifyListener( const Reference< XModifyListener >& aListener )
2401{
2402 StringResourceImpl::removeModifyListener( aListener );
2403}
2404
2405// XStringResourceResolver
2406OUString StringResourceWithLocationImpl::resolveString( const OUString& ResourceID )
2407{
2408 return StringResourceImpl::resolveString( ResourceID ) ;
2409}
2410OUString StringResourceWithLocationImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale )
2411{
2412 return StringResourceImpl::resolveStringForLocale( ResourceID, locale );
2413}
2414sal_Bool StringResourceWithLocationImpl::hasEntryForId( const OUString& ResourceID )
2415{
2416 return StringResourceImpl::hasEntryForId( ResourceID ) ;
2417}
2418sal_Bool StringResourceWithLocationImpl::hasEntryForIdAndLocale( const OUString& ResourceID,
2419 const Locale& locale )
2420{
2421 return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale );
2422}
2423Sequence< OUString > StringResourceWithLocationImpl::getResourceIDs( )
2424{
2425 return StringResourceImpl::getResourceIDs();
2426}
2427Sequence< OUString > StringResourceWithLocationImpl::getResourceIDsForLocale
2428 ( const Locale& locale )
2429{
2430 return StringResourceImpl::getResourceIDsForLocale( locale );
2431}
2432Locale StringResourceWithLocationImpl::getCurrentLocale()
2433{
2434 return StringResourceImpl::getCurrentLocale();
2435}
2436Locale StringResourceWithLocationImpl::getDefaultLocale( )
2437{
2438 return StringResourceImpl::getDefaultLocale();
2439}
2440Sequence< Locale > StringResourceWithLocationImpl::getLocales( )
2441{
2442 return StringResourceImpl::getLocales();
2443}
2444
2445// XStringResourceManager
2446sal_Bool StringResourceWithLocationImpl::isReadOnly()
2447{
2448 return StringResourceImpl::isReadOnly();
2449}
2450void StringResourceWithLocationImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch )
2451{
2452 StringResourceImpl::setCurrentLocale( locale, FindClosestMatch );
2453}
2454void StringResourceWithLocationImpl::setDefaultLocale( const Locale& locale )
2455{
2456 StringResourceImpl::setDefaultLocale( locale );
2457}
2458void StringResourceWithLocationImpl::setString( const OUString& ResourceID, const OUString& Str )
2459{
2460 StringResourceImpl::setString( ResourceID, Str );
2461}
2462void StringResourceWithLocationImpl::setStringForLocale
2463 ( const OUString& ResourceID, const OUString& Str, const Locale& locale )
2464{
2465 StringResourceImpl::setStringForLocale( ResourceID, Str, locale );
2466}
2467void StringResourceWithLocationImpl::removeId( const OUString& ResourceID )
2468{
2469 StringResourceImpl::removeId( ResourceID );
2470}
2471void StringResourceWithLocationImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale )
2472{
2473 StringResourceImpl::removeIdForLocale( ResourceID, locale );
2474}
2475void StringResourceWithLocationImpl::newLocale( const Locale& locale )
2476{
2477 StringResourceImpl::newLocale( locale );
2478}
2479void StringResourceWithLocationImpl::removeLocale( const Locale& locale )
2480{
2481 StringResourceImpl::removeLocale( locale );
5
Calling 'StringResourceImpl::removeLocale'
2482}
2483sal_Int32 StringResourceWithLocationImpl::getUniqueNumericId( )
2484{
2485 return StringResourceImpl::getUniqueNumericId();
2486}
2487
2488// XStringResourcePersistence
2489void StringResourceWithLocationImpl::store()
2490{
2491 ::osl::MutexGuard aGuard( getMutex() );
2492 implCheckReadOnly( "StringResourceWithLocationImpl::store(): Read only" );
2493
2494 bool bStoreAll = m_bLocationChanged;
2495 m_bLocationChanged = false;
2496 if( !m_bModified && !bStoreAll )
2497 return;
2498
2499 Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccess();
2500 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2501 xFileAccess, true/*bUsedForStore*/, bStoreAll );
2502 m_bModified = false;
2503}
2504
2505sal_Bool StringResourceWithLocationImpl::isModified( )
2506{
2507 return StringResourcePersistenceImpl::isModified();
2508}
2509void StringResourceWithLocationImpl::setComment( const OUString& Comment )
2510{
2511 StringResourcePersistenceImpl::setComment( Comment );
2512}
2513void StringResourceWithLocationImpl::storeToStorage( const Reference< XStorage >& Storage,
2514 const OUString& NameBase, const OUString& Comment )
2515{
2516 StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment );
2517}
2518void StringResourceWithLocationImpl::storeToURL( const OUString& URL,
2519 const OUString& NameBase, const OUString& Comment,
2520 const Reference< css::task::XInteractionHandler >& Handler )
2521{
2522 StringResourcePersistenceImpl::storeToURL( URL, NameBase, Comment, Handler );
2523}
2524Sequence< ::sal_Int8 > StringResourceWithLocationImpl::exportBinary( )
2525{
2526 return StringResourcePersistenceImpl::exportBinary();
2527}
2528void StringResourceWithLocationImpl::importBinary( const Sequence< ::sal_Int8 >& Data )
2529{
2530 StringResourcePersistenceImpl::importBinary( Data );
1
Calling 'StringResourcePersistenceImpl::importBinary'
2531}
2532
2533
2534// XStringResourceWithLocation
2535
2536// XStringResourceWithLocation
2537void StringResourceWithLocationImpl::storeAsURL( const OUString& URL )
2538{
2539 setURL( URL );
2540 store();
2541}
2542
2543void StringResourceWithLocationImpl::setURL( const OUString& URL )
2544{
2545 ::osl::MutexGuard aGuard( getMutex() );
2546 implCheckReadOnly( "StringResourceWithLocationImpl::setURL(): Read only" );
2547
2548 sal_Int32 nLen = URL.getLength();
2549 if( nLen == 0 )
2550 {
2551 throw IllegalArgumentException( "StringResourceWithLocationImpl::setURL: invalid URL", Reference< XInterface >(), 0 );
2552 }
2553
2554 implLoadAllLocales();
2555
2556 // Delete files at old location
2557 implStoreAtLocation( m_aLocation, m_aNameBase, m_aComment,
2558 getFileAccess(), false/*bUsedForStore*/, false/*bStoreAll*/, true/*bKillAll*/ );
2559
2560 m_aLocation = URL;
2561 m_bLocationChanged = true;
2562}
2563
2564
2565// Private helper methods
2566
2567
2568// Scan locale properties files
2569void StringResourceWithLocationImpl::implScanLocales()
2570{
2571 const Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccess();
2572 if( xFileAccess.is() && xFileAccess->isFolder( m_aLocation ) )
2573 {
2574 Sequence< OUString > aContentSeq = xFileAccess->getFolderContents( m_aLocation, false );
2575 implScanLocaleNames( aContentSeq );
2576 }
2577}
2578
2579// Loading
2580bool StringResourceWithLocationImpl::implLoadLocale( LocaleItem* pLocaleItem )
2581{
2582 bool bSuccess = false;
2583
2584 const Reference< ucb::XSimpleFileAccess3 > xFileAccess = getFileAccess();
2585 if( xFileAccess.is() )
2586 {
2587 OUString aCompleteFileName =
2588 implGetPathForLocaleItem( pLocaleItem, m_aNameBase, m_aLocation );
2589
2590 Reference< io::XInputStream > xInputStream;
2591 try
2592 {
2593 xInputStream = xFileAccess->openFileRead( aCompleteFileName );
2594 }
2595 catch( Exception& )
2596 {}
2597 if( xInputStream.is() )
2598 {
2599 bSuccess = StringResourcePersistenceImpl::implReadPropertiesFile( pLocaleItem, xInputStream );
2600 xInputStream->closeInput();
2601 }
2602 }
2603
2604 return bSuccess;
2605}
2606
2607const Reference< ucb::XSimpleFileAccess3 > & StringResourceWithLocationImpl::getFileAccess()
2608{
2609 ::osl::MutexGuard aGuard( getMutex() );
2610
2611 if( !m_xSFI.is() )
2612 {
2613 m_xSFI = ucb::SimpleFileAccess::create(m_xContext);
2614
2615 if( m_xSFI.is() && m_xInteractionHandler.is() )
2616 m_xSFI->setInteractionHandler( m_xInteractionHandler );
2617 }
2618 return m_xSFI;
2619}
2620
2621} // namespace stringresource
2622
2623
2624/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/unique_ptr.h

1// unique_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2008-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _UNIQUE_PTR_H1
31#define _UNIQUE_PTR_H1 1
32
33#include <bits/c++config.h>
34#include <debug/assertions.h>
35#include <type_traits>
36#include <utility>
37#include <tuple>
38#include <bits/stl_function.h>
39#include <bits/functional_hash.h>
40#if __cplusplus201703L > 201703L
41# include <compare>
42# include <ostream>
43#endif
44
45namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 /**
50 * @addtogroup pointer_abstractions
51 * @{
52 */
53
54#if _GLIBCXX_USE_DEPRECATED1
55#pragma GCC diagnostic push
56#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57 template<typename> class auto_ptr;
58#pragma GCC diagnostic pop
59#endif
60
61 /// Primary template of default_delete, used by unique_ptr for single objects
62 template<typename _Tp>
63 struct default_delete
64 {
65 /// Default constructor
66 constexpr default_delete() noexcept = default;
67
68 /** @brief Converting constructor.
69 *
70 * Allows conversion from a deleter for objects of another type, `_Up`,
71 * only if `_Up*` is convertible to `_Tp*`.
72 */
73 template<typename _Up,
74 typename = _Require<is_convertible<_Up*, _Tp*>>>
75 default_delete(const default_delete<_Up>&) noexcept { }
76
77 /// Calls `delete __ptr`
78 void
79 operator()(_Tp* __ptr) const
80 {
81 static_assert(!is_void<_Tp>::value,
82 "can't delete pointer to incomplete type");
83 static_assert(sizeof(_Tp)>0,
84 "can't delete pointer to incomplete type");
85 delete __ptr;
86 }
87 };
88
89 // _GLIBCXX_RESOLVE_LIB_DEFECTS
90 // DR 740 - omit specialization for array objects with a compile time length
91
92 /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>`
93 template<typename _Tp>
94 struct default_delete<_Tp[]>
95 {
96 public:
97 /// Default constructor
98 constexpr default_delete() noexcept = default;
99
100 /** @brief Converting constructor.
101 *
102 * Allows conversion from a deleter for arrays of another type, such as
103 * a const-qualified version of `_Tp`.
104 *
105 * Conversions from types derived from `_Tp` are not allowed because
106 * it is undefined to `delete[]` an array of derived types through a
107 * pointer to the base type.
108 */
109 template<typename _Up,
110 typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
111 default_delete(const default_delete<_Up[]>&) noexcept { }
112
113 /// Calls `delete[] __ptr`
114 template<typename _Up>
115 typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
116 operator()(_Up* __ptr) const
117 {
118 static_assert(sizeof(_Tp)>0,
119 "can't delete pointer to incomplete type");
120 delete [] __ptr;
121 }
122 };
123
124 /// @cond undocumented
125
126 // Manages the pointer and deleter of a unique_ptr
127 template <typename _Tp, typename _Dp>
128 class __uniq_ptr_impl
129 {
130 template <typename _Up, typename _Ep, typename = void>
131 struct _Ptr
132 {
133 using type = _Up*;
134 };
135
136 template <typename _Up, typename _Ep>
137 struct
138 _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
139 {
140 using type = typename remove_reference<_Ep>::type::pointer;
141 };
142
143 public:
144 using _DeleterConstraint = enable_if<
145 __and_<__not_<is_pointer<_Dp>>,
146 is_default_constructible<_Dp>>::value>;
147
148 using pointer = typename _Ptr<_Tp, _Dp>::type;
149
150 static_assert( !is_rvalue_reference<_Dp>::value,
151 "unique_ptr's deleter type must be a function object type"
152 " or an lvalue reference type" );
153
154 __uniq_ptr_impl() = default;
155 __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
156
157 template<typename _Del>
158 __uniq_ptr_impl(pointer __p, _Del&& __d)
159 : _M_t(__p, std::forward<_Del>(__d)) { }
160
161 __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
162 : _M_t(std::move(__u._M_t))
163 { __u._M_ptr() = nullptr; }
164
165 __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
166 {
167 reset(__u.release());
168 _M_deleter() = std::forward<_Dp>(__u._M_deleter());
169 return *this;
170 }
171
172 pointer& _M_ptr() { return std::get<0>(_M_t); }
173 pointer _M_ptr() const { return std::get<0>(_M_t); }
174 _Dp& _M_deleter() { return std::get<1>(_M_t); }
175 const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
176
177 void reset(pointer __p) noexcept
178 {
179 const pointer __old_p = _M_ptr();
180 _M_ptr() = __p;
181 if (__old_p)
182 _M_deleter()(__old_p);
183 }
184
185 pointer release() noexcept
186 {
187 pointer __p = _M_ptr();
188 _M_ptr() = nullptr;
189 return __p;
190 }
191
192 void
193 swap(__uniq_ptr_impl& __rhs) noexcept
194 {
195 using std::swap;
196 swap(this->_M_ptr(), __rhs._M_ptr());
197 swap(this->_M_deleter(), __rhs._M_deleter());
198 }
199
200 private:
201 tuple<pointer, _Dp> _M_t;
202 };
203
204 // Defines move construction + assignment as either defaulted or deleted.
205 template <typename _Tp, typename _Dp,
206 bool = is_move_constructible<_Dp>::value,
207 bool = is_move_assignable<_Dp>::value>
208 struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp>
209 {
210 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
211 __uniq_ptr_data(__uniq_ptr_data&&) = default;
212 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
213 };
214
215 template <typename _Tp, typename _Dp>
216 struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
217 {
218 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
219 __uniq_ptr_data(__uniq_ptr_data&&) = default;
220 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
221 };
222
223 template <typename _Tp, typename _Dp>
224 struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp>
225 {
226 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
227 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
228 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
229 };
230
231 template <typename _Tp, typename _Dp>
232 struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp>
233 {
234 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
235 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
236 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
237 };
238 /// @endcond
239
240 /// 20.7.1.2 unique_ptr for single objects.
241 template <typename _Tp, typename _Dp = default_delete<_Tp>>
242 class unique_ptr
243 {
244 template <typename _Up>
245 using _DeleterConstraint =
246 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
247
248 __uniq_ptr_data<_Tp, _Dp> _M_t;
249
250 public:
251 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
252 using element_type = _Tp;
253 using deleter_type = _Dp;
254
255 private:
256 // helper template for detecting a safe conversion from another
257 // unique_ptr
258 template<typename _Up, typename _Ep>
259 using __safe_conversion_up = __and_<
260 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
261 __not_<is_array<_Up>>
262 >;
263
264 public:
265 // Constructors.
266
267 /// Default constructor, creates a unique_ptr that owns nothing.
268 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
269 constexpr unique_ptr() noexcept
270 : _M_t()
271 { }
272
273 /** Takes ownership of a pointer.
274 *
275 * @param __p A pointer to an object of @c element_type
276 *
277 * The deleter will be value-initialized.
278 */
279 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
280 explicit
281 unique_ptr(pointer __p) noexcept
282 : _M_t(__p)
283 { }
284
285 /** Takes ownership of a pointer.
286 *
287 * @param __p A pointer to an object of @c element_type
288 * @param __d A reference to a deleter.
289 *
290 * The deleter will be initialized with @p __d
291 */
292 template<typename _Del = deleter_type,
293 typename = _Require<is_copy_constructible<_Del>>>
294 unique_ptr(pointer __p, const deleter_type& __d) noexcept
295 : _M_t(__p, __d) { }
296
297 /** Takes ownership of a pointer.
298 *
299 * @param __p A pointer to an object of @c element_type
300 * @param __d An rvalue reference to a (non-reference) deleter.
301 *
302 * The deleter will be initialized with @p std::move(__d)
303 */
304 template<typename _Del = deleter_type,
305 typename = _Require<is_move_constructible<_Del>>>
306 unique_ptr(pointer __p,
307 __enable_if_t<!is_lvalue_reference<_Del>::value,
308 _Del&&> __d) noexcept
309 : _M_t(__p, std::move(__d))
310 { }
311
312 template<typename _Del = deleter_type,
313 typename _DelUnref = typename remove_reference<_Del>::type>
314 unique_ptr(pointer,
315 __enable_if_t<is_lvalue_reference<_Del>::value,
316 _DelUnref&&>) = delete;
317
318 /// Creates a unique_ptr that owns nothing.
319 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
320 constexpr unique_ptr(nullptr_t) noexcept
321 : _M_t()
322 { }
323
324 // Move constructors.
325
326 /// Move constructor.
327 unique_ptr(unique_ptr&&) = default;
328
329 /** @brief Converting constructor from another type
330 *
331 * Requires that the pointer owned by @p __u is convertible to the
332 * type of pointer owned by this object, @p __u does not own an array,
333 * and @p __u has a compatible deleter type.
334 */
335 template<typename _Up, typename _Ep, typename = _Require<
336 __safe_conversion_up<_Up, _Ep>,
337 typename conditional<is_reference<_Dp>::value,
338 is_same<_Ep, _Dp>,
339 is_convertible<_Ep, _Dp>>::type>>
340 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
341 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
342 { }
343
344#if _GLIBCXX_USE_DEPRECATED1
345#pragma GCC diagnostic push
346#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
347 /// Converting constructor from @c auto_ptr
348 template<typename _Up, typename = _Require<
349 is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
350 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
351#pragma GCC diagnostic pop
352#endif
353
354 /// Destructor, invokes the deleter if the stored pointer is not null.
355 ~unique_ptr() noexcept
356 {
357 static_assert(__is_invocable<deleter_type&, pointer>::value,
358 "unique_ptr's deleter must be invocable with a pointer");
359 auto& __ptr = _M_t._M_ptr();
360 if (__ptr != nullptr)
361 get_deleter()(std::move(__ptr));
362 __ptr = pointer();
363 }
364
365 // Assignment.
366
367 /** @brief Move assignment operator.
368 *
369 * Invokes the deleter if this object owns a pointer.
370 */
371 unique_ptr& operator=(unique_ptr&&) = default;
372
373 /** @brief Assignment from another type.
374 *
375 * @param __u The object to transfer ownership from, which owns a
376 * convertible pointer to a non-array object.
377 *
378 * Invokes the deleter if this object owns a pointer.
379 */
380 template<typename _Up, typename _Ep>
381 typename enable_if< __and_<
382 __safe_conversion_up<_Up, _Ep>,
383 is_assignable<deleter_type&, _Ep&&>
384 >::value,
385 unique_ptr&>::type
386 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
387 {
388 reset(__u.release());
389 get_deleter() = std::forward<_Ep>(__u.get_deleter());
390 return *this;
391 }
392
393 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
394 unique_ptr&
395 operator=(nullptr_t) noexcept
396 {
397 reset();
398 return *this;
399 }
400
401 // Observers.
402
403 /// Dereference the stored pointer.
404 typename add_lvalue_reference<element_type>::type
405 operator*() const
406 {
407 __glibcxx_assert(get() != pointer());
408 return *get();
409 }
410
411 /// Return the stored pointer.
412 pointer
413 operator->() const noexcept
414 {
415 _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
416 return get();
417 }
418
419 /// Return the stored pointer.
420 pointer
421 get() const noexcept
422 { return _M_t._M_ptr(); }
423
424 /// Return a reference to the stored deleter.
425 deleter_type&
426 get_deleter() noexcept
427 { return _M_t._M_deleter(); }
428
429 /// Return a reference to the stored deleter.
430 const deleter_type&
431 get_deleter() const noexcept
432 { return _M_t._M_deleter(); }
433
434 /// Return @c true if the stored pointer is not null.
435 explicit operator bool() const noexcept
436 { return get() == pointer() ? false : true; }
8
Assuming pointer value is null
9
Assuming the condition is false
10
'?' condition is false
11
Returning the value 1, which participates in a condition later
437
438 // Modifiers.
439
440 /// Release ownership of any stored pointer.
441 pointer
442 release() noexcept
443 { return _M_t.release(); }
444
445 /** @brief Replace the stored pointer.
446 *
447 * @param __p The new pointer to store.
448 *
449 * The deleter will be invoked if a pointer is already owned.
450 */
451 void
452 reset(pointer __p = pointer()) noexcept
453 {
454 static_assert(__is_invocable<deleter_type&, pointer>::value,
455 "unique_ptr's deleter must be invocable with a pointer");
456 _M_t.reset(std::move(__p));
457 }
458
459 /// Exchange the pointer and deleter with another object.
460 void
461 swap(unique_ptr& __u) noexcept
462 {
463 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
464 _M_t.swap(__u._M_t);
465 }
466
467 // Disable copy from lvalue.
468 unique_ptr(const unique_ptr&) = delete;
469 unique_ptr& operator=(const unique_ptr&) = delete;
470 };
471
472 /// 20.7.1.3 unique_ptr for array objects with a runtime length
473 // [unique.ptr.runtime]
474 // _GLIBCXX_RESOLVE_LIB_DEFECTS
475 // DR 740 - omit specialization for array objects with a compile time length
476 template<typename _Tp, typename _Dp>
477 class unique_ptr<_Tp[], _Dp>
478 {
479 template <typename _Up>
480 using _DeleterConstraint =
481 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
482
483 __uniq_ptr_data<_Tp, _Dp> _M_t;
484
485 template<typename _Up>
486 using __remove_cv = typename remove_cv<_Up>::type;
487
488 // like is_base_of<_Tp, _Up> but false if unqualified types are the same
489 template<typename _Up>
490 using __is_derived_Tp
491 = __and_< is_base_of<_Tp, _Up>,
492 __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
493
494 public:
495 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
496 using element_type = _Tp;
497 using deleter_type = _Dp;
498
499 // helper template for detecting a safe conversion from another
500 // unique_ptr
501 template<typename _Up, typename _Ep,
502 typename _UPtr = unique_ptr<_Up, _Ep>,
503 typename _UP_pointer = typename _UPtr::pointer,
504 typename _UP_element_type = typename _UPtr::element_type>
505 using __safe_conversion_up = __and_<
506 is_array<_Up>,
507 is_same<pointer, element_type*>,
508 is_same<_UP_pointer, _UP_element_type*>,
509 is_convertible<_UP_element_type(*)[], element_type(*)[]>
510 >;
511
512 // helper template for detecting a safe conversion from a raw pointer
513 template<typename _Up>
514 using __safe_conversion_raw = __and_<
515 __or_<__or_<is_same<_Up, pointer>,
516 is_same<_Up, nullptr_t>>,
517 __and_<is_pointer<_Up>,
518 is_same<pointer, element_type*>,
519 is_convertible<
520 typename remove_pointer<_Up>::type(*)[],
521 element_type(*)[]>
522 >
523 >
524 >;
525
526 // Constructors.
527
528 /// Default constructor, creates a unique_ptr that owns nothing.
529 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
530 constexpr unique_ptr() noexcept
531 : _M_t()
532 { }
533
534 /** Takes ownership of a pointer.
535 *
536 * @param __p A pointer to an array of a type safely convertible
537 * to an array of @c element_type
538 *
539 * The deleter will be value-initialized.
540 */
541 template<typename _Up,
542 typename _Vp = _Dp,
543 typename = _DeleterConstraint<_Vp>,
544 typename = typename enable_if<
545 __safe_conversion_raw<_Up>::value, bool>::type>
546 explicit
547 unique_ptr(_Up __p) noexcept
548 : _M_t(__p)
549 { }
550
551 /** Takes ownership of a pointer.
552 *
553 * @param __p A pointer to an array of a type safely convertible
554 * to an array of @c element_type
555 * @param __d A reference to a deleter.
556 *
557 * The deleter will be initialized with @p __d
558 */
559 template<typename _Up, typename _Del = deleter_type,
560 typename = _Require<__safe_conversion_raw<_Up>,
561 is_copy_constructible<_Del>>>
562 unique_ptr(_Up __p, const deleter_type& __d) noexcept
563 : _M_t(__p, __d) { }
564
565 /** Takes ownership of a pointer.
566 *
567 * @param __p A pointer to an array of a type safely convertible
568 * to an array of @c element_type
569 * @param __d A reference to a deleter.
570 *
571 * The deleter will be initialized with @p std::move(__d)
572 */
573 template<typename _Up, typename _Del = deleter_type,
574 typename = _Require<__safe_conversion_raw<_Up>,
575 is_move_constructible<_Del>>>
576 unique_ptr(_Up __p,
577 __enable_if_t<!is_lvalue_reference<_Del>::value,
578 _Del&&> __d) noexcept
579 : _M_t(std::move(__p), std::move(__d))
580 { }
581
582 template<typename _Up, typename _Del = deleter_type,
583 typename _DelUnref = typename remove_reference<_Del>::type,
584 typename = _Require<__safe_conversion_raw<_Up>>>
585 unique_ptr(_Up,
586 __enable_if_t<is_lvalue_reference<_Del>::value,
587 _DelUnref&&>) = delete;
588
589 /// Move constructor.
590 unique_ptr(unique_ptr&&) = default;
591
592 /// Creates a unique_ptr that owns nothing.
593 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
594 constexpr unique_ptr(nullptr_t) noexcept
595 : _M_t()
596 { }
597
598 template<typename _Up, typename _Ep, typename = _Require<
599 __safe_conversion_up<_Up, _Ep>,
600 typename conditional<is_reference<_Dp>::value,
601 is_same<_Ep, _Dp>,
602 is_convertible<_Ep, _Dp>>::type>>
603 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
604 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
605 { }
606
607 /// Destructor, invokes the deleter if the stored pointer is not null.
608 ~unique_ptr()
609 {
610 auto& __ptr = _M_t._M_ptr();
611 if (__ptr != nullptr)
612 get_deleter()(__ptr);
613 __ptr = pointer();
614 }
615
616 // Assignment.
617
618 /** @brief Move assignment operator.
619 *
620 * Invokes the deleter if this object owns a pointer.
621 */
622 unique_ptr&
623 operator=(unique_ptr&&) = default;
624
625 /** @brief Assignment from another type.
626 *
627 * @param __u The object to transfer ownership from, which owns a
628 * convertible pointer to an array object.
629 *
630 * Invokes the deleter if this object owns a pointer.
631 */
632 template<typename _Up, typename _Ep>
633 typename
634 enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
635 is_assignable<deleter_type&, _Ep&&>
636 >::value,
637 unique_ptr&>::type
638 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
639 {
640 reset(__u.release());
641 get_deleter() = std::forward<_Ep>(__u.get_deleter());
642 return *this;
643 }
644
645 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
646 unique_ptr&
647 operator=(nullptr_t) noexcept
648 {
649 reset();
650 return *this;
651 }
652
653 // Observers.
654
655 /// Access an element of owned array.
656 typename std::add_lvalue_reference<element_type>::type
657 operator[](size_t __i) const
658 {
659 __glibcxx_assert(get() != pointer());
660 return get()[__i];
661 }
662
663 /// Return the stored pointer.
664 pointer
665 get() const noexcept
666 { return _M_t._M_ptr(); }
667
668 /// Return a reference to the stored deleter.
669 deleter_type&
670 get_deleter() noexcept
671 { return _M_t._M_deleter(); }
672
673 /// Return a reference to the stored deleter.
674 const deleter_type&
675 get_deleter() const noexcept
676 { return _M_t._M_deleter(); }
677
678 /// Return @c true if the stored pointer is not null.
679 explicit operator bool() const noexcept
680 { return get() == pointer() ? false : true; }
681
682 // Modifiers.
683
684 /// Release ownership of any stored pointer.
685 pointer
686 release() noexcept
687 { return _M_t.release(); }
688
689 /** @brief Replace the stored pointer.
690 *
691 * @param __p The new pointer to store.
692 *
693 * The deleter will be invoked if a pointer is already owned.
694 */
695 template <typename _Up,
696 typename = _Require<
697 __or_<is_same<_Up, pointer>,
698 __and_<is_same<pointer, element_type*>,
699 is_pointer<_Up>,
700 is_convertible<
701 typename remove_pointer<_Up>::type(*)[],
702 element_type(*)[]
703 >
704 >
705 >
706 >>
707 void
708 reset(_Up __p) noexcept
709 { _M_t.reset(std::move(__p)); }
710
711 void reset(nullptr_t = nullptr) noexcept
712 { reset(pointer()); }
713
714 /// Exchange the pointer and deleter with another object.
715 void
716 swap(unique_ptr& __u) noexcept
717 {
718 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
719 _M_t.swap(__u._M_t);
720 }
721
722 // Disable copy from lvalue.
723 unique_ptr(const unique_ptr&) = delete;
724 unique_ptr& operator=(const unique_ptr&) = delete;
725 };
726
727 /// @relates unique_ptr @{
728
729 /// Swap overload for unique_ptr
730 template<typename _Tp, typename _Dp>
731 inline
732#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
733 // Constrained free swap overload, see p0185r1
734 typename enable_if<__is_swappable<_Dp>::value>::type
735#else
736 void
737#endif
738 swap(unique_ptr<_Tp, _Dp>& __x,
739 unique_ptr<_Tp, _Dp>& __y) noexcept
740 { __x.swap(__y); }
741
742#if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
743 template<typename _Tp, typename _Dp>
744 typename enable_if<!__is_swappable<_Dp>::value>::type
745 swap(unique_ptr<_Tp, _Dp>&,
746 unique_ptr<_Tp, _Dp>&) = delete;
747#endif
748
749 /// Equality operator for unique_ptr objects, compares the owned pointers
750 template<typename _Tp, typename _Dp,
751 typename _Up, typename _Ep>
752 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
753 operator==(const unique_ptr<_Tp, _Dp>& __x,
754 const unique_ptr<_Up, _Ep>& __y)
755 { return __x.get() == __y.get(); }
756
757 /// unique_ptr comparison with nullptr
758 template<typename _Tp, typename _Dp>
759 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
760 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
761 { return !__x; }
762
763#ifndef __cpp_lib_three_way_comparison
764 /// unique_ptr comparison with nullptr
765 template<typename _Tp, typename _Dp>
766 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
767 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
768 { return !__x; }
769
770 /// Inequality operator for unique_ptr objects, compares the owned pointers
771 template<typename _Tp, typename _Dp,
772 typename _Up, typename _Ep>
773 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
774 operator!=(const unique_ptr<_Tp, _Dp>& __x,
775 const unique_ptr<_Up, _Ep>& __y)
776 { return __x.get() != __y.get(); }
777
778 /// unique_ptr comparison with nullptr
779 template<typename _Tp, typename _Dp>
780 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
781 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
782 { return (bool)__x; }
783
784 /// unique_ptr comparison with nullptr
785 template<typename _Tp, typename _Dp>
786 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
787 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
788 { return (bool)__x; }
789#endif // three way comparison
790
791 /// Relational operator for unique_ptr objects, compares the owned pointers
792 template<typename _Tp, typename _Dp,
793 typename _Up, typename _Ep>
794 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
795 operator<(const unique_ptr<_Tp, _Dp>& __x,
796 const unique_ptr<_Up, _Ep>& __y)
797 {
798 typedef typename
799 std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
800 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
801 return std::less<_CT>()(__x.get(), __y.get());
802 }
803
804 /// unique_ptr comparison with nullptr
805 template<typename _Tp, typename _Dp>
806 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
807 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
808 {
809 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
810 nullptr);
811 }
812
813 /// unique_ptr comparison with nullptr
814 template<typename _Tp, typename _Dp>
815 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
816 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
817 {
818 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
819 __x.get());
820 }
821
822 /// Relational operator for unique_ptr objects, compares the owned pointers
823 template<typename _Tp, typename _Dp,
824 typename _Up, typename _Ep>
825 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
826 operator<=(const unique_ptr<_Tp, _Dp>& __x,
827 const unique_ptr<_Up, _Ep>& __y)
828 { return !(__y < __x); }
829
830 /// unique_ptr comparison with nullptr
831 template<typename _Tp, typename _Dp>
832 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
833 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
834 { return !(nullptr < __x); }
835
836 /// unique_ptr comparison with nullptr
837 template<typename _Tp, typename _Dp>
838 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
839 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
840 { return !(__x < nullptr); }
841
842 /// Relational operator for unique_ptr objects, compares the owned pointers
843 template<typename _Tp, typename _Dp,
844 typename _Up, typename _Ep>
845 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
846 operator>(const unique_ptr<_Tp, _Dp>& __x,
847 const unique_ptr<_Up, _Ep>& __y)
848 { return (__y < __x); }
849
850 /// unique_ptr comparison with nullptr
851 template<typename _Tp, typename _Dp>
852 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
853 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
854 {
855 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
856 __x.get());
857 }
858
859 /// unique_ptr comparison with nullptr
860 template<typename _Tp, typename _Dp>
861 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
862 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
863 {
864 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
865 nullptr);
866 }
867
868 /// Relational operator for unique_ptr objects, compares the owned pointers
869 template<typename _Tp, typename _Dp,
870 typename _Up, typename _Ep>
871 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
872 operator>=(const unique_ptr<_Tp, _Dp>& __x,
873 const unique_ptr<_Up, _Ep>& __y)
874 { return !(__x < __y); }
875
876 /// unique_ptr comparison with nullptr
877 template<typename _Tp, typename _Dp>
878 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
879 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
880 { return !(__x < nullptr); }
881
882 /// unique_ptr comparison with nullptr
883 template<typename _Tp, typename _Dp>
884 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
885 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
886 { return !(nullptr < __x); }
887
888#ifdef __cpp_lib_three_way_comparison
889 template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
890 requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
891 typename unique_ptr<_Up, _Ep>::pointer>
892 inline
893 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
894 typename unique_ptr<_Up, _Ep>::pointer>
895 operator<=>(const unique_ptr<_Tp, _Dp>& __x,
896 const unique_ptr<_Up, _Ep>& __y)
897 { return compare_three_way()(__x.get(), __y.get()); }
898
899 template<typename _Tp, typename _Dp>
900 requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
901 inline
902 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
903 operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
904 {
905 using pointer = typename unique_ptr<_Tp, _Dp>::pointer;
906 return compare_three_way()(__x.get(), static_cast<pointer>(nullptr));
907 }
908#endif
909 // @} relates unique_ptr
910
911 /// @cond undocumented
912 template<typename _Up, typename _Ptr = typename _Up::pointer,
913 bool = __poison_hash<_Ptr>::__enable_hash_call>
914 struct __uniq_ptr_hash
915#if ! _GLIBCXX_INLINE_VERSION0
916 : private __poison_hash<_Ptr>
917#endif
918 {
919 size_t
920 operator()(const _Up& __u) const
921 noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
922 { return hash<_Ptr>()(__u.get()); }
923 };
924
925 template<typename _Up, typename _Ptr>
926 struct __uniq_ptr_hash<_Up, _Ptr, false>
927 : private __poison_hash<_Ptr>
928 { };
929 /// @endcond
930
931 /// std::hash specialization for unique_ptr.
932 template<typename _Tp, typename _Dp>
933 struct hash<unique_ptr<_Tp, _Dp>>
934 : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
935 public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>>
936 { };
937
938#if __cplusplus201703L >= 201402L
939 /// @relates unique_ptr @{
940#define __cpp_lib_make_unique201304 201304
941
942 /// @cond undocumented
943
944 template<typename _Tp>
945 struct _MakeUniq
946 { typedef unique_ptr<_Tp> __single_object; };
947
948 template<typename _Tp>
949 struct _MakeUniq<_Tp[]>
950 { typedef unique_ptr<_Tp[]> __array; };
951
952 template<typename _Tp, size_t _Bound>
953 struct _MakeUniq<_Tp[_Bound]>
954 { struct __invalid_type { }; };
955
956 /// @endcond
957
958 /// std::make_unique for single objects
959 template<typename _Tp, typename... _Args>
960 inline typename _MakeUniq<_Tp>::__single_object
961 make_unique(_Args&&... __args)
962 { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
963
964 /// std::make_unique for arrays of unknown bound
965 template<typename _Tp>
966 inline typename _MakeUniq<_Tp>::__array
967 make_unique(size_t __num)
968 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
969
970 /// Disable std::make_unique for arrays of known bound
971 template<typename _Tp, typename... _Args>
972 inline typename _MakeUniq<_Tp>::__invalid_type
973 make_unique(_Args&&...) = delete;
974 // @} relates unique_ptr
975#endif // C++14
976
977#if __cplusplus201703L > 201703L && __cpp_concepts
978 // _GLIBCXX_RESOLVE_LIB_DEFECTS
979 // 2948. unique_ptr does not define operator<< for stream output
980 /// Stream output operator for unique_ptr
981 template<typename _CharT, typename _Traits, typename _Tp, typename _Dp>
982 inline basic_ostream<_CharT, _Traits>&
983 operator<<(basic_ostream<_CharT, _Traits>& __os,
984 const unique_ptr<_Tp, _Dp>& __p)
985 requires requires { __os << __p.get(); }
986 {
987 __os << __p.get();
988 return __os;
989 }
990#endif // C++20
991
992 // @} group pointer_abstractions
993
994#if __cplusplus201703L >= 201703L
995 namespace __detail::__variant
996 {
997 template<typename> struct _Never_valueless_alt; // see <variant>
998
999 // Provide the strong exception-safety guarantee when emplacing a
1000 // unique_ptr into a variant.
1001 template<typename _Tp, typename _Del>
1002 struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>>
1003 : std::true_type
1004 { };
1005 } // namespace __detail::__variant
1006#endif // C++17
1007
1008_GLIBCXX_END_NAMESPACE_VERSION
1009} // namespace
1010
1011#endif /* _UNIQUE_PTR_H */

/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx

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_USTRING_HXX
21#define INCLUDED_RTL_USTRING_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <cstdlib>
28#include <limits>
29#include <new>
30#include <ostream>
31#include <utility>
32
33#if defined LIBO_INTERNAL_ONLY1
34#include <string_view>
35#include <type_traits>
36#endif
37
38#include "rtl/ustring.h"
39#include "rtl/string.hxx"
40#include "rtl/stringutils.hxx"
41#include "rtl/textenc.h"
42
43#ifdef LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
44#include "config_global.h"
45#include "rtl/stringconcat.hxx"
46#endif
47
48#ifdef RTL_STRING_UNITTEST
49extern bool rtl_string_unittest_invalid_conversion;
50#endif
51
52// The unittest uses slightly different code to help check that the proper
53// calls are made. The class is put into a different namespace to make
54// sure the compiler generates a different (if generating also non-inline)
55// copy of the function and does not merge them together. The class
56// is "brought" into the proper rtl namespace by a typedef below.
57#ifdef RTL_STRING_UNITTEST
58#define rtl rtlunittest
59#endif
60
61namespace rtl
62{
63
64class OUStringBuffer;
65
66#ifdef RTL_STRING_UNITTEST
67#undef rtl
68#endif
69
70#if defined LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
71/// @cond INTERNAL
72
73/**
74A wrapper dressing a string literal as a static-refcount rtl_uString.
75
76This class is not part of public API and is meant to be used only in LibreOffice code.
77@since LibreOffice 4.0
78*/
79template<std::size_t N> class SAL_WARN_UNUSED__attribute__((warn_unused)) OUStringLiteral {
80 static_assert(N != 0);
81 static_assert(N - 1 <= std::numeric_limits<sal_Int32>::max(), "literal too long");
82
83public:
84#if HAVE_CPP_CONSTEVAL0
85 consteval
86#else
87 constexpr
88#endif
89 OUStringLiteral(char16_t const (&literal)[N]) {
90 assertLayout();
91 assert(literal[N - 1] == '\0')(static_cast <bool> (literal[N - 1] == '\0') ? void (0)
: __assert_fail ("literal[N - 1] == '\\0'", "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 91, __extension__ __PRETTY_FUNCTION__))
;
92 //TODO: Use C++20 constexpr std::copy_n (P0202R3):
93 for (std::size_t i = 0; i != N; ++i) {
94 buffer[i] = literal[i];
95 }
96 }
97
98 constexpr sal_Int32 getLength() const { return length; }
99
100 constexpr sal_Unicode const * getStr() const SAL_RETURNS_NONNULL__attribute__((returns_nonnull)) { return buffer; }
101
102 constexpr operator std::u16string_view() const { return {buffer, sal_uInt32(length)}; }
103
104private:
105 static constexpr void assertLayout() {
106 // These static_asserts verifying the layout compatibility with rtl_uString cannot be class
107 // member declarations, as offsetof requires a complete type, so defer them to here:
108 static_assert(offsetof(OUStringLiteral, refCount)__builtin_offsetof(OUStringLiteral, refCount) == offsetof(rtl_uString, refCount)__builtin_offsetof(rtl_uString, refCount));
109 static_assert(std::is_same_v<decltype(refCount), decltype(rtl_uString::refCount)>);
110 static_assert(offsetof(OUStringLiteral, length)__builtin_offsetof(OUStringLiteral, length) == offsetof(rtl_uString, length)__builtin_offsetof(rtl_uString, length));
111 static_assert(std::is_same_v<decltype(length), decltype(rtl_uString::length)>);
112 static_assert(offsetof(OUStringLiteral, buffer)__builtin_offsetof(OUStringLiteral, buffer) == offsetof(rtl_uString, buffer)__builtin_offsetof(rtl_uString, buffer));
113 static_assert(
114 std::is_same_v<
115 std::remove_extent_t<decltype(buffer)>,
116 std::remove_extent_t<decltype(rtl_uString::buffer)>>);
117 }
118
119 // Same layout as rtl_uString (include/rtl/ustring.h):
120 oslInterlockedCount refCount = 0x40000000; // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
121 sal_Int32 length = N - 1;
122 sal_Unicode buffer[N] = {}; //TODO: drop initialization for C++20 (P1331R2)
123};
124
125#if defined RTL_STRING_UNITTEST
126namespace libreoffice_internal {
127template<std::size_t N> struct ExceptConstCharArrayDetector<OUStringLiteral<N>> {};
128template<std::size_t N> struct ExceptCharArrayDetector<OUStringLiteral<N>> {};
129}
130#endif
131
132/// @endcond
133#endif
134
135/* ======================================================================= */
136
137/**
138 This String class provides base functionality for C++ like Unicode
139 character array handling. The advantage of this class is that it
140 handles all the memory management for you - and it does it
141 more efficiently. If you assign a string to another string, the
142 data of both strings are shared (without any copy operation or
143 memory allocation) as long as you do not change the string. This class
144 also stores the length of the string, so that many operations are
145 faster than the C-str-functions.
146
147 This class provides only readonly string handling. So you could create
148 a string and you could only query the content from this string.
149 It provides also functionality to change the string, but this results
150 in every case in a new string instance (in the most cases with a
151 memory allocation). You don't have functionality to change the
152 content of the string. If you want to change the string content, then
153 you should use the OStringBuffer class, which provides these
154 functionalities and avoids too much memory allocation.
155
156 The design of this class is similar to the string classes in Java so
157 less people should have understanding problems when they use this class.
158*/
159
160class SAL_WARN_UNUSED__attribute__((warn_unused)) SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) OUString
161{
162public:
163 /// @cond INTERNAL
164 rtl_uString * pData;
165 /// @endcond
166
167 /**
168 New string containing no characters.
169 */
170 OUString()
171 {
172 pData = NULL__null;
173 rtl_uString_new( &pData );
174 }
175
176 /**
177 New string from OUString.
178
179 @param str an OUString.
180 */
181 OUString( const OUString & str )
182 {
183 pData = str.pData;
184 rtl_uString_acquire( pData );
185 }
186
187#if defined LIBO_INTERNAL_ONLY1
188 /**
189 Move constructor.
190
191 @param str an OUString.
192 @since LibreOffice 5.2
193 */
194 OUString( OUString && str ) noexcept
195 {
196 pData = str.pData;
197 str.pData = nullptr;
198 rtl_uString_new( &str.pData );
199 }
200#endif
201
202 /**
203 New string from OUString data.
204
205 @param str an OUString data.
206 */
207 OUString( rtl_uString * str )
208 {
209 pData = str;
210 rtl_uString_acquire( pData );
211 }
212
213 /** New OUString from OUString data without acquiring it. Takeover of ownership.
214
215 The SAL_NO_ACQUIRE dummy parameter is only there to distinguish this
216 from other constructors.
217
218 @param str
219 OUString data
220 */
221 OUString( rtl_uString * str, __sal_NoAcquire )
222 { pData = str; }
223
224 /**
225 New string from a single Unicode character.
226
227 @param value a Unicode character.
228 */
229 explicit OUString( sal_Unicode value )
230 : pData (NULL__null)
231 {
232 rtl_uString_newFromStr_WithLength( &pData, &value, 1 );
233 }
234
235#if defined LIBO_INTERNAL_ONLY1 && !defined RTL_STRING_UNITTEST_CONCAT
236 /// @cond INTERNAL
237 // Catch inadvertent conversions to the above ctor (but still allow
238 // construction from char literals):
239 OUString(int) = delete;
240 explicit OUString(char c):
241 OUString(sal_Unicode(static_cast<unsigned char>(c)))
242 {}
243 /// @endcond
244#endif
245
246#if defined LIBO_INTERNAL_ONLY1
247
248 template<typename T> explicit OUString(
249 T const & value,
250 typename libreoffice_internal::CharPtrDetector<T, libreoffice_internal::Dummy>::TypeUtf16
251 = libreoffice_internal::Dummy()):
252 pData(nullptr)
253 { rtl_uString_newFromStr(&pData, value); }
254
255 template<typename T> explicit OUString(
256 T & value,
257 typename
258 libreoffice_internal::NonConstCharArrayDetector<T, libreoffice_internal::Dummy>::TypeUtf16
259 = libreoffice_internal::Dummy()):
260 pData(nullptr)
261 { rtl_uString_newFromStr(&pData, value); }
262
263#else
264
265 /**
266 New string from a Unicode character buffer array.
267
268 @param value a NULL-terminated Unicode character array.
269 */
270 OUString( const sal_Unicode * value )
271 {
272 pData = NULL__null;
273 rtl_uString_newFromStr( &pData, value );
274 }
275
276#endif
277
278 /**
279 New string from a Unicode character buffer array.
280
281 @param value a Unicode character array.
282 @param length the number of character which should be copied.
283 The character array length must be greater than
284 or equal to this value.
285 */
286 OUString( const sal_Unicode * value, sal_Int32 length )
287 {
288 pData = NULL__null;
289 rtl_uString_newFromStr_WithLength( &pData, value, length );
290 }
291
292 /**
293 New string from an 8-Bit string literal that is expected to contain only
294 characters in the ASCII set (i.e. first 128 characters). This constructor
295 allows an efficient and convenient way to create OUString
296 instances from ASCII literals. When creating strings from data that
297 is not pure ASCII, it needs to be converted to OUString by explicitly
298 providing the encoding to use for the conversion.
299
300 If there are any embedded \0's in the string literal, the result is undefined.
301 Use the overload that explicitly accepts length.
302
303 @param literal the 8-bit ASCII string literal
304
305 @since LibreOffice 3.6
306 */
307 template< typename T >
308 OUString( T& literal, typename libreoffice_internal::ConstCharArrayDetector< T, libreoffice_internal::Dummy >::Type = libreoffice_internal::Dummy() )
309 {
310 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 311, __extension__ __PRETTY_FUNCTION__))
311 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 311, __extension__ __PRETTY_FUNCTION__))
;
312 pData = NULL__null;
313 if (libreoffice_internal::ConstCharArrayDetector<T>::length == 0) {
314 rtl_uString_new(&pData);
315 } else {
316 rtl_uString_newFromLiteral(
317 &pData,
318 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
319 literal),
320 libreoffice_internal::ConstCharArrayDetector<T>::length, 0);
321 }
322#ifdef RTL_STRING_UNITTEST
323 rtl_string_unittest_const_literal = true;
324#endif
325 }
326
327#if defined LIBO_INTERNAL_ONLY1
328 /** @overload @since LibreOffice 5.3 */
329 template<typename T> OUString(
330 T & literal,
331 typename libreoffice_internal::ConstCharArrayDetector<
332 T, libreoffice_internal::Dummy>::TypeUtf16
333 = libreoffice_internal::Dummy()):
334 pData(nullptr)
335 {
336 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 337, __extension__ __PRETTY_FUNCTION__))
337 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 337, __extension__ __PRETTY_FUNCTION__))
;
338 if (libreoffice_internal::ConstCharArrayDetector<T>::length == 0) {
339 rtl_uString_new(&pData);
340 } else {
341 rtl_uString_newFromStr_WithLength(
342 &pData,
343 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
344 literal),
345 libreoffice_internal::ConstCharArrayDetector<T>::length);
346 }
347 }
348#endif
349
350#if defined LIBO_INTERNAL_ONLY1 && defined RTL_STRING_UNITTEST
351 /// @cond INTERNAL
352 /**
353 * Only used by unittests to detect incorrect conversions.
354 * @internal
355 */
356 template< typename T >
357 OUString( T&, typename libreoffice_internal::ExceptConstCharArrayDetector< T >::Type = libreoffice_internal::Dummy() )
358 {
359 pData = NULL__null;
360 rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
361 rtl_string_unittest_invalid_conversion = true;
362 }
363 /**
364 * Only used by unittests to detect incorrect conversions.
365 * @internal
366 */
367 template< typename T >
368 OUString( const T&, typename libreoffice_internal::ExceptCharArrayDetector< T >::Type = libreoffice_internal::Dummy() )
369 {
370 pData = NULL__null;
371 rtl_uString_newFromLiteral( &pData, "!!br0ken!!", 10, 0 ); // set to garbage
372 rtl_string_unittest_invalid_conversion = true;
373 }
374 /// @endcond
375#endif
376
377#ifdef LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
378 /// @cond INTERNAL
379 /**
380 New string from a string literal.
381
382 @since LibreOffice 5.0
383 */
384 template<std::size_t N> OUString(OUStringLiteral<N> const & literal):
385 pData(const_cast<rtl_uString *>(reinterpret_cast<rtl_uString const *>(&literal))) {}
386 template<std::size_t N> OUString(OUStringLiteral<N> &&) = delete;
387 /// @endcond
388#endif
389
390 /**
391 New string from an 8-Bit character buffer array.
392
393 @param value An 8-Bit character array.
394 @param length The number of character which should be converted.
395 The 8-Bit character array length must be
396 greater than or equal to this value.
397 @param encoding The text encoding from which the 8-Bit character
398 sequence should be converted.
399 @param convertFlags Flags which control the conversion.
400 see RTL_TEXTTOUNICODE_FLAGS_...
401
402 @exception std::bad_alloc is thrown if an out-of-memory condition occurs
403 */
404 OUString( const char * value, sal_Int32 length,
405 rtl_TextEncoding encoding,
406 sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS(((sal_uInt32)0x0003) | ((sal_uInt32)0x0030) | ((sal_uInt32)0x0300
))
)
407 {
408 pData = NULL__null;
409 rtl_string2UString( &pData, value, length, encoding, convertFlags );
410 if (pData == NULL__null) {
411 throw std::bad_alloc();
412 }
413 }
414
415 /** Create a new string from an array of Unicode code points.
416
417 @param codePoints
418 an array of at least codePointCount code points, which each must be in
419 the range from 0 to 0x10FFFF, inclusive. May be null if codePointCount
420 is zero.
421
422 @param codePointCount
423 the non-negative number of code points.
424
425 @exception std::bad_alloc
426 is thrown if either an out-of-memory condition occurs or the resulting
427 number of UTF-16 code units would have been larger than SAL_MAX_INT32.
428
429 @since UDK 3.2.7
430 */
431 explicit OUString(
432 sal_uInt32 const * codePoints, sal_Int32 codePointCount):
433 pData(NULL__null)
434 {
435 rtl_uString_newFromCodePoints(&pData, codePoints, codePointCount);
436 if (pData == NULL__null) {
437 throw std::bad_alloc();
438 }
439 }
440
441#ifdef LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
442 /**
443 @overload
444 @internal
445 */
446 template< typename T1, typename T2 >
447 OUString( OUStringConcat< T1, T2 >&& c )
448 {
449 const sal_Int32 l = c.length();
450 pData = rtl_uString_alloc( l );
451 if (l != 0)
452 {
453 sal_Unicode* end = c.addData( pData->buffer );
454 pData->length = l;
455 *end = '\0';
456 // TODO realloc in case pData->length is noticeably smaller than l?
457 }
458 }
459
460 /**
461 @overload
462 @internal
463 */
464 template< typename T >
465 OUString( OUStringNumber< T >&& n )
466 : OUString( n.buf, n.length )
467 {}
468#endif
469
470#if defined LIBO_INTERNAL_ONLY1
471 OUString(std::u16string_view sv) {
472 if (sv.size() > sal_uInt32(std::numeric_limits<sal_Int32>::max())) {
473 throw std::bad_alloc();
474 }
475 pData = nullptr;
476 rtl_uString_newFromStr_WithLength(&pData, sv.data(), sv.size());
477 }
478#endif
479
480 /**
481 Release the string data.
482 */
483 ~OUString()
484 {
485 rtl_uString_release( pData );
486 }
487
488 /** Provides an OUString const & passing a storage pointer of an
489 rtl_uString * handle.
490 It is more convenient to use C++ OUString member functions when dealing
491 with rtl_uString * handles. Using this function avoids unnecessary
492 acquire()/release() calls for a temporary OUString object.
493
494 @param ppHandle
495 pointer to storage
496 @return
497 OUString const & based on given storage
498 */
499 static OUString const & unacquired( rtl_uString * const * ppHandle )
500 { return * reinterpret_cast< OUString const * >( ppHandle ); }
501
502 /**
503 Assign a new string.
504
505 @param str an OUString.
506 */
507 OUString & operator=( const OUString & str )
508 {
509 rtl_uString_assign( &pData, str.pData );
510 return *this;
511 }
512
513#if defined LIBO_INTERNAL_ONLY1
514 /**
515 Move assign a new string.
516
517 @param str an OUString.
518 @since LibreOffice 5.2
519 */
520 OUString & operator=( OUString && str ) noexcept
521 {
522 rtl_uString_release( pData );
523 pData = str.pData;
524 str.pData = nullptr;
525 rtl_uString_new( &str.pData );
526 return *this;
527 }
528#endif
529
530 /**
531 Assign a new string from an 8-Bit string literal that is expected to contain only
532 characters in the ASCII set (i.e. first 128 characters). This operator
533 allows an efficient and convenient way to assign OUString
534 instances from ASCII literals. When assigning strings from data that
535 is not pure ASCII, it needs to be converted to OUString by explicitly
536 providing the encoding to use for the conversion.
537
538 @param literal the 8-bit ASCII string literal
539
540 @since LibreOffice 3.6
541 */
542 template< typename T >
543 typename libreoffice_internal::ConstCharArrayDetector< T, OUString& >::Type operator=( T& literal )
544 {
545 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 546, __extension__ __PRETTY_FUNCTION__))
546 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 546, __extension__ __PRETTY_FUNCTION__))
;
547 if (libreoffice_internal::ConstCharArrayDetector<T>::length == 0) {
548 rtl_uString_new(&pData);
549 } else {
550 rtl_uString_newFromLiteral(
551 &pData,
552 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
553 literal),
554 libreoffice_internal::ConstCharArrayDetector<T>::length, 0);
555 }
556 return *this;
557 }
558
559#if defined LIBO_INTERNAL_ONLY1
560 /** @overload @since LibreOffice 5.3 */
561 template<typename T>
562 typename
563 libreoffice_internal::ConstCharArrayDetector<T, OUString &>::TypeUtf16
564 operator =(T & literal) {
565 if (libreoffice_internal::ConstCharArrayDetector<T>::length == 0) {
566 rtl_uString_new(&pData);
567 } else {
568 rtl_uString_newFromStr_WithLength(
569 &pData,
570 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
571 literal),
572 libreoffice_internal::ConstCharArrayDetector<T>::length);
573 }
574 return *this;
575 }
576
577 /** @overload @since LibreOffice 5.4 */
578 template<std::size_t N> OUString & operator =(OUStringLiteral<N> const & literal) {
579 if (literal.getLength() == 0) {
580 rtl_uString_new(&pData);
581 } else {
582 rtl_uString_newFromStr_WithLength(&pData, literal.getStr(), literal.getLength());
583 }
584 return *this;
585 }
586
587 template<typename T>
588 OUString & operator =(OUStringNumber<T> && n) {
589 // n.length should never be zero, so no need to add an optimization for that case
590 rtl_uString_newFromStr_WithLength(&pData, n.buf, n.length);
591 return *this;
592 }
593
594 OUString & operator =(std::u16string_view sv) {
595 if (sv.empty()) {
596 rtl_uString_new(&pData);
597 } else {
598 rtl_uString_newFromStr_WithLength(&pData, sv.data(), sv.size());
599 }
600 return *this;
601 }
602#endif
603
604#if defined LIBO_INTERNAL_ONLY1
605 /**
606 Append the contents of an OUStringBuffer to this string.
607
608 @param str an OUStringBuffer.
609
610 @exception std::bad_alloc is thrown if an out-of-memory condition occurs
611 @since LibreOffice 6.2
612 */
613 inline OUString & operator+=( const OUStringBuffer & str ) &;
614#endif
615
616 /**
617 Append a string to this string.
618
619 @param str an OUString.
620
621 @exception std::bad_alloc is thrown if an out-of-memory condition occurs
622 */
623 OUString & operator+=( const OUString & str )
624#if defined LIBO_INTERNAL_ONLY1
625 &
626#endif
627 {
628 return internalAppend(str.pData);
629 }
630#if defined LIBO_INTERNAL_ONLY1
631 void operator+=(OUString const &) && = delete;
632#endif
633
634 /** Append an ASCII string literal to this string.
635
636 @param literal an 8-bit ASCII-only string literal
637
638 @since LibreOffice 5.1
639 */
640 template<typename T>
641 typename libreoffice_internal::ConstCharArrayDetector<T, OUString &>::Type
642 operator +=(T & literal)
643#if defined LIBO_INTERNAL_ONLY1
644 &
645#endif
646 {
647 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 648, __extension__ __PRETTY_FUNCTION__))
648 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 648, __extension__ __PRETTY_FUNCTION__))
;
649 rtl_uString_newConcatAsciiL(
650 &pData, pData,
651 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
652 libreoffice_internal::ConstCharArrayDetector<T>::length);
653 return *this;
654 }
655#if defined LIBO_INTERNAL_ONLY1
656 template<typename T>
657 typename libreoffice_internal::ConstCharArrayDetector<T, OUString &>::Type
658 operator +=(T &) && = delete;
659#endif
660
661#if defined LIBO_INTERNAL_ONLY1
662 /** @overload @since LibreOffice 5.3 */
663 template<typename T>
664 typename
665 libreoffice_internal::ConstCharArrayDetector<T, OUString &>::TypeUtf16
666 operator +=(T & literal) & {
667 rtl_uString_newConcatUtf16L(
668 &pData, pData,
669 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
670 libreoffice_internal::ConstCharArrayDetector<T>::length);
671 return *this;
672 }
673 template<typename T>
674 typename
675 libreoffice_internal::ConstCharArrayDetector<T, OUString &>::TypeUtf16
676 operator +=(T &) && = delete;
677
678 /** @overload @since LibreOffice 5.4 */
679 template<std::size_t N> OUString & operator +=(OUStringLiteral<N> const & literal) & {
680 rtl_uString_newConcatUtf16L(&pData, pData, literal.getStr(), literal.getLength());
681 return *this;
682 }
683 template<std::size_t N> void operator +=(OUStringLiteral<N> const &) && = delete;
684
685 OUString & operator +=(std::u16string_view sv) & {
686 if (sv.size() > sal_uInt32(std::numeric_limits<sal_Int32>::max())) {
687 throw std::bad_alloc();
688 }
689 rtl_uString_newConcatUtf16L(&pData, pData, sv.data(), sv.size());
690 return *this;
691 }
692 void operator +=(std::u16string_view) && = delete;
693#endif
694
695#ifdef LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
696 /**
697 @overload
698 @internal
699 */
700 template< typename T1, typename T2 >
701 OUString& operator+=( OUStringConcat< T1, T2 >&& c ) & {
702 sal_Int32 l = c.length();
703 if( l == 0 )
704 return *this;
705 l += pData->length;
706 rtl_uString_ensureCapacity( &pData, l );
707 sal_Unicode* end = c.addData( pData->buffer + pData->length );
708 *end = '\0';
709 pData->length = l;
710 return *this;
711 }
712 template<typename T1, typename T2> void operator +=(
713 OUStringConcat<T1, T2> &&) && = delete;
714
715 /**
716 @overload
717 @internal
718 */
719 template< typename T >
720 OUString& operator+=( OUStringNumber< T >&& n ) & {
721 sal_Int32 l = n.length;
722 if( l == 0 )
723 return *this;
724 l += pData->length;
725 rtl_uString_ensureCapacity( &pData, l );
726 sal_Unicode* end = addDataHelper( pData->buffer + pData->length, n.buf, n.length );
727 *end = '\0';
728 pData->length = l;
729 return *this;
730 }
731 template<typename T> void operator +=(
732 OUStringNumber<T> &&) && = delete;
733#endif
734
735 /**
736 Clears the string, i.e, makes a zero-character string
737 @since LibreOffice 4.4
738 */
739 void clear()
740 {
741 rtl_uString_new( &pData );
742 }
743
744 /**
745 Returns the length of this string.
746
747 The length is equal to the number of Unicode characters in this string.
748
749 @return the length of the sequence of characters represented by this
750 object.
751 */
752 sal_Int32 getLength() const { return pData->length; }
753
754 /**
755 Checks if a string is empty.
756
757 @return true if the string is empty;
758 false, otherwise.
759
760 @since LibreOffice 3.4
761 */
762 bool isEmpty() const
763 {
764 return pData->length == 0;
765 }
766
767 /**
768 Returns a pointer to the Unicode character buffer for this string.
769
770 It isn't necessarily NULL terminated.
771
772 @return a pointer to the Unicode characters buffer for this object.
773 */
774 const sal_Unicode * getStr() const SAL_RETURNS_NONNULL__attribute__((returns_nonnull)) { return pData->buffer; }
775
776 /**
777 Access to individual characters.
778
779 @param index must be non-negative and less than length.
780
781 @return the character at the given index.
782
783 @since LibreOffice 3.5
784 */
785 sal_Unicode operator [](sal_Int32 index) const {
786 // silence spurious -Werror=strict-overflow warnings from GCC 4.8.2
787 assert(index >= 0 && static_cast<sal_uInt32>(index) < static_cast<sal_uInt32>(getLength()))(static_cast <bool> (index >= 0 && static_cast
<sal_uInt32>(index) < static_cast<sal_uInt32>(
getLength())) ? void (0) : __assert_fail ("index >= 0 && static_cast<sal_uInt32>(index) < static_cast<sal_uInt32>(getLength())"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 787, __extension__ __PRETTY_FUNCTION__))
;
788 return getStr()[index];
789 }
790
791 /**
792 Compares two strings.
793
794 The comparison is based on the numeric value of each character in
795 the strings and return a value indicating their relationship.
796 This function can't be used for language specific sorting.
797
798 @param str the object to be compared.
799 @return 0 - if both strings are equal
800 < 0 - if this string is less than the string argument
801 > 0 - if this string is greater than the string argument
802 */
803 sal_Int32 compareTo( const OUString & str ) const
804 {
805 return rtl_ustr_compare_WithLength( pData->buffer, pData->length,
806 str.pData->buffer, str.pData->length );
807 }
808
809 /**
810 Compares two strings with a maximum count of characters.
811
812 The comparison is based on the numeric value of each character in
813 the strings and return a value indicating their relationship.
814 This function can't be used for language specific sorting.
815
816 @param str the object to be compared.
817 @param maxLength the maximum count of characters to be compared.
818 @return 0 - if both strings are equal
819 < 0 - if this string is less than the string argument
820 > 0 - if this string is greater than the string argument
821
822 @since UDK 3.2.7
823 */
824 sal_Int32 compareTo( const OUString & str, sal_Int32 maxLength ) const
825 {
826 return rtl_ustr_shortenedCompare_WithLength( pData->buffer, pData->length,
827 str.pData->buffer, str.pData->length, maxLength );
828 }
829
830 /**
831 Compares two strings in reverse order.
832
833 The comparison is based on the numeric value of each character in
834 the strings and return a value indicating their relationship.
835 This function can't be used for language specific sorting.
836
837 @param str the object to be compared.
838 @return 0 - if both strings are equal
839 < 0 - if this string is less than the string argument
840 > 0 - if this string is greater than the string argument
841 */
842#if defined LIBO_INTERNAL_ONLY1
843 sal_Int32 reverseCompareTo(std::u16string_view sv) const {
844 return rtl_ustr_reverseCompare_WithLength(
845 pData->buffer, pData->length, sv.data(), sv.size());
846 }
847#else
848 sal_Int32 reverseCompareTo( const OUString & str ) const
849 {
850 return rtl_ustr_reverseCompare_WithLength( pData->buffer, pData->length,
851 str.pData->buffer, str.pData->length );
852 }
853#endif
854
855 /**
856 @overload
857 This function accepts an ASCII string literal as its argument.
858 @since LibreOffice 4.1
859 */
860 template< typename T >
861 typename libreoffice_internal::ConstCharArrayDetector< T, sal_Int32 >::Type reverseCompareTo( T& literal ) const
862 {
863 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 864, __extension__ __PRETTY_FUNCTION__))
864 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 864, __extension__ __PRETTY_FUNCTION__))
;
865 return rtl_ustr_asciil_reverseCompare_WithLength(
866 pData->buffer, pData->length,
867 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
868 libreoffice_internal::ConstCharArrayDetector<T>::length);
869 }
870
871 /**
872 Perform a comparison of two strings.
873
874 The result is true if and only if second string
875 represents the same sequence of characters as the first string.
876 This function can't be used for language specific comparison.
877
878 @param str the object to be compared.
879 @return true if the strings are equal;
880 false, otherwise.
881 */
882 bool equals( const OUString & str ) const
883 {
884 if ( pData->length != str.pData->length )
16
Assuming 'pData->length' is equal to 'str.pData->length'
17
Taking false branch
27
Assuming 'pData->length' is equal to 'str.pData->length'
28
Taking false branch
38
Assuming 'pData->length' is equal to 'str.pData->length'
39
Taking false branch
885 return false;
886 if ( pData == str.pData )
18
Assuming 'pData' is not equal to 'str.pData'
19
Taking false branch
29
Assuming 'pData' is not equal to 'str.pData'
30
Taking false branch
40
Assuming 'pData' is equal to 'str.pData'
41
Taking true branch
887 return true;
42
Returning the value 1, which participates in a condition later
888 return rtl_ustr_reverseCompare_WithLength( pData->buffer, pData->length,
20
Assuming the condition is true
21
Returning the value 1, which participates in a condition later
31
Assuming the condition is true
32
Returning the value 1, which participates in a condition later
889 str.pData->buffer, str.pData->length ) == 0;
890 }
891
892 /**
893 Perform an ASCII lowercase comparison of two strings.
894
895 The result is true if and only if second string
896 represents the same sequence of characters as the first string,
897 ignoring the case.
898 Character values between 65 and 90 (ASCII A-Z) are interpreted as
899 values between 97 and 122 (ASCII a-z).
900 This function can't be used for language specific comparison.
901
902 @param str the object to be compared.
903 @return true if the strings are equal;
904 false, otherwise.
905 */
906#if defined LIBO_INTERNAL_ONLY1
907 bool equalsIgnoreAsciiCase(std::u16string_view sv) const {
908 return
909 rtl_ustr_compareIgnoreAsciiCase_WithLength(
910 pData->buffer, pData->length, sv.data(), sv.size())
911 == 0;
912 }
913#else
914 bool equalsIgnoreAsciiCase( const OUString & str ) const
915 {
916 if ( pData->length != str.pData->length )
917 return false;
918 if ( pData == str.pData )
919 return true;
920 return rtl_ustr_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length,
921 str.pData->buffer, str.pData->length ) == 0;
922 }
923#endif
924
925 /**
926 Perform an ASCII lowercase comparison of two strings.
927
928 Compare the two strings with uppercase ASCII
929 character values between 65 and 90 (ASCII A-Z) interpreted as
930 values between 97 and 122 (ASCII a-z).
931 This function can't be used for language specific comparison.
932
933 @param str the object to be compared.
934 @return 0 - if both strings are equal
935 < 0 - if this string is less than the string argument
936 > 0 - if this string is greater than the string argument
937
938 @since LibreOffice 4.0
939 */
940#if defined LIBO_INTERNAL_ONLY1
941 sal_Int32 compareToIgnoreAsciiCase(std::u16string_view sv) const {
942 return rtl_ustr_compareIgnoreAsciiCase_WithLength(
943 pData->buffer, pData->length, sv.data(), sv.size());
944 }
945#else
946 sal_Int32 compareToIgnoreAsciiCase( const OUString & str ) const
947 {
948 return rtl_ustr_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length,
949 str.pData->buffer, str.pData->length );
950 }
951#endif
952
953 /**
954 @overload
955 This function accepts an ASCII string literal as its argument.
956 @since LibreOffice 3.6
957 */
958 template< typename T >
959 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type equalsIgnoreAsciiCase( T& literal ) const
960 {
961 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 962, __extension__ __PRETTY_FUNCTION__))
962 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 962, __extension__ __PRETTY_FUNCTION__))
;
963 return
964 (pData->length
965 == libreoffice_internal::ConstCharArrayDetector<T>::length)
966 && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength(
967 pData->buffer, pData->length,
968 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
969 literal))
970 == 0);
971 }
972
973 /**
974 Match against a substring appearing in this string.
975
976 The result is true if and only if the second string appears as a substring
977 of this string, at the given position.
978 This function can't be used for language specific comparison.
979
980 @param str the object (substring) to be compared.
981 @param fromIndex the index to start the comparison from.
982 The index must be greater than or equal to 0
983 and less or equal as the string length.
984 @return true if str match with the characters in the string
985 at the given position;
986 false, otherwise.
987 */
988#if defined LIBO_INTERNAL_ONLY1
989 bool match(std::u16string_view sv, sal_Int32 fromIndex = 0) const {
990 return
991 rtl_ustr_shortenedCompare_WithLength(
992 pData->buffer + fromIndex, pData->length - fromIndex, sv.data(), sv.size(),
993 sv.size())
994 == 0;
995 }
996#else
997 bool match( const OUString & str, sal_Int32 fromIndex = 0 ) const
998 {
999 return rtl_ustr_shortenedCompare_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1000 str.pData->buffer, str.pData->length, str.pData->length ) == 0;
1001 }
1002#endif
1003
1004 /**
1005 @overload
1006 This function accepts an ASCII string literal as its argument.
1007 @since LibreOffice 3.6
1008 */
1009 template< typename T >
1010 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type match( T& literal, sal_Int32 fromIndex = 0 ) const
1011 {
1012 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1013, __extension__ __PRETTY_FUNCTION__))
1013 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1013, __extension__ __PRETTY_FUNCTION__))
;
1014 return
1015 rtl_ustr_ascii_shortenedCompare_WithLength(
1016 pData->buffer+fromIndex, pData->length-fromIndex,
1017 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1018 literal),
1019 libreoffice_internal::ConstCharArrayDetector<T>::length)
1020 == 0;
1021 }
1022
1023 /**
1024 Match against a substring appearing in this string, ignoring the case of
1025 ASCII letters.
1026
1027 The result is true if and only if the second string appears as a substring
1028 of this string, at the given position.
1029 Character values between 65 and 90 (ASCII A-Z) are interpreted as
1030 values between 97 and 122 (ASCII a-z).
1031 This function can't be used for language specific comparison.
1032
1033 @param str the object (substring) to be compared.
1034 @param fromIndex the index to start the comparison from.
1035 The index must be greater than or equal to 0
1036 and less than or equal to the string length.
1037 @return true if str match with the characters in the string
1038 at the given position;
1039 false, otherwise.
1040 */
1041#if defined LIBO_INTERNAL_ONLY1
1042 bool matchIgnoreAsciiCase(std::u16string_view sv, sal_Int32 fromIndex = 0) const {
1043 return
1044 rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength(
1045 pData->buffer + fromIndex, pData->length - fromIndex, sv.data(), sv.size(),
1046 sv.size())
1047 == 0;
1048 }
1049#else
1050 bool matchIgnoreAsciiCase( const OUString & str, sal_Int32 fromIndex = 0 ) const
1051 {
1052 return rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1053 str.pData->buffer, str.pData->length,
1054 str.pData->length ) == 0;
1055 }
1056#endif
1057
1058 /**
1059 @overload
1060 This function accepts an ASCII string literal as its argument.
1061 @since LibreOffice 3.6
1062 */
1063 template< typename T >
1064 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type matchIgnoreAsciiCase( T& literal, sal_Int32 fromIndex = 0 ) const
1065 {
1066 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1067, __extension__ __PRETTY_FUNCTION__))
1067 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1067, __extension__ __PRETTY_FUNCTION__))
;
1068 return
1069 rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
1070 pData->buffer+fromIndex, pData->length-fromIndex,
1071 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1072 literal),
1073 libreoffice_internal::ConstCharArrayDetector<T>::length)
1074 == 0;
1075 }
1076
1077 /**
1078 Compares two strings.
1079
1080 The comparison is based on the numeric value of each character in
1081 the strings and return a value indicating their relationship.
1082 Since this method is optimized for performance, the ASCII character
1083 values are not converted in any way. The caller has to make sure that
1084 all ASCII characters are in the allowed range between 0 and 127.
1085 The ASCII string must be NULL-terminated.
1086 This function can't be used for language specific sorting.
1087
1088 @param asciiStr the 8-Bit ASCII character string to be compared.
1089 @return 0 - if both strings are equal
1090 < 0 - if this string is less than the string argument
1091 > 0 - if this string is greater than the string argument
1092 */
1093 sal_Int32 compareToAscii( const char* asciiStr ) const
1094 {
1095 return rtl_ustr_ascii_compare_WithLength( pData->buffer, pData->length, asciiStr );
1096 }
1097
1098 /**
1099 Compares two strings with a maximum count of characters.
1100
1101 The comparison is based on the numeric value of each character in
1102 the strings and return a value indicating their relationship.
1103 Since this method is optimized for performance, the ASCII character
1104 values are not converted in any way. The caller has to make sure that
1105 all ASCII characters are in the allowed range between 0 and 127.
1106 The ASCII string must be NULL-terminated.
1107 This function can't be used for language specific sorting.
1108
1109 @deprecated This is a confusing overload with unexpectedly different
1110 semantics from the one-parameter form, so it is marked as deprecated.
1111 Practically all uses compare the return value against zero and can thus
1112 be replaced with uses of startsWith.
1113
1114 @param asciiStr the 8-Bit ASCII character string to be compared.
1115 @param maxLength the maximum count of characters to be compared.
1116 @return 0 - if both strings are equal
1117 < 0 - if this string is less than the string argument
1118 > 0 - if this string is greater than the string argument
1119 */
1120 SAL_DEPRECATED(__attribute__((deprecated("replace s1.compareToAscii(s2, strlen(s2)) == 0 with s1.startsWith(s2)"
)))
1121 "replace s1.compareToAscii(s2, strlen(s2)) == 0 with s1.startsWith(s2)")__attribute__((deprecated("replace s1.compareToAscii(s2, strlen(s2)) == 0 with s1.startsWith(s2)"
)))
1122 sal_Int32 compareToAscii( const char * asciiStr, sal_Int32 maxLength ) const
1123 {
1124 return rtl_ustr_ascii_shortenedCompare_WithLength( pData->buffer, pData->length,
1125 asciiStr, maxLength );
1126 }
1127
1128 /**
1129 Compares two strings in reverse order.
1130
1131 This could be useful, if normally both strings start with the same
1132 content. The comparison is based on the numeric value of each character
1133 in the strings and return a value indicating their relationship.
1134 Since this method is optimized for performance, the ASCII character
1135 values are not converted in any way. The caller has to make sure that
1136 all ASCII characters are in the allowed range between 0 and 127.
1137 The ASCII string must be NULL-terminated and must be greater than
1138 or equal to asciiStrLength.
1139 This function can't be used for language specific sorting.
1140
1141 @param asciiStr the 8-Bit ASCII character string to be compared.
1142 @param asciiStrLength the length of the ascii string
1143 @return 0 - if both strings are equal
1144 < 0 - if this string is less than the string argument
1145 > 0 - if this string is greater than the string argument
1146 */
1147 sal_Int32 reverseCompareToAsciiL( const char * asciiStr, sal_Int32 asciiStrLength ) const
1148 {
1149 return rtl_ustr_asciil_reverseCompare_WithLength( pData->buffer, pData->length,
1150 asciiStr, asciiStrLength );
1151 }
1152
1153 /**
1154 Perform a comparison of two strings.
1155
1156 The result is true if and only if second string
1157 represents the same sequence of characters as the first string.
1158 Since this method is optimized for performance, the ASCII character
1159 values are not converted in any way. The caller has to make sure that
1160 all ASCII characters are in the allowed range between 0 and 127.
1161 The ASCII string must be NULL-terminated.
1162 This function can't be used for language specific comparison.
1163
1164 @param asciiStr the 8-Bit ASCII character string to be compared.
1165 @return true if the strings are equal;
1166 false, otherwise.
1167 */
1168 bool equalsAscii( const char* asciiStr ) const
1169 {
1170 return rtl_ustr_ascii_compare_WithLength( pData->buffer, pData->length,
1171 asciiStr ) == 0;
1172 }
1173
1174 /**
1175 Perform a comparison of two strings.
1176
1177 The result is true if and only if second string
1178 represents the same sequence of characters as the first string.
1179 Since this method is optimized for performance, the ASCII character
1180 values are not converted in any way. The caller has to make sure that
1181 all ASCII characters are in the allowed range between 0 and 127.
1182 The ASCII string must be NULL-terminated and must be greater than
1183 or equal to asciiStrLength.
1184 This function can't be used for language specific comparison.
1185
1186 @param asciiStr the 8-Bit ASCII character string to be compared.
1187 @param asciiStrLength the length of the ascii string
1188 @return true if the strings are equal;
1189 false, otherwise.
1190 */
1191 bool equalsAsciiL( const char* asciiStr, sal_Int32 asciiStrLength ) const
1192 {
1193 if ( pData->length != asciiStrLength )
1194 return false;
1195
1196 return rtl_ustr_asciil_reverseEquals_WithLength(
1197 pData->buffer, asciiStr, asciiStrLength );
1198 }
1199
1200 /**
1201 Perform an ASCII lowercase comparison of two strings.
1202
1203 The result is true if and only if second string
1204 represents the same sequence of characters as the first string,
1205 ignoring the case.
1206 Character values between 65 and 90 (ASCII A-Z) are interpreted as
1207 values between 97 and 122 (ASCII a-z).
1208 Since this method is optimized for performance, the ASCII character
1209 values are not converted in any way. The caller has to make sure that
1210 all ASCII characters are in the allowed range between 0 and 127.
1211 The ASCII string must be NULL-terminated.
1212 This function can't be used for language specific comparison.
1213
1214 @param asciiStr the 8-Bit ASCII character string to be compared.
1215 @return true if the strings are equal;
1216 false, otherwise.
1217 */
1218 bool equalsIgnoreAsciiCaseAscii( const char * asciiStr ) const
1219 {
1220 return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, asciiStr ) == 0;
1221 }
1222
1223 /**
1224 Compares two ASCII strings ignoring case
1225
1226 The comparison is based on the numeric value of each character in
1227 the strings and return a value indicating their relationship.
1228 Since this method is optimized for performance, the ASCII character
1229 values are not converted in any way. The caller has to make sure that
1230 all ASCII characters are in the allowed range between 0 and 127.
1231 The ASCII string must be NULL-terminated.
1232 This function can't be used for language specific sorting.
1233
1234 @param asciiStr the 8-Bit ASCII character string to be compared.
1235 @return 0 - if both strings are equal
1236 < 0 - if this string is less than the string argument
1237 > 0 - if this string is greater than the string argument
1238
1239 @since LibreOffice 3.5
1240 */
1241 sal_Int32 compareToIgnoreAsciiCaseAscii( const char * asciiStr ) const
1242 {
1243 return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, asciiStr );
1244 }
1245
1246 /**
1247 Perform an ASCII lowercase comparison of two strings.
1248
1249 The result is true if and only if second string
1250 represents the same sequence of characters as the first string,
1251 ignoring the case.
1252 Character values between 65 and 90 (ASCII A-Z) are interpreted as
1253 values between 97 and 122 (ASCII a-z).
1254 Since this method is optimized for performance, the ASCII character
1255 values are not converted in any way. The caller has to make sure that
1256 all ASCII characters are in the allowed range between 0 and 127.
1257 The ASCII string must be NULL-terminated and must be greater than
1258 or equal to asciiStrLength.
1259 This function can't be used for language specific comparison.
1260
1261 @param asciiStr the 8-Bit ASCII character string to be compared.
1262 @param asciiStrLength the length of the ascii string
1263 @return true if the strings are equal;
1264 false, otherwise.
1265 */
1266 bool equalsIgnoreAsciiCaseAsciiL( const char * asciiStr, sal_Int32 asciiStrLength ) const
1267 {
1268 if ( pData->length != asciiStrLength )
1269 return false;
1270
1271 return rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( pData->buffer, pData->length, asciiStr ) == 0;
1272 }
1273
1274 /**
1275 Match against a substring appearing in this string.
1276
1277 The result is true if and only if the second string appears as a substring
1278 of this string, at the given position.
1279 Since this method is optimized for performance, the ASCII character
1280 values are not converted in any way. The caller has to make sure that
1281 all ASCII characters are in the allowed range between 0 and 127.
1282 The ASCII string must be NULL-terminated and must be greater than or
1283 equal to asciiStrLength.
1284 This function can't be used for language specific comparison.
1285
1286 @param asciiStr the object (substring) to be compared.
1287 @param asciiStrLength the length of asciiStr.
1288 @param fromIndex the index to start the comparison from.
1289 The index must be greater than or equal to 0
1290 and less than or equal to the string length.
1291 @return true if str match with the characters in the string
1292 at the given position;
1293 false, otherwise.
1294 */
1295 bool matchAsciiL( const char* asciiStr, sal_Int32 asciiStrLength, sal_Int32 fromIndex = 0 ) const
1296 {
1297 return rtl_ustr_ascii_shortenedCompare_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1298 asciiStr, asciiStrLength ) == 0;
1299 }
1300
1301 // This overload is left undefined, to detect calls of matchAsciiL that
1302 // erroneously use RTL_CONSTASCII_USTRINGPARAM instead of
1303 // RTL_CONSTASCII_STRINGPARAM (but would lead to ambiguities on 32 bit
1304 // platforms):
1305#if SAL_TYPES_SIZEOFLONG8 == 8
1306 void matchAsciiL(char const *, sal_Int32, rtl_TextEncoding) const;
1307#endif
1308
1309 /**
1310 Match against a substring appearing in this string, ignoring the case of
1311 ASCII letters.
1312
1313 The result is true if and only if the second string appears as a substring
1314 of this string, at the given position.
1315 Character values between 65 and 90 (ASCII A-Z) are interpreted as
1316 values between 97 and 122 (ASCII a-z).
1317 Since this method is optimized for performance, the ASCII character
1318 values are not converted in any way. The caller has to make sure that
1319 all ASCII characters are in the allowed range between 0 and 127.
1320 The ASCII string must be NULL-terminated and must be greater than or
1321 equal to asciiStrLength.
1322 This function can't be used for language specific comparison.
1323
1324 @param asciiStr the 8-Bit ASCII character string to be compared.
1325 @param asciiStrLength the length of the ascii string
1326 @param fromIndex the index to start the comparison from.
1327 The index must be greater than or equal to 0
1328 and less than or equal to the string length.
1329 @return true if str match with the characters in the string
1330 at the given position;
1331 false, otherwise.
1332 */
1333 bool matchIgnoreAsciiCaseAsciiL( const char* asciiStr, sal_Int32 asciiStrLength, sal_Int32 fromIndex = 0 ) const
1334 {
1335 return rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
1336 asciiStr, asciiStrLength ) == 0;
1337 }
1338
1339 // This overload is left undefined, to detect calls of
1340 // matchIgnoreAsciiCaseAsciiL that erroneously use
1341 // RTL_CONSTASCII_USTRINGPARAM instead of RTL_CONSTASCII_STRINGPARAM (but
1342 // would lead to ambiguities on 32 bit platforms):
1343#if SAL_TYPES_SIZEOFLONG8 == 8
1344 void matchIgnoreAsciiCaseAsciiL(char const *, sal_Int32, rtl_TextEncoding)
1345 const;
1346#endif
1347
1348 /**
1349 Check whether this string starts with a given substring.
1350
1351 @param str the substring to be compared
1352
1353 @param rest if non-null, and this function returns true, then assign a
1354 copy of the remainder of this string to *rest. Available since
1355 LibreOffice 4.2
1356
1357 @return true if and only if the given str appears as a substring at the
1358 start of this string
1359
1360 @since LibreOffice 4.0
1361 */
1362#if defined LIBO_INTERNAL_ONLY1
1363 bool startsWith(std::u16string_view sv, OUString * rest = nullptr) const {
1364 auto const b = match(sv);
1365 if (b && rest != nullptr) {
1366 *rest = copy(sv.size());
1367 }
1368 return b;
1369 }
1370#else
1371 bool startsWith(OUString const & str, OUString * rest = NULL__null) const {
1372 bool b = match(str);
1373 if (b && rest != NULL__null) {
1374 *rest = copy(str.getLength());
1375 }
1376 return b;
1377 }
1378#endif
1379
1380 /**
1381 @overload
1382 This function accepts an ASCII string literal as its argument.
1383 @since LibreOffice 4.0
1384 */
1385 template< typename T >
1386 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type startsWith(
1387 T & literal, OUString * rest = NULL__null) const
1388 {
1389 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1390, __extension__ __PRETTY_FUNCTION__))
1390 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1390, __extension__ __PRETTY_FUNCTION__))
;
1391 bool b
1392 = (libreoffice_internal::ConstCharArrayDetector<T>::length
1393 <= sal_uInt32(pData->length))
1394 && rtl_ustr_asciil_reverseEquals_WithLength(
1395 pData->buffer,
1396 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1397 literal),
1398 libreoffice_internal::ConstCharArrayDetector<T>::length);
1399 if (b && rest != NULL__null) {
1400 *rest = copy(
1401 libreoffice_internal::ConstCharArrayDetector<T>::length);
1402 }
1403 return b;
1404 }
1405
1406 /**
1407 Check whether this string starts with a given string, ignoring the case of
1408 ASCII letters.
1409
1410 Character values between 65 and 90 (ASCII A-Z) are interpreted as
1411 values between 97 and 122 (ASCII a-z).
1412 This function can't be used for language specific comparison.
1413
1414 @param str the substring to be compared
1415
1416 @param rest if non-null, and this function returns true, then assign a
1417 copy of the remainder of this string to *rest. Available since
1418 LibreOffice 4.2
1419
1420 @return true if and only if the given str appears as a substring at the
1421 start of this string, ignoring the case of ASCII letters ("A"--"Z" and
1422 "a"--"z")
1423
1424 @since LibreOffice 4.0
1425 */
1426#if defined LIBO_INTERNAL_ONLY1
1427 bool startsWithIgnoreAsciiCase(std::u16string_view sv, OUString * rest = nullptr) const {
1428 auto const b = matchIgnoreAsciiCase(sv);
1429 if (b && rest != nullptr) {
1430 *rest = copy(sv.size());
1431 }
1432 return b;
1433 }
1434#else
1435 bool startsWithIgnoreAsciiCase(OUString const & str, OUString * rest = NULL__null)
1436 const
1437 {
1438 bool b = matchIgnoreAsciiCase(str);
1439 if (b && rest != NULL__null) {
1440 *rest = copy(str.getLength());
1441 }
1442 return b;
1443 }
1444#endif
1445
1446 /**
1447 @overload
1448 This function accepts an ASCII string literal as its argument.
1449 @since LibreOffice 4.0
1450 */
1451 template< typename T >
1452 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type
1453 startsWithIgnoreAsciiCase(T & literal, OUString * rest = NULL__null) const
1454 {
1455 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1456, __extension__ __PRETTY_FUNCTION__))
1456 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1456, __extension__ __PRETTY_FUNCTION__))
;
1457 bool b
1458 = (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
1459 pData->buffer,
1460 libreoffice_internal::ConstCharArrayDetector<T>::length,
1461 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1462 literal),
1463 libreoffice_internal::ConstCharArrayDetector<T>::length)
1464 == 0);
1465 if (b && rest != NULL__null) {
1466 *rest = copy(
1467 libreoffice_internal::ConstCharArrayDetector<T>::length);
1468 }
1469 return b;
1470 }
1471
1472 /**
1473 Check whether this string ends with a given substring.
1474
1475 @param str the substring to be compared
1476
1477 @param rest if non-null, and this function returns true, then assign a
1478 copy of the remainder of this string to *rest. Available since
1479 LibreOffice 4.2
1480
1481 @return true if and only if the given str appears as a substring at the
1482 end of this string
1483
1484 @since LibreOffice 3.6
1485 */
1486#if defined LIBO_INTERNAL_ONLY1
1487 bool endsWith(std::u16string_view sv, OUString * rest = nullptr) const {
1488 auto const b = sv.size() <= sal_uInt32(pData->length)
1489 && match(sv, pData->length - sv.size());
1490 if (b && rest != nullptr) {
1491 *rest = copy(0, (pData->length - sv.size()));
1492 }
1493 return b;
1494 }
1495#else
1496 bool endsWith(OUString const & str, OUString * rest = NULL__null) const {
1497 bool b = str.getLength() <= getLength()
1498 && match(str, getLength() - str.getLength());
1499 if (b && rest != NULL__null) {
1500 *rest = copy(0, getLength() - str.getLength());
1501 }
1502 return b;
1503 }
1504#endif
1505
1506 /**
1507 @overload
1508 This function accepts an ASCII string literal as its argument.
1509 @since LibreOffice 3.6
1510 */
1511 template< typename T >
1512 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type
1513 endsWith(T & literal, OUString * rest = NULL__null) const
1514 {
1515 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1516, __extension__ __PRETTY_FUNCTION__))
1516 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1516, __extension__ __PRETTY_FUNCTION__))
;
1517 bool b
1518 = (libreoffice_internal::ConstCharArrayDetector<T>::length
1519 <= sal_uInt32(pData->length))
1520 && rtl_ustr_asciil_reverseEquals_WithLength(
1521 (pData->buffer + pData->length
1522 - libreoffice_internal::ConstCharArrayDetector<T>::length),
1523 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1524 literal),
1525 libreoffice_internal::ConstCharArrayDetector<T>::length);
1526 if (b && rest != NULL__null) {
1527 *rest = copy(
1528 0,
1529 (getLength()
1530 - libreoffice_internal::ConstCharArrayDetector<T>::length));
1531 }
1532 return b;
1533 }
1534
1535 /**
1536 Check whether this string ends with a given ASCII string.
1537
1538 @param asciiStr a sequence of at least asciiStrLength ASCII characters
1539 (bytes in the range 0x00--0x7F)
1540 @param asciiStrLength the length of asciiStr; must be non-negative
1541 @return true if this string ends with asciiStr; otherwise, false is
1542 returned
1543
1544 @since UDK 3.2.7
1545 */
1546 bool endsWithAsciiL(char const * asciiStr, sal_Int32 asciiStrLength)
1547 const
1548 {
1549 return asciiStrLength <= pData->length
1550 && rtl_ustr_asciil_reverseEquals_WithLength(
1551 pData->buffer + pData->length - asciiStrLength, asciiStr,
1552 asciiStrLength);
1553 }
1554
1555 /**
1556 Check whether this string ends with a given string, ignoring the case of
1557 ASCII letters.
1558
1559 Character values between 65 and 90 (ASCII A-Z) are interpreted as
1560 values between 97 and 122 (ASCII a-z).
1561 This function can't be used for language specific comparison.
1562
1563 @param str the substring to be compared
1564
1565 @param rest if non-null, and this function returns true, then assign a
1566 copy of the remainder of this string to *rest. Available since
1567 LibreOffice 4.2
1568
1569 @return true if and only if the given str appears as a substring at the
1570 end of this string, ignoring the case of ASCII letters ("A"--"Z" and
1571 "a"--"z")
1572
1573 @since LibreOffice 3.6
1574 */
1575#if defined LIBO_INTERNAL_ONLY1
1576 bool endsWithIgnoreAsciiCase(std::u16string_view sv, OUString * rest = nullptr) const {
1577 auto const b = sv.size() <= sal_uInt32(pData->length)
1578 && matchIgnoreAsciiCase(sv, pData->length - sv.size());
1579 if (b && rest != nullptr) {
1580 *rest = copy(0, pData->length - sv.size());
1581 }
1582 return b;
1583 }
1584#else
1585 bool endsWithIgnoreAsciiCase(OUString const & str, OUString * rest = NULL__null) const
1586 {
1587 bool b = str.getLength() <= getLength()
1588 && matchIgnoreAsciiCase(str, getLength() - str.getLength());
1589 if (b && rest != NULL__null) {
1590 *rest = copy(0, getLength() - str.getLength());
1591 }
1592 return b;
1593 }
1594#endif
1595
1596 /**
1597 @overload
1598 This function accepts an ASCII string literal as its argument.
1599 @since LibreOffice 3.6
1600 */
1601 template< typename T >
1602 typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type
1603 endsWithIgnoreAsciiCase(T & literal, OUString * rest = NULL__null) const
1604 {
1605 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1606, __extension__ __PRETTY_FUNCTION__))
1606 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1606, __extension__ __PRETTY_FUNCTION__))
;
1607 bool b
1608 = (libreoffice_internal::ConstCharArrayDetector<T>::length
1609 <= sal_uInt32(pData->length))
1610 && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
1611 (pData->buffer + pData->length
1612 - libreoffice_internal::ConstCharArrayDetector<T>::length),
1613 libreoffice_internal::ConstCharArrayDetector<T>::length,
1614 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1615 literal),
1616 libreoffice_internal::ConstCharArrayDetector<T>::length)
1617 == 0);
1618 if (b && rest != NULL__null) {
1619 *rest = copy(
1620 0,
1621 (getLength()
1622 - libreoffice_internal::ConstCharArrayDetector<T>::length));
1623 }
1624 return b;
1625 }
1626
1627 /**
1628 Check whether this string ends with a given ASCII string, ignoring the
1629 case of ASCII letters.
1630
1631 @param asciiStr a sequence of at least asciiStrLength ASCII characters
1632 (bytes in the range 0x00--0x7F)
1633 @param asciiStrLength the length of asciiStr; must be non-negative
1634 @return true if this string ends with asciiStr, ignoring the case of ASCII
1635 letters ("A"--"Z" and "a"--"z"); otherwise, false is returned
1636 */
1637 bool endsWithIgnoreAsciiCaseAsciiL(
1638 char const * asciiStr, sal_Int32 asciiStrLength) const
1639 {
1640 return asciiStrLength <= pData->length
1641 && (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
1642 pData->buffer + pData->length - asciiStrLength,
1643 asciiStrLength, asciiStr, asciiStrLength)
1644 == 0);
1645 }
1646
1647 friend bool operator == ( const OUString& rStr1, const OUString& rStr2 )
1648 { return rStr1.equals(rStr2); }
15
Calling 'OUString::equals'
22
Returning from 'OUString::equals'
23
Returning the value 1, which participates in a condition later
26
Calling 'OUString::equals'
33
Returning from 'OUString::equals'
34
Returning the value 1, which participates in a condition later
37
Calling 'OUString::equals'
43
Returning from 'OUString::equals'
44
Returning the value 1, which participates in a condition later
1649
1650 friend bool operator != ( const OUString& rStr1, const OUString& rStr2 )
1651 { return !(operator == ( rStr1, rStr2 )); }
1652
1653 friend bool operator < ( const OUString& rStr1, const OUString& rStr2 )
1654 { return rStr1.compareTo( rStr2 ) < 0; }
1655 friend bool operator > ( const OUString& rStr1, const OUString& rStr2 )
1656 { return rStr1.compareTo( rStr2 ) > 0; }
1657 friend bool operator <= ( const OUString& rStr1, const OUString& rStr2 )
1658 { return rStr1.compareTo( rStr2 ) <= 0; }
1659 friend bool operator >= ( const OUString& rStr1, const OUString& rStr2 )
1660 { return rStr1.compareTo( rStr2 ) >= 0; }
1661
1662#if defined LIBO_INTERNAL_ONLY1
1663
1664 template<typename T> friend typename libreoffice_internal::CharPtrDetector<T, bool>::TypeUtf16
1665 operator ==(OUString const & s1, T const & s2) {
1666 return rtl_ustr_compare_WithLength(s1.getStr(), s1.getLength(), s2, rtl_ustr_getLength(s2))
1667 == 0;
1668 }
1669
1670 template<typename T>
1671 friend typename libreoffice_internal::NonConstCharArrayDetector<T, bool>::TypeUtf16
1672 operator ==(OUString const & s1, T & s2) {
1673 return rtl_ustr_compare_WithLength(s1.getStr(), s1.getLength(), s2, rtl_ustr_getLength(s2))
1674 == 0;
1675 }
1676
1677 template<typename T> friend typename libreoffice_internal::CharPtrDetector<T, bool>::TypeUtf16
1678 operator ==(T const & s1, OUString const & s2) {
1679 return rtl_ustr_compare_WithLength(s1, rtl_ustr_getLength(s1), s2.getStr(), s2.getLength())
1680 == 0;
1681 }
1682
1683 template<typename T>
1684 friend typename libreoffice_internal::NonConstCharArrayDetector<T, bool>::TypeUtf16
1685 operator ==(T & s1, OUString const & s2) {
1686 return rtl_ustr_compare_WithLength(s1, rtl_ustr_getLength(s1), s2.getStr(), s2.getLength())
1687 == 0;
1688 }
1689
1690 template<typename T> friend typename libreoffice_internal::CharPtrDetector<T, bool>::TypeUtf16
1691 operator !=(OUString const & s1, T const & s2) { return !(s1 == s2); }
1692
1693 template<typename T>
1694 friend typename libreoffice_internal::NonConstCharArrayDetector<T, bool>::TypeUtf16
1695 operator !=(OUString const & s1, T & s2) { return !(s1 == s2); }
1696
1697 template<typename T> friend typename libreoffice_internal::CharPtrDetector<T, bool>::TypeUtf16
1698 operator !=(T const & s1, OUString const & s2) { return !(s1 == s2); }
1699
1700 template<typename T>
1701 friend typename libreoffice_internal::NonConstCharArrayDetector<T, bool>::TypeUtf16
1702 operator !=(T & s1, OUString const & s2) { return !(s1 == s2); }
1703
1704#else
1705
1706 friend bool operator == ( const OUString& rStr1, const sal_Unicode * pStr2 )
1707 { return rStr1.compareTo( pStr2 ) == 0; }
1708 friend bool operator == ( const sal_Unicode * pStr1, const OUString& rStr2 )
1709 { return OUString( pStr1 ).compareTo( rStr2 ) == 0; }
1710
1711 friend bool operator != ( const OUString& rStr1, const sal_Unicode * pStr2 )
1712 { return !(operator == ( rStr1, pStr2 )); }
1713 friend bool operator != ( const sal_Unicode * pStr1, const OUString& rStr2 )
1714 { return !(operator == ( pStr1, rStr2 )); }
1715
1716#endif
1717
1718 /**
1719 * Compare string to an ASCII string literal.
1720 *
1721 * This operator is equal to calling equalsAsciiL().
1722 *
1723 * @since LibreOffice 3.6
1724 */
1725 template< typename T >
1726 friend typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type operator==( const OUString& rString, T& literal )
1727 {
1728 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1729, __extension__ __PRETTY_FUNCTION__))
1729 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1729, __extension__ __PRETTY_FUNCTION__))
;
1730 return rString.equalsAsciiL(
1731 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
1732 libreoffice_internal::ConstCharArrayDetector<T>::length);
1733 }
1734 /**
1735 * Compare string to an ASCII string literal.
1736 *
1737 * This operator is equal to calling equalsAsciiL().
1738 *
1739 * @since LibreOffice 3.6
1740 */
1741 template< typename T >
1742 friend typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type operator==( T& literal, const OUString& rString )
1743 {
1744 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1745, __extension__ __PRETTY_FUNCTION__))
1745 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1745, __extension__ __PRETTY_FUNCTION__))
;
1746 return rString.equalsAsciiL(
1747 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
1748 libreoffice_internal::ConstCharArrayDetector<T>::length);
1749 }
1750 /**
1751 * Compare string to an ASCII string literal.
1752 *
1753 * This operator is equal to calling !equalsAsciiL().
1754 *
1755 * @since LibreOffice 3.6
1756 */
1757 template< typename T >
1758 friend typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type operator!=( const OUString& rString, T& literal )
1759 {
1760 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1761, __extension__ __PRETTY_FUNCTION__))
1761 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1761, __extension__ __PRETTY_FUNCTION__))
;
1762 return !rString.equalsAsciiL(
1763 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
1764 libreoffice_internal::ConstCharArrayDetector<T>::length);
1765 }
1766 /**
1767 * Compare string to an ASCII string literal.
1768 *
1769 * This operator is equal to calling !equalsAsciiL().
1770 *
1771 * @since LibreOffice 3.6
1772 */
1773 template< typename T >
1774 friend typename libreoffice_internal::ConstCharArrayDetector< T, bool >::Type operator!=( T& literal, const OUString& rString )
1775 {
1776 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1777, __extension__ __PRETTY_FUNCTION__))
1777 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 1777, __extension__ __PRETTY_FUNCTION__))
;
1778 return !rString.equalsAsciiL(
1779 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
1780 libreoffice_internal::ConstCharArrayDetector<T>::length);
1781 }
1782
1783#if defined LIBO_INTERNAL_ONLY1
1784 /** @overload @since LibreOffice 5.3 */
1785 template<typename T> friend typename libreoffice_internal::ConstCharArrayDetector<T, bool>::TypeUtf16
1786 operator ==(OUString const & string, T & literal) {
1787 return
1788 rtl_ustr_reverseCompare_WithLength(
1789 string.pData->buffer, string.pData->length,
1790 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1791 literal),
1792 libreoffice_internal::ConstCharArrayDetector<T>::length)
1793 == 0;
1794 }
1795 /** @overload @since LibreOffice 5.3 */
1796 template<typename T> friend typename libreoffice_internal::ConstCharArrayDetector<T, bool>::TypeUtf16
1797 operator ==(T & literal, OUString const & string) {
1798 return
1799 rtl_ustr_reverseCompare_WithLength(
1800 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1801 literal),
1802 libreoffice_internal::ConstCharArrayDetector<T>::length,
1803 string.pData->buffer, string.pData->length)
1804 == 0;
1805 }
1806 /** @overload @since LibreOffice 5.3 */
1807 template<typename T> friend typename libreoffice_internal::ConstCharArrayDetector<T, bool>::TypeUtf16
1808 operator !=(OUString const & string, T & literal) {
1809 return
1810 rtl_ustr_reverseCompare_WithLength(
1811 string.pData->buffer, string.pData->length,
1812 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1813 literal),
1814 libreoffice_internal::ConstCharArrayDetector<T>::length)
1815 != 0;
1816 }
1817 /** @overload @since LibreOffice 5.3 */
1818 template<typename T> friend typename libreoffice_internal::ConstCharArrayDetector<T, bool>::TypeUtf16
1819 operator !=(T & literal, OUString const & string) {
1820 return
1821 rtl_ustr_reverseCompare_WithLength(
1822 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(
1823 literal),
1824 libreoffice_internal::ConstCharArrayDetector<T>::length,
1825 string.pData->buffer, string.pData->length)
1826 != 0;
1827 }
1828#endif
1829
1830#if defined LIBO_INTERNAL_ONLY1
1831 /// @cond INTERNAL
1832
1833 /* Comparison between OUString and OUStringLiteral.
1834
1835 @since LibreOffice 5.0
1836 */
1837
1838 template<std::size_t N>
1839 friend bool operator ==(OUString const & lhs, OUStringLiteral<N> const & rhs) {
1840 return
1841 rtl_ustr_reverseCompare_WithLength(
1842 lhs.pData->buffer, lhs.pData->length, rhs.getStr(), rhs.getLength())
1843 == 0;
1844 }
1845
1846 template<std::size_t N>
1847 friend bool operator !=(OUString const & lhs, OUStringLiteral<N> const & rhs) {
1848 return
1849 rtl_ustr_reverseCompare_WithLength(
1850 lhs.pData->buffer, lhs.pData->length, rhs.getStr(), rhs.getLength())
1851 != 0;
1852 }
1853
1854 template<std::size_t N>
1855 friend bool operator <(OUString const & lhs, OUStringLiteral<N> const & rhs) {
1856 return
1857 (rtl_ustr_compare_WithLength(
1858 lhs.pData->buffer, lhs.pData->length, rhs.getStr(), rhs.getLength()))
1859 < 0;
1860 }
1861
1862 template<std::size_t N>
1863 friend bool operator <=(OUString const & lhs, OUStringLiteral<N> const & rhs) {
1864 return
1865 (rtl_ustr_compare_WithLength(
1866 lhs.pData->buffer, lhs.pData->length, rhs.getStr(), rhs.getLength()))
1867 <= 0;
1868 }
1869
1870 template<std::size_t N>
1871 friend bool operator >(OUString const & lhs, OUStringLiteral<N> const & rhs) {
1872 return
1873 (rtl_ustr_compare_WithLength(
1874 lhs.pData->buffer, lhs.pData->length, rhs.getStr(), rhs.getLength()))
1875 > 0;
1876 }
1877
1878 template<std::size_t N>
1879 friend bool operator >=(OUString const & lhs, OUStringLiteral<N> const & rhs) {
1880 return
1881 (rtl_ustr_compare_WithLength(
1882 lhs.pData->buffer, lhs.pData->length, rhs.getStr(), rhs.getLength()))
1883 >= 0;
1884 }
1885
1886 template<std::size_t N>
1887 friend bool operator ==(OUStringLiteral<N> const & lhs, OUString const & rhs) {
1888 return
1889 rtl_ustr_reverseCompare_WithLength(
1890 lhs.getStr(), lhs.getLength(), rhs.pData->buffer, rhs.pData->length)
1891 == 0;
1892 }
1893
1894 template<std::size_t N>
1895 friend bool operator !=(OUStringLiteral<N> const & lhs, OUString const & rhs) {
1896 return
1897 rtl_ustr_reverseCompare_WithLength(
1898 lhs.getStr(), lhs.getLength(), rhs.pData->buffer, rhs.pData->length)
1899 != 0;
1900 }
1901
1902 template<std::size_t N>
1903 friend bool operator <(OUStringLiteral<N> const & lhs, OUString const & rhs) {
1904 return
1905 (rtl_ustr_compare_WithLength(
1906 lhs.getStr(), lhs.getLength(), rhs.pData->buffer, rhs.pData->length))
1907 < 0;
1908 }
1909
1910 template<std::size_t N>
1911 friend bool operator <=(OUStringLiteral<N> const & lhs, OUString const & rhs) {
1912 return
1913 (rtl_ustr_compare_WithLength(
1914 lhs.getStr(), lhs.getLength(), rhs.pData->buffer, rhs.pData->length))
1915 <= 0;
1916 }
1917
1918 template<std::size_t N>
1919 friend bool operator >(OUStringLiteral<N> const & lhs, OUString const & rhs) {
1920 return
1921 (rtl_ustr_compare_WithLength(
1922 lhs.getStr(), lhs.getLength(), rhs.pData->buffer, rhs.pData->length))
1923 > 0;
1924 }
1925
1926 template<std::size_t N>
1927 friend bool operator >=(OUStringLiteral<N> const & lhs, OUString const & rhs) {
1928 return
1929 (rtl_ustr_compare_WithLength(
1930 lhs.getStr(), lhs.getLength(), rhs.pData->buffer, rhs.pData->length))
1931 >= 0;
1932 }
1933
1934 /// @endcond
1935#endif
1936
1937#if defined LIBO_INTERNAL_ONLY1
1938 friend bool operator ==(OUString const & lhs, std::u16string_view rhs) {
1939 return
1940 rtl_ustr_reverseCompare_WithLength(
1941 lhs.pData->buffer, lhs.pData->length, rhs.data(), rhs.size())
1942 == 0;
1943 }
1944
1945 friend bool operator !=(OUString const & lhs, std::u16string_view rhs) {
1946 return
1947 rtl_ustr_reverseCompare_WithLength(
1948 lhs.pData->buffer, lhs.pData->length, rhs.data(), rhs.size())
1949 != 0;
1950 }
1951
1952 friend bool operator <(OUString const & lhs, std::u16string_view rhs) {
1953 return
1954 (rtl_ustr_compare_WithLength(
1955 lhs.pData->buffer, lhs.pData->length, rhs.data(), rhs.size()))
1956 < 0;
1957 }
1958
1959 friend bool operator <=(OUString const & lhs, std::u16string_view rhs) {
1960 return
1961 (rtl_ustr_compare_WithLength(
1962 lhs.pData->buffer, lhs.pData->length, rhs.data(), rhs.size()))
1963 <= 0;
1964 }
1965
1966 friend bool operator >(OUString const & lhs, std::u16string_view rhs) {
1967 return
1968 (rtl_ustr_compare_WithLength(
1969 lhs.pData->buffer, lhs.pData->length, rhs.data(), rhs.size()))
1970 > 0;
1971 }
1972
1973 friend bool operator >=(OUString const & lhs, std::u16string_view rhs) {
1974 return
1975 (rtl_ustr_compare_WithLength(
1976 lhs.pData->buffer, lhs.pData->length, rhs.data(), rhs.size()))
1977 >= 0;
1978 }
1979
1980 friend bool operator ==(std::u16string_view lhs, OUString const & rhs) {
1981 return
1982 rtl_ustr_reverseCompare_WithLength(
1983 lhs.data(), lhs.size(), rhs.pData->buffer, rhs.pData->length)
1984 == 0;
1985 }
1986
1987 friend bool operator !=(std::u16string_view lhs, OUString const & rhs) {
1988 return
1989 rtl_ustr_reverseCompare_WithLength(
1990 lhs.data(), lhs.size(), rhs.pData->buffer, rhs.pData->length)
1991 != 0;
1992 }
1993
1994 friend bool operator <(std::u16string_view lhs, OUString const & rhs) {
1995 return
1996 (rtl_ustr_compare_WithLength(
1997 lhs.data(), lhs.size(), rhs.pData->buffer, rhs.pData->length))
1998 < 0;
1999 }
2000
2001 friend bool operator <=(std::u16string_view lhs, OUString const & rhs) {
2002 return
2003 (rtl_ustr_compare_WithLength(
2004 lhs.data(), lhs.size(), rhs.pData->buffer, rhs.pData->length))
2005 <= 0;
2006 }
2007
2008 friend bool operator >(std::u16string_view lhs, OUString const & rhs) {
2009 return
2010 (rtl_ustr_compare_WithLength(
2011 lhs.data(), lhs.size(), rhs.pData->buffer, rhs.pData->length))
2012 > 0;
2013 }
2014
2015 friend bool operator >=(std::u16string_view lhs, OUString const & rhs) {
2016 return
2017 (rtl_ustr_compare_WithLength(
2018 lhs.data(), lhs.size(), rhs.pData->buffer, rhs.pData->length))
2019 >= 0;
2020 }
2021#endif
2022
2023 /**
2024 Returns a hashcode for this string.
2025
2026 @return a hash code value for this object.
2027
2028 @see rtl::OUStringHash for convenient use of std::unordered_map
2029 */
2030 sal_Int32 hashCode() const
2031 {
2032 return rtl_ustr_hashCode_WithLength( pData->buffer, pData->length );
2033 }
2034
2035 /**
2036 Returns the index within this string of the first occurrence of the
2037 specified character, starting the search at the specified index.
2038
2039 @param ch character to be located.
2040 @param fromIndex the index to start the search from.
2041 The index must be greater than or equal to 0
2042 and less than or equal to the string length.
2043 @return the index of the first occurrence of the character in the
2044 character sequence represented by this string that is
2045 greater than or equal to fromIndex, or
2046 -1 if the character does not occur.
2047 */
2048 sal_Int32 indexOf( sal_Unicode ch, sal_Int32 fromIndex = 0 ) const
2049 {
2050 sal_Int32 ret = rtl_ustr_indexOfChar_WithLength( pData->buffer+fromIndex, pData->length-fromIndex, ch );
2051 return (ret < 0 ? ret : ret+fromIndex);
2052 }
2053
2054 /**
2055 Returns the index within this string of the last occurrence of the
2056 specified character, searching backward starting at the end.
2057
2058 @param ch character to be located.
2059 @return the index of the last occurrence of the character in the
2060 character sequence represented by this string, or
2061 -1 if the character does not occur.
2062 */
2063 sal_Int32 lastIndexOf( sal_Unicode ch ) const
2064 {
2065 return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, pData->length, ch );
2066 }
2067
2068 /**
2069 Returns the index within this string of the last occurrence of the
2070 specified character, searching backward starting before the specified
2071 index.
2072
2073 @param ch character to be located.
2074 @param fromIndex the index before which to start the search.
2075 @return the index of the last occurrence of the character in the
2076 character sequence represented by this string that
2077 is less than fromIndex, or -1
2078 if the character does not occur before that point.
2079 */
2080 sal_Int32 lastIndexOf( sal_Unicode ch, sal_Int32 fromIndex ) const
2081 {
2082 return rtl_ustr_lastIndexOfChar_WithLength( pData->buffer, fromIndex, ch );
2083 }
2084
2085 /**
2086 Returns the index within this string of the first occurrence of the
2087 specified substring, starting at the specified index.
2088
2089 If str doesn't include any character, always -1 is
2090 returned. This is also the case, if both strings are empty.
2091
2092 @param str the substring to search for.
2093 @param fromIndex the index to start the search from.
2094 @return If the string argument occurs one or more times as a substring
2095 within this string at the starting index, then the index
2096 of the first character of the first such substring is
2097 returned. If it does not occur as a substring starting
2098 at fromIndex or beyond, -1 is returned.
2099 */
2100#if defined LIBO_INTERNAL_ONLY1
2101 sal_Int32 indexOf(std::u16string_view sv, sal_Int32 fromIndex = 0) const {
2102 auto const n = rtl_ustr_indexOfStr_WithLength(
2103 pData->buffer + fromIndex, pData->length - fromIndex, sv.data(), sv.size());
2104 return n < 0 ? n : n + fromIndex;
2105 }
2106#else
2107 sal_Int32 indexOf( const OUString & str, sal_Int32 fromIndex = 0 ) const
2108 {
2109 sal_Int32 ret = rtl_ustr_indexOfStr_WithLength( pData->buffer+fromIndex, pData->length-fromIndex,
2110 str.pData->buffer, str.pData->length );
2111 return (ret < 0 ? ret : ret+fromIndex);
2112 }
2113#endif
2114
2115 /**
2116 @overload
2117 This function accepts an ASCII string literal as its argument.
2118 @since LibreOffice 3.6
2119 */
2120 template< typename T >
2121 typename libreoffice_internal::ConstCharArrayDetector< T, sal_Int32 >::Type indexOf( T& literal, sal_Int32 fromIndex = 0 ) const
2122 {
2123 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2124, __extension__ __PRETTY_FUNCTION__))
2124 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2124, __extension__ __PRETTY_FUNCTION__))
;
2125 sal_Int32 n = rtl_ustr_indexOfAscii_WithLength(
2126 pData->buffer + fromIndex, pData->length - fromIndex,
2127 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
2128 libreoffice_internal::ConstCharArrayDetector<T>::length);
2129 return n < 0 ? n : n + fromIndex;
2130 }
2131
2132 /**
2133 Returns the index within this string of the first occurrence of the
2134 specified ASCII substring, starting at the specified index.
2135
2136 @param str
2137 the substring to be searched for. Need not be null-terminated, but must
2138 be at least as long as the specified len. Must only contain characters
2139 in the ASCII range 0x00--7F.
2140
2141 @param len
2142 the length of the substring; must be non-negative.
2143
2144 @param fromIndex
2145 the index to start the search from. Must be in the range from zero to
2146 the length of this string, inclusive.
2147
2148 @return
2149 the index (starting at 0) of the first character of the first occurrence
2150 of the substring within this string starting at the given fromIndex, or
2151 -1 if the substring does not occur. If len is zero, -1 is returned.
2152
2153 @since UDK 3.2.7
2154 */
2155 sal_Int32 indexOfAsciiL(
2156 char const * str, sal_Int32 len, sal_Int32 fromIndex = 0) const
2157 {
2158 sal_Int32 ret = rtl_ustr_indexOfAscii_WithLength(
2159 pData->buffer + fromIndex, pData->length - fromIndex, str, len);
2160 return ret < 0 ? ret : ret + fromIndex;
2161 }
2162
2163 // This overload is left undefined, to detect calls of indexOfAsciiL that
2164 // erroneously use RTL_CONSTASCII_USTRINGPARAM instead of
2165 // RTL_CONSTASCII_STRINGPARAM (but would lead to ambiguities on 32 bit
2166 // platforms):
2167#if SAL_TYPES_SIZEOFLONG8 == 8
2168 void indexOfAsciiL(char const *, sal_Int32 len, rtl_TextEncoding) const;
2169#endif
2170
2171 /**
2172 Returns the index within this string of the last occurrence of
2173 the specified substring, searching backward starting at the end.
2174
2175 The returned index indicates the starting index of the substring
2176 in this string.
2177 If str doesn't include any character, always -1 is
2178 returned. This is also the case, if both strings are empty.
2179
2180 @param str the substring to search for.
2181 @return If the string argument occurs one or more times as a substring
2182 within this string, then the index of the first character of
2183 the last such substring is returned. If it does not occur as
2184 a substring, -1 is returned.
2185 */
2186#if defined LIBO_INTERNAL_ONLY1
2187 sal_Int32 lastIndexOf(std::u16string_view sv) const {
2188 return rtl_ustr_lastIndexOfStr_WithLength(
2189 pData->buffer, pData->length, sv.data(), sv.size());
2190 }
2191#else
2192 sal_Int32 lastIndexOf( const OUString & str ) const
2193 {
2194 return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, pData->length,
2195 str.pData->buffer, str.pData->length );
2196 }
2197#endif
2198
2199 /**
2200 Returns the index within this string of the last occurrence of
2201 the specified substring, searching backward starting before the specified
2202 index.
2203
2204 The returned index indicates the starting index of the substring
2205 in this string.
2206 If str doesn't include any character, always -1 is
2207 returned. This is also the case, if both strings are empty.
2208
2209 @param str the substring to search for.
2210 @param fromIndex the index before which to start the search.
2211 @return If the string argument occurs one or more times as a substring
2212 within this string before the starting index, then the index
2213 of the first character of the last such substring is
2214 returned. Otherwise, -1 is returned.
2215 */
2216#if defined LIBO_INTERNAL_ONLY1
2217 sal_Int32 lastIndexOf(std::u16string_view sv, sal_Int32 fromIndex) const {
2218 return rtl_ustr_lastIndexOfStr_WithLength(pData->buffer, fromIndex, sv.data(), sv.size());
2219 }
2220#else
2221 sal_Int32 lastIndexOf( const OUString & str, sal_Int32 fromIndex ) const
2222 {
2223 return rtl_ustr_lastIndexOfStr_WithLength( pData->buffer, fromIndex,
2224 str.pData->buffer, str.pData->length );
2225 }
2226#endif
2227
2228 /**
2229 @overload
2230 This function accepts an ASCII string literal as its argument.
2231 @since LibreOffice 3.6
2232 */
2233 template< typename T >
2234 typename libreoffice_internal::ConstCharArrayDetector< T, sal_Int32 >::Type lastIndexOf( T& literal ) const
2235 {
2236 assert((static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2237, __extension__ __PRETTY_FUNCTION__))
2237 libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(literal)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(literal)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2237, __extension__ __PRETTY_FUNCTION__))
;
2238 return rtl_ustr_lastIndexOfAscii_WithLength(
2239 pData->buffer, pData->length,
2240 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(literal),
2241 libreoffice_internal::ConstCharArrayDetector<T>::length);
2242 }
2243
2244 /**
2245 Returns the index within this string of the last occurrence of the
2246 specified ASCII substring.
2247
2248 @param str
2249 the substring to be searched for. Need not be null-terminated, but must
2250 be at least as long as the specified len. Must only contain characters
2251 in the ASCII range 0x00--7F.
2252
2253 @param len
2254 the length of the substring; must be non-negative.
2255
2256 @return
2257 the index (starting at 0) of the first character of the last occurrence
2258 of the substring within this string, or -1 if the substring does not
2259 occur. If len is zero, -1 is returned.
2260
2261 @since UDK 3.2.7
2262 */
2263 sal_Int32 lastIndexOfAsciiL(char const * str, sal_Int32 len) const
2264 {
2265 return rtl_ustr_lastIndexOfAscii_WithLength(
2266 pData->buffer, pData->length, str, len);
2267 }
2268
2269 /**
2270 Returns a new string that is a substring of this string.
2271
2272 The substring begins at the specified beginIndex. If
2273 beginIndex is negative or be greater than the length of
2274 this string, behaviour is undefined.
2275
2276 @param beginIndex the beginning index, inclusive.
2277 @return the specified substring.
2278 */
2279 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString copy( sal_Int32 beginIndex ) const
2280 {
2281 return copy(beginIndex, getLength() - beginIndex);
2282 }
2283
2284 /**
2285 Returns a new string that is a substring of this string.
2286
2287 The substring begins at the specified beginIndex and contains count
2288 characters. If either beginIndex or count are negative,
2289 or beginIndex + count are greater than the length of this string
2290 then behaviour is undefined.
2291
2292 @param beginIndex the beginning index, inclusive.
2293 @param count the number of characters.
2294 @return the specified substring.
2295 */
2296 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString copy( sal_Int32 beginIndex, sal_Int32 count ) const
2297 {
2298 rtl_uString *pNew = NULL__null;
2299 rtl_uString_newFromSubString( &pNew, pData, beginIndex, count );
2300 return OUString( pNew, SAL_NO_ACQUIRE );
2301 }
2302
2303 /**
2304 Concatenates the specified string to the end of this string.
2305
2306 @param str the string that is concatenated to the end
2307 of this string.
2308 @return a string that represents the concatenation of this string
2309 followed by the string argument.
2310 */
2311 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString concat( const OUString & str ) const
2312 {
2313 rtl_uString* pNew = NULL__null;
2314 rtl_uString_newConcat( &pNew, pData, str.pData );
2315 return OUString( pNew, SAL_NO_ACQUIRE );
2316 }
2317
2318#ifndef LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
2319 friend OUString operator+( const OUString& rStr1, const OUString& rStr2 )
2320 {
2321 return rStr1.concat( rStr2 );
2322 }
2323#endif
2324
2325 /**
2326 Returns a new string resulting from replacing n = count characters
2327 from position index in this string with newStr.
2328
2329 @param index the replacing index in str.
2330 The index must be greater than or equal to 0 and
2331 less than or equal to the length of the string.
2332 @param count the count of characters that will be replaced
2333 The count must be greater than or equal to 0 and
2334 less than or equal to the length of the string minus index.
2335 @param newStr the new substring.
2336 @return the new string.
2337 */
2338 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString replaceAt( sal_Int32 index, sal_Int32 count, const OUString& newStr ) const
2339 {
2340 rtl_uString* pNew = NULL__null;
2341 rtl_uString_newReplaceStrAt( &pNew, pData, index, count, newStr.pData );
2342 return OUString( pNew, SAL_NO_ACQUIRE );
2343 }
2344
2345 /**
2346 Returns a new string resulting from replacing all occurrences of
2347 oldChar in this string with newChar.
2348
2349 If the character oldChar does not occur in the character sequence
2350 represented by this object, then the string is assigned with
2351 str.
2352
2353 @param oldChar the old character.
2354 @param newChar the new character.
2355 @return a string derived from this string by replacing every
2356 occurrence of oldChar with newChar.
2357 */
2358 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString replace( sal_Unicode oldChar, sal_Unicode newChar ) const
2359 {
2360 rtl_uString* pNew = NULL__null;
2361 rtl_uString_newReplace( &pNew, pData, oldChar, newChar );
2362 return OUString( pNew, SAL_NO_ACQUIRE );
2363 }
2364
2365 /**
2366 Returns a new string resulting from replacing the first occurrence of a
2367 given substring with another substring.
2368
2369 @param from the substring to be replaced
2370
2371 @param to the replacing substring
2372
2373 @param[in,out] index pointer to a start index; if the pointer is
2374 non-null: upon entry to the function, its value is the index into this
2375 string at which to start searching for the \p from substring, the value
2376 must be non-negative and not greater than this string's length; upon exiting
2377 the function its value is the index into this string at which the
2378 replacement took place or -1 if no replacement took place; if the pointer
2379 is null, searching always starts at index 0
2380
2381 @since LibreOffice 3.6
2382 */
2383#if defined LIBO_INTERNAL_ONLY1
2384 [[nodiscard]] OUString replaceFirst(
2385 std::u16string_view from, std::u16string_view to, sal_Int32 * index = nullptr) const
2386 {
2387 rtl_uString * s = nullptr;
2388 sal_Int32 i = 0;
2389 rtl_uString_newReplaceFirstUtf16LUtf16L(
2390 &s, pData, from.data(), from.size(), to.data(), to.size(),
2391 index == nullptr ? &i : index);
2392 return OUString(s, SAL_NO_ACQUIRE);
2393 }
2394#else
2395 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString replaceFirst(
2396 OUString const & from, OUString const & to, sal_Int32 * index = NULL__null) const
2397 {
2398 rtl_uString * s = NULL__null;
2399 sal_Int32 i = 0;
2400 rtl_uString_newReplaceFirst(
2401 &s, pData, from.pData, to.pData, index == NULL__null ? &i : index);
2402 return OUString(s, SAL_NO_ACQUIRE);
2403 }
2404#endif
2405
2406 /**
2407 Returns a new string resulting from replacing the first occurrence of a
2408 given substring with another substring.
2409
2410 @param from ASCII string literal, the substring to be replaced
2411
2412 @param to the replacing substring
2413
2414 @param[in,out] index pointer to a start index; if the pointer is
2415 non-null: upon entry to the function, its value is the index into the this
2416 string at which to start searching for the \p from substring, the value
2417 must be non-negative and not greater than this string's length; upon exiting
2418 the function its value is the index into this string at which the
2419 replacement took place or -1 if no replacement took place; if the pointer
2420 is null, searching always starts at index 0
2421
2422 @since LibreOffice 3.6
2423 */
2424#if defined LIBO_INTERNAL_ONLY1
2425 template<typename T> [[nodiscard]]
2426 typename libreoffice_internal::ConstCharArrayDetector<T, OUString >::Type replaceFirst(
2427 T & from, std::u16string_view to, sal_Int32 * index = nullptr) const
2428 {
2429 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(from))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(from)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(from)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2429, __extension__ __PRETTY_FUNCTION__))
;
2430 rtl_uString * s = nullptr;
2431 sal_Int32 i = 0;
2432 rtl_uString_newReplaceFirstAsciiLUtf16L(
2433 &s, pData, libreoffice_internal::ConstCharArrayDetector<T>::toPointer(from),
2434 libreoffice_internal::ConstCharArrayDetector<T>::length, to.data(), to.size(),
2435 index == nullptr ? &i : index);
2436 return OUString(s, SAL_NO_ACQUIRE);
2437 }
2438#else
2439 template< typename T >
2440 SAL_WARN_UNUSED_RESULT[[nodiscard]] typename libreoffice_internal::ConstCharArrayDetector< T, OUString >::Type replaceFirst( T& from, OUString const & to,
2441 sal_Int32 * index = NULL__null) const
2442 {
2443 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(from))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(from)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(from)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2443, __extension__ __PRETTY_FUNCTION__))
;
2444 rtl_uString * s = NULL__null;
2445 sal_Int32 i = 0;
2446 rtl_uString_newReplaceFirstAsciiL(
2447 &s, pData,
2448 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(from),
2449 libreoffice_internal::ConstCharArrayDetector<T>::length, to.pData,
2450 index == NULL__null ? &i : index);
2451 return OUString(s, SAL_NO_ACQUIRE);
2452 }
2453#endif
2454
2455 /**
2456 Returns a new string resulting from replacing the first occurrence of a
2457 given substring with another substring.
2458
2459 @param from the substring to be replaced
2460
2461 @param to ASCII string literal, the replacing substring
2462
2463 @param[in,out] index pointer to a start index; if the pointer is
2464 non-null: upon entry to the function, its value is the index into the this
2465 string at which to start searching for the \p from substring, the value
2466 must be non-negative and not greater than this string's length; upon exiting
2467 the function its value is the index into this string at which the
2468 replacement took place or -1 if no replacement took place; if the pointer
2469 is null, searching always starts at index 0
2470
2471 @since LibreOffice 5.1
2472 */
2473#if defined LIBO_INTERNAL_ONLY1
2474 template<typename T> [[nodiscard]]
2475 typename libreoffice_internal::ConstCharArrayDetector<T, OUString >::Type replaceFirst(
2476 std::u16string_view from, T & to, sal_Int32 * index = nullptr) const
2477 {
2478 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(to))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(to)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(to)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2478, __extension__ __PRETTY_FUNCTION__))
;
2479 rtl_uString * s = nullptr;
2480 sal_Int32 i = 0;
2481 rtl_uString_newReplaceFirstUtf16LAsciiL(
2482 &s, pData, from.data(), from.size(),
2483 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(to),
2484 libreoffice_internal::ConstCharArrayDetector<T>::length, index == nullptr ? &i : index);
2485 return OUString(s, SAL_NO_ACQUIRE);
2486 }
2487#else
2488 template< typename T >
2489 SAL_WARN_UNUSED_RESULT[[nodiscard]] typename libreoffice_internal::ConstCharArrayDetector< T, OUString >::Type replaceFirst( OUString const & from, T& to,
2490 sal_Int32 * index = NULL__null) const
2491 {
2492 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(to))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(to)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(to)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2492, __extension__ __PRETTY_FUNCTION__))
;
2493 rtl_uString * s = NULL__null;
2494 sal_Int32 i = 0;
2495 rtl_uString_newReplaceFirstToAsciiL(
2496 &s, pData, from.pData,
2497 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(to),
2498 libreoffice_internal::ConstCharArrayDetector<T>::length,
2499 index == NULL__null ? &i : index);
2500 return OUString(s, SAL_NO_ACQUIRE);
2501 }
2502#endif
2503
2504 /**
2505 Returns a new string resulting from replacing the first occurrence of a
2506 given substring with another substring.
2507
2508 @param from ASCII string literal, the substring to be replaced
2509
2510 @param to ASCII string literal, the substring to be replaced
2511
2512 @param[in,out] index pointer to a start index; if the pointer is
2513 non-null: upon entry to the function, its value is the index into the this
2514 string at which to start searching for the \p from substring, the value
2515 must be non-negative and not greater than this string's length; upon exiting
2516 the function its value is the index into this string at which the
2517 replacement took place or -1 if no replacement took place; if the pointer
2518 is null, searching always starts at index 0
2519
2520 @since LibreOffice 3.6
2521 */
2522 template< typename T1, typename T2 >
2523 SAL_WARN_UNUSED_RESULT[[nodiscard]] typename libreoffice_internal::ConstCharArrayDetector< T1, typename libreoffice_internal::ConstCharArrayDetector< T2, OUString >::Type >::Type
2524 replaceFirst( T1& from, T2& to, sal_Int32 * index = NULL__null) const
2525 {
2526 assert(libreoffice_internal::ConstCharArrayDetector<T1>::isValid(from))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T1>::isValid(from)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T1>::isValid(from)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2526, __extension__ __PRETTY_FUNCTION__))
;
2527 assert(libreoffice_internal::ConstCharArrayDetector<T2>::isValid(to))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T2>::isValid(to)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T2>::isValid(to)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2527, __extension__ __PRETTY_FUNCTION__))
;
2528 rtl_uString * s = NULL__null;
2529 sal_Int32 i = 0;
2530 rtl_uString_newReplaceFirstAsciiLAsciiL(
2531 &s, pData,
2532 libreoffice_internal::ConstCharArrayDetector<T1>::toPointer(from),
2533 libreoffice_internal::ConstCharArrayDetector<T1>::length,
2534 libreoffice_internal::ConstCharArrayDetector<T2>::toPointer(to),
2535 libreoffice_internal::ConstCharArrayDetector<T2>::length,
2536 index == NULL__null ? &i : index);
2537 return OUString(s, SAL_NO_ACQUIRE);
2538 }
2539
2540 /**
2541 Returns a new string resulting from replacing all occurrences of a given
2542 substring with another substring.
2543
2544 Replacing subsequent occurrences picks up only after a given replacement.
2545 That is, replacing from "xa" to "xx" in "xaa" results in "xxa", not "xxx".
2546
2547 @param from the substring to be replaced
2548
2549 @param to the replacing substring
2550
2551 @param fromIndex the position in the string where we will begin searching
2552
2553 @since LibreOffice 4.0
2554 */
2555#if defined LIBO_INTERNAL_ONLY1
2556 [[nodiscard]] OUString replaceAll(
2557 std::u16string_view from, std::u16string_view to, sal_Int32 fromIndex = 0) const
2558 {
2559 rtl_uString * s = nullptr;
2560 rtl_uString_newReplaceAllFromIndexUtf16LUtf16L(
2561 &s, pData, from.data(), from.size(), to.data(), to.size(), fromIndex);
2562 return OUString(s, SAL_NO_ACQUIRE);
2563 }
2564#else
2565 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString replaceAll(
2566 OUString const & from, OUString const & to, sal_Int32 fromIndex = 0) const
2567 {
2568 rtl_uString * s = NULL__null;
2569 rtl_uString_newReplaceAllFromIndex(&s, pData, from.pData, to.pData, fromIndex);
2570 return OUString(s, SAL_NO_ACQUIRE);
2571 }
2572#endif
2573
2574 /**
2575 Returns a new string resulting from replacing all occurrences of a given
2576 substring with another substring.
2577
2578 Replacing subsequent occurrences picks up only after a given replacement.
2579 That is, replacing from "xa" to "xx" in "xaa" results in "xxa", not "xxx".
2580
2581 @param from ASCII string literal, the substring to be replaced
2582
2583 @param to the replacing substring
2584
2585 @since LibreOffice 3.6
2586 */
2587#if defined LIBO_INTERNAL_ONLY1
2588 template<typename T> [[nodiscard]]
2589 typename libreoffice_internal::ConstCharArrayDetector<T, OUString >::Type replaceAll(
2590 T & from, std::u16string_view to) const
2591 {
2592 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(from))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(from)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(from)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2592, __extension__ __PRETTY_FUNCTION__))
;
2593 rtl_uString * s = nullptr;
2594 rtl_uString_newReplaceAllAsciiLUtf16L(
2595 &s, pData, libreoffice_internal::ConstCharArrayDetector<T>::toPointer(from),
2596 libreoffice_internal::ConstCharArrayDetector<T>::length, to.data(), to.size());
2597 return OUString(s, SAL_NO_ACQUIRE);
2598 }
2599#else
2600 template< typename T >
2601 SAL_WARN_UNUSED_RESULT[[nodiscard]] typename libreoffice_internal::ConstCharArrayDetector< T, OUString >::Type replaceAll( T& from, OUString const & to) const
2602 {
2603 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(from))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(from)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(from)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2603, __extension__ __PRETTY_FUNCTION__))
;
2604 rtl_uString * s = NULL__null;
2605 rtl_uString_newReplaceAllAsciiL(
2606 &s, pData,
2607 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(from),
2608 libreoffice_internal::ConstCharArrayDetector<T>::length, to.pData);
2609 return OUString(s, SAL_NO_ACQUIRE);
2610 }
2611#endif
2612
2613 /**
2614 Returns a new string resulting from replacing all occurrences of a given
2615 substring with another substring.
2616
2617 Replacing subsequent occurrences picks up only after a given replacement.
2618 That is, replacing from "xa" to "xx" in "xaa" results in "xxa", not "xxx".
2619
2620 @param from the substring to be replaced
2621
2622 @param to ASCII string literal, the replacing substring
2623
2624 @since LibreOffice 5.1
2625 */
2626#if defined LIBO_INTERNAL_ONLY1
2627 template<typename T> [[nodiscard]]
2628 typename libreoffice_internal::ConstCharArrayDetector<T, OUString >::Type replaceAll(
2629 std::u16string_view from, T & to) const
2630 {
2631 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(to))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(to)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(to)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2631, __extension__ __PRETTY_FUNCTION__))
;
2632 rtl_uString * s = nullptr;
2633 rtl_uString_newReplaceAllUtf16LAsciiL(
2634 &s, pData, from.data(), from.size(),
2635 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(to),
2636 libreoffice_internal::ConstCharArrayDetector<T>::length);
2637 return OUString(s, SAL_NO_ACQUIRE);
2638 }
2639#else
2640 template< typename T >
2641 SAL_WARN_UNUSED_RESULT[[nodiscard]] typename libreoffice_internal::ConstCharArrayDetector< T, OUString >::Type replaceAll( OUString const & from, T& to) const
2642 {
2643 assert(libreoffice_internal::ConstCharArrayDetector<T>::isValid(to))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T>::isValid(to)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T>::isValid(to)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2643, __extension__ __PRETTY_FUNCTION__))
;
2644 rtl_uString * s = NULL__null;
2645 rtl_uString_newReplaceAllToAsciiL(
2646 &s, pData, from.pData,
2647 libreoffice_internal::ConstCharArrayDetector<T>::toPointer(to),
2648 libreoffice_internal::ConstCharArrayDetector<T>::length);
2649 return OUString(s, SAL_NO_ACQUIRE);
2650 }
2651#endif
2652
2653 /**
2654 Returns a new string resulting from replacing all occurrences of a given
2655 substring with another substring.
2656
2657 Replacing subsequent occurrences picks up only after a given replacement.
2658 That is, replacing from "xa" to "xx" in "xaa" results in "xxa", not "xxx".
2659
2660 @param from ASCII string literal, the substring to be replaced
2661
2662 @param to ASCII string literal, the substring to be replaced
2663
2664 @since LibreOffice 3.6
2665 */
2666 template< typename T1, typename T2 >
2667 SAL_WARN_UNUSED_RESULT[[nodiscard]] typename libreoffice_internal::ConstCharArrayDetector< T1, typename libreoffice_internal::ConstCharArrayDetector< T2, OUString >::Type >::Type
2668 replaceAll( T1& from, T2& to ) const
2669 {
2670 assert(libreoffice_internal::ConstCharArrayDetector<T1>::isValid(from))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T1>::isValid(from)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T1>::isValid(from)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2670, __extension__ __PRETTY_FUNCTION__))
;
2671 assert(libreoffice_internal::ConstCharArrayDetector<T2>::isValid(to))(static_cast <bool> (libreoffice_internal::ConstCharArrayDetector
<T2>::isValid(to)) ? void (0) : __assert_fail ("libreoffice_internal::ConstCharArrayDetector<T2>::isValid(to)"
, "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 2671, __extension__ __PRETTY_FUNCTION__))
;
2672 rtl_uString * s = NULL__null;
2673 rtl_uString_newReplaceAllAsciiLAsciiL(
2674 &s, pData,
2675 libreoffice_internal::ConstCharArrayDetector<T1>::toPointer(from),
2676 libreoffice_internal::ConstCharArrayDetector<T1>::length,
2677 libreoffice_internal::ConstCharArrayDetector<T2>::toPointer(to),
2678 libreoffice_internal::ConstCharArrayDetector<T2>::length);
2679 return OUString(s, SAL_NO_ACQUIRE);
2680 }
2681
2682 /**
2683 Converts from this string all ASCII uppercase characters (65-90)
2684 to ASCII lowercase characters (97-122).
2685
2686 This function can't be used for language specific conversion.
2687 If the string doesn't contain characters which must be converted,
2688 then the new string is assigned with str.
2689
2690 @return the string, converted to ASCII lowercase.
2691 */
2692 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString toAsciiLowerCase() const
2693 {
2694 rtl_uString* pNew = NULL__null;
2695 rtl_uString_newToAsciiLowerCase( &pNew, pData );
2696 return OUString( pNew, SAL_NO_ACQUIRE );
2697 }
2698
2699 /**
2700 Converts from this string all ASCII lowercase characters (97-122)
2701 to ASCII uppercase characters (65-90).
2702
2703 This function can't be used for language specific conversion.
2704 If the string doesn't contain characters which must be converted,
2705 then the new string is assigned with str.
2706
2707 @return the string, converted to ASCII uppercase.
2708 */
2709 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString toAsciiUpperCase() const
2710 {
2711 rtl_uString* pNew = NULL__null;
2712 rtl_uString_newToAsciiUpperCase( &pNew, pData );
2713 return OUString( pNew, SAL_NO_ACQUIRE );
2714 }
2715
2716 /**
2717 Returns a new string resulting from removing white space from both ends
2718 of the string.
2719
2720 All characters that have codes less than or equal to
2721 32 (the space character), and Unicode General Punctuation area Space
2722 and some Control characters are considered to be white space (see
2723 rtl_ImplIsWhitespace).
2724 If the string doesn't contain white spaces at both ends,
2725 then the new string is assigned with str.
2726
2727 @return the string, with white space removed from the front and end.
2728 */
2729 SAL_WARN_UNUSED_RESULT[[nodiscard]] OUString trim() const
2730 {
2731 rtl_uString* pNew = NULL__null;
2732 rtl_uString_newTrim( &pNew, pData );
2733 return OUString( pNew, SAL_NO_ACQUIRE );
2734 }
2735
2736 /**
2737 Returns a token in the string.
2738
2739 Example:
2740 sal_Int32 nIndex = 0;
2741 do
2742 {
2743 ...
2744 OUString aToken = aStr.getToken( 0, ';', nIndex );
2745 ...
2746 }
2747 while ( nIndex >= 0 );
2748
2749 @param token the number of the token to return
2750 @param cTok the character which separate the tokens.
2751 @param index the position at which the token is searched in the
2752 string.
2753 The index must not be greater than the length of the
2754 string.
2755 This param is set to the position of the
2756 next token or to -1, if it is the last token.
2757 @return the token; if either token or index is negative, an empty token
2758 is returned (and index is set to -1)
2759 */
2760 OUString getToken( sal_Int32 token, sal_Unicode cTok, sal_Int32& index ) const
2761 {
2762 rtl_uString * pNew = NULL__null;
2763 index = rtl_uString_getToken( &pNew, pData, token, cTok, index );
2764 return OUString( pNew, SAL_NO_ACQUIRE );
2765 }
2766
2767 /**
2768 Returns a token from the string.
2769
2770 The same as getToken(sal_Int32, sal_Unicode, sal_Int32 &), but always
2771 passing in 0 as the start index in the third argument.
2772
2773 @param count the number of the token to return, starting with 0
2774 @param separator the character which separates the tokens
2775
2776 @return the given token, or an empty string
2777
2778 @since LibreOffice 3.6
2779 */
2780 OUString getToken(sal_Int32 count, sal_Unicode separator) const {
2781 sal_Int32 n = 0;
2782 return getToken(count, separator, n);
2783 }
2784
2785 /**
2786 Returns the Boolean value from this string.
2787
2788 This function can't be used for language specific conversion.
2789
2790 @return true, if the string is 1 or "True" in any ASCII case.
2791 false in any other case.
2792 */
2793 bool toBoolean() const
2794 {
2795 return rtl_ustr_toBoolean( pData->buffer );
2796 }
2797
2798 /**
2799 Returns the first character from this string.
2800
2801 @return the first character from this string or 0, if this string
2802 is empty.
2803 */
2804 sal_Unicode toChar() const
2805 {
2806 return pData->buffer[0];
2807 }
2808
2809 /**
2810 Returns the int32 value from this string.
2811
2812 This function can't be used for language specific conversion.
2813
2814 @param radix the radix (between 2 and 36)
2815 @return the int32 represented from this string.
2816 0 if this string represents no number or one of too large
2817 magnitude.
2818 */
2819 sal_Int32 toInt32( sal_Int16 radix = 10 ) const
2820 {
2821 return rtl_ustr_toInt32( pData->buffer, radix );
2822 }
2823
2824 /**
2825 Returns the uint32 value from this string.
2826
2827 This function can't be used for language specific conversion.
2828
2829 @param radix the radix (between 2 and 36)
2830 @return the uint32 represented from this string.
2831 0 if this string represents no number or one of too large
2832 magnitude.
2833
2834 @since LibreOffice 4.2
2835 */
2836 sal_uInt32 toUInt32( sal_Int16 radix = 10 ) const
2837 {
2838 return rtl_ustr_toUInt32( pData->buffer, radix );
2839 }
2840
2841 /**
2842 Returns the int64 value from this string.
2843
2844 This function can't be used for language specific conversion.
2845
2846 @param radix the radix (between 2 and 36)
2847 @return the int64 represented from this string.
2848 0 if this string represents no number or one of too large
2849 magnitude.
2850 */
2851 sal_Int64 toInt64( sal_Int16 radix = 10 ) const
2852 {
2853 return rtl_ustr_toInt64( pData->buffer, radix );
2854 }
2855
2856 /**
2857 Returns the uint64 value from this string.
2858
2859 This function can't be used for language specific conversion.
2860
2861 @param radix the radix (between 2 and 36)
2862 @return the uint64 represented from this string.
2863 0 if this string represents no number or one of too large
2864 magnitude.
2865
2866 @since LibreOffice 4.1
2867 */
2868 sal_uInt64 toUInt64( sal_Int16 radix = 10 ) const
2869 {
2870 return rtl_ustr_toUInt64( pData->buffer, radix );
2871 }
2872
2873 /**
2874 Returns the float value from this string.
2875
2876 This function can't be used for language specific conversion.
2877
2878 @return the float represented from this string.
2879 0.0 if this string represents no number.
2880 */
2881 float toFloat() const
2882 {
2883 return rtl_ustr_toFloat( pData->buffer );
2884 }
2885
2886 /**
2887 Returns the double value from this string.
2888
2889 This function can't be used for language specific conversion.
2890
2891 @return the double represented from this string.
2892 0.0 if this string represents no number.
2893 */
2894 double toDouble() const
2895 {
2896 return rtl_ustr_toDouble( pData->buffer );
2897 }
2898
2899
2900 /**
2901 Return a canonical representation for a string.
2902
2903 A pool of strings, initially empty is maintained privately
2904 by the string class. On invocation, if present in the pool
2905 the original string will be returned. Otherwise this string,
2906 or a copy thereof will be added to the pool and returned.
2907
2908 @return
2909 a version of the string from the pool.
2910
2911 @exception std::bad_alloc is thrown if an out-of-memory condition occurs
2912
2913 @since UDK 3.2.7
2914 */
2915 OUString intern() const
2916 {
2917 rtl_uString * pNew = NULL__null;
2918 rtl_uString_intern( &pNew, pData );
2919 if (pNew == NULL__null) {
2920 throw std::bad_alloc();
2921 }
2922 return OUString( pNew, SAL_NO_ACQUIRE );
2923 }
2924
2925 /**
2926 Return a canonical representation for a converted string.
2927
2928 A pool of strings, initially empty is maintained privately
2929 by the string class. On invocation, if present in the pool
2930 the original string will be returned. Otherwise this string,
2931 or a copy thereof will be added to the pool and returned.
2932
2933 @param value a 8-Bit character array.
2934 @param length the number of character which should be converted.
2935 The 8-Bit character array length must be
2936 greater than or equal to this value.
2937 @param encoding the text encoding from which the 8-Bit character
2938 sequence should be converted.
2939 @param convertFlags flags which controls the conversion.
2940 see RTL_TEXTTOUNICODE_FLAGS_...
2941 @param pInfo pointer to return conversion status or NULL.
2942
2943 @return
2944 a version of the converted string from the pool.
2945
2946 @exception std::bad_alloc is thrown if an out-of-memory condition occurs
2947
2948 @since UDK 3.2.7
2949 */
2950 static OUString intern( const char * value, sal_Int32 length,
2951 rtl_TextEncoding encoding,
2952 sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS(((sal_uInt32)0x0003) | ((sal_uInt32)0x0030) | ((sal_uInt32)0x0300
))
,
2953 sal_uInt32 *pInfo = NULL__null )
2954 {
2955 rtl_uString * pNew = NULL__null;
2956 rtl_uString_internConvert( &pNew, value, length, encoding,
2957 convertFlags, pInfo );
2958 if (pNew == NULL__null) {
2959 throw std::bad_alloc();
2960 }
2961 return OUString( pNew, SAL_NO_ACQUIRE );
2962 }
2963
2964 /**
2965 Converts to an OString, signalling failure.
2966
2967 @param pTarget
2968 An out parameter receiving the converted OString. Must not be null; the
2969 contents are not modified if conversion fails (convertToOString returns
2970 false).
2971
2972 @param nEncoding
2973 The text encoding to convert into. Must be an octet encoding (i.e.,
2974 rtl_isOctetTextEncoding(nEncoding) must return true).
2975
2976 @param nFlags
2977 A combination of RTL_UNICODETOTEXT_FLAGS that detail how to do the
2978 conversion (see rtl_convertUnicodeToText). RTL_UNICODETOTEXT_FLAGS_FLUSH
2979 need not be included, it is implicitly assumed. Typical uses are either
2980 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
2981 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR (fail if a Unicode character cannot
2982 be converted to the target nEncoding) or OUSTRING_TO_OSTRING_CVTFLAGS
2983 (make a best efforts conversion).
2984
2985 @return
2986 True if the conversion succeeded, false otherwise.
2987 */
2988 bool convertToString(OString * pTarget, rtl_TextEncoding nEncoding,
2989 sal_uInt32 nFlags) const
2990 {
2991 return rtl_convertUStringToString(&pTarget->pData, pData->buffer,
2992 pData->length, nEncoding, nFlags);
2993 }
2994
2995 /** Iterate through this string based on code points instead of UTF-16 code
2996 units.
2997
2998 See Chapter 3 of The Unicode Standard 5.0 (Addison--Wesley, 2006) for
2999 definitions of the various terms used in this description.
3000
3001 This string is interpreted as a sequence of zero or more UTF-16 code
3002 units. For each index into this sequence (from zero to one less than
3003 the length of the sequence, inclusive), a code point represented
3004 starting at the given index is computed as follows:
3005
3006 - If the UTF-16 code unit addressed by the index constitutes a
3007 well-formed UTF-16 code unit sequence, the computed code point is the
3008 scalar value encoded by that UTF-16 code unit sequence.
3009
3010 - Otherwise, if the index is at least two UTF-16 code units away from
3011 the end of the sequence, and the sequence of two UTF-16 code units
3012 addressed by the index constitutes a well-formed UTF-16 code unit
3013 sequence, the computed code point is the scalar value encoded by that
3014 UTF-16 code unit sequence.
3015
3016 - Otherwise, the computed code point is the UTF-16 code unit addressed
3017 by the index. (This last case catches unmatched surrogates as well as
3018 indices pointing into the middle of surrogate pairs.)
3019
3020 @param indexUtf16
3021 pointer to a UTF-16 based index into this string; must not be null. On
3022 entry, the index must be in the range from zero to the length of this
3023 string (in UTF-16 code units), inclusive. Upon successful return, the
3024 index will be updated to address the UTF-16 code unit that is the given
3025 incrementCodePoints away from the initial index.
3026
3027 @param incrementCodePoints
3028 the number of code points to move the given *indexUtf16. If
3029 non-negative, moving is done after determining the code point at the
3030 index. If negative, moving is done before determining the code point
3031 at the (then updated) index. The value must be such that the resulting
3032 UTF-16 based index is in the range from zero to the length of this
3033 string (in UTF-16 code units), inclusive.
3034
3035 @return
3036 the code point (an integer in the range from 0 to 0x10FFFF, inclusive)
3037 that is represented within this string starting at the index computed as
3038 follows: If incrementCodePoints is non-negative, the index is the
3039 initial value of *indexUtf16; if incrementCodePoints is negative, the
3040 index is the updated value of *indexUtf16. In either case, the computed
3041 index must be in the range from zero to one less than the length of this
3042 string (in UTF-16 code units), inclusive.
3043
3044 @since UDK 3.2.7
3045 */
3046 sal_uInt32 iterateCodePoints(
3047 sal_Int32 * indexUtf16, sal_Int32 incrementCodePoints = 1) const
3048 {
3049 return rtl_uString_iterateCodePoints(
3050 pData, indexUtf16, incrementCodePoints);
3051 }
3052
3053 /**
3054 * Convert an OString to an OUString, assuming that the OString is
3055 * UTF-8-encoded.
3056 *
3057 * @param rSource
3058 * an OString to convert
3059 *
3060 * @since LibreOffice 4.4
3061 */
3062 static OUString fromUtf8(const OString& rSource)
3063 {
3064 OUString aTarget;
3065 bool bSuccess = rtl_convertStringToUString(&aTarget.pData,
3066 rSource.getStr(),
3067 rSource.getLength(),
3068 RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)),
3069 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR((sal_uInt32)0x0001)|RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR((sal_uInt32)0x0010)|RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR((sal_uInt32)0x0100));
3070 (void) bSuccess;
3071 assert(bSuccess)(static_cast <bool> (bSuccess) ? void (0) : __assert_fail
("bSuccess", "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 3071, __extension__ __PRETTY_FUNCTION__))
;
3072 return aTarget;
3073 }
3074
3075 /**
3076 * Convert this string to an OString, assuming that the string can be
3077 * UTF-8-encoded successfully.
3078 *
3079 * In other words, you must not use this method on a random sequence of
3080 * UTF-16 code units, but only at places where it is assumed that the
3081 * content is a proper string.
3082 *
3083 * @since LibreOffice 4.4
3084 */
3085 OString toUtf8() const
3086 {
3087 OString aTarget;
3088 bool bSuccess = rtl_convertUStringToString(&aTarget.pData,
3089 getStr(),
3090 getLength(),
3091 RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)),
3092 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR((sal_uInt32)0x0001)|RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR((sal_uInt32)0x0010));
3093 (void) bSuccess;
3094 assert(bSuccess)(static_cast <bool> (bSuccess) ? void (0) : __assert_fail
("bSuccess", "/home/maarten/src/libreoffice/core/include/rtl/ustring.hxx"
, 3094, __extension__ __PRETTY_FUNCTION__))
;
3095 return aTarget;
3096 }
3097
3098#ifdef LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
3099
3100 static OUStringNumber< int > number( int i, sal_Int16 radix = 10 )
3101 {
3102 return OUStringNumber< int >( i, radix );
3103 }
3104 static OUStringNumber< long long > number( long long ll, sal_Int16 radix = 10 )
3105 {
3106 return OUStringNumber< long long >( ll, radix );
3107 }
3108 static OUStringNumber< unsigned long long > number( unsigned long long ll, sal_Int16 radix = 10 )
3109 {
3110 return OUStringNumber< unsigned long long >( ll, radix );
3111 }
3112 static OUStringNumber< unsigned long long > number( unsigned int i, sal_Int16 radix = 10 )
3113 {
3114 return number( static_cast< unsigned long long >( i ), radix );
3115 }
3116 static OUStringNumber< long long > number( long i, sal_Int16 radix = 10)
3117 {
3118 return number( static_cast< long long >( i ), radix );
3119 }
3120 static OUStringNumber< unsigned long long > number( unsigned long i, sal_Int16 radix = 10 )
3121 {
3122 return number( static_cast< unsigned long long >( i ), radix );
3123 }
3124 static OUStringNumber< float > number( float f )
3125 {
3126 return OUStringNumber< float >( f );
3127 }
3128 static OUStringNumber< double > number( double d )
3129 {
3130 return OUStringNumber< double >( d );
3131 }
3132#else
3133 /**
3134 Returns the string representation of the integer argument.
3135
3136 This function can't be used for language specific conversion.
3137
3138 @param i an integer value
3139 @param radix the radix (between 2 and 36)
3140 @return a string with the string representation of the argument.
3141 @since LibreOffice 4.1
3142 */
3143 static OUString number( int i, sal_Int16 radix = 10 )
3144 {
3145 sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT3233];
3146 return OUString(aBuf, rtl_ustr_valueOfInt32(aBuf, i, radix));
3147 }
3148 /// @overload
3149 /// @since LibreOffice 4.1
3150 static OUString number( unsigned int i, sal_Int16 radix = 10 )
3151 {
3152 return number( static_cast< unsigned long long >( i ), radix );
3153 }
3154 /// @overload
3155 /// @since LibreOffice 4.1
3156 static OUString number( long i, sal_Int16 radix = 10)
3157 {
3158 return number( static_cast< long long >( i ), radix );
3159 }
3160 /// @overload
3161 /// @since LibreOffice 4.1
3162 static OUString number( unsigned long i, sal_Int16 radix = 10 )
3163 {
3164 return number( static_cast< unsigned long long >( i ), radix );
3165 }
3166 /// @overload
3167 /// @since LibreOffice 4.1
3168 static OUString number( long long ll, sal_Int16 radix = 10 )
3169 {
3170 sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT6465];
3171 return OUString(aBuf, rtl_ustr_valueOfInt64(aBuf, ll, radix));
3172 }
3173 /// @overload
3174 /// @since LibreOffice 4.1
3175 static OUString number( unsigned long long ll, sal_Int16 radix = 10 )
3176 {
3177 sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFUINT6465];
3178 return OUString(aBuf, rtl_ustr_valueOfUInt64(aBuf, ll, radix));
3179 }
3180
3181 /**
3182 Returns the string representation of the float argument.
3183
3184 This function can't be used for language specific conversion.
3185
3186 @param f a float.
3187 @return a string with the decimal representation of the argument.
3188 @since LibreOffice 4.1
3189 */
3190 static OUString number( float f )
3191 {
3192 sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFFLOAT15];
3193 return OUString(aBuf, rtl_ustr_valueOfFloat(aBuf, f));
3194 }
3195
3196 /**
3197 Returns the string representation of the double argument.
3198
3199 This function can't be used for language specific conversion.
3200
3201 @param d a double.
3202 @return a string with the decimal representation of the argument.
3203 @since LibreOffice 4.1
3204 */
3205 static OUString number( double d )
3206 {
3207 sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFDOUBLE25];
3208 return OUString(aBuf, rtl_ustr_valueOfDouble(aBuf, d));
3209 }
3210#endif
3211
3212 /**
3213 Returns the string representation of the sal_Bool argument.
3214
3215 If the sal_Bool is true, the string "true" is returned.
3216 If the sal_Bool is false, the string "false" is returned.
3217 This function can't be used for language specific conversion.
3218
3219 @param b a sal_Bool.
3220 @return a string with the string representation of the argument.
3221 @deprecated use boolean()
3222 */
3223 SAL_DEPRECATED("use boolean()")__attribute__((deprecated("use boolean()"))) static OUString valueOf( sal_Bool b )
3224 {
3225 return boolean(b);
3226 }
3227
3228 /**
3229 Returns the string representation of the boolean argument.
3230
3231 If the argument is true, the string "true" is returned.
3232 If the argument is false, the string "false" is returned.
3233 This function can't be used for language specific conversion.
3234
3235 @param b a bool.
3236 @return a string with the string representation of the argument.
3237 @since LibreOffice 4.1
3238 */
3239 static OUString boolean( bool b )
3240 {
3241 sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFBOOLEAN6];
3242 return OUString(aBuf, rtl_ustr_valueOfBoolean(aBuf, b));
3243 }
3244
3245 /**
3246 Returns the string representation of the char argument.
3247
3248 @param c a character.
3249 @return a string with the string representation of the argument.
3250 @deprecated use operator, function or constructor taking char or sal_Unicode argument
3251 */
3252 SAL_DEPRECATED("convert to OUString or use directly")__attribute__((deprecated("convert to OUString or use directly"
)))
static OUString valueOf( sal_Unicode c )
3253 {
3254 return OUString( &c, 1 );
3255 }
3256
3257 /**
3258 Returns the string representation of the int argument.
3259
3260 This function can't be used for language specific conversion.
3261
3262 @param i a int32.
3263 @param radix the radix (between 2 and 36)
3264 @return a string with the string representation of the argument.
3265 @deprecated use number()
3266 */
3267 SAL_DEPRECATED("use number()")__attribute__((deprecated("use number()"))) static OUString valueOf( sal_Int32 i, sal_Int16 radix = 10 )
3268 {
3269 return number( i, radix );
3270 }
3271
3272 /**
3273 Returns the string representation of the long argument.
3274
3275 This function can't be used for language specific conversion.
3276
3277 @param ll a int64.
3278 @param radix the radix (between 2 and 36)
3279 @return a string with the string representation of the argument.
3280 @deprecated use number()
3281 */
3282 SAL_DEPRECATED("use number()")__attribute__((deprecated("use number()"))) static OUString valueOf( sal_Int64 ll, sal_Int16 radix = 10 )
3283 {
3284 return number( ll, radix );
3285 }
3286
3287 /**
3288 Returns the string representation of the float argument.
3289
3290 This function can't be used for language specific conversion.
3291
3292 @param f a float.
3293 @return a string with the string representation of the argument.
3294 @deprecated use number()
3295 */
3296 SAL_DEPRECATED("use number()")__attribute__((deprecated("use number()"))) static OUString valueOf( float f )
3297 {
3298 return number(f);
3299 }
3300
3301 /**
3302 Returns the string representation of the double argument.
3303
3304 This function can't be used for language specific conversion.
3305
3306 @param d a double.
3307 @return a string with the string representation of the argument.
3308 @deprecated use number()
3309 */
3310 SAL_DEPRECATED("use number()")__attribute__((deprecated("use number()"))) static OUString valueOf( double d )
3311 {
3312 return number(d);
3313 }
3314
3315 /**
3316 Returns an OUString copied without conversion from an ASCII
3317 character string.
3318
3319 Since this method is optimized for performance, the ASCII character
3320 values are not converted in any way. The caller has to make sure that
3321 all ASCII characters are in the allowed range between 0 and 127.
3322 The ASCII string must be NULL-terminated.
3323
3324 Note that for string literals it is simpler and more efficient
3325 to directly use the OUString constructor.
3326
3327 @param value the 8-Bit ASCII character string
3328 @return a string with the string representation of the argument.
3329 */
3330 static OUString createFromAscii( const char * value )
3331 {
3332 rtl_uString* pNew = NULL__null;
3333 rtl_uString_newFromAscii( &pNew, value );
3334 return OUString( pNew, SAL_NO_ACQUIRE );
3335 }
3336
3337#if defined LIBO_INTERNAL_ONLY1
3338 static OUString createFromAscii(std::string_view value) {
3339 rtl_uString * p = nullptr;
3340 rtl_uString_newFromLiteral(&p, value.data(), value.size(), 0); //TODO: check for overflow
3341 return OUString(p, SAL_NO_ACQUIRE);
3342 }
3343 #endif
3344
3345#if defined LIBO_INTERNAL_ONLY1
3346 operator std::u16string_view() const { return {getStr(), sal_uInt32(getLength())}; }
3347#endif
3348
3349#if defined LIBO_INTERNAL_ONLY1
3350 // A wrapper for the first expression in an
3351 //
3352 // OUString::Concat(e1) + e2 + ...
3353 //
3354 // concatenation chain, when neither of the first two e1, e2 is one of our rtl string-related
3355 // classes (so something like
3356 //
3357 // OUString s = "a" + (b ? std::u16string_view(u"c") : std::u16string_view(u"dd"));
3358 //
3359 // would not compile):
3360 template<typename T> [[nodiscard]] static
3361 typename std::enable_if_t<
3362 ToStringHelper<T>::allowOUStringConcat, OUStringConcat<OUStringConcatMarker, T>>
3363 Concat(T const & value) { return OUStringConcat<OUStringConcatMarker, T>({}, value); }
3364
3365 // This overload is needed so that an argument of type 'char const[N]' ends up as
3366 // 'OUStringConcat<rtl::OUStringConcatMarker, char const[N]>' rather than as
3367 // 'OUStringConcat<rtl::OUStringConcatMarker, char[N]>':
3368 template<typename T, std::size_t N> [[nodiscard]] static
3369 typename std::enable_if_t<
3370 ToStringHelper<T[N]>::allowOUStringConcat, OUStringConcat<OUStringConcatMarker, T[N]>>
3371 Concat(T (& value)[N]) { return OUStringConcat<OUStringConcatMarker, T[N]>({}, value); }
3372#endif
3373
3374private:
3375 OUString & internalAppend( rtl_uString* pOtherData )
3376 {
3377 rtl_uString* pNewData = NULL__null;
3378 rtl_uString_newConcat( &pNewData, pData, pOtherData );
3379 if (pNewData == NULL__null) {
3380 throw std::bad_alloc();
3381 }
3382 rtl_uString_assign(&pData, pNewData);
3383 rtl_uString_release(pNewData);
3384 return *this;
3385 }
3386
3387};
3388
3389#if defined LIBO_INTERNAL_ONLY1
3390// Prevent the operator ==/!= overloads with 'sal_Unicode const *' parameter from
3391// being selected for nonsensical code like
3392//
3393// if (ouIdAttr == nullptr)
3394//
3395void operator ==(OUString const &, std::nullptr_t) = delete;
3396void operator ==(std::nullptr_t, OUString const &) = delete;
3397void operator !=(OUString const &, std::nullptr_t) = delete;
3398void operator !=(std::nullptr_t, OUString const &) = delete;
3399#endif
3400
3401#if defined LIBO_INTERNAL_ONLY1 // "RTL_FAST_STRING"
3402/// @cond INTERNAL
3403
3404/**
3405 @internal
3406*/
3407template<>
3408struct ToStringHelper< OUString >
3409 {
3410 static std::size_t length( const OUString& s ) { return s.getLength(); }
3411 static sal_Unicode* addData( sal_Unicode* buffer, const OUString& s ) { return addDataHelper( buffer, s.getStr(), s.getLength()); }
3412 static const bool allowOStringConcat = false;
3413 static const bool allowOUStringConcat = true;
3414 };
3415
3416/**
3417 @internal
3418*/
3419template<std::size_t N>
3420struct ToStringHelper< OUStringLiteral<N> >
3421 {
3422 static std::size_t length( const OUStringLiteral<N>& str ) { return str.getLength(); }
3423 static sal_Unicode* addData( sal_Unicode* buffer, const OUStringLiteral<N>& str ) { return addDataHelper( buffer, str.getStr(), str.getLength() ); }
3424 static const bool allowOStringConcat = false;
3425 static const bool allowOUStringConcat = true;
3426 };
3427
3428/**
3429 @internal
3430*/
3431template< typename charT, typename traits, typename T1, typename T2 >
3432inline std::basic_ostream<charT, traits> & operator <<(
3433 std::basic_ostream<charT, traits> & stream, OUStringConcat< T1, T2 >&& concat)
3434{
3435 return stream << OUString( std::move(concat) );
3436}
3437
3438/// @endcond
3439#endif
3440
3441/** A helper to use OUStrings with hash maps.
3442
3443 Instances of this class are unary function objects that can be used as
3444 hash function arguments to std::unordered_map and similar constructs.
3445 */
3446struct OUStringHash
3447{
3448 /** Compute a hash code for a string.
3449
3450 @param rString
3451 a string.
3452
3453 @return
3454 a hash code for the string. This hash code should not be stored
3455 persistently, as its computation may change in later revisions.
3456 */
3457 size_t operator()(const OUString& rString) const
3458 { return static_cast<size_t>(rString.hashCode()); }
3459};
3460
3461/* ======================================================================= */
3462
3463/** Convert an OString to an OUString, using a specific text encoding.
3464
3465 The lengths of the two strings may differ (e.g., for double-byte
3466 encodings, UTF-7, UTF-8).
3467
3468 @param rStr
3469 an OString to convert.
3470
3471 @param encoding
3472 the text encoding to use for conversion.
3473
3474 @param convertFlags
3475 flags which control the conversion. Either use
3476 OSTRING_TO_OUSTRING_CVTFLAGS, or see
3477 <http://udk.openoffice.org/cpp/man/spec/textconversion.html> for more
3478 details.
3479 */
3480inline OUString OStringToOUString( const OString & rStr,
3481 rtl_TextEncoding encoding,
3482 sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS(((sal_uInt32)0x0003) | ((sal_uInt32)0x0030) | ((sal_uInt32)0x0300
))
)
3483{
3484 return OUString( rStr.getStr(), rStr.getLength(), encoding, convertFlags );
3485}
3486
3487/** Convert an OUString to an OString, using a specific text encoding.
3488
3489 The lengths of the two strings may differ (e.g., for double-byte
3490 encodings, UTF-7, UTF-8).
3491
3492 @param rUnicode
3493 an OUString to convert.
3494
3495 @param encoding
3496 the text encoding to use for conversion.
3497
3498 @param convertFlags
3499 flags which control the conversion. Either use
3500 OUSTRING_TO_OSTRING_CVTFLAGS, or see
3501 <http://udk.openoffice.org/cpp/man/spec/textconversion.html> for more
3502 details.
3503 */
3504inline OString OUStringToOString( const OUString & rUnicode,
3505 rtl_TextEncoding encoding,
3506 sal_uInt32 convertFlags = OUSTRING_TO_OSTRING_CVTFLAGS(((sal_uInt32)0x0006) | ((sal_uInt32)0x0060) | ((sal_uInt32)0x0100
) | ((sal_uInt32)0x0400))
)
3507{
3508 return OString( rUnicode.getStr(), rUnicode.getLength(), encoding, convertFlags );
3509}
3510
3511/* ======================================================================= */
3512
3513/**
3514 Support for rtl::OUString in std::ostream (and thus in
3515 CPPUNIT_ASSERT or SAL_INFO macros, for example).
3516
3517 The rtl::OUString is converted to UTF-8.
3518
3519 @since LibreOffice 3.5.
3520*/
3521template< typename charT, typename traits >
3522inline std::basic_ostream<charT, traits> & operator <<(
3523 std::basic_ostream<charT, traits> & stream, OUString const & rString)
3524{
3525 return stream <<
3526 OUStringToOString(rString, RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)));
3527 // best effort; potentially loses data due to conversion failures
3528 // (stray surrogate halves) and embedded null characters
3529}
3530
3531} // namespace
3532
3533#ifdef RTL_STRING_UNITTEST
3534namespace rtl
3535{
3536typedef rtlunittest::OUString OUString;
3537}
3538#endif
3539
3540// In internal code, allow to use classes like OUString without having to
3541// explicitly refer to the rtl namespace, which is kind of superfluous given
3542// that OUString itself is namespaced by its OU prefix:
3543#if defined LIBO_INTERNAL_ONLY1 && !defined RTL_STRING_UNITTEST
3544using ::rtl::OUString;
3545using ::rtl::OUStringHash;
3546using ::rtl::OStringToOUString;
3547using ::rtl::OUStringToOString;
3548using ::rtl::OUStringLiteral;
3549using ::rtl::OUStringChar;
3550#endif
3551
3552/// @cond INTERNAL
3553/**
3554 Make OUString hashable by default for use in STL containers.
3555
3556 @since LibreOffice 6.0
3557*/
3558#if defined LIBO_INTERNAL_ONLY1
3559namespace std {
3560
3561template<>
3562struct hash<::rtl::OUString>
3563{
3564 std::size_t operator()(::rtl::OUString const & s) const
3565 { return std::size_t(s.hashCode()); }
3566};
3567
3568}
3569
3570#endif
3571/// @endcond
3572
3573#endif /* _RTL_USTRING_HXX */
3574
3575/* vim:set shiftwidth=4 softtabstop=4 expandtab: */