Bug 1700051: part 30) Narrow scope of `newOffset`. r=smaug
[gecko.git] / mfbt / UniquePtrExtensions.h
blob82ad2b5d73e9ec146d35d634df2dd63a9786391b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Useful extensions to UniquePtr. */
9 #ifndef mozilla_UniquePtrExtensions_h
10 #define mozilla_UniquePtrExtensions_h
12 #include <type_traits>
14 #include "mozilla/Attributes.h"
15 #include "mozilla/fallible.h"
16 #include "mozilla/UniquePtr.h"
18 #ifdef XP_WIN
19 # include <cstdint>
20 #endif
22 namespace mozilla {
24 /**
25 * MakeUniqueFallible works exactly like MakeUnique, except that the memory
26 * allocation performed is done fallibly, i.e. it can return nullptr.
28 template <typename T, typename... Args>
29 typename detail::UniqueSelector<T>::SingleObject MakeUniqueFallible(
30 Args&&... aArgs) {
31 return UniquePtr<T>(new (fallible) T(std::forward<Args>(aArgs)...));
34 template <typename T>
35 typename detail::UniqueSelector<T>::UnknownBound MakeUniqueFallible(
36 decltype(sizeof(int)) aN) {
37 using ArrayType = std::remove_extent_t<T>;
38 return UniquePtr<T>(new (fallible) ArrayType[aN]());
41 template <typename T, typename... Args>
42 typename detail::UniqueSelector<T>::KnownBound MakeUniqueFallible(
43 Args&&... aArgs) = delete;
45 /**
46 * MakeUniqueForOverwrite and MakeUniqueFallibleForOverwrite are like MakeUnique
47 * and MakeUniqueFallible except they use default-initialization. This is
48 * useful, for example, when you have a POD type array that will be overwritten
49 * directly after construction and so zero-initialization is a waste.
51 template <typename T, typename... Args>
52 typename detail::UniqueSelector<T>::SingleObject MakeUniqueForOverwrite() {
53 return UniquePtr<T>(new T);
56 template <typename T>
57 typename detail::UniqueSelector<T>::UnknownBound MakeUniqueForOverwrite(
58 decltype(sizeof(int)) aN) {
59 using ArrayType = std::remove_extent_t<T>;
60 return UniquePtr<T>(new ArrayType[aN]);
63 template <typename T, typename... Args>
64 typename detail::UniqueSelector<T>::KnownBound MakeUniqueForOverwrite(
65 Args&&... aArgs) = delete;
67 template <typename T, typename... Args>
68 typename detail::UniqueSelector<T>::SingleObject
69 MakeUniqueForOverwriteFallible() {
70 return UniquePtr<T>(new (fallible) T);
73 template <typename T>
74 typename detail::UniqueSelector<T>::UnknownBound MakeUniqueForOverwriteFallible(
75 decltype(sizeof(int)) aN) {
76 using ArrayType = std::remove_extent_t<T>;
77 return UniquePtr<T>(new (fallible) ArrayType[aN]);
80 template <typename T, typename... Args>
81 typename detail::UniqueSelector<T>::KnownBound MakeUniqueForOverwriteFallible(
82 Args&&... aArgs) = delete;
84 namespace detail {
86 template <typename T>
87 struct FreePolicy {
88 void operator()(const void* ptr) { free(const_cast<void*>(ptr)); }
91 #if defined(XP_WIN)
92 // Can't include <windows.h> to get the actual definition of HANDLE
93 // because of namespace pollution.
94 typedef void* FileHandleType;
95 #elif defined(XP_UNIX)
96 typedef int FileHandleType;
97 #else
98 # error "Unsupported OS?"
99 #endif
101 struct FileHandleHelper {
102 MOZ_IMPLICIT FileHandleHelper(FileHandleType aHandle) : mHandle(aHandle) {}
104 MOZ_IMPLICIT constexpr FileHandleHelper(std::nullptr_t)
105 : mHandle(kInvalidHandle) {}
107 bool operator!=(std::nullptr_t) const {
108 #ifdef XP_WIN
109 // Windows uses both nullptr and INVALID_HANDLE_VALUE (-1 cast to
110 // HANDLE) in different situations, but nullptr is more reliably
111 // null while -1 is also valid input to some calls that take
112 // handles. So class considers both to be null (since neither
113 // should be closed) but default-constructs as nullptr.
114 if (mHandle == (void*)-1) {
115 return false;
117 #endif
118 return mHandle != kInvalidHandle;
121 operator FileHandleType() const { return mHandle; }
123 #ifdef XP_WIN
124 // NSPR uses an integer type for PROsfd, so this conversion is
125 // provided for working with it without needing reinterpret casts
126 // everywhere.
127 operator std::intptr_t() const {
128 return reinterpret_cast<std::intptr_t>(mHandle);
130 #endif
132 // When there's only one user-defined conversion operator, the
133 // compiler will use that to derive equality, but that doesn't work
134 // when the conversion is ambiguoug (the XP_WIN case above).
135 bool operator==(const FileHandleHelper& aOther) const {
136 return mHandle == aOther.mHandle;
139 private:
140 FileHandleType mHandle;
142 #ifdef XP_WIN
143 // See above for why this is nullptr. (Also, INVALID_HANDLE_VALUE
144 // can't be expressed as a constexpr.)
145 static constexpr FileHandleType kInvalidHandle = nullptr;
146 #else
147 static constexpr FileHandleType kInvalidHandle = -1;
148 #endif
151 struct FileHandleDeleter {
152 typedef FileHandleHelper pointer;
153 MFBT_API void operator()(FileHandleHelper aHelper);
156 } // namespace detail
158 template <typename T>
159 using UniqueFreePtr = UniquePtr<T, detail::FreePolicy<T>>;
161 // A RAII class for the OS construct used for open files and similar
162 // objects: a file descriptor on Unix or a handle on Windows.
163 using UniqueFileHandle =
164 UniquePtr<detail::FileHandleType, detail::FileHandleDeleter>;
166 // Helper for passing a UniquePtr to an old-style function that uses raw
167 // pointers for out params. Example usage:
169 // void AllocateFoo(Foo** out) { *out = new Foo(); }
170 // UniquePtr<Foo> foo;
171 // AllocateFoo(getter_Transfers(foo));
172 template <typename T, typename D>
173 auto getter_Transfers(UniquePtr<T, D>& up) {
174 class MOZ_TEMPORARY_CLASS UniquePtrGetterTransfers {
175 public:
176 using Ptr = UniquePtr<T, D>;
177 explicit UniquePtrGetterTransfers(Ptr& p) : mPtr(p) {}
178 ~UniquePtrGetterTransfers() { mPtr.reset(mRawPtr); }
180 operator typename Ptr::ElementType **() { return &mRawPtr; }
181 operator void**() { return reinterpret_cast<void**>(&mRawPtr); }
182 typename Ptr::ElementType*& operator*() { return mRawPtr; }
184 private:
185 Ptr& mPtr;
186 typename Ptr::Pointer mRawPtr = nullptr;
189 return UniquePtrGetterTransfers(up);
192 } // namespace mozilla
194 #endif // mozilla_UniquePtrExtensions_h