tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

localpointer.h (19985B)


      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    explicit LocalPointerBase(T *p=nullptr) : ptr(p) {}
     81    /**
     82     * Destructor deletes the object it owns.
     83     * Subclass must override: Base class does nothing.
     84     * @stable ICU 4.4
     85     */
     86    ~LocalPointerBase() { /* delete ptr; */ }
     87    /**
     88     * nullptr check.
     89     * @return true if ==nullptr
     90     * @stable ICU 4.4
     91     */
     92    UBool isNull() const { return ptr==nullptr; }
     93    /**
     94     * nullptr check.
     95     * @return true if !=nullptr
     96     * @stable ICU 4.4
     97     */
     98    UBool isValid() const { return ptr!=nullptr; }
     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    T *getAlias() const { return ptr; }
    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    T *operator->() const { return ptr; }
    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    T *orphan() {
    140        T *p=ptr;
    141        ptr=nullptr;
    142        return p;
    143    }
    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    explicit LocalPointer(T *p=nullptr) : LocalPointerBase<T>(p) {}
    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    LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
    213        if(p==nullptr && U_SUCCESS(errorCode)) {
    214            errorCode=U_MEMORY_ALLOCATION_ERROR;
    215        }
    216    }
    217    /**
    218     * Move constructor, leaves src with isNull().
    219     * @param src source smart pointer
    220     * @stable ICU 56
    221     */
    222    LocalPointer(LocalPointer<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
    223        src.ptr=nullptr;
    224    }
    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    ~LocalPointer() {
    244        delete LocalPointerBase<T>::ptr;
    245    }
    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    void adoptInstead(T *p) {
    299        delete LocalPointerBase<T>::ptr;
    300        LocalPointerBase<T>::ptr=p;
    301    }
    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    void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
    318        if(U_SUCCESS(errorCode)) {
    319            delete LocalPointerBase<T>::ptr;
    320            LocalPointerBase<T>::ptr=p;
    321            if(p==nullptr) {
    322                errorCode=U_MEMORY_ALLOCATION_ERROR;
    323            }
    324        } else {
    325            delete p;
    326        }
    327    }
    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    explicit LocalOpenPointer(Type *p=nullptr) : LocalPointerBase<Type>(p) {}
    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    ~LocalOpenPointer() { if (ptr != nullptr) { closeFunction(ptr); } }
    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    void adoptInstead(Type *p) {
    594        if (ptr != nullptr) { closeFunction(ptr); }
    595        ptr=p;
    596    }
    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__ */