Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/source/common/unicode/localpointer.h
Line
Count
Source
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
*******************************************************************************
5
*
6
*   Copyright (C) 2009-2016, International Business Machines
7
*   Corporation and others.  All Rights Reserved.
8
*
9
*******************************************************************************
10
*   file name:  localpointer.h
11
*   encoding:   UTF-8
12
*   tab size:   8 (not used)
13
*   indentation:4
14
*
15
*   created on: 2009nov13
16
*   created by: Markus W. Scherer
17
*/
18
19
#ifndef __LOCALPOINTER_H__
20
#define __LOCALPOINTER_H__
21
22
/**
23
 * \file
24
 * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code.
25
 *
26
 * These classes are inspired by
27
 * - std::auto_ptr
28
 * - boost::scoped_ptr & boost::scoped_array
29
 * - Taligent Safe Pointers (TOnlyPointerTo)
30
 *
31
 * but none of those provide for all of the goals for ICU smart pointers:
32
 * - Smart pointer owns the object and releases it when it goes out of scope.
33
 * - No transfer of ownership via copy/assignment to reduce misuse. Simpler & more robust.
34
 * - ICU-compatible: No exceptions.
35
 * - Need to be able to orphan/release the pointer and its ownership.
36
 * - Need variants for normal C++ object pointers, C++ arrays, and ICU C service objects.
37
 *
38
 * For details see https://icu.unicode.org/design/cpp/scoped_ptr
39
 */
40
41
#include "unicode/utypes.h"
42
43
#if U_SHOW_CPLUSPLUS_API
44
45
#include <memory>
46
47
U_NAMESPACE_BEGIN
48
49
/**
50
 * "Smart pointer" base class; do not use directly: use LocalPointer etc.
51
 *
52
 * Base class for smart pointer classes that do not throw exceptions.
53
 *
54
 * Do not use this base class directly, since it does not delete its pointer.
55
 * A subclass must implement methods that delete the pointer:
56
 * Destructor and adoptInstead().
57
 *
58
 * There is no operator T *() provided because the programmer must decide
59
 * whether to use getAlias() (without transfer of ownership) or orphan()
60
 * (with transfer of ownership and NULLing of the pointer).
61
 *
62
 * @see LocalPointer
63
 * @see LocalArray
64
 * @see U_DEFINE_LOCAL_OPEN_POINTER
65
 * @stable ICU 4.4
66
 */
67
template<typename T>
68
class LocalPointerBase {
69
public:
70
    // No heap allocation. Use only on the stack.
71
    static void* U_EXPORT2 operator new(size_t) = delete;
72
    static void* U_EXPORT2 operator new[](size_t) = delete;
73
    static void* U_EXPORT2 operator new(size_t, void*) = delete;
74
75
    /**
76
     * Constructor takes ownership.
77
     * @param p simple pointer to an object that is adopted
78
     * @stable ICU 4.4
79
     */
80
0
    explicit LocalPointerBase(T *p=nullptr) : ptr(p) {}
Unexecuted instantiation: icu_78::LocalPointerBase<UKeywordsContext>::LocalPointerBase(UKeywordsContext*)
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::LocalPointerBase(UEnumeration*)
Unexecuted instantiation: icu_78::LocalPointerBase<UResourceBundle>::LocalPointerBase(UResourceBundle*)
Unexecuted instantiation: icu_78::LocalPointerBase<UHashtable>::LocalPointerBase(UHashtable*)
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::VariantListEntry>::LocalPointerBase((anonymous namespace)::VariantListEntry*)
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ExtensionListEntry>::LocalPointerBase((anonymous namespace)::ExtensionListEntry*)
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ULanguageTag>::LocalPointerBase((anonymous namespace)::ULanguageTag*)
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UnicodeString>::LocalPointerBase(icu_78::UnicodeString*)
Unexecuted instantiation: icu_78::LocalPointerBase<char const*>::LocalPointerBase(char const**)
Unexecuted instantiation: icu_78::LocalPointerBase<int>::LocalPointerBase(int*)
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::CharString>::LocalPointerBase(icu_78::CharString*)
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::StringEnumeration>::LocalPointerBase(icu_78::StringEnumeration*)
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UVector>::LocalPointerBase(icu_78::UVector*)
81
    /**
82
     * Destructor deletes the object it owns.
83
     * Subclass must override: Base class does nothing.
84
     * @stable ICU 4.4
85
     */
86
0
    ~LocalPointerBase() { /* delete ptr; */ }
Unexecuted instantiation: icu_78::LocalPointerBase<UKeywordsContext>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<UHashtable>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<UResourceBundle>::~LocalPointerBase()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::VariantListEntry>::~LocalPointerBase()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ExtensionListEntry>::~LocalPointerBase()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ULanguageTag>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UnicodeString>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<int>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<char const*>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::CharString>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::StringEnumeration>::~LocalPointerBase()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UVector>::~LocalPointerBase()
87
    /**
88
     * nullptr check.
89
     * @return true if ==nullptr
90
     * @stable ICU 4.4
91
     */
92
0
    UBool isNull() const { return ptr==nullptr; }
Unexecuted instantiation: icu_78::LocalPointerBase<UKeywordsContext>::isNull() const
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::isNull() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ULanguageTag>::isNull() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::CharString>::isNull() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::StringEnumeration>::isNull() const
93
    /**
94
     * nullptr check.
95
     * @return true if !=nullptr
96
     * @stable ICU 4.4
97
     */
98
0
    UBool isValid() const { return ptr!=nullptr; }
Unexecuted instantiation: icu_78::LocalPointerBase<UResourceBundle>::isValid() const
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::isValid() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ExtensionListEntry>::isValid() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UnicodeString>::isValid() const
99
    /**
100
     * Comparison with a simple pointer, so that existing code
101
     * with ==nullptr need not be changed.
102
     * @param other simple pointer for comparison
103
     * @return true if this pointer value equals other
104
     * @stable ICU 4.4
105
     */
106
    bool operator==(const T *other) const { return ptr==other; }
107
    /**
108
     * Comparison with a simple pointer, so that existing code
109
     * with !=nullptr need not be changed.
110
     * @param other simple pointer for comparison
111
     * @return true if this pointer value differs from other
112
     * @stable ICU 4.4
113
     */
114
    bool operator!=(const T *other) const { return ptr!=other; }
115
    /**
116
     * Access without ownership change.
117
     * @return the pointer value
118
     * @stable ICU 4.4
119
     */
120
0
    T *getAlias() const { return ptr; }
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::getAlias() const
Unexecuted instantiation: icu_78::LocalPointerBase<UResourceBundle>::getAlias() const
Unexecuted instantiation: icu_78::LocalPointerBase<UHashtable>::getAlias() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ExtensionListEntry>::getAlias() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ULanguageTag>::getAlias() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UVector>::getAlias() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::StringEnumeration>::getAlias() const
121
    /**
122
     * Access without ownership change.
123
     * @return the pointer value as a reference
124
     * @stable ICU 4.4
125
     */
126
    T &operator*() const { return *ptr; }
127
    /**
128
     * Access without ownership change.
129
     * @return the pointer value
130
     * @stable ICU 4.4
131
     */
132
0
    T *operator->() const { return ptr; }
Unexecuted instantiation: icu_78::LocalPointerBase<UKeywordsContext>::operator->() const
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::operator->() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::VariantListEntry>::operator->() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ULanguageTag>::operator->() const
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ExtensionListEntry>::operator->() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UnicodeString>::operator->() const
Unexecuted instantiation: icu_78::LocalPointerBase<UResourceBundle>::operator->() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::CharString>::operator->() const
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::StringEnumeration>::operator->() const
133
    /**
134
     * Gives up ownership; the internal pointer becomes nullptr.
135
     * @return the pointer value;
136
     *         caller becomes responsible for deleting the object
137
     * @stable ICU 4.4
138
     */
139
0
    T *orphan() {
140
0
        T *p=ptr;
141
0
        ptr=nullptr;
142
0
        return p;
143
0
    }
Unexecuted instantiation: icu_78::LocalPointerBase<UKeywordsContext>::orphan()
Unexecuted instantiation: icu_78::LocalPointerBase<UEnumeration>::orphan()
Unexecuted instantiation: icu_78::LocalPointerBase<UResourceBundle>::orphan()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::VariantListEntry>::orphan()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ULanguageTag>::orphan()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointerBase<(anonymous namespace)::ExtensionListEntry>::orphan()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UnicodeString>::orphan()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::CharString>::orphan()
Unexecuted instantiation: icu_78::LocalPointerBase<UHashtable>::orphan()
Unexecuted instantiation: icu_78::LocalPointerBase<icu_78::UVector>::orphan()
144
    /**
145
     * Deletes the object it owns,
146
     * and adopts (takes ownership of) the one passed in.
147
     * Subclass must override: Base class does not delete the object.
148
     * @param p simple pointer to an object that is adopted
149
     * @stable ICU 4.4
150
     */
151
    void adoptInstead(T *p) {
152
        // delete ptr;
153
        ptr=p;
154
    }
155
protected:
156
    /**
157
     * Actual pointer.
158
     * @internal
159
     */
160
    T *ptr;
161
private:
162
    // No comparison operators with other LocalPointerBases.
163
    bool operator==(const LocalPointerBase<T> &other) = delete;
164
    bool operator!=(const LocalPointerBase<T> &other) = delete;
165
    // No ownership sharing: No copy constructor, no assignment operator.
166
    LocalPointerBase(const LocalPointerBase<T> &other) = delete;
167
    void operator=(const LocalPointerBase<T> &other) = delete;
168
};
169
170
/**
171
 * "Smart pointer" class, deletes objects via the standard C++ delete operator.
172
 * For most methods see the LocalPointerBase base class.
173
 *
174
 * Usage example:
175
 * \code
176
 * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
177
 * int32_t length=s->length();  // 2
178
 * char16_t lead=s->charAt(0);  // 0xd900
179
 * if(some condition) { return; }  // no need to explicitly delete the pointer
180
 * s.adoptInstead(new UnicodeString((char16_t)0xfffc));
181
 * length=s->length();  // 1
182
 * // no need to explicitly delete the pointer
183
 * \endcode
184
 *
185
 * @see LocalPointerBase
186
 * @stable ICU 4.4
187
 */
188
template<typename T>
189
class LocalPointer : public LocalPointerBase<T> {
190
public:
191
    using LocalPointerBase<T>::operator*;
192
    using LocalPointerBase<T>::operator->;
193
    /**
194
     * Constructor takes ownership.
195
     * @param p simple pointer to an object that is adopted
196
     * @stable ICU 4.4
197
     */
198
0
    explicit LocalPointer(T *p=nullptr) : LocalPointerBase<T>(p) {}
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointer<(anonymous namespace)::ExtensionListEntry>::LocalPointer((anonymous namespace)::ExtensionListEntry*)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::UnicodeString>::LocalPointer(icu_78::UnicodeString*)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::CharString>::LocalPointer(icu_78::CharString*)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::StringEnumeration>::LocalPointer(icu_78::StringEnumeration*)
199
    /**
200
     * Constructor takes ownership and reports an error if nullptr.
201
     *
202
     * This constructor is intended to be used with other-class constructors
203
     * that may report a failure UErrorCode,
204
     * so that callers need to check only for U_FAILURE(errorCode)
205
     * and not also separately for isNull().
206
     *
207
     * @param p simple pointer to an object that is adopted
208
     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
209
     *     if p==nullptr and no other failure code had been set
210
     * @stable ICU 55
211
     */
212
0
    LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
213
0
        if(p==nullptr && U_SUCCESS(errorCode)) {
214
0
            errorCode=U_MEMORY_ALLOCATION_ERROR;
215
0
        }
216
0
    }
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointer<(anonymous namespace)::VariantListEntry>::LocalPointer((anonymous namespace)::VariantListEntry*, UErrorCode&)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::CharString>::LocalPointer(icu_78::CharString*, UErrorCode&)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::UVector>::LocalPointer(icu_78::UVector*, UErrorCode&)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::UnicodeString>::LocalPointer(icu_78::UnicodeString*, UErrorCode&)
217
    /**
218
     * Move constructor, leaves src with isNull().
219
     * @param src source smart pointer
220
     * @stable ICU 56
221
     */
222
0
    LocalPointer(LocalPointer<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
223
0
        src.ptr=nullptr;
224
0
    }
225
226
    /**
227
     * Constructs a LocalPointer from a C++11 std::unique_ptr.
228
     * The LocalPointer steals the object owned by the std::unique_ptr.
229
     *
230
     * This constructor works via move semantics. If your std::unique_ptr is
231
     * in a local variable, you must use std::move.
232
     *
233
     * @param p The std::unique_ptr from which the pointer will be stolen.
234
     * @stable ICU 64
235
     */
236
    explicit LocalPointer(std::unique_ptr<T> &&p)
237
        : LocalPointerBase<T>(p.release()) {}
238
239
    /**
240
     * Destructor deletes the object it owns.
241
     * @stable ICU 4.4
242
     */
243
0
    ~LocalPointer() {
244
0
        delete LocalPointerBase<T>::ptr;
245
0
    }
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointer<(anonymous namespace)::VariantListEntry>::~LocalPointer()
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointer<(anonymous namespace)::ExtensionListEntry>::~LocalPointer()
Unexecuted instantiation: icu_78::LocalPointer<icu_78::UnicodeString>::~LocalPointer()
Unexecuted instantiation: icu_78::LocalPointer<icu_78::CharString>::~LocalPointer()
Unexecuted instantiation: icu_78::LocalPointer<icu_78::StringEnumeration>::~LocalPointer()
Unexecuted instantiation: icu_78::LocalPointer<icu_78::UVector>::~LocalPointer()
246
    /**
247
     * Move assignment operator, leaves src with isNull().
248
     * The behavior is undefined if *this and src are the same object.
249
     * @param src source smart pointer
250
     * @return *this
251
     * @stable ICU 56
252
     */
253
    LocalPointer<T> &operator=(LocalPointer<T> &&src) noexcept {
254
        delete LocalPointerBase<T>::ptr;
255
        LocalPointerBase<T>::ptr=src.ptr;
256
        src.ptr=nullptr;
257
        return *this;
258
    }
259
260
    /**
261
     * Move-assign from an std::unique_ptr to this LocalPointer.
262
     * Steals the pointer from the std::unique_ptr.
263
     *
264
     * @param p The std::unique_ptr from which the pointer will be stolen.
265
     * @return *this
266
     * @stable ICU 64
267
     */
268
    LocalPointer<T> &operator=(std::unique_ptr<T> &&p) noexcept {
269
        adoptInstead(p.release());
270
        return *this;
271
    }
272
273
    /**
274
     * Swap pointers.
275
     * @param other other smart pointer
276
     * @stable ICU 56
277
     */
278
    void swap(LocalPointer<T> &other) noexcept {
279
        T *temp=LocalPointerBase<T>::ptr;
280
        LocalPointerBase<T>::ptr=other.ptr;
281
        other.ptr=temp;
282
    }
283
    /**
284
     * Non-member LocalPointer swap function.
285
     * @param p1 will get p2's pointer
286
     * @param p2 will get p1's pointer
287
     * @stable ICU 56
288
     */
289
    friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) noexcept {
290
        p1.swap(p2);
291
    }
292
    /**
293
     * Deletes the object it owns,
294
     * and adopts (takes ownership of) the one passed in.
295
     * @param p simple pointer to an object that is adopted
296
     * @stable ICU 4.4
297
     */
298
0
    void adoptInstead(T *p) {
299
0
        delete LocalPointerBase<T>::ptr;
300
0
        LocalPointerBase<T>::ptr=p;
301
0
    }
302
    /**
303
     * Deletes the object it owns,
304
     * and adopts (takes ownership of) the one passed in.
305
     *
306
     * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
307
     *
308
     * If U_SUCCESS(errorCode) but the input pointer is nullptr,
309
     * then U_MEMORY_ALLOCATION_ERROR is set,
310
     * the current object is deleted, and nullptr is set.
311
     *
312
     * @param p simple pointer to an object that is adopted
313
     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
314
     *     if p==nullptr and no other failure code had been set
315
     * @stable ICU 55
316
     */
317
0
    void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
318
0
        if(U_SUCCESS(errorCode)) {
319
0
            delete LocalPointerBase<T>::ptr;
320
0
            LocalPointerBase<T>::ptr=p;
321
0
            if(p==nullptr) {
322
0
                errorCode=U_MEMORY_ALLOCATION_ERROR;
323
0
            }
324
0
        } else {
325
0
            delete p;
326
0
        }
327
0
    }
Unexecuted instantiation: uloc_tag.cpp:icu_78::LocalPointer<(anonymous namespace)::ExtensionListEntry>::adoptInsteadAndCheckErrorCode((anonymous namespace)::ExtensionListEntry*, UErrorCode&)
Unexecuted instantiation: icu_78::LocalPointer<icu_78::CharString>::adoptInsteadAndCheckErrorCode(icu_78::CharString*, UErrorCode&)
328
329
    /**
330
     * Conversion operator to a C++11 std::unique_ptr.
331
     * Disowns the object and gives it to the returned std::unique_ptr.
332
     *
333
     * This operator works via move semantics. If your LocalPointer is
334
     * in a local variable, you must use std::move.
335
     *
336
     * @return An std::unique_ptr owning the pointer previously owned by this
337
     *         icu::LocalPointer.
338
     * @stable ICU 64
339
     */
340
    operator std::unique_ptr<T> () && {
341
        return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
342
    }
343
};
344
345
/**
346
 * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
347
 * For most methods see the LocalPointerBase base class.
348
 * Adds operator[] for array item access.
349
 *
350
 * Usage example:
351
 * \code
352
 * LocalArray<UnicodeString> a(new UnicodeString[2]);
353
 * a[0].append((char16_t)0x61);
354
 * if(some condition) { return; }  // no need to explicitly delete the array
355
 * a.adoptInstead(new UnicodeString[4]);
356
 * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse();
357
 * // no need to explicitly delete the array
358
 * \endcode
359
 *
360
 * @see LocalPointerBase
361
 * @stable ICU 4.4
362
 */
363
template<typename T>
364
class LocalArray : public LocalPointerBase<T> {
365
public:
366
    using LocalPointerBase<T>::operator*;
367
    using LocalPointerBase<T>::operator->;
368
    /**
369
     * Constructor takes ownership.
370
     * @param p simple pointer to an array of T objects that is adopted
371
     * @stable ICU 4.4
372
     */
373
    explicit LocalArray(T *p=nullptr) : LocalPointerBase<T>(p) {}
374
    /**
375
     * Constructor takes ownership and reports an error if nullptr.
376
     *
377
     * This constructor is intended to be used with other-class constructors
378
     * that may report a failure UErrorCode,
379
     * so that callers need to check only for U_FAILURE(errorCode)
380
     * and not also separately for isNull().
381
     *
382
     * @param p simple pointer to an array of T objects that is adopted
383
     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
384
     *     if p==nullptr and no other failure code had been set
385
     * @stable ICU 56
386
     */
387
    LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
388
        if(p==nullptr && U_SUCCESS(errorCode)) {
389
            errorCode=U_MEMORY_ALLOCATION_ERROR;
390
        }
391
    }
392
    /**
393
     * Move constructor, leaves src with isNull().
394
     * @param src source smart pointer
395
     * @stable ICU 56
396
     */
397
    LocalArray(LocalArray<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
398
        src.ptr=nullptr;
399
    }
400
401
    /**
402
     * Constructs a LocalArray from a C++11 std::unique_ptr of an array type.
403
     * The LocalPointer steals the array owned by the std::unique_ptr.
404
     *
405
     * This constructor works via move semantics. If your std::unique_ptr is
406
     * in a local variable, you must use std::move.
407
     *
408
     * @param p The std::unique_ptr from which the array will be stolen.
409
     * @stable ICU 64
410
     */
411
    explicit LocalArray(std::unique_ptr<T[]> &&p)
412
        : LocalPointerBase<T>(p.release()) {}
413
414
    /**
415
     * Destructor deletes the array it owns.
416
     * @stable ICU 4.4
417
     */
418
    ~LocalArray() {
419
        delete[] LocalPointerBase<T>::ptr;
420
    }
421
    /**
422
     * Move assignment operator, leaves src with isNull().
423
     * The behavior is undefined if *this and src are the same object.
424
     * @param src source smart pointer
425
     * @return *this
426
     * @stable ICU 56
427
     */
428
    LocalArray<T> &operator=(LocalArray<T> &&src) noexcept {
429
        delete[] LocalPointerBase<T>::ptr;
430
        LocalPointerBase<T>::ptr=src.ptr;
431
        src.ptr=nullptr;
432
        return *this;
433
    }
434
435
    /**
436
     * Move-assign from an std::unique_ptr to this LocalPointer.
437
     * Steals the array from the std::unique_ptr.
438
     *
439
     * @param p The std::unique_ptr from which the array will be stolen.
440
     * @return *this
441
     * @stable ICU 64
442
     */
443
    LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) noexcept {
444
        adoptInstead(p.release());
445
        return *this;
446
    }
447
448
    /**
449
     * Swap pointers.
450
     * @param other other smart pointer
451
     * @stable ICU 56
452
     */
453
    void swap(LocalArray<T> &other) noexcept {
454
        T *temp=LocalPointerBase<T>::ptr;
455
        LocalPointerBase<T>::ptr=other.ptr;
456
        other.ptr=temp;
457
    }
458
    /**
459
     * Non-member LocalArray swap function.
460
     * @param p1 will get p2's pointer
461
     * @param p2 will get p1's pointer
462
     * @stable ICU 56
463
     */
464
    friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) noexcept {
465
        p1.swap(p2);
466
    }
467
    /**
468
     * Deletes the array it owns,
469
     * and adopts (takes ownership of) the one passed in.
470
     * @param p simple pointer to an array of T objects that is adopted
471
     * @stable ICU 4.4
472
     */
473
    void adoptInstead(T *p) {
474
        delete[] LocalPointerBase<T>::ptr;
475
        LocalPointerBase<T>::ptr=p;
476
    }
477
    /**
478
     * Deletes the array it owns,
479
     * and adopts (takes ownership of) the one passed in.
480
     *
481
     * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
482
     *
483
     * If U_SUCCESS(errorCode) but the input pointer is nullptr,
484
     * then U_MEMORY_ALLOCATION_ERROR is set,
485
     * the current array is deleted, and nullptr is set.
486
     *
487
     * @param p simple pointer to an array of T objects that is adopted
488
     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
489
     *     if p==nullptr and no other failure code had been set
490
     * @stable ICU 56
491
     */
492
    void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
493
        if(U_SUCCESS(errorCode)) {
494
            delete[] LocalPointerBase<T>::ptr;
495
            LocalPointerBase<T>::ptr=p;
496
            if(p==nullptr) {
497
                errorCode=U_MEMORY_ALLOCATION_ERROR;
498
            }
499
        } else {
500
            delete[] p;
501
        }
502
    }
503
    /**
504
     * Array item access (writable).
505
     * No index bounds check.
506
     * @param i array index
507
     * @return reference to the array item
508
     * @stable ICU 4.4
509
     */
510
    T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
511
512
    /**
513
     * Conversion operator to a C++11 std::unique_ptr.
514
     * Disowns the object and gives it to the returned std::unique_ptr.
515
     *
516
     * This operator works via move semantics. If your LocalPointer is
517
     * in a local variable, you must use std::move.
518
     *
519
     * @return An std::unique_ptr owning the pointer previously owned by this
520
     *         icu::LocalPointer.
521
     * @stable ICU 64
522
     */
523
    operator std::unique_ptr<T[]> () && {
524
        return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
525
    }
526
};
527
528
/**
529
 * \def U_DEFINE_LOCAL_OPEN_POINTER
530
 * "Smart pointer" definition macro, deletes objects via the closeFunction.
531
 * Defines a subclass of LocalPointerBase which works just
532
 * like LocalPointer<Type> except that this subclass will use the closeFunction
533
 * rather than the C++ delete operator.
534
 *
535
 * Usage example:
536
 * \code
537
 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
538
 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
539
 *     utf8Out, (int32_t)sizeof(utf8Out),
540
 *     utf8In, utf8InLength, &errorCode);
541
 * if(U_FAILURE(errorCode)) { return; }  // no need to explicitly delete the UCaseMap
542
 * \endcode
543
 *
544
 * @see LocalPointerBase
545
 * @see LocalPointer
546
 * @stable ICU 4.4
547
 */
548
#define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
549
    using LocalPointerClassName = internal::LocalOpenPointer<Type, closeFunction>
550
551
#ifndef U_IN_DOXYGEN
552
namespace internal {
553
/**
554
 * Implementation, do not use directly: use U_DEFINE_LOCAL_OPEN_POINTER.
555
 *
556
 * @see U_DEFINE_LOCAL_OPEN_POINTER
557
 * @internal
558
 */
559
template <typename Type, auto closeFunction>
560
class LocalOpenPointer : public LocalPointerBase<Type> {
561
    using LocalPointerBase<Type>::ptr;
562
public:
563
    using LocalPointerBase<Type>::operator*;
564
    using LocalPointerBase<Type>::operator->;
565
0
    explicit LocalOpenPointer(Type *p=nullptr) : LocalPointerBase<Type>(p) {}
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UResourceBundle, &ures_close_78>::LocalOpenPointer(UResourceBundle*)
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UHashtable, &uhash_close_78>::LocalOpenPointer(UHashtable*)
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UEnumeration, &uenum_close_78>::LocalOpenPointer(UEnumeration*)
Unexecuted instantiation: uloc_tag.cpp:icu_78::internal::LocalOpenPointer<(anonymous namespace)::ULanguageTag, &(anonymous namespace)::ultag_close>::LocalOpenPointer((anonymous namespace)::ULanguageTag*)
566
    LocalOpenPointer(LocalOpenPointer &&src) noexcept
567
            : LocalPointerBase<Type>(src.ptr) {
568
        src.ptr=nullptr;
569
    }
570
    /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */
571
    explicit LocalOpenPointer(std::unique_ptr<Type, decltype(closeFunction)> &&p)
572
            : LocalPointerBase<Type>(p.release()) {}
573
0
    ~LocalOpenPointer() { if (ptr != nullptr) { closeFunction(ptr); } }
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UHashtable, &uhash_close_78>::~LocalOpenPointer()
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UResourceBundle, &ures_close_78>::~LocalOpenPointer()
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UEnumeration, &uenum_close_78>::~LocalOpenPointer()
Unexecuted instantiation: uloc_tag.cpp:icu_78::internal::LocalOpenPointer<(anonymous namespace)::ULanguageTag, &(anonymous namespace)::ultag_close>::~LocalOpenPointer()
574
    LocalOpenPointer &operator=(LocalOpenPointer &&src) noexcept {
575
        if (ptr != nullptr) { closeFunction(ptr); }
576
        LocalPointerBase<Type>::ptr=src.ptr;
577
        src.ptr=nullptr;
578
        return *this;
579
    }
580
    /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */
581
    LocalOpenPointer &operator=(std::unique_ptr<Type, decltype(closeFunction)> &&p) {
582
        adoptInstead(p.release());
583
        return *this;
584
    }
585
    void swap(LocalOpenPointer &other) noexcept {
586
        Type *temp=LocalPointerBase<Type>::ptr;
587
        LocalPointerBase<Type>::ptr=other.ptr;
588
        other.ptr=temp;
589
    }
590
    friend inline void swap(LocalOpenPointer &p1, LocalOpenPointer &p2) noexcept {
591
        p1.swap(p2);
592
    }
593
0
    void adoptInstead(Type *p) {
594
0
        if (ptr != nullptr) { closeFunction(ptr); }
595
0
        ptr=p;
596
0
    }
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UResourceBundle, &ures_close_78>::adoptInstead(UResourceBundle*)
Unexecuted instantiation: icu_78::internal::LocalOpenPointer<UHashtable, &uhash_close_78>::adoptInstead(UHashtable*)
597
    operator std::unique_ptr<Type, decltype(closeFunction)> () && {
598
        return std::unique_ptr<Type, decltype(closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction);
599
    }
600
};
601
}  // namespace internal
602
#endif
603
604
U_NAMESPACE_END
605
606
#endif  /* U_SHOW_CPLUSPLUS_API */
607
#endif  /* __LOCALPOINTER_H__ */