1e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Copyright 2013 Google Inc. All Rights Reserved. 22466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// 3e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Redistribution and use in source and binary forms, with or without 4e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// modification, are permitted provided that the following conditions are 5e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// met: 62466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// 7e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// * Redistributions of source code must retain the above copyright 8e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// notice, this list of conditions and the following disclaimer. 9e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// * Redistributions in binary form must reproduce the above 10e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// copyright notice, this list of conditions and the following disclaimer 11e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// in the documentation and/or other materials provided with the 12e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// distribution. 13e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// * Neither the name of Google Inc. nor the names of its 14e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// contributors may be used to endorse or promote products derived from 15e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// this software without specific prior written permission. 162466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// 17e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 29e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Scopers help you manage ownership of a pointer, helping you easily manage the 30e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// a pointer within a scope, and automatically destroying the pointer at the 31e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// end of a scope. There are two main classes you will use, which correspond 32e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// to the operators new/delete and new[]/delete[]. 332466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// 34e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Example usage (scoped_ptr): 35e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// { 36e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// scoped_ptr<Foo> foo(new Foo("wee")); 37e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// } // foo goes out of scope, releasing the pointer with it. 382466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// 39e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// { 40e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// scoped_ptr<Foo> foo; // No pointer managed. 41e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.reset(new Foo("wee")); // Now a pointer is managed. 42e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. 43e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. 44e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo->Method(); // Foo::Method() called. 45e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.get()->Method(); // Foo::Method() called. 46e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer 47e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// // manages a pointer. 48e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.reset(new Foo("wee4")); // foo manages a pointer again. 49e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.reset(); // Foo("wee4") destroyed, foo no longer 50e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// // manages a pointer. 51e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// } // foo wasn't managing a pointer, so nothing was destroyed. 522466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// 53e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Example usage (scoped_array): 54e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// { 55e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// scoped_array<Foo> foo(new Foo[100]); 56e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo.get()->Method(); // Foo::Method on the 0th element. 57e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// foo[10].Method(); // Foo::Method on the 10th element. 58e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// } 592466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 602cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#ifndef COMMON_SCOPED_PTR_H_ 612cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#define COMMON_SCOPED_PTR_H_ 622466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 63e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// This is an implementation designed to match the anticipated future TR2 64e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// implementation of the scoped_ptr class, and its closely-related brethren, 65e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// scoped_array, scoped_ptr_malloc. 66e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 67e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org#include <assert.h> 68e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org#include <stddef.h> 69e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org#include <stdlib.h> 702466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 71e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad { 722466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 73e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> 74e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// automatically deletes the pointer it holds (if any). 75e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// That is, scoped_ptr<T> owns the T object that it points to. 76e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. 77e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Also like T*, scoped_ptr<T> is thread-compatible, and once you 78e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// dereference it, you get the threadsafety guarantees of T. 79e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// 80e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// The size of a scoped_ptr is small: 81e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// sizeof(scoped_ptr<C>) == sizeof(C*) 82e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 832466d8e993a800a17e00deda2f3a27e0505140e1mmentovaiclass scoped_ptr { 842466d8e993a800a17e00deda2f3a27e0505140e1mmentovai public: 852466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 86e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The element type 87e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org typedef C element_type; 882466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 89e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Constructor. Defaults to initializing with NULL. 90e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // There is no way to create an uninitialized scoped_ptr. 91e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The input parameter must be allocated with new. 92e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org explicit scoped_ptr(C* p = NULL) : ptr_(p) { } 932466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 94e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Destructor. If there is a C object, delete it. 95e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // We don't need to test ptr_ == NULL because C++ does that for us. 962466d8e993a800a17e00deda2f3a27e0505140e1mmentovai ~scoped_ptr() { 97e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org enum { type_must_be_complete = sizeof(C) }; 98e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org delete ptr_; 992466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 1002466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 101e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Reset. Deletes the current owned object, if any. 102e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Then takes ownership of a new object, if given. 103e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // this->reset(this->get()) works. 104e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void reset(C* p = NULL) { 105e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org if (p != ptr_) { 106e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org enum { type_must_be_complete = sizeof(C) }; 107e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org delete ptr_; 108e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org ptr_ = p; 1092466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 1102466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 1112466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 112e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Accessors to get the owned object. 113e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // operator* and operator-> will assert() if there is no current object. 114e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C& operator*() const { 115e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org assert(ptr_ != NULL); 116e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return *ptr_; 1172466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 118e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* operator->() const { 119e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org assert(ptr_ != NULL); 120e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return ptr_; 1212466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 122e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* get() const { return ptr_; } 123e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 124e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Comparison operators. 125e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // These return whether two scoped_ptr refer to the same object, not just to 126e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // two different but equal objects. 127e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator==(C* p) const { return ptr_ == p; } 128e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator!=(C* p) const { return ptr_ != p; } 129e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 130e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Swap two scoped pointers. 131e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void swap(scoped_ptr& p2) { 132e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* tmp = ptr_; 133e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org ptr_ = p2.ptr_; 134e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org p2.ptr_ = tmp; 1352466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 1362466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 137e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Release a pointer. 138e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The return value is the current pointer held by this object. 139e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // If this object holds a NULL pointer, the return value is NULL. 140e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // After this operation, this object will hold a NULL pointer, 141e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // and will not own the object any more. 142e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* release() { 143e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* retVal = ptr_; 144e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org ptr_ = NULL; 145e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return retVal; 1462466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 1472466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 1482466d8e993a800a17e00deda2f3a27e0505140e1mmentovai private: 149e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* ptr_; 150e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 151e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't 152e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // make sense, and if C2 == C, it still doesn't make sense because you should 153e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // never have the same object owned by two different scoped_ptrs. 154e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; 155e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; 1562466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 157e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Disallow evil constructors 158e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org scoped_ptr(const scoped_ptr&); 159e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void operator=(const scoped_ptr&); 1602466d8e993a800a17e00deda2f3a27e0505140e1mmentovai}; 1612466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 162e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Free functions 163e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 164e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgvoid swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { 165e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org p1.swap(p2); 1662466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 1672466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 168e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 169e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgbool operator==(C* p1, const scoped_ptr<C>& p2) { 170e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return p1 == p2.get(); 1712466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 1722466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 173e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 174e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgbool operator!=(C* p1, const scoped_ptr<C>& p2) { 175e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return p1 != p2.get(); 1762466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 1772466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 178e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate 179e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// with new [] and the destructor deletes objects with delete []. 180e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// 181e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// As with scoped_ptr<C>, a scoped_array<C> either points to an object 182e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// or is NULL. A scoped_array<C> owns the object that it points to. 183e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// scoped_array<T> is thread-compatible, and once you index into it, 184e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// the returned objects have only the threadsafety guarantees of T. 185e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// 186e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Size: sizeof(scoped_array<C>) == sizeof(C*) 187e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 1882466d8e993a800a17e00deda2f3a27e0505140e1mmentovaiclass scoped_array { 1892466d8e993a800a17e00deda2f3a27e0505140e1mmentovai public: 1902466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 191e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The element type 192e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org typedef C element_type; 1932466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 194e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Constructor. Defaults to intializing with NULL. 195e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // There is no way to create an uninitialized scoped_array. 196e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The input parameter must be allocated with new []. 197e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org explicit scoped_array(C* p = NULL) : array_(p) { } 1982466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 199e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Destructor. If there is a C object, delete it. 200e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // We don't need to test ptr_ == NULL because C++ does that for us. 2012466d8e993a800a17e00deda2f3a27e0505140e1mmentovai ~scoped_array() { 202e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org enum { type_must_be_complete = sizeof(C) }; 203e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org delete[] array_; 2042466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2052466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 206e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Reset. Deletes the current owned object, if any. 207e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Then takes ownership of a new object, if given. 208e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // this->reset(this->get()) works. 209e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void reset(C* p = NULL) { 210e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org if (p != array_) { 211e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org enum { type_must_be_complete = sizeof(C) }; 212e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org delete[] array_; 213e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org array_ = p; 2142466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2152466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2162466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 217e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Get one element of the current object. 218e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Will assert() if there is no current object, or index i is negative. 219e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C& operator[](ptrdiff_t i) const { 2202466d8e993a800a17e00deda2f3a27e0505140e1mmentovai assert(i >= 0); 221e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org assert(array_ != NULL); 222e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return array_[i]; 2232466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2242466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 225e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Get a pointer to the zeroth element of the current object. 226e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // If there is no current object, return NULL. 227e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* get() const { 228e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return array_; 2292466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2302466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 231e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Comparison operators. 232e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // These return whether two scoped_array refer to the same object, not just to 233e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // two different but equal objects. 234e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator==(C* p) const { return array_ == p; } 235e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator!=(C* p) const { return array_ != p; } 236e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 237e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Swap two scoped arrays. 238e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void swap(scoped_array& p2) { 239e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* tmp = array_; 240e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org array_ = p2.array_; 241e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org p2.array_ = tmp; 2422466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2432466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 244e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Release an array. 245e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The return value is the current pointer held by this object. 246e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // If this object holds a NULL pointer, the return value is NULL. 247e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // After this operation, this object will hold a NULL pointer, 248e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // and will not own the object any more. 249e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* release() { 250e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* retVal = array_; 251e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org array_ = NULL; 252e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return retVal; 2532466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2542466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 2552466d8e993a800a17e00deda2f3a27e0505140e1mmentovai private: 256e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* array_; 2572466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 258e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Forbid comparison of different scoped_array types. 259e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org template <class C2> bool operator==(scoped_array<C2> const& p2) const; 260e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org template <class C2> bool operator!=(scoped_array<C2> const& p2) const; 261e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 262e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Disallow evil constructors 263e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org scoped_array(const scoped_array&); 264e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void operator=(const scoped_array&); 2652466d8e993a800a17e00deda2f3a27e0505140e1mmentovai}; 2662466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 267e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org// Free functions 268e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 269e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgvoid swap(scoped_array<C>& p1, scoped_array<C>& p2) { 270e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org p1.swap(p2); 2712466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 2722466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 273e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 274e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgbool operator==(C* p1, const scoped_array<C>& p2) { 275e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return p1 == p2.get(); 2762466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 2772466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 278e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate <class C> 279e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgbool operator!=(C* p1, const scoped_array<C>& p2) { 280e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return p1 != p2.get(); 2812466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 2822466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 2832466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// This class wraps the c library function free() in a class that can be 2842466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// passed as a template argument to scoped_ptr_malloc below. 2852466d8e993a800a17e00deda2f3a27e0505140e1mmentovaiclass ScopedPtrMallocFree { 2862466d8e993a800a17e00deda2f3a27e0505140e1mmentovai public: 2872466d8e993a800a17e00deda2f3a27e0505140e1mmentovai inline void operator()(void* x) const { 2882466d8e993a800a17e00deda2f3a27e0505140e1mmentovai free(x); 2892466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 2902466d8e993a800a17e00deda2f3a27e0505140e1mmentovai}; 2912466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 2922466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a 2932466d8e993a800a17e00deda2f3a27e0505140e1mmentovai// second template argument, the functor used to free the object. 2942466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 295e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate<class C, class FreeProc = ScopedPtrMallocFree> 2962466d8e993a800a17e00deda2f3a27e0505140e1mmentovaiclass scoped_ptr_malloc { 2972466d8e993a800a17e00deda2f3a27e0505140e1mmentovai public: 2982466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 299e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The element type 300e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org typedef C element_type; 3012466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 302e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Constructor. Defaults to initializing with NULL. 303e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // There is no way to create an uninitialized scoped_ptr. 304e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The input parameter must be allocated with an allocator that matches the 305e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Free functor. For the default Free functor, this is malloc, calloc, or 306e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // realloc. 307e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} 3082466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 309e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Destructor. If there is a C object, call the Free functor. 3102466d8e993a800a17e00deda2f3a27e0505140e1mmentovai ~scoped_ptr_malloc() { 311e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org reset(); 3122466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3132466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 314e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Reset. Calls the Free functor on the current owned object, if any. 315e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Then takes ownership of a new object, if given. 316e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // this->reset(this->get()) works. 317e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void reset(C* p = NULL) { 318e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org if (ptr_ != p) { 319e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org FreeProc free_proc; 320e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org free_proc(ptr_); 321e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org ptr_ = p; 3222466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3232466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3242466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 325e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Get the current object. 326e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // operator* and operator-> will cause an assert() failure if there is 327e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // no current object. 328e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C& operator*() const { 329e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org assert(ptr_ != NULL); 330e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return *ptr_; 3312466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3322466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 333e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* operator->() const { 334e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org assert(ptr_ != NULL); 335e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return ptr_; 3362466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3372466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 338e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* get() const { 339e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return ptr_; 3402466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3412466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 342e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Comparison operators. 343e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // These return whether a scoped_ptr_malloc and a plain pointer refer 344e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // to the same object, not just to two different but equal objects. 345e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // For compatibility with the boost-derived implementation, these 346e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // take non-const arguments. 347e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator==(C* p) const { 348e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return ptr_ == p; 3492466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3502466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 351e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator!=(C* p) const { 352e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org return ptr_ != p; 3532466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3542466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 355e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Swap two scoped pointers. 3562466d8e993a800a17e00deda2f3a27e0505140e1mmentovai void swap(scoped_ptr_malloc & b) { 357e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* tmp = b.ptr_; 358e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org b.ptr_ = ptr_; 359e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org ptr_ = tmp; 3602466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3612466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 362e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Release a pointer. 363e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // The return value is the current pointer held by this object. 364e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // If this object holds a NULL pointer, the return value is NULL. 365e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // After this operation, this object will hold a NULL pointer, 366e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // and will not own the object any more. 367e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* release() { 368e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* tmp = ptr_; 369e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org ptr_ = NULL; 3702466d8e993a800a17e00deda2f3a27e0505140e1mmentovai return tmp; 3712466d8e993a800a17e00deda2f3a27e0505140e1mmentovai } 3722466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 3732466d8e993a800a17e00deda2f3a27e0505140e1mmentovai private: 374e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org C* ptr_; 3752466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 3762466d8e993a800a17e00deda2f3a27e0505140e1mmentovai // no reason to use these: each scoped_ptr_malloc should have its own object 377e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org template <class C2, class GP> 378e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; 379e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org template <class C2, class GP> 380e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; 381e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org 382e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org // Disallow evil constructors 383e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org scoped_ptr_malloc(const scoped_ptr_malloc&); 384e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.org void operator=(const scoped_ptr_malloc&); 3852466d8e993a800a17e00deda2f3a27e0505140e1mmentovai}; 3862466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 387e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate<class C, class FP> inline 388e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgvoid swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { 3892466d8e993a800a17e00deda2f3a27e0505140e1mmentovai a.swap(b); 3902466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 3912466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 392e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate<class C, class FP> inline 393e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgbool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { 3942466d8e993a800a17e00deda2f3a27e0505140e1mmentovai return p == b.get(); 3952466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 3962466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 397e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgtemplate<class C, class FP> inline 398e53fb7e2733f1a730b1f0d31a7505189405b25aathestig@chromium.orgbool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { 3992466d8e993a800a17e00deda2f3a27e0505140e1mmentovai return p != b.get(); 4002466d8e993a800a17e00deda2f3a27e0505140e1mmentovai} 4012466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 402e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 4032466d8e993a800a17e00deda2f3a27e0505140e1mmentovai 4042cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#endif // COMMON_SCOPED_PTR_H_ 405