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