File: | home/maarten/src/libreoffice/core/scripting/source/stringresource/stringresource.cxx |
Warning: | line 486, column 17 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||||
42 | using namespace ::com::sun::star; | ||||||
43 | using namespace ::com::sun::star::lang; | ||||||
44 | using namespace ::com::sun::star::uno; | ||||||
45 | using namespace ::com::sun::star::ucb; | ||||||
46 | using namespace ::com::sun::star::util; | ||||||
47 | using namespace ::com::sun::star::embed; | ||||||
48 | using namespace ::com::sun::star::container; | ||||||
49 | |||||||
50 | |||||||
51 | namespace 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 | |||||||
68 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface* | ||||||
69 | scripting_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 | |||||||
76 | StringResourceImpl::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 | |||||||
89 | StringResourceImpl::~StringResourceImpl() | ||||||
90 | { | ||||||
91 | } | ||||||
92 | |||||||
93 | |||||||
94 | // XServiceInfo | ||||||
95 | |||||||
96 | OUString StringResourceImpl::getImplementationName( ) | ||||||
97 | { | ||||||
98 | return "com.sun.star.comp.scripting.StringResource"; | ||||||
99 | } | ||||||
100 | |||||||
101 | sal_Bool StringResourceImpl::supportsService( const OUString& rServiceName ) | ||||||
102 | { | ||||||
103 | return cppu::supportsService(this, rServiceName); | ||||||
104 | } | ||||||
105 | |||||||
106 | Sequence< OUString > StringResourceImpl::getSupportedServiceNames( ) | ||||||
107 | { | ||||||
108 | return { "com.sun.star.resource.StringResource" }; | ||||||
109 | } | ||||||
110 | |||||||
111 | |||||||
112 | // XModifyBroadcaster | ||||||
113 | |||||||
114 | void 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 | |||||||
123 | void 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 | |||||||
135 | OUString 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 | |||||||
156 | OUString StringResourceImpl::resolveString( const OUString& ResourceID ) | ||||||
157 | { | ||||||
158 | ::osl::MutexGuard aGuard( getMutex() ); | ||||||
159 | return implResolveString( ResourceID, m_pCurrentLocaleItem ); | ||||||
160 | } | ||||||
161 | |||||||
162 | OUString 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 | |||||||
169 | bool 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 | |||||||
181 | sal_Bool StringResourceImpl::hasEntryForId( const OUString& ResourceID ) | ||||||
182 | { | ||||||
183 | ::osl::MutexGuard aGuard( getMutex() ); | ||||||
184 | return implHasEntryForId( ResourceID, m_pCurrentLocaleItem ); | ||||||
185 | } | ||||||
186 | |||||||
187 | sal_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 | |||||||
195 | Sequence< 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 | |||||||
216 | Sequence< 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 | |||||||
224 | Sequence< OUString > StringResourceImpl::getResourceIDs( ) | ||||||
225 | { | ||||||
226 | ::osl::MutexGuard aGuard( getMutex() ); | ||||||
227 | return implGetResourceIDs( m_pCurrentLocaleItem ); | ||||||
228 | } | ||||||
229 | |||||||
230 | Locale 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 | |||||||
240 | Locale 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 | |||||||
250 | Sequence< 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 | |||||||
269 | void StringResourceImpl::implCheckReadOnly( const char* pExceptionMsg ) | ||||||
270 | { | ||||||
271 | if( m_bReadOnly ) | ||||||
272 | { | ||||||
273 | OUString errorMsg = OUString::createFromAscii( pExceptionMsg ); | ||||||
274 | throw NoSupportException( errorMsg ); | ||||||
275 | } | ||||||
276 | } | ||||||
277 | |||||||
278 | sal_Bool StringResourceImpl::isReadOnly() | ||||||
279 | { | ||||||
280 | return m_bReadOnly; | ||||||
281 | } | ||||||
282 | |||||||
283 | void 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 | |||||||
307 | void StringResourceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) | ||||||
308 | { | ||||||
309 | implSetCurrentLocale( locale, FindClosestMatch, false/*bUseDefaultIfNoMatch*/ ); | ||||||
310 | } | ||||||
311 | |||||||
312 | void 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 | |||||||
332 | void 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 | |||||||
353 | void 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 | |||||||
360 | void 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 | |||||||
369 | void 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 | |||||||
385 | void StringResourceImpl::removeId( const OUString& ResourceID ) | ||||||
386 | { | ||||||
387 | ::osl::MutexGuard aGuard( getMutex() ); | ||||||
388 | implCheckReadOnly( "StringResourceImpl::removeId(): Read only" ); | ||||||
389 | implRemoveId( ResourceID, m_pCurrentLocaleItem ); | ||||||
390 | } | ||||||
391 | |||||||
392 | void 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 | |||||||
400 | void 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 | |||||||
459 | void StringResourceImpl::removeLocale( const Locale& locale ) | ||||||
460 | { | ||||||
461 | ::osl::MutexGuard aGuard( getMutex() ); | ||||||
462 | implCheckReadOnly( "StringResourceImpl::removeLocale(): Read only" ); | ||||||
463 | |||||||
464 | LocaleItem* pRemoveItem = getItemForLocale( locale, true ); | ||||||
465 | if( !pRemoveItem
| ||||||
466 | return; | ||||||
467 | |||||||
468 | // Last locale? | ||||||
469 | sal_Int32 nLocaleCount = m_aLocaleItemVector.size(); | ||||||
470 | if( nLocaleCount > 1 ) | ||||||
471 | { | ||||||
472 | if( m_pCurrentLocaleItem == pRemoveItem || | ||||||
473 | m_pDefaultLocaleItem == pRemoveItem ) | ||||||
474 | { | ||||||
475 | LocaleItem* pFallbackItem = nullptr; | ||||||
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 ) | ||||||
485 | { | ||||||
486 | setCurrentLocale( pFallbackItem->m_locale, false/*FindClosestMatch*/ ); | ||||||
| |||||||
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 | |||||||
520 | void 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 | |||||||
542 | sal_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 | |||||||
560 | LocaleItem* 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 ) | ||||||
569 | { | ||||||
570 | Locale& cmp_locale = pLocaleItem->m_locale; | ||||||
571 | if( cmp_locale.Language == locale.Language && | ||||||
572 | cmp_locale.Country == locale.Country && | ||||||
573 | cmp_locale.Variant == locale.Variant ) | ||||||
574 | { | ||||||
575 | pRetItem = pLocaleItem.get(); | ||||||
576 | break; | ||||||
577 | } | ||||||
578 | } | ||||||
579 | } | ||||||
580 | |||||||
581 | if( pRetItem == nullptr && bException ) | ||||||
582 | { | ||||||
583 | throw IllegalArgumentException( "StringResourceImpl: Invalid locale", Reference< XInterface >(), 0 ); | ||||||
584 | } | ||||||
585 | return pRetItem; | ||||||
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. | ||||||
590 | LocaleItem* 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 | |||||||
608 | void StringResourceImpl::implModified() | ||||||
609 | { | ||||||
610 | m_bModified = true; | ||||||
611 | implNotifyListeners(); | ||||||
612 | } | ||||||
613 | |||||||
614 | void 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 | |||||||
638 | bool StringResourceImpl::loadLocale( LocaleItem* ) | ||||||
639 | { | ||||||
640 | // Base implementation has nothing to load | ||||||
641 | return true; | ||||||
642 | } | ||||||
643 | |||||||
644 | void StringResourceImpl::implLoadAllLocales() | ||||||
645 | { | ||||||
646 | // Base implementation has nothing to load | ||||||
647 | } | ||||||
648 | |||||||
649 | |||||||
650 | // StringResourcePersistenceImpl | ||||||
651 | |||||||
652 | |||||||
653 | StringResourcePersistenceImpl::StringResourcePersistenceImpl( const Reference< XComponentContext >& rxContext ) | ||||||
654 | : StringResourcePersistenceImpl_BASE( rxContext ) | ||||||
655 | { | ||||||
656 | } | ||||||
657 | |||||||
658 | |||||||
659 | StringResourcePersistenceImpl::~StringResourcePersistenceImpl() | ||||||
660 | { | ||||||
661 | } | ||||||
662 | |||||||
663 | |||||||
664 | // XServiceInfo | ||||||
665 | |||||||
666 | |||||||
667 | OUString StringResourcePersistenceImpl::getImplementationName( ) | ||||||
668 | { | ||||||
669 | return "com.sun.star.comp.scripting.StringResource"; | ||||||
670 | } | ||||||
671 | |||||||
672 | |||||||
673 | sal_Bool StringResourcePersistenceImpl::supportsService( const OUString& rServiceName ) | ||||||
674 | { | ||||||
675 | return cppu::supportsService( this, rServiceName ); | ||||||
676 | } | ||||||
677 | |||||||
678 | |||||||
679 | Sequence< OUString > StringResourcePersistenceImpl::getSupportedServiceNames( ) | ||||||
680 | { | ||||||
681 | return StringResourceImpl::getSupportedServiceNames(); | ||||||
682 | } | ||||||
683 | |||||||
684 | |||||||
685 | // XInitialization base functionality for derived classes | ||||||
686 | |||||||
687 | |||||||
688 | const char aNameBaseDefaultStr[] = "strings"; | ||||||
689 | |||||||
690 | void 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 | ||||||
729 | void StringResourcePersistenceImpl::addModifyListener( const Reference< XModifyListener >& aListener ) | ||||||
730 | { | ||||||
731 | StringResourceImpl::addModifyListener( aListener ); | ||||||
732 | } | ||||||
733 | void StringResourcePersistenceImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) | ||||||
734 | { | ||||||
735 | StringResourceImpl::removeModifyListener( aListener ); | ||||||
736 | } | ||||||
737 | |||||||
738 | // XStringResourceResolver | ||||||
739 | OUString StringResourcePersistenceImpl::resolveString( const OUString& ResourceID ) | ||||||
740 | { | ||||||
741 | return StringResourceImpl::resolveString( ResourceID ) ; | ||||||
742 | } | ||||||
743 | OUString StringResourcePersistenceImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale ) | ||||||
744 | { | ||||||
745 | return StringResourceImpl::resolveStringForLocale( ResourceID, locale ); | ||||||
746 | } | ||||||
747 | sal_Bool StringResourcePersistenceImpl::hasEntryForId( const OUString& ResourceID ) | ||||||
748 | { | ||||||
749 | return StringResourceImpl::hasEntryForId( ResourceID ) ; | ||||||
750 | } | ||||||
751 | sal_Bool StringResourcePersistenceImpl::hasEntryForIdAndLocale( const OUString& ResourceID, | ||||||
752 | const Locale& locale ) | ||||||
753 | { | ||||||
754 | return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale ); | ||||||
755 | } | ||||||
756 | Locale StringResourcePersistenceImpl::getCurrentLocale() | ||||||
757 | { | ||||||
758 | return StringResourceImpl::getCurrentLocale(); | ||||||
759 | } | ||||||
760 | Locale StringResourcePersistenceImpl::getDefaultLocale( ) | ||||||
761 | { | ||||||
762 | return StringResourceImpl::getDefaultLocale(); | ||||||
763 | } | ||||||
764 | Sequence< Locale > StringResourcePersistenceImpl::getLocales( ) | ||||||
765 | { | ||||||
766 | return StringResourceImpl::getLocales(); | ||||||
767 | } | ||||||
768 | |||||||
769 | // XStringResourceManager | ||||||
770 | sal_Bool StringResourcePersistenceImpl::isReadOnly() | ||||||
771 | { | ||||||
772 | return StringResourceImpl::isReadOnly(); | ||||||
773 | } | ||||||
774 | void StringResourcePersistenceImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) | ||||||
775 | { | ||||||
776 | StringResourceImpl::setCurrentLocale( locale, FindClosestMatch ); | ||||||
777 | } | ||||||
778 | void StringResourcePersistenceImpl::setDefaultLocale( const Locale& locale ) | ||||||
779 | { | ||||||
780 | StringResourceImpl::setDefaultLocale( locale ); | ||||||
781 | } | ||||||
782 | Sequence< OUString > StringResourcePersistenceImpl::getResourceIDs( ) | ||||||
783 | { | ||||||
784 | return StringResourceImpl::getResourceIDs(); | ||||||
785 | } | ||||||
786 | void StringResourcePersistenceImpl::setString( const OUString& ResourceID, const OUString& Str ) | ||||||
787 | { | ||||||
788 | StringResourceImpl::setString( ResourceID, Str ); | ||||||
789 | } | ||||||
790 | void StringResourcePersistenceImpl::setStringForLocale | ||||||
791 | ( const OUString& ResourceID, const OUString& Str, const Locale& locale ) | ||||||
792 | { | ||||||
793 | StringResourceImpl::setStringForLocale( ResourceID, Str, locale ); | ||||||
794 | } | ||||||
795 | Sequence< OUString > StringResourcePersistenceImpl::getResourceIDsForLocale | ||||||
796 | ( const Locale& locale ) | ||||||
797 | { | ||||||
798 | return StringResourceImpl::getResourceIDsForLocale( locale ); | ||||||
799 | } | ||||||
800 | void StringResourcePersistenceImpl::removeId( const OUString& ResourceID ) | ||||||
801 | { | ||||||
802 | StringResourceImpl::removeId( ResourceID ); | ||||||
803 | } | ||||||
804 | void StringResourcePersistenceImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale ) | ||||||
805 | { | ||||||
806 | StringResourceImpl::removeIdForLocale( ResourceID, locale ); | ||||||
807 | } | ||||||
808 | void StringResourcePersistenceImpl::newLocale( const Locale& locale ) | ||||||
809 | { | ||||||
810 | StringResourceImpl::newLocale( locale ); | ||||||
811 | } | ||||||
812 | void StringResourcePersistenceImpl::removeLocale( const Locale& locale ) | ||||||
813 | { | ||||||
814 | StringResourceImpl::removeLocale( locale ); | ||||||
815 | } | ||||||
816 | sal_Int32 StringResourcePersistenceImpl::getUniqueNumericId( ) | ||||||
817 | { | ||||||
818 | return StringResourceImpl::getUniqueNumericId(); | ||||||
819 | } | ||||||
820 | |||||||
821 | |||||||
822 | // XStringResourcePersistence | ||||||
823 | |||||||
824 | void StringResourcePersistenceImpl::store() | ||||||
825 | { | ||||||
826 | } | ||||||
827 | |||||||
828 | sal_Bool StringResourcePersistenceImpl::isModified( ) | ||||||
829 | { | ||||||
830 | ::osl::MutexGuard aGuard( getMutex() ); | ||||||
831 | |||||||
832 | return m_bModified; | ||||||
833 | } | ||||||
834 | |||||||
835 | void StringResourcePersistenceImpl::setComment( const OUString& Comment ) | ||||||
836 | { | ||||||
837 | m_aComment = Comment; | ||||||
838 | } | ||||||
839 | |||||||
840 | void 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 | |||||||
848 | void 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 | |||||||
947 | void 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 | |||||||
960 | void 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 | |||||||
983 | void 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 | |||||||
1002 | void 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 | |||||||
1070 | class BinaryOutput | ||||||
1071 | { | ||||||
1072 | Reference< XComponentContext > m_xContext; | ||||||
1073 | Reference< XInterface > m_xTempFile; | ||||||
1074 | Reference< io::XOutputStream > m_xOutputStream; | ||||||
1075 | |||||||
1076 | public: | ||||||
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 | |||||||
1095 | BinaryOutput::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 | |||||||
1102 | template< class T > | ||||||
1103 | void 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 | |||||||
1119 | void 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 | |||||||
1135 | void 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 | |||||||
1146 | Sequence< ::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 | |||||||
1199 | Sequence< 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 | |||||||
1258 | void 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 | |||||||
1275 | namespace { | ||||||
1276 | |||||||
1277 | class 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 | |||||||
1286 | public: | ||||||
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 | |||||||
1303 | BinaryInput::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 | |||||||
1312 | Reference< 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 | |||||||
1333 | void 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 | |||||||
1342 | sal_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 | |||||||
1356 | sal_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 | |||||||
1374 | sal_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 | |||||||
1389 | OUString 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 | |||||||
1405 | void 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 ) | ||||||
1414 | { | ||||||
1415 | Locale aLocale = aLocaleSeq[0]; | ||||||
1416 | removeLocale( aLocale ); | ||||||
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 | |||||||
1464 | static 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 | |||||||
1505 | void StringResourcePersistenceImpl::implLoadAllLocales() | ||||||
1506 | { | ||||||
1507 | for( auto& pLocaleItem : m_aLocaleItemVector ) | ||||||
1508 | if( pLocaleItem ) | ||||||
1509 | loadLocale( pLocaleItem.get() ); | ||||||
1510 | } | ||||||
1511 | |||||||
1512 | // Scan locale properties files helper | ||||||
1513 | void 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 | ||||||
1569 | void StringResourcePersistenceImpl::implScanLocales() | ||||||
1570 | { | ||||||
1571 | // Dummy implementation, method not called for this | ||||||
1572 | // base class, but pure virtual not possible- | ||||||
1573 | } | ||||||
1574 | |||||||
1575 | bool 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 | |||||||
1595 | bool 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 | |||||||
1602 | static 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 | |||||||
1630 | OUString 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 | |||||||
1641 | OUString 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) | ||||||
1658 | static 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 | |||||||
1668 | static 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 | |||||||
1678 | static 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 | |||||||
1692 | static 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 | |||||||
1747 | static 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 | |||||||
1767 | bool 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 | |||||||
1889 | static sal_Unicode getHexCharForDigit( sal_uInt16 nDigitVal ) | ||||||
1890 | { | ||||||
1891 | sal_Unicode cRet = ( nDigitVal < 10 ) ? ('0' + nDigitVal) : ('a' + (nDigitVal-10)); | ||||||
1892 | return cRet; | ||||||
1893 | } | ||||||
1894 | |||||||
1895 | static 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 | |||||||
1949 | static 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 | |||||||
1970 | bool 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 | |||||||
2038 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface* | ||||||
2039 | scripting_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 | |||||||
2046 | StringResourceWithStorageImpl::StringResourceWithStorageImpl( const Reference< XComponentContext >& rxContext ) | ||||||
2047 | : StringResourceWithStorageImpl_BASE( rxContext ) | ||||||
2048 | , m_bStorageChanged( false ) | ||||||
2049 | { | ||||||
2050 | } | ||||||
2051 | |||||||
2052 | |||||||
2053 | StringResourceWithStorageImpl::~StringResourceWithStorageImpl() | ||||||
2054 | { | ||||||
2055 | } | ||||||
2056 | |||||||
2057 | |||||||
2058 | // XServiceInfo | ||||||
2059 | |||||||
2060 | |||||||
2061 | OUString StringResourceWithStorageImpl::getImplementationName( ) | ||||||
2062 | { | ||||||
2063 | return "com.sun.star.comp.scripting.StringResourceWithStorage"; | ||||||
2064 | } | ||||||
2065 | |||||||
2066 | sal_Bool StringResourceWithStorageImpl::supportsService( const OUString& rServiceName ) | ||||||
2067 | { | ||||||
2068 | return cppu::supportsService(this, rServiceName); | ||||||
2069 | } | ||||||
2070 | |||||||
2071 | Sequence< OUString > StringResourceWithStorageImpl::getSupportedServiceNames( ) | ||||||
2072 | { | ||||||
2073 | return { "com.sun.star.resource.StringResourceWithStorage" }; | ||||||
2074 | } | ||||||
2075 | |||||||
2076 | |||||||
2077 | // XInitialization | ||||||
2078 | |||||||
2079 | |||||||
2080 | void 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 | ||||||
2106 | void StringResourceWithStorageImpl::addModifyListener( const Reference< XModifyListener >& aListener ) | ||||||
2107 | { | ||||||
2108 | StringResourceImpl::addModifyListener( aListener ); | ||||||
2109 | } | ||||||
2110 | void StringResourceWithStorageImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) | ||||||
2111 | { | ||||||
2112 | StringResourceImpl::removeModifyListener( aListener ); | ||||||
2113 | } | ||||||
2114 | |||||||
2115 | // XStringResourceResolver | ||||||
2116 | OUString StringResourceWithStorageImpl::resolveString( const OUString& ResourceID ) | ||||||
2117 | { | ||||||
2118 | return StringResourceImpl::resolveString( ResourceID ) ; | ||||||
2119 | } | ||||||
2120 | OUString StringResourceWithStorageImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale ) | ||||||
2121 | { | ||||||
2122 | return StringResourceImpl::resolveStringForLocale( ResourceID, locale ); | ||||||
2123 | } | ||||||
2124 | sal_Bool StringResourceWithStorageImpl::hasEntryForId( const OUString& ResourceID ) | ||||||
2125 | { | ||||||
2126 | return StringResourceImpl::hasEntryForId( ResourceID ) ; | ||||||
2127 | } | ||||||
2128 | sal_Bool StringResourceWithStorageImpl::hasEntryForIdAndLocale( const OUString& ResourceID, | ||||||
2129 | const Locale& locale ) | ||||||
2130 | { | ||||||
2131 | return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale ); | ||||||
2132 | } | ||||||
2133 | Sequence< OUString > StringResourceWithStorageImpl::getResourceIDs( ) | ||||||
2134 | { | ||||||
2135 | return StringResourceImpl::getResourceIDs(); | ||||||
2136 | } | ||||||
2137 | Sequence< OUString > StringResourceWithStorageImpl::getResourceIDsForLocale | ||||||
2138 | ( const Locale& locale ) | ||||||
2139 | { | ||||||
2140 | return StringResourceImpl::getResourceIDsForLocale( locale ); | ||||||
2141 | } | ||||||
2142 | Locale StringResourceWithStorageImpl::getCurrentLocale() | ||||||
2143 | { | ||||||
2144 | return StringResourceImpl::getCurrentLocale(); | ||||||
2145 | } | ||||||
2146 | Locale StringResourceWithStorageImpl::getDefaultLocale( ) | ||||||
2147 | { | ||||||
2148 | return StringResourceImpl::getDefaultLocale(); | ||||||
2149 | } | ||||||
2150 | Sequence< Locale > StringResourceWithStorageImpl::getLocales( ) | ||||||
2151 | { | ||||||
2152 | return StringResourceImpl::getLocales(); | ||||||
2153 | } | ||||||
2154 | |||||||
2155 | // XStringResourceManager | ||||||
2156 | sal_Bool StringResourceWithStorageImpl::isReadOnly() | ||||||
2157 | { | ||||||
2158 | return StringResourceImpl::isReadOnly(); | ||||||
2159 | } | ||||||
2160 | void StringResourceWithStorageImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) | ||||||
2161 | { | ||||||
2162 | StringResourceImpl::setCurrentLocale( locale, FindClosestMatch ); | ||||||
2163 | } | ||||||
2164 | void StringResourceWithStorageImpl::setDefaultLocale( const Locale& locale ) | ||||||
2165 | { | ||||||
2166 | StringResourceImpl::setDefaultLocale( locale ); | ||||||
2167 | } | ||||||
2168 | void StringResourceWithStorageImpl::setString( const OUString& ResourceID, const OUString& Str ) | ||||||
2169 | { | ||||||
2170 | StringResourceImpl::setString( ResourceID, Str ); | ||||||
2171 | } | ||||||
2172 | void StringResourceWithStorageImpl::setStringForLocale | ||||||
2173 | ( const OUString& ResourceID, const OUString& Str, const Locale& locale ) | ||||||
2174 | { | ||||||
2175 | StringResourceImpl::setStringForLocale( ResourceID, Str, locale ); | ||||||
2176 | } | ||||||
2177 | void StringResourceWithStorageImpl::removeId( const OUString& ResourceID ) | ||||||
2178 | { | ||||||
2179 | StringResourceImpl::removeId( ResourceID ); | ||||||
2180 | } | ||||||
2181 | void StringResourceWithStorageImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale ) | ||||||
2182 | { | ||||||
2183 | StringResourceImpl::removeIdForLocale( ResourceID, locale ); | ||||||
2184 | } | ||||||
2185 | void StringResourceWithStorageImpl::newLocale( const Locale& locale ) | ||||||
2186 | { | ||||||
2187 | StringResourceImpl::newLocale( locale ); | ||||||
2188 | } | ||||||
2189 | void StringResourceWithStorageImpl::removeLocale( const Locale& locale ) | ||||||
2190 | { | ||||||
2191 | StringResourceImpl::removeLocale( locale ); | ||||||
2192 | } | ||||||
2193 | sal_Int32 StringResourceWithStorageImpl::getUniqueNumericId( ) | ||||||
2194 | { | ||||||
2195 | return StringResourceImpl::getUniqueNumericId(); | ||||||
2196 | } | ||||||
2197 | |||||||
2198 | // XStringResourcePersistence | ||||||
2199 | void 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 | |||||||
2213 | sal_Bool StringResourceWithStorageImpl::isModified( ) | ||||||
2214 | { | ||||||
2215 | return StringResourcePersistenceImpl::isModified(); | ||||||
2216 | } | ||||||
2217 | void StringResourceWithStorageImpl::setComment( const OUString& Comment ) | ||||||
2218 | { | ||||||
2219 | StringResourcePersistenceImpl::setComment( Comment ); | ||||||
2220 | } | ||||||
2221 | void StringResourceWithStorageImpl::storeToStorage( const Reference< XStorage >& Storage, | ||||||
2222 | const OUString& NameBase, const OUString& Comment ) | ||||||
2223 | { | ||||||
2224 | StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment ); | ||||||
2225 | } | ||||||
2226 | void 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 | } | ||||||
2232 | Sequence< ::sal_Int8 > StringResourceWithStorageImpl::exportBinary( ) | ||||||
2233 | { | ||||||
2234 | return StringResourcePersistenceImpl::exportBinary(); | ||||||
2235 | } | ||||||
2236 | void StringResourceWithStorageImpl::importBinary( const Sequence< ::sal_Int8 >& Data ) | ||||||
2237 | { | ||||||
2238 | StringResourcePersistenceImpl::importBinary( Data ); | ||||||
2239 | } | ||||||
2240 | |||||||
2241 | |||||||
2242 | // XStringResourceWithStorage | ||||||
2243 | |||||||
2244 | void StringResourceWithStorageImpl::storeAsStorage( const Reference< XStorage >& Storage ) | ||||||
2245 | { | ||||||
2246 | setStorage( Storage ); | ||||||
2247 | store(); | ||||||
2248 | } | ||||||
2249 | |||||||
2250 | void 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 | ||||||
2270 | void 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 | ||||||
2282 | bool 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 | |||||||
2312 | extern "C" SAL_DLLPUBLIC_EXPORT__attribute__ ((visibility("default"))) css::uno::XInterface* | ||||||
2313 | scripting_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 | |||||||
2321 | StringResourceWithLocationImpl::StringResourceWithLocationImpl( const Reference< XComponentContext >& rxContext ) | ||||||
2322 | : StringResourceWithLocationImpl_BASE( rxContext ) | ||||||
2323 | , m_bLocationChanged( false ) | ||||||
2324 | { | ||||||
2325 | } | ||||||
2326 | |||||||
2327 | |||||||
2328 | StringResourceWithLocationImpl::~StringResourceWithLocationImpl() | ||||||
2329 | { | ||||||
2330 | } | ||||||
2331 | |||||||
2332 | |||||||
2333 | // XServiceInfo | ||||||
2334 | |||||||
2335 | |||||||
2336 | OUString StringResourceWithLocationImpl::getImplementationName( ) | ||||||
2337 | { | ||||||
2338 | return "com.sun.star.comp.scripting.StringResourceWithLocation"; | ||||||
2339 | } | ||||||
2340 | |||||||
2341 | sal_Bool StringResourceWithLocationImpl::supportsService( const OUString& rServiceName ) | ||||||
2342 | { | ||||||
2343 | return cppu::supportsService(this, rServiceName); | ||||||
2344 | } | ||||||
2345 | |||||||
2346 | Sequence< OUString > StringResourceWithLocationImpl::getSupportedServiceNames( ) | ||||||
2347 | { | ||||||
2348 | return { "com.sun.star.resource.StringResourceWithLocation" }; | ||||||
2349 | } | ||||||
2350 | |||||||
2351 | |||||||
2352 | // XInitialization | ||||||
2353 | |||||||
2354 | |||||||
2355 | void 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 | ||||||
2396 | void StringResourceWithLocationImpl::addModifyListener( const Reference< XModifyListener >& aListener ) | ||||||
2397 | { | ||||||
2398 | StringResourceImpl::addModifyListener( aListener ); | ||||||
2399 | } | ||||||
2400 | void StringResourceWithLocationImpl::removeModifyListener( const Reference< XModifyListener >& aListener ) | ||||||
2401 | { | ||||||
2402 | StringResourceImpl::removeModifyListener( aListener ); | ||||||
2403 | } | ||||||
2404 | |||||||
2405 | // XStringResourceResolver | ||||||
2406 | OUString StringResourceWithLocationImpl::resolveString( const OUString& ResourceID ) | ||||||
2407 | { | ||||||
2408 | return StringResourceImpl::resolveString( ResourceID ) ; | ||||||
2409 | } | ||||||
2410 | OUString StringResourceWithLocationImpl::resolveStringForLocale( const OUString& ResourceID, const Locale& locale ) | ||||||
2411 | { | ||||||
2412 | return StringResourceImpl::resolveStringForLocale( ResourceID, locale ); | ||||||
2413 | } | ||||||
2414 | sal_Bool StringResourceWithLocationImpl::hasEntryForId( const OUString& ResourceID ) | ||||||
2415 | { | ||||||
2416 | return StringResourceImpl::hasEntryForId( ResourceID ) ; | ||||||
2417 | } | ||||||
2418 | sal_Bool StringResourceWithLocationImpl::hasEntryForIdAndLocale( const OUString& ResourceID, | ||||||
2419 | const Locale& locale ) | ||||||
2420 | { | ||||||
2421 | return StringResourceImpl::hasEntryForIdAndLocale( ResourceID, locale ); | ||||||
2422 | } | ||||||
2423 | Sequence< OUString > StringResourceWithLocationImpl::getResourceIDs( ) | ||||||
2424 | { | ||||||
2425 | return StringResourceImpl::getResourceIDs(); | ||||||
2426 | } | ||||||
2427 | Sequence< OUString > StringResourceWithLocationImpl::getResourceIDsForLocale | ||||||
2428 | ( const Locale& locale ) | ||||||
2429 | { | ||||||
2430 | return StringResourceImpl::getResourceIDsForLocale( locale ); | ||||||
2431 | } | ||||||
2432 | Locale StringResourceWithLocationImpl::getCurrentLocale() | ||||||
2433 | { | ||||||
2434 | return StringResourceImpl::getCurrentLocale(); | ||||||
2435 | } | ||||||
2436 | Locale StringResourceWithLocationImpl::getDefaultLocale( ) | ||||||
2437 | { | ||||||
2438 | return StringResourceImpl::getDefaultLocale(); | ||||||
2439 | } | ||||||
2440 | Sequence< Locale > StringResourceWithLocationImpl::getLocales( ) | ||||||
2441 | { | ||||||
2442 | return StringResourceImpl::getLocales(); | ||||||
2443 | } | ||||||
2444 | |||||||
2445 | // XStringResourceManager | ||||||
2446 | sal_Bool StringResourceWithLocationImpl::isReadOnly() | ||||||
2447 | { | ||||||
2448 | return StringResourceImpl::isReadOnly(); | ||||||
2449 | } | ||||||
2450 | void StringResourceWithLocationImpl::setCurrentLocale( const Locale& locale, sal_Bool FindClosestMatch ) | ||||||
2451 | { | ||||||
2452 | StringResourceImpl::setCurrentLocale( locale, FindClosestMatch ); | ||||||
2453 | } | ||||||
2454 | void StringResourceWithLocationImpl::setDefaultLocale( const Locale& locale ) | ||||||
2455 | { | ||||||
2456 | StringResourceImpl::setDefaultLocale( locale ); | ||||||
2457 | } | ||||||
2458 | void StringResourceWithLocationImpl::setString( const OUString& ResourceID, const OUString& Str ) | ||||||
2459 | { | ||||||
2460 | StringResourceImpl::setString( ResourceID, Str ); | ||||||
2461 | } | ||||||
2462 | void StringResourceWithLocationImpl::setStringForLocale | ||||||
2463 | ( const OUString& ResourceID, const OUString& Str, const Locale& locale ) | ||||||
2464 | { | ||||||
2465 | StringResourceImpl::setStringForLocale( ResourceID, Str, locale ); | ||||||
2466 | } | ||||||
2467 | void StringResourceWithLocationImpl::removeId( const OUString& ResourceID ) | ||||||
2468 | { | ||||||
2469 | StringResourceImpl::removeId( ResourceID ); | ||||||
2470 | } | ||||||
2471 | void StringResourceWithLocationImpl::removeIdForLocale( const OUString& ResourceID, const Locale& locale ) | ||||||
2472 | { | ||||||
2473 | StringResourceImpl::removeIdForLocale( ResourceID, locale ); | ||||||
2474 | } | ||||||
2475 | void StringResourceWithLocationImpl::newLocale( const Locale& locale ) | ||||||
2476 | { | ||||||
2477 | StringResourceImpl::newLocale( locale ); | ||||||
2478 | } | ||||||
2479 | void StringResourceWithLocationImpl::removeLocale( const Locale& locale ) | ||||||
2480 | { | ||||||
2481 | StringResourceImpl::removeLocale( locale ); | ||||||
2482 | } | ||||||
2483 | sal_Int32 StringResourceWithLocationImpl::getUniqueNumericId( ) | ||||||
2484 | { | ||||||
2485 | return StringResourceImpl::getUniqueNumericId(); | ||||||
2486 | } | ||||||
2487 | |||||||
2488 | // XStringResourcePersistence | ||||||
2489 | void 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 | |||||||
2505 | sal_Bool StringResourceWithLocationImpl::isModified( ) | ||||||
2506 | { | ||||||
2507 | return StringResourcePersistenceImpl::isModified(); | ||||||
2508 | } | ||||||
2509 | void StringResourceWithLocationImpl::setComment( const OUString& Comment ) | ||||||
2510 | { | ||||||
2511 | StringResourcePersistenceImpl::setComment( Comment ); | ||||||
2512 | } | ||||||
2513 | void StringResourceWithLocationImpl::storeToStorage( const Reference< XStorage >& Storage, | ||||||
2514 | const OUString& NameBase, const OUString& Comment ) | ||||||
2515 | { | ||||||
2516 | StringResourcePersistenceImpl::storeToStorage( Storage, NameBase, Comment ); | ||||||
2517 | } | ||||||
2518 | void 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 | } | ||||||
2524 | Sequence< ::sal_Int8 > StringResourceWithLocationImpl::exportBinary( ) | ||||||
2525 | { | ||||||
2526 | return StringResourcePersistenceImpl::exportBinary(); | ||||||
2527 | } | ||||||
2528 | void StringResourceWithLocationImpl::importBinary( const Sequence< ::sal_Int8 >& Data ) | ||||||
2529 | { | ||||||
2530 | StringResourcePersistenceImpl::importBinary( Data ); | ||||||
| |||||||
2531 | } | ||||||
2532 | |||||||
2533 | |||||||
2534 | // XStringResourceWithLocation | ||||||
2535 | |||||||
2536 | // XStringResourceWithLocation | ||||||
2537 | void StringResourceWithLocationImpl::storeAsURL( const OUString& URL ) | ||||||
2538 | { | ||||||
2539 | setURL( URL ); | ||||||
2540 | store(); | ||||||
2541 | } | ||||||
2542 | |||||||
2543 | void 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 | ||||||
2569 | void 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 | ||||||
2580 | bool 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 | |||||||
2607 | const 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: */ |
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 | |
45 | namespace 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; } |
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 */ |
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 |
49 | extern 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 | |
61 | namespace rtl |
62 | { |
63 | |
64 | class 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 | /** |
74 | A wrapper dressing a string literal as a static-refcount rtl_uString. |
75 | |
76 | This class is not part of public API and is meant to be used only in LibreOffice code. |
77 | @since LibreOffice 4.0 |
78 | */ |
79 | template<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 | |
83 | public: |
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 | |
104 | private: |
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 |
126 | namespace libreoffice_internal { |
127 | template<std::size_t N> struct ExceptConstCharArrayDetector<OUStringLiteral<N>> {}; |
128 | template<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 | |
160 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) OUString |
161 | { |
162 | public: |
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 ) |
885 | return false; |
886 | if ( pData == str.pData ) |
887 | return true; |
888 | return rtl_ustr_reverseCompare_WithLength( pData->buffer, pData->length, |
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); } |
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 | |
3374 | private: |
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 | // |
3395 | void operator ==(OUString const &, std::nullptr_t) = delete; |
3396 | void operator ==(std::nullptr_t, OUString const &) = delete; |
3397 | void operator !=(OUString const &, std::nullptr_t) = delete; |
3398 | void 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 | */ |
3407 | template<> |
3408 | struct 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 | */ |
3419 | template<std::size_t N> |
3420 | struct 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 | */ |
3431 | template< typename charT, typename traits, typename T1, typename T2 > |
3432 | inline 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 | */ |
3446 | struct 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 | */ |
3480 | inline 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 | */ |
3504 | inline 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 | */ |
3521 | template< typename charT, typename traits > |
3522 | inline 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 |
3534 | namespace rtl |
3535 | { |
3536 | typedef 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 |
3544 | using ::rtl::OUString; |
3545 | using ::rtl::OUStringHash; |
3546 | using ::rtl::OStringToOUString; |
3547 | using ::rtl::OUStringToOString; |
3548 | using ::rtl::OUStringLiteral; |
3549 | using ::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 |
3559 | namespace std { |
3560 | |
3561 | template<> |
3562 | struct 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: */ |