Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | // Scopers help you manage ownership of a pointer, helping you easily manage the |
michael@0 | 6 | // a pointer within a scope, and automatically destroying the pointer at the |
michael@0 | 7 | // end of a scope. There are two main classes you will use, which coorespond |
michael@0 | 8 | // to the operators new/delete and new[]/delete[]. |
michael@0 | 9 | // |
michael@0 | 10 | // Example usage (scoped_ptr): |
michael@0 | 11 | // { |
michael@0 | 12 | // scoped_ptr<Foo> foo(new Foo("wee")); |
michael@0 | 13 | // } // foo goes out of scope, releasing the pointer with it. |
michael@0 | 14 | // |
michael@0 | 15 | // { |
michael@0 | 16 | // scoped_ptr<Foo> foo; // No pointer managed. |
michael@0 | 17 | // foo.reset(new Foo("wee")); // Now a pointer is managed. |
michael@0 | 18 | // foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. |
michael@0 | 19 | // foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. |
michael@0 | 20 | // foo->Method(); // Foo::Method() called. |
michael@0 | 21 | // foo.get()->Method(); // Foo::Method() called. |
michael@0 | 22 | // SomeFunc(foo.Release()); // SomeFunc takes owernship, foo no longer |
michael@0 | 23 | // // manages a pointer. |
michael@0 | 24 | // foo.reset(new Foo("wee4")); // foo manages a pointer again. |
michael@0 | 25 | // foo.reset(); // Foo("wee4") destroyed, foo no longer |
michael@0 | 26 | // // manages a pointer. |
michael@0 | 27 | // } // foo wasn't managing a pointer, so nothing was destroyed. |
michael@0 | 28 | // |
michael@0 | 29 | // Example usage (scoped_array): |
michael@0 | 30 | // { |
michael@0 | 31 | // scoped_array<Foo> foo(new Foo[100]); |
michael@0 | 32 | // foo.get()->Method(); // Foo::Method on the 0th element. |
michael@0 | 33 | // foo[10].Method(); // Foo::Method on the 10th element. |
michael@0 | 34 | // } |
michael@0 | 35 | |
michael@0 | 36 | #ifndef BASE_SCOPED_PTR_H_ |
michael@0 | 37 | #define BASE_SCOPED_PTR_H_ |
michael@0 | 38 | |
michael@0 | 39 | // This is an implementation designed to match the anticipated future TR2 |
michael@0 | 40 | // implementation of the scoped_ptr class, and its closely-related brethren, |
michael@0 | 41 | // scoped_array, scoped_ptr_malloc. |
michael@0 | 42 | |
michael@0 | 43 | #include <assert.h> |
michael@0 | 44 | #include <stdlib.h> |
michael@0 | 45 | #include <cstddef> |
michael@0 | 46 | |
michael@0 | 47 | // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> |
michael@0 | 48 | // automatically deletes the pointer it holds (if any). |
michael@0 | 49 | // That is, scoped_ptr<T> owns the T object that it points to. |
michael@0 | 50 | // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. |
michael@0 | 51 | // Also like T*, scoped_ptr<T> is thread-compatible, and once you |
michael@0 | 52 | // dereference it, you get the threadsafety guarantees of T. |
michael@0 | 53 | // |
michael@0 | 54 | // The size of a scoped_ptr is small: |
michael@0 | 55 | // sizeof(scoped_ptr<C>) == sizeof(C*) |
michael@0 | 56 | template <class C> |
michael@0 | 57 | class scoped_ptr { |
michael@0 | 58 | public: |
michael@0 | 59 | |
michael@0 | 60 | // The element type |
michael@0 | 61 | typedef C element_type; |
michael@0 | 62 | |
michael@0 | 63 | // Constructor. Defaults to intializing with NULL. |
michael@0 | 64 | // There is no way to create an uninitialized scoped_ptr. |
michael@0 | 65 | // The input parameter must be allocated with new. |
michael@0 | 66 | explicit scoped_ptr(C* p = NULL) : ptr_(p) { } |
michael@0 | 67 | |
michael@0 | 68 | // Destructor. If there is a C object, delete it. |
michael@0 | 69 | // We don't need to test ptr_ == NULL because C++ does that for us. |
michael@0 | 70 | ~scoped_ptr() { |
michael@0 | 71 | enum { type_must_be_complete = sizeof(C) }; |
michael@0 | 72 | delete ptr_; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | // Reset. Deletes the current owned object, if any. |
michael@0 | 76 | // Then takes ownership of a new object, if given. |
michael@0 | 77 | // this->reset(this->get()) works. |
michael@0 | 78 | void reset(C* p = NULL) { |
michael@0 | 79 | if (p != ptr_) { |
michael@0 | 80 | enum { type_must_be_complete = sizeof(C) }; |
michael@0 | 81 | delete ptr_; |
michael@0 | 82 | ptr_ = p; |
michael@0 | 83 | } |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | // Accessors to get the owned object. |
michael@0 | 87 | // operator* and operator-> will assert() if there is no current object. |
michael@0 | 88 | C& operator*() const { |
michael@0 | 89 | assert(ptr_ != NULL); |
michael@0 | 90 | return *ptr_; |
michael@0 | 91 | } |
michael@0 | 92 | C* operator->() const { |
michael@0 | 93 | assert(ptr_ != NULL); |
michael@0 | 94 | return ptr_; |
michael@0 | 95 | } |
michael@0 | 96 | C* get() const { return ptr_; } |
michael@0 | 97 | |
michael@0 | 98 | // Comparison operators. |
michael@0 | 99 | // These return whether two scoped_ptr refer to the same object, not just to |
michael@0 | 100 | // two different but equal objects. |
michael@0 | 101 | bool operator==(C* p) const { return ptr_ == p; } |
michael@0 | 102 | bool operator!=(C* p) const { return ptr_ != p; } |
michael@0 | 103 | |
michael@0 | 104 | // Swap two scoped pointers. |
michael@0 | 105 | void swap(scoped_ptr& p2) { |
michael@0 | 106 | C* tmp = ptr_; |
michael@0 | 107 | ptr_ = p2.ptr_; |
michael@0 | 108 | p2.ptr_ = tmp; |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | // Release a pointer. |
michael@0 | 112 | // The return value is the current pointer held by this object. |
michael@0 | 113 | // If this object holds a NULL pointer, the return value is NULL. |
michael@0 | 114 | // After this operation, this object will hold a NULL pointer, |
michael@0 | 115 | // and will not own the object any more. |
michael@0 | 116 | C* release() { |
michael@0 | 117 | C* retVal = ptr_; |
michael@0 | 118 | ptr_ = NULL; |
michael@0 | 119 | return retVal; |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | private: |
michael@0 | 123 | C* ptr_; |
michael@0 | 124 | |
michael@0 | 125 | // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't |
michael@0 | 126 | // make sense, and if C2 == C, it still doesn't make sense because you should |
michael@0 | 127 | // never have the same object owned by two different scoped_ptrs. |
michael@0 | 128 | template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; |
michael@0 | 129 | template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; |
michael@0 | 130 | |
michael@0 | 131 | // Disallow evil constructors |
michael@0 | 132 | scoped_ptr(const scoped_ptr&); |
michael@0 | 133 | void operator=(const scoped_ptr&); |
michael@0 | 134 | }; |
michael@0 | 135 | |
michael@0 | 136 | // Free functions |
michael@0 | 137 | template <class C> |
michael@0 | 138 | void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { |
michael@0 | 139 | p1.swap(p2); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | template <class C> |
michael@0 | 143 | bool operator==(C* p1, const scoped_ptr<C>& p2) { |
michael@0 | 144 | return p1 == p2.get(); |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | template <class C> |
michael@0 | 148 | bool operator!=(C* p1, const scoped_ptr<C>& p2) { |
michael@0 | 149 | return p1 != p2.get(); |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate |
michael@0 | 153 | // with new [] and the destructor deletes objects with delete []. |
michael@0 | 154 | // |
michael@0 | 155 | // As with scoped_ptr<C>, a scoped_array<C> either points to an object |
michael@0 | 156 | // or is NULL. A scoped_array<C> owns the object that it points to. |
michael@0 | 157 | // scoped_array<T> is thread-compatible, and once you index into it, |
michael@0 | 158 | // the returned objects have only the threadsafety guarantees of T. |
michael@0 | 159 | // |
michael@0 | 160 | // Size: sizeof(scoped_array<C>) == sizeof(C*) |
michael@0 | 161 | template <class C> |
michael@0 | 162 | class scoped_array { |
michael@0 | 163 | public: |
michael@0 | 164 | |
michael@0 | 165 | // The element type |
michael@0 | 166 | typedef C element_type; |
michael@0 | 167 | |
michael@0 | 168 | // Constructor. Defaults to intializing with NULL. |
michael@0 | 169 | // There is no way to create an uninitialized scoped_array. |
michael@0 | 170 | // The input parameter must be allocated with new []. |
michael@0 | 171 | explicit scoped_array(C* p = NULL) : array_(p) { } |
michael@0 | 172 | |
michael@0 | 173 | // Destructor. If there is a C object, delete it. |
michael@0 | 174 | // We don't need to test ptr_ == NULL because C++ does that for us. |
michael@0 | 175 | ~scoped_array() { |
michael@0 | 176 | enum { type_must_be_complete = sizeof(C) }; |
michael@0 | 177 | delete[] array_; |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | // Reset. Deletes the current owned object, if any. |
michael@0 | 181 | // Then takes ownership of a new object, if given. |
michael@0 | 182 | // this->reset(this->get()) works. |
michael@0 | 183 | void reset(C* p = NULL) { |
michael@0 | 184 | if (p != array_) { |
michael@0 | 185 | enum { type_must_be_complete = sizeof(C) }; |
michael@0 | 186 | delete[] array_; |
michael@0 | 187 | array_ = p; |
michael@0 | 188 | } |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | // Get one element of the current object. |
michael@0 | 192 | // Will assert() if there is no current object, or index i is negative. |
michael@0 | 193 | C& operator[](std::ptrdiff_t i) const { |
michael@0 | 194 | assert(i >= 0); |
michael@0 | 195 | assert(array_ != NULL); |
michael@0 | 196 | return array_[i]; |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | // Get a pointer to the zeroth element of the current object. |
michael@0 | 200 | // If there is no current object, return NULL. |
michael@0 | 201 | C* get() const { |
michael@0 | 202 | return array_; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | // Comparison operators. |
michael@0 | 206 | // These return whether two scoped_array refer to the same object, not just to |
michael@0 | 207 | // two different but equal objects. |
michael@0 | 208 | bool operator==(C* p) const { return array_ == p; } |
michael@0 | 209 | bool operator!=(C* p) const { return array_ != p; } |
michael@0 | 210 | |
michael@0 | 211 | // Swap two scoped arrays. |
michael@0 | 212 | void swap(scoped_array& p2) { |
michael@0 | 213 | C* tmp = array_; |
michael@0 | 214 | array_ = p2.array_; |
michael@0 | 215 | p2.array_ = tmp; |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | // Release an array. |
michael@0 | 219 | // The return value is the current pointer held by this object. |
michael@0 | 220 | // If this object holds a NULL pointer, the return value is NULL. |
michael@0 | 221 | // After this operation, this object will hold a NULL pointer, |
michael@0 | 222 | // and will not own the object any more. |
michael@0 | 223 | C* release() { |
michael@0 | 224 | C* retVal = array_; |
michael@0 | 225 | array_ = NULL; |
michael@0 | 226 | return retVal; |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | private: |
michael@0 | 230 | C* array_; |
michael@0 | 231 | |
michael@0 | 232 | // Forbid comparison of different scoped_array types. |
michael@0 | 233 | template <class C2> bool operator==(scoped_array<C2> const& p2) const; |
michael@0 | 234 | template <class C2> bool operator!=(scoped_array<C2> const& p2) const; |
michael@0 | 235 | |
michael@0 | 236 | // Disallow evil constructors |
michael@0 | 237 | scoped_array(const scoped_array&); |
michael@0 | 238 | void operator=(const scoped_array&); |
michael@0 | 239 | }; |
michael@0 | 240 | |
michael@0 | 241 | // Free functions |
michael@0 | 242 | template <class C> |
michael@0 | 243 | void swap(scoped_array<C>& p1, scoped_array<C>& p2) { |
michael@0 | 244 | p1.swap(p2); |
michael@0 | 245 | } |
michael@0 | 246 | |
michael@0 | 247 | template <class C> |
michael@0 | 248 | bool operator==(C* p1, const scoped_array<C>& p2) { |
michael@0 | 249 | return p1 == p2.get(); |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | template <class C> |
michael@0 | 253 | bool operator!=(C* p1, const scoped_array<C>& p2) { |
michael@0 | 254 | return p1 != p2.get(); |
michael@0 | 255 | } |
michael@0 | 256 | |
michael@0 | 257 | // This class wraps the c library function free() in a class that can be |
michael@0 | 258 | // passed as a template argument to scoped_ptr_malloc below. |
michael@0 | 259 | class ScopedPtrMallocFree { |
michael@0 | 260 | public: |
michael@0 | 261 | inline void operator()(void* x) const { |
michael@0 | 262 | free(x); |
michael@0 | 263 | } |
michael@0 | 264 | }; |
michael@0 | 265 | |
michael@0 | 266 | // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a |
michael@0 | 267 | // second template argument, the functor used to free the object. |
michael@0 | 268 | |
michael@0 | 269 | template<class C, class FreeProc = ScopedPtrMallocFree> |
michael@0 | 270 | class scoped_ptr_malloc { |
michael@0 | 271 | public: |
michael@0 | 272 | |
michael@0 | 273 | // The element type |
michael@0 | 274 | typedef C element_type; |
michael@0 | 275 | |
michael@0 | 276 | // Constructor. Defaults to intializing with NULL. |
michael@0 | 277 | // There is no way to create an uninitialized scoped_ptr. |
michael@0 | 278 | // The input parameter must be allocated with an allocator that matches the |
michael@0 | 279 | // Free functor. For the default Free functor, this is malloc, calloc, or |
michael@0 | 280 | // realloc. |
michael@0 | 281 | explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} |
michael@0 | 282 | |
michael@0 | 283 | // Destructor. If there is a C object, call the Free functor. |
michael@0 | 284 | ~scoped_ptr_malloc() { |
michael@0 | 285 | free_(ptr_); |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | // Reset. Calls the Free functor on the current owned object, if any. |
michael@0 | 289 | // Then takes ownership of a new object, if given. |
michael@0 | 290 | // this->reset(this->get()) works. |
michael@0 | 291 | void reset(C* p = NULL) { |
michael@0 | 292 | if (ptr_ != p) { |
michael@0 | 293 | free_(ptr_); |
michael@0 | 294 | ptr_ = p; |
michael@0 | 295 | } |
michael@0 | 296 | } |
michael@0 | 297 | |
michael@0 | 298 | // Get the current object. |
michael@0 | 299 | // operator* and operator-> will cause an assert() failure if there is |
michael@0 | 300 | // no current object. |
michael@0 | 301 | C& operator*() const { |
michael@0 | 302 | assert(ptr_ != NULL); |
michael@0 | 303 | return *ptr_; |
michael@0 | 304 | } |
michael@0 | 305 | |
michael@0 | 306 | C* operator->() const { |
michael@0 | 307 | assert(ptr_ != NULL); |
michael@0 | 308 | return ptr_; |
michael@0 | 309 | } |
michael@0 | 310 | |
michael@0 | 311 | C* get() const { |
michael@0 | 312 | return ptr_; |
michael@0 | 313 | } |
michael@0 | 314 | |
michael@0 | 315 | // Comparison operators. |
michael@0 | 316 | // These return whether a scoped_ptr_malloc and a plain pointer refer |
michael@0 | 317 | // to the same object, not just to two different but equal objects. |
michael@0 | 318 | // For compatibility wwith the boost-derived implementation, these |
michael@0 | 319 | // take non-const arguments. |
michael@0 | 320 | bool operator==(C* p) const { |
michael@0 | 321 | return ptr_ == p; |
michael@0 | 322 | } |
michael@0 | 323 | |
michael@0 | 324 | bool operator!=(C* p) const { |
michael@0 | 325 | return ptr_ != p; |
michael@0 | 326 | } |
michael@0 | 327 | |
michael@0 | 328 | // Swap two scoped pointers. |
michael@0 | 329 | void swap(scoped_ptr_malloc & b) { |
michael@0 | 330 | C* tmp = b.ptr_; |
michael@0 | 331 | b.ptr_ = ptr_; |
michael@0 | 332 | ptr_ = tmp; |
michael@0 | 333 | } |
michael@0 | 334 | |
michael@0 | 335 | // Release a pointer. |
michael@0 | 336 | // The return value is the current pointer held by this object. |
michael@0 | 337 | // If this object holds a NULL pointer, the return value is NULL. |
michael@0 | 338 | // After this operation, this object will hold a NULL pointer, |
michael@0 | 339 | // and will not own the object any more. |
michael@0 | 340 | C* release() { |
michael@0 | 341 | C* tmp = ptr_; |
michael@0 | 342 | ptr_ = NULL; |
michael@0 | 343 | return tmp; |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | private: |
michael@0 | 347 | C* ptr_; |
michael@0 | 348 | |
michael@0 | 349 | // no reason to use these: each scoped_ptr_malloc should have its own object |
michael@0 | 350 | template <class C2, class GP> |
michael@0 | 351 | bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; |
michael@0 | 352 | template <class C2, class GP> |
michael@0 | 353 | bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; |
michael@0 | 354 | |
michael@0 | 355 | static FreeProc const free_; |
michael@0 | 356 | |
michael@0 | 357 | // Disallow evil constructors |
michael@0 | 358 | scoped_ptr_malloc(const scoped_ptr_malloc&); |
michael@0 | 359 | void operator=(const scoped_ptr_malloc&); |
michael@0 | 360 | }; |
michael@0 | 361 | |
michael@0 | 362 | template<class C, class FP> |
michael@0 | 363 | FP const scoped_ptr_malloc<C, FP>::free_ = FP(); |
michael@0 | 364 | |
michael@0 | 365 | template<class C, class FP> inline |
michael@0 | 366 | void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { |
michael@0 | 367 | a.swap(b); |
michael@0 | 368 | } |
michael@0 | 369 | |
michael@0 | 370 | template<class C, class FP> inline |
michael@0 | 371 | bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { |
michael@0 | 372 | return p == b.get(); |
michael@0 | 373 | } |
michael@0 | 374 | |
michael@0 | 375 | template<class C, class FP> inline |
michael@0 | 376 | bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { |
michael@0 | 377 | return p != b.get(); |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | #endif // BASE_SCOPED_PTR_H_ |