Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
localpointer.h596 linesDownload Raw Back to unicode
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 http://site.icu-project.org/design/cpp/scoped_ptr
39 */
40
41#include "unicode/utypes.h"
42
43#if U_SHOW_CPLUSPLUS_API
44
45#include <memory>
46
47U_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 */
67template<typename T>
68class LocalPointerBase {
69public:
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#if U_HAVE_PLACEMENT_NEW
74    static void* U_EXPORT2 operator new(size_t, void*) = delete;
75#endif
76
77    /**
78     * Constructor takes ownership.
79     * @param p simple pointer to an object that is adopted
80     * @stable ICU 4.4
81     */
82    explicit LocalPointerBase(T *p=NULL) : ptr(p) {}
83    /**
84     * Destructor deletes the object it owns.
85     * Subclass must override: Base class does nothing.
86     * @stable ICU 4.4
87     */
88    ~LocalPointerBase() { /* delete ptr; */ }
89    /**
90     * NULL check.
91     * @return TRUE if ==NULL
92     * @stable ICU 4.4
93     */
94    UBool isNull() const { return ptr==NULL; }
95    /**
96     * NULL check.
97     * @return TRUE if !=NULL
98     * @stable ICU 4.4
99     */
100    UBool isValid() const { return ptr!=NULL; }
101    /**
102     * Comparison with a simple pointer, so that existing code
103     * with ==NULL need not be changed.
104     * @param other simple pointer for comparison
105     * @return true if this pointer value equals other
106     * @stable ICU 4.4
107     */
108    bool operator==(const T *other) const { return ptr==other; }
109    /**
110     * Comparison with a simple pointer, so that existing code
111     * with !=NULL need not be changed.
112     * @param other simple pointer for comparison
113     * @return true if this pointer value differs from other
114     * @stable ICU 4.4
115     */
116    bool operator!=(const T *other) const { return ptr!=other; }
117    /**
118     * Access without ownership change.
119     * @return the pointer value
120     * @stable ICU 4.4
121     */
122    T *getAlias() const { return ptr; }
123    /**
124     * Access without ownership change.
125     * @return the pointer value as a reference
126     * @stable ICU 4.4
127     */
128    T &operator*() const { return *ptr; }
129    /**
130     * Access without ownership change.
131     * @return the pointer value
132     * @stable ICU 4.4
133     */
134    T *operator->() const { return ptr; }
135    /**
136     * Gives up ownership; the internal pointer becomes NULL.
137     * @return the pointer value;
138     *         caller becomes responsible for deleting the object
139     * @stable ICU 4.4
140     */
141    T *orphan() {
142        T *p=ptr;
143        ptr=NULL;
144        return p;
145    }
146    /**
147     * Deletes the object it owns,
148     * and adopts (takes ownership of) the one passed in.
149     * Subclass must override: Base class does not delete the object.
150     * @param p simple pointer to an object that is adopted
151     * @stable ICU 4.4
152     */
153    void adoptInstead(T *p) {
154        // delete ptr;
155        ptr=p;
156    }
157protected:
158    /**
159     * Actual pointer.
160     * @internal
161     */
162    T *ptr;
163private:
164    // No comparison operators with other LocalPointerBases.
165    bool operator==(const LocalPointerBase<T> &other);
166    bool operator!=(const LocalPointerBase<T> &other);
167    // No ownership sharing: No copy constructor, no assignment operator.
168    LocalPointerBase(const LocalPointerBase<T> &other);
169    void operator=(const LocalPointerBase<T> &other);
170};
171
172/**
173 * "Smart pointer" class, deletes objects via the standard C++ delete operator.
174 * For most methods see the LocalPointerBase base class.
175 *
176 * Usage example:
177 * \code
178 * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
179 * int32_t length=s->length();  // 2
180 * char16_t lead=s->charAt(0);  // 0xd900
181 * if(some condition) { return; }  // no need to explicitly delete the pointer
182 * s.adoptInstead(new UnicodeString((char16_t)0xfffc));
183 * length=s->length();  // 1
184 * // no need to explicitly delete the pointer
185 * \endcode
186 *
187 * @see LocalPointerBase
188 * @stable ICU 4.4
189 */
190template<typename T>
191class LocalPointer : public LocalPointerBase<T> {
192public:
193    using LocalPointerBase<T>::operator*;
194    using LocalPointerBase<T>::operator->;
195    /**
196     * Constructor takes ownership.
197     * @param p simple pointer to an object that is adopted
198     * @stable ICU 4.4
199     */
200    explicit LocalPointer(T *p=NULL) : LocalPointerBase<T>(p) {}
201    /**
202     * Constructor takes ownership and reports an error if NULL.
203     *
204     * This constructor is intended to be used with other-class constructors
205     * that may report a failure UErrorCode,
206     * so that callers need to check only for U_FAILURE(errorCode)
207     * and not also separately for isNull().
208     *
209     * @param p simple pointer to an object that is adopted
210     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
211     *     if p==NULL and no other failure code had been set
212     * @stable ICU 55
213     */
214    LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
215        if(p==NULL && U_SUCCESS(errorCode)) {
216            errorCode=U_MEMORY_ALLOCATION_ERROR;
217        }
218    }
219    /**
220     * Move constructor, leaves src with isNull().
221     * @param src source smart pointer
222     * @stable ICU 56
223     */
224    LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
225        src.ptr=NULL;
226    }
227
228    /**
229     * Constructs a LocalPointer from a C++11 std::unique_ptr.
230     * The LocalPointer steals the object owned by the std::unique_ptr.
231     *
232     * This constructor works via move semantics. If your std::unique_ptr is
233     * in a local variable, you must use std::move.
234     *
235     * @param p The std::unique_ptr from which the pointer will be stolen.
236     * @stable ICU 64
237     */
238    explicit LocalPointer(std::unique_ptr<T> &&p)
239        : LocalPointerBase<T>(p.release()) {}
240
241    /**
242     * Destructor deletes the object it owns.
243     * @stable ICU 4.4
244     */
245    ~LocalPointer() {
246        delete LocalPointerBase<T>::ptr;
247    }
248    /**
249     * Move assignment operator, leaves src with isNull().
250     * The behavior is undefined if *this and src are the same object.
251     * @param src source smart pointer
252     * @return *this
253     * @stable ICU 56
254     */
255    LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT {
256        delete LocalPointerBase<T>::ptr;
257        LocalPointerBase<T>::ptr=src.ptr;
258        src.ptr=NULL;
259        return *this;
260    }
261
262    /**
263     * Move-assign from an std::unique_ptr to this LocalPointer.
264     * Steals the pointer from the std::unique_ptr.
265     *
266     * @param p The std::unique_ptr from which the pointer will be stolen.
267     * @return *this
268     * @stable ICU 64
269     */
270    LocalPointer<T> &operator=(std::unique_ptr<T> &&p) U_NOEXCEPT {
271        adoptInstead(p.release());
272        return *this;
273    }
274
275    /**
276     * Swap pointers.
277     * @param other other smart pointer
278     * @stable ICU 56
279     */
280    void swap(LocalPointer<T> &other) U_NOEXCEPT {
281        T *temp=LocalPointerBase<T>::ptr;
282        LocalPointerBase<T>::ptr=other.ptr;
283        other.ptr=temp;
284    }
285    /**
286     * Non-member LocalPointer swap function.
287     * @param p1 will get p2's pointer
288     * @param p2 will get p1's pointer
289     * @stable ICU 56
290     */
291    friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT {
292        p1.swap(p2);
293    }
294    /**
295     * Deletes the object it owns,
296     * and adopts (takes ownership of) the one passed in.
297     * @param p simple pointer to an object that is adopted
298     * @stable ICU 4.4
299     */
300    void adoptInstead(T *p) {
301        delete LocalPointerBase<T>::ptr;
302        LocalPointerBase<T>::ptr=p;
303    }
304    /**
305     * Deletes the object it owns,
306     * and adopts (takes ownership of) the one passed in.
307     *
308     * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
309     *
310     * If U_SUCCESS(errorCode) but the input pointer is NULL,
311     * then U_MEMORY_ALLOCATION_ERROR is set,
312     * the current object is deleted, and NULL is set.
313     *
314     * @param p simple pointer to an object that is adopted
315     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
316     *     if p==NULL and no other failure code had been set
317     * @stable ICU 55
318     */
319    void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
320        if(U_SUCCESS(errorCode)) {
321            delete LocalPointerBase<T>::ptr;
322            LocalPointerBase<T>::ptr=p;
323            if(p==NULL) {
324                errorCode=U_MEMORY_ALLOCATION_ERROR;
325            }
326        } else {
327            delete p;
328        }
329    }
330
331    /**
332     * Conversion operator to a C++11 std::unique_ptr.
333     * Disowns the object and gives it to the returned std::unique_ptr.
334     *
335     * This operator works via move semantics. If your LocalPointer is
336     * in a local variable, you must use std::move.
337     *
338     * @return An std::unique_ptr owning the pointer previously owned by this
339     *         icu::LocalPointer.
340     * @stable ICU 64
341     */
342    operator std::unique_ptr<T> () && {
343        return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
344    }
345};
346
347/**
348 * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
349 * For most methods see the LocalPointerBase base class.
350 * Adds operator[] for array item access.
351 *
352 * Usage example:
353 * \code
354 * LocalArray<UnicodeString> a(new UnicodeString[2]);
355 * a[0].append((char16_t)0x61);
356 * if(some condition) { return; }  // no need to explicitly delete the array
357 * a.adoptInstead(new UnicodeString[4]);
358 * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse();
359 * // no need to explicitly delete the array
360 * \endcode
361 *
362 * @see LocalPointerBase
363 * @stable ICU 4.4
364 */
365template<typename T>
366class LocalArray : public LocalPointerBase<T> {
367public:
368    using LocalPointerBase<T>::operator*;
369    using LocalPointerBase<T>::operator->;
370    /**
371     * Constructor takes ownership.
372     * @param p simple pointer to an array of T objects that is adopted
373     * @stable ICU 4.4
374     */
375    explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
376    /**
377     * Constructor takes ownership and reports an error if NULL.
378     *
379     * This constructor is intended to be used with other-class constructors
380     * that may report a failure UErrorCode,
381     * so that callers need to check only for U_FAILURE(errorCode)
382     * and not also separately for isNull().
383     *
384     * @param p simple pointer to an array of T objects that is adopted
385     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
386     *     if p==NULL and no other failure code had been set
387     * @stable ICU 56
388     */
389    LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
390        if(p==NULL && U_SUCCESS(errorCode)) {
391            errorCode=U_MEMORY_ALLOCATION_ERROR;
392        }
393    }
394    /**
395     * Move constructor, leaves src with isNull().
396     * @param src source smart pointer
397     * @stable ICU 56
398     */
399    LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
400        src.ptr=NULL;
401    }
402
403    /**
404     * Constructs a LocalArray from a C++11 std::unique_ptr of an array type.
405     * The LocalPointer steals the array owned by the std::unique_ptr.
406     *
407     * This constructor works via move semantics. If your std::unique_ptr is
408     * in a local variable, you must use std::move.
409     *
410     * @param p The std::unique_ptr from which the array will be stolen.
411     * @stable ICU 64
412     */
413    explicit LocalArray(std::unique_ptr<T[]> &&p)
414        : LocalPointerBase<T>(p.release()) {}
415
416    /**
417     * Destructor deletes the array it owns.
418     * @stable ICU 4.4
419     */
420    ~LocalArray() {
421        delete[] LocalPointerBase<T>::ptr;
422    }
423    /**
424     * Move assignment operator, leaves src with isNull().
425     * The behavior is undefined if *this and src are the same object.
426     * @param src source smart pointer
427     * @return *this
428     * @stable ICU 56
429     */
430    LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
431        delete[] LocalPointerBase<T>::ptr;
432        LocalPointerBase<T>::ptr=src.ptr;
433        src.ptr=NULL;
434        return *this;
435    }
436
437    /**
438     * Move-assign from an std::unique_ptr to this LocalPointer.
439     * Steals the array from the std::unique_ptr.
440     *
441     * @param p The std::unique_ptr from which the array will be stolen.
442     * @return *this
443     * @stable ICU 64
444     */
445    LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) U_NOEXCEPT {
446        adoptInstead(p.release());
447        return *this;
448    }
449
450    /**
451     * Swap pointers.
452     * @param other other smart pointer
453     * @stable ICU 56
454     */
455    void swap(LocalArray<T> &other) U_NOEXCEPT {
456        T *temp=LocalPointerBase<T>::ptr;
457        LocalPointerBase<T>::ptr=other.ptr;
458        other.ptr=temp;
459    }
460    /**
461     * Non-member LocalArray swap function.
462     * @param p1 will get p2's pointer
463     * @param p2 will get p1's pointer
464     * @stable ICU 56
465     */
466    friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT {
467        p1.swap(p2);
468    }
469    /**
470     * Deletes the array it owns,
471     * and adopts (takes ownership of) the one passed in.
472     * @param p simple pointer to an array of T objects that is adopted
473     * @stable ICU 4.4
474     */
475    void adoptInstead(T *p) {
476        delete[] LocalPointerBase<T>::ptr;
477        LocalPointerBase<T>::ptr=p;
478    }
479    /**
480     * Deletes the array it owns,
481     * and adopts (takes ownership of) the one passed in.
482     *
483     * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
484     *
485     * If U_SUCCESS(errorCode) but the input pointer is NULL,
486     * then U_MEMORY_ALLOCATION_ERROR is set,
487     * the current array is deleted, and NULL is set.
488     *
489     * @param p simple pointer to an array of T objects that is adopted
490     * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
491     *     if p==NULL and no other failure code had been set
492     * @stable ICU 56
493     */
494    void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
495        if(U_SUCCESS(errorCode)) {
496            delete[] LocalPointerBase<T>::ptr;
497            LocalPointerBase<T>::ptr=p;
498            if(p==NULL) {
499                errorCode=U_MEMORY_ALLOCATION_ERROR;
500            }
501        } else {
502            delete[] p;
503        }
504    }
505    /**
506     * Array item access (writable).
507     * No index bounds check.
508     * @param i array index
509     * @return reference to the array item
510     * @stable ICU 4.4
511     */
512    T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
513
514    /**
515     * Conversion operator to a C++11 std::unique_ptr.
516     * Disowns the object and gives it to the returned std::unique_ptr.
517     *
518     * This operator works via move semantics. If your LocalPointer is
519     * in a local variable, you must use std::move.
520     *
521     * @return An std::unique_ptr owning the pointer previously owned by this
522     *         icu::LocalPointer.
523     * @stable ICU 64
524     */
525    operator std::unique_ptr<T[]> () && {
526        return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
527    }
528};
529
530/**
531 * \def U_DEFINE_LOCAL_OPEN_POINTER
532 * "Smart pointer" definition macro, deletes objects via the closeFunction.
533 * Defines a subclass of LocalPointerBase which works just
534 * like LocalPointer<Type> except that this subclass will use the closeFunction
535 * rather than the C++ delete operator.
536 *
537 * Usage example:
538 * \code
539 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
540 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
541 *     utf8Out, (int32_t)sizeof(utf8Out),
542 *     utf8In, utf8InLength, &errorCode);
543 * if(U_FAILURE(errorCode)) { return; }  // no need to explicitly delete the UCaseMap
544 * \endcode
545 *
546 * @see LocalPointerBase
547 * @see LocalPointer
548 * @stable ICU 4.4
549 */
550#define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
551    class LocalPointerClassName : public LocalPointerBase<Type> { \
552    public: \
553        using LocalPointerBase<Type>::operator*; \
554        using LocalPointerBase<Type>::operator->; \
555        explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
556        LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
557                : LocalPointerBase<Type>(src.ptr) { \
558            src.ptr=NULL; \
559        } \
560        /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
561        explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
562                : LocalPointerBase<Type>(p.release()) {} \
563        ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
564        LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
565            if (ptr != NULL) { closeFunction(ptr); } \
566            LocalPointerBase<Type>::ptr=src.ptr; \
567            src.ptr=NULL; \
568            return *this; \
569        } \
570        /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
571        LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
572            adoptInstead(p.release()); \
573            return *this; \
574        } \
575        void swap(LocalPointerClassName &other) U_NOEXCEPT { \
576            Type *temp=LocalPointerBase<Type>::ptr; \
577            LocalPointerBase<Type>::ptr=other.ptr; \
578            other.ptr=temp; \
579        } \
580        friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
581            p1.swap(p2); \
582        } \
583        void adoptInstead(Type *p) { \
584            if (ptr != NULL) { closeFunction(ptr); } \
585            ptr=p; \
586        } \
587        operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
588            return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
589        } \
590    }
591
592U_NAMESPACE_END
593
594#endif  /* U_SHOW_CPLUSPLUS_API */
595#endif  /* __LOCALPOINTER_H__ */
596 
codekingpro/portable-devtools · Team Ai