1c55a96383497a772a307b346368133960b02ad03Eric Laurent//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
2c55a96383497a772a307b346368133960b02ad03Eric Laurent//  Copyright (c) 2001, 2002 Peter Dimov
3c55a96383497a772a307b346368133960b02ad03Eric Laurent//
4c55a96383497a772a307b346368133960b02ad03Eric Laurent//  Permission to copy, use, modify, sell and distribute this software
5c55a96383497a772a307b346368133960b02ad03Eric Laurent//  is granted provided this copyright notice appears in all copies.
6c55a96383497a772a307b346368133960b02ad03Eric Laurent//  This software is provided "as is" without express or implied
7c55a96383497a772a307b346368133960b02ad03Eric Laurent//  warranty, and with no claim as to its suitability for any purpose.
8c55a96383497a772a307b346368133960b02ad03Eric Laurent//
9c55a96383497a772a307b346368133960b02ad03Eric Laurent//  See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
10c55a96383497a772a307b346368133960b02ad03Eric Laurent//
11c55a96383497a772a307b346368133960b02ad03Eric Laurent
12c55a96383497a772a307b346368133960b02ad03Eric Laurent//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
13c55a96383497a772a307b346368133960b02ad03Eric Laurent//  of the object pointed to, either on destruction of the scoped_ptr or via
14c55a96383497a772a307b346368133960b02ad03Eric Laurent//  an explicit reset(). scoped_ptr is a simple solution for simple needs;
15c55a96383497a772a307b346368133960b02ad03Eric Laurent//  use shared_ptr or std::auto_ptr if your needs are more complex.
16c55a96383497a772a307b346368133960b02ad03Eric Laurent
17c55a96383497a772a307b346368133960b02ad03Eric Laurent//  scoped_ptr_malloc added in by Google.  When one of
18c55a96383497a772a307b346368133960b02ad03Eric Laurent//  these goes out of scope, instead of doing a delete or delete[], it
19c55a96383497a772a307b346368133960b02ad03Eric Laurent//  calls free().  scoped_ptr_malloc<char> is likely to see much more
20c55a96383497a772a307b346368133960b02ad03Eric Laurent//  use than any other specializations.
21c55a96383497a772a307b346368133960b02ad03Eric Laurent
22c55a96383497a772a307b346368133960b02ad03Eric Laurent//  release() added in by Google. Use this to conditionally
23c55a96383497a772a307b346368133960b02ad03Eric Laurent//  transfer ownership of a heap-allocated object to the caller, usually on
24c55a96383497a772a307b346368133960b02ad03Eric Laurent//  method success.
25c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
26c55a96383497a772a307b346368133960b02ad03Eric Laurent#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
27c55a96383497a772a307b346368133960b02ad03Eric Laurent
28c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <assert.h>            // for assert
29c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <stdlib.h>            // for free() decl
30c55a96383497a772a307b346368133960b02ad03Eric Laurent
31c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <cstddef>             // for std::ptrdiff_t
32c55a96383497a772a307b346368133960b02ad03Eric Laurent
33c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef _WIN32
34c55a96383497a772a307b346368133960b02ad03Eric Laurentnamespace std { using ::ptrdiff_t; };
35c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif // _WIN32
36c55a96383497a772a307b346368133960b02ad03Eric Laurent
37c55a96383497a772a307b346368133960b02ad03Eric Laurentnamespace webrtc {
38c55a96383497a772a307b346368133960b02ad03Eric Laurent
39c55a96383497a772a307b346368133960b02ad03Eric Laurenttemplate <typename T>
40c55a96383497a772a307b346368133960b02ad03Eric Laurentclass scoped_ptr {
41c55a96383497a772a307b346368133960b02ad03Eric Laurent private:
42c55a96383497a772a307b346368133960b02ad03Eric Laurent
43c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* ptr;
44c55a96383497a772a307b346368133960b02ad03Eric Laurent
45c55a96383497a772a307b346368133960b02ad03Eric Laurent  scoped_ptr(scoped_ptr const &);
46c55a96383497a772a307b346368133960b02ad03Eric Laurent  scoped_ptr & operator=(scoped_ptr const &);
47c55a96383497a772a307b346368133960b02ad03Eric Laurent
48c55a96383497a772a307b346368133960b02ad03Eric Laurent public:
49c55a96383497a772a307b346368133960b02ad03Eric Laurent
50c55a96383497a772a307b346368133960b02ad03Eric Laurent  typedef T element_type;
51c55a96383497a772a307b346368133960b02ad03Eric Laurent
52c55a96383497a772a307b346368133960b02ad03Eric Laurent  explicit scoped_ptr(T* p = NULL): ptr(p) {}
53c55a96383497a772a307b346368133960b02ad03Eric Laurent
54c55a96383497a772a307b346368133960b02ad03Eric Laurent  ~scoped_ptr() {
55c55a96383497a772a307b346368133960b02ad03Eric Laurent    typedef char type_must_be_complete[sizeof(T)];
56c55a96383497a772a307b346368133960b02ad03Eric Laurent    delete ptr;
57c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
58c55a96383497a772a307b346368133960b02ad03Eric Laurent
59c55a96383497a772a307b346368133960b02ad03Eric Laurent  void reset(T* p = NULL) {
60c55a96383497a772a307b346368133960b02ad03Eric Laurent    typedef char type_must_be_complete[sizeof(T)];
61c55a96383497a772a307b346368133960b02ad03Eric Laurent
62c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (ptr != p) {
63c55a96383497a772a307b346368133960b02ad03Eric Laurent      T* obj = ptr;
64c55a96383497a772a307b346368133960b02ad03Eric Laurent      ptr = p;
65c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Delete last, in case obj destructor indirectly results in ~scoped_ptr
66c55a96383497a772a307b346368133960b02ad03Eric Laurent      delete obj;
67c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
68c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
69c55a96383497a772a307b346368133960b02ad03Eric Laurent
70c55a96383497a772a307b346368133960b02ad03Eric Laurent  T& operator*() const {
71c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(ptr != NULL);
72c55a96383497a772a307b346368133960b02ad03Eric Laurent    return *ptr;
73c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
74c55a96383497a772a307b346368133960b02ad03Eric Laurent
75c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* operator->() const  {
76c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(ptr != NULL);
77c55a96383497a772a307b346368133960b02ad03Eric Laurent    return ptr;
78c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
79c55a96383497a772a307b346368133960b02ad03Eric Laurent
80c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* get() const  {
81c55a96383497a772a307b346368133960b02ad03Eric Laurent    return ptr;
82c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
83c55a96383497a772a307b346368133960b02ad03Eric Laurent
84c55a96383497a772a307b346368133960b02ad03Eric Laurent  void swap(scoped_ptr & b) {
85c55a96383497a772a307b346368133960b02ad03Eric Laurent    T* tmp = b.ptr;
86c55a96383497a772a307b346368133960b02ad03Eric Laurent    b.ptr = ptr;
87c55a96383497a772a307b346368133960b02ad03Eric Laurent    ptr = tmp;
88c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
89c55a96383497a772a307b346368133960b02ad03Eric Laurent
90c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* release() {
91c55a96383497a772a307b346368133960b02ad03Eric Laurent    T* tmp = ptr;
92c55a96383497a772a307b346368133960b02ad03Eric Laurent    ptr = NULL;
93c55a96383497a772a307b346368133960b02ad03Eric Laurent    return tmp;
94c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
95c55a96383497a772a307b346368133960b02ad03Eric Laurent
96c55a96383497a772a307b346368133960b02ad03Eric Laurent  T** accept() {
97c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (ptr) {
98c55a96383497a772a307b346368133960b02ad03Eric Laurent      delete ptr;
99c55a96383497a772a307b346368133960b02ad03Eric Laurent      ptr = NULL;
100c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
101c55a96383497a772a307b346368133960b02ad03Eric Laurent    return &ptr;
102c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
103c55a96383497a772a307b346368133960b02ad03Eric Laurent
104c55a96383497a772a307b346368133960b02ad03Eric Laurent  T** use() {
105c55a96383497a772a307b346368133960b02ad03Eric Laurent    return &ptr;
106c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
107c55a96383497a772a307b346368133960b02ad03Eric Laurent};
108c55a96383497a772a307b346368133960b02ad03Eric Laurent
109c55a96383497a772a307b346368133960b02ad03Eric Laurenttemplate<typename T> inline
110c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
111c55a96383497a772a307b346368133960b02ad03Eric Laurent  a.swap(b);
112c55a96383497a772a307b346368133960b02ad03Eric Laurent}
113c55a96383497a772a307b346368133960b02ad03Eric Laurent
114c55a96383497a772a307b346368133960b02ad03Eric Laurent
115c55a96383497a772a307b346368133960b02ad03Eric Laurent
116c55a96383497a772a307b346368133960b02ad03Eric Laurent
117c55a96383497a772a307b346368133960b02ad03Eric Laurent//  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
118c55a96383497a772a307b346368133960b02ad03Eric Laurent//  is guaranteed, either on destruction of the scoped_array or via an explicit
119c55a96383497a772a307b346368133960b02ad03Eric Laurent//  reset(). Use shared_array or std::vector if your needs are more complex.
120c55a96383497a772a307b346368133960b02ad03Eric Laurent
121c55a96383497a772a307b346368133960b02ad03Eric Laurenttemplate<typename T>
122c55a96383497a772a307b346368133960b02ad03Eric Laurentclass scoped_array {
123c55a96383497a772a307b346368133960b02ad03Eric Laurent private:
124c55a96383497a772a307b346368133960b02ad03Eric Laurent
125c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* ptr;
126c55a96383497a772a307b346368133960b02ad03Eric Laurent
127c55a96383497a772a307b346368133960b02ad03Eric Laurent  scoped_array(scoped_array const &);
128c55a96383497a772a307b346368133960b02ad03Eric Laurent  scoped_array & operator=(scoped_array const &);
129c55a96383497a772a307b346368133960b02ad03Eric Laurent
130c55a96383497a772a307b346368133960b02ad03Eric Laurent public:
131c55a96383497a772a307b346368133960b02ad03Eric Laurent
132c55a96383497a772a307b346368133960b02ad03Eric Laurent  typedef T element_type;
133c55a96383497a772a307b346368133960b02ad03Eric Laurent
134c55a96383497a772a307b346368133960b02ad03Eric Laurent  explicit scoped_array(T* p = NULL) : ptr(p) {}
135c55a96383497a772a307b346368133960b02ad03Eric Laurent
136c55a96383497a772a307b346368133960b02ad03Eric Laurent  ~scoped_array() {
137c55a96383497a772a307b346368133960b02ad03Eric Laurent    typedef char type_must_be_complete[sizeof(T)];
138c55a96383497a772a307b346368133960b02ad03Eric Laurent    delete[] ptr;
139c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
140c55a96383497a772a307b346368133960b02ad03Eric Laurent
141c55a96383497a772a307b346368133960b02ad03Eric Laurent  void reset(T* p = NULL) {
142c55a96383497a772a307b346368133960b02ad03Eric Laurent    typedef char type_must_be_complete[sizeof(T)];
143c55a96383497a772a307b346368133960b02ad03Eric Laurent
144c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (ptr != p) {
145c55a96383497a772a307b346368133960b02ad03Eric Laurent      T* arr = ptr;
146c55a96383497a772a307b346368133960b02ad03Eric Laurent      ptr = p;
147c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Delete last, in case arr destructor indirectly results in ~scoped_array
148c55a96383497a772a307b346368133960b02ad03Eric Laurent      delete [] arr;
149c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
150c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
151c55a96383497a772a307b346368133960b02ad03Eric Laurent
152c55a96383497a772a307b346368133960b02ad03Eric Laurent  T& operator[](std::ptrdiff_t i) const {
153c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(ptr != NULL);
154c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(i >= 0);
155c55a96383497a772a307b346368133960b02ad03Eric Laurent    return ptr[i];
156c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
157c55a96383497a772a307b346368133960b02ad03Eric Laurent
158c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* get() const {
159c55a96383497a772a307b346368133960b02ad03Eric Laurent    return ptr;
160c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
161c55a96383497a772a307b346368133960b02ad03Eric Laurent
162c55a96383497a772a307b346368133960b02ad03Eric Laurent  void swap(scoped_array & b) {
163c55a96383497a772a307b346368133960b02ad03Eric Laurent    T* tmp = b.ptr;
164c55a96383497a772a307b346368133960b02ad03Eric Laurent    b.ptr = ptr;
165c55a96383497a772a307b346368133960b02ad03Eric Laurent    ptr = tmp;
166c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
167c55a96383497a772a307b346368133960b02ad03Eric Laurent
168c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* release() {
169c55a96383497a772a307b346368133960b02ad03Eric Laurent    T* tmp = ptr;
170c55a96383497a772a307b346368133960b02ad03Eric Laurent    ptr = NULL;
171c55a96383497a772a307b346368133960b02ad03Eric Laurent    return tmp;
172c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
173c55a96383497a772a307b346368133960b02ad03Eric Laurent
174c55a96383497a772a307b346368133960b02ad03Eric Laurent  T** accept() {
175c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (ptr) {
176c55a96383497a772a307b346368133960b02ad03Eric Laurent      delete [] ptr;
177c55a96383497a772a307b346368133960b02ad03Eric Laurent      ptr = NULL;
178c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
179c55a96383497a772a307b346368133960b02ad03Eric Laurent    return &ptr;
180c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
181c55a96383497a772a307b346368133960b02ad03Eric Laurent};
182c55a96383497a772a307b346368133960b02ad03Eric Laurent
183c55a96383497a772a307b346368133960b02ad03Eric Laurenttemplate<class T> inline
184c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid swap(scoped_array<T>& a, scoped_array<T>& b) {
185c55a96383497a772a307b346368133960b02ad03Eric Laurent  a.swap(b);
186c55a96383497a772a307b346368133960b02ad03Eric Laurent}
187c55a96383497a772a307b346368133960b02ad03Eric Laurent
188c55a96383497a772a307b346368133960b02ad03Eric Laurent// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
189c55a96383497a772a307b346368133960b02ad03Eric Laurent// second template argument, the function used to free the object.
190c55a96383497a772a307b346368133960b02ad03Eric Laurent
191c55a96383497a772a307b346368133960b02ad03Eric Laurenttemplate<typename T, void (*FF)(void*) = free> class scoped_ptr_malloc {
192c55a96383497a772a307b346368133960b02ad03Eric Laurent private:
193c55a96383497a772a307b346368133960b02ad03Eric Laurent
194c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* ptr;
195c55a96383497a772a307b346368133960b02ad03Eric Laurent
196c55a96383497a772a307b346368133960b02ad03Eric Laurent  scoped_ptr_malloc(scoped_ptr_malloc const &);
197c55a96383497a772a307b346368133960b02ad03Eric Laurent  scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
198c55a96383497a772a307b346368133960b02ad03Eric Laurent
199c55a96383497a772a307b346368133960b02ad03Eric Laurent public:
200c55a96383497a772a307b346368133960b02ad03Eric Laurent
201c55a96383497a772a307b346368133960b02ad03Eric Laurent  typedef T element_type;
202c55a96383497a772a307b346368133960b02ad03Eric Laurent
203c55a96383497a772a307b346368133960b02ad03Eric Laurent  explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
204c55a96383497a772a307b346368133960b02ad03Eric Laurent
205c55a96383497a772a307b346368133960b02ad03Eric Laurent  ~scoped_ptr_malloc() {
206c55a96383497a772a307b346368133960b02ad03Eric Laurent    FF(static_cast<void*>(ptr));
207c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
208c55a96383497a772a307b346368133960b02ad03Eric Laurent
209c55a96383497a772a307b346368133960b02ad03Eric Laurent  void reset(T* p = 0) {
210c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (ptr != p) {
211c55a96383497a772a307b346368133960b02ad03Eric Laurent      FF(static_cast<void*>(ptr));
212c55a96383497a772a307b346368133960b02ad03Eric Laurent      ptr = p;
213c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
214c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
215c55a96383497a772a307b346368133960b02ad03Eric Laurent
216c55a96383497a772a307b346368133960b02ad03Eric Laurent  T& operator*() const {
217c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(ptr != 0);
218c55a96383497a772a307b346368133960b02ad03Eric Laurent    return *ptr;
219c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
220c55a96383497a772a307b346368133960b02ad03Eric Laurent
221c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* operator->() const {
222c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(ptr != 0);
223c55a96383497a772a307b346368133960b02ad03Eric Laurent    return ptr;
224c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
225c55a96383497a772a307b346368133960b02ad03Eric Laurent
226c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* get() const {
227c55a96383497a772a307b346368133960b02ad03Eric Laurent    return ptr;
228c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
229c55a96383497a772a307b346368133960b02ad03Eric Laurent
230c55a96383497a772a307b346368133960b02ad03Eric Laurent  void swap(scoped_ptr_malloc & b) {
231c55a96383497a772a307b346368133960b02ad03Eric Laurent    T* tmp = b.ptr;
232c55a96383497a772a307b346368133960b02ad03Eric Laurent    b.ptr = ptr;
233c55a96383497a772a307b346368133960b02ad03Eric Laurent    ptr = tmp;
234c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
235c55a96383497a772a307b346368133960b02ad03Eric Laurent
236c55a96383497a772a307b346368133960b02ad03Eric Laurent  T* release() {
237c55a96383497a772a307b346368133960b02ad03Eric Laurent    T* tmp = ptr;
238c55a96383497a772a307b346368133960b02ad03Eric Laurent    ptr = 0;
239c55a96383497a772a307b346368133960b02ad03Eric Laurent    return tmp;
240c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
241c55a96383497a772a307b346368133960b02ad03Eric Laurent
242c55a96383497a772a307b346368133960b02ad03Eric Laurent  T** accept() {
243c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (ptr) {
244c55a96383497a772a307b346368133960b02ad03Eric Laurent      FF(static_cast<void*>(ptr));
245c55a96383497a772a307b346368133960b02ad03Eric Laurent      ptr = 0;
246c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
247c55a96383497a772a307b346368133960b02ad03Eric Laurent    return &ptr;
248c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
249c55a96383497a772a307b346368133960b02ad03Eric Laurent};
250c55a96383497a772a307b346368133960b02ad03Eric Laurent
251c55a96383497a772a307b346368133960b02ad03Eric Laurenttemplate<typename T, void (*FF)(void*)> inline
252c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) {
253c55a96383497a772a307b346368133960b02ad03Eric Laurent  a.swap(b);
254c55a96383497a772a307b346368133960b02ad03Eric Laurent}
255c55a96383497a772a307b346368133960b02ad03Eric Laurent
256c55a96383497a772a307b346368133960b02ad03Eric Laurent} // namespace webrtc
257c55a96383497a772a307b346368133960b02ad03Eric Laurent
258c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif  // #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
259