Bug 752461 - Hide click-to-play overlays when choosing "never activate plugins.....
[gecko.git] / mfbt / RangedPtr.h
blob74ad1c75e4562d1305f17a7f35cec629e7923aff
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99 ft=cpp:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at:
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is Mozilla Code.
19 * The Initial Developer of the Original Code is
20 * The Mozilla Foundation
21 * Portions created by the Initial Developer are Copyright (C) 2011
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
25 * Jeff Walden <jwalden+code@mit.edu> (original author)
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * Implements a smart pointer asserted to remain within a range specified at
43 * construction.
46 #ifndef mozilla_RangedPtr_h_
47 #define mozilla_RangedPtr_h_
49 #include "mozilla/Assertions.h"
50 #include "mozilla/Attributes.h"
51 #include "mozilla/Util.h"
53 namespace mozilla {
56 * RangedPtr is a smart pointer restricted to an address range specified at
57 * creation. The pointer (and any smart pointers derived from it) must remain
58 * within the range [start, end] (inclusive of end to facilitate use as
59 * sentinels). Dereferencing or indexing into the pointer (or pointers derived
60 * from it) must remain within the range [start, end). All the standard pointer
61 * operators are defined on it; in debug builds these operations assert that the
62 * range specified at construction is respected.
64 * In theory passing a smart pointer instance as an argument can be slightly
65 * slower than passing a T* (due to ABI requirements for passing structs versus
66 * passing pointers), if the method being called isn't inlined. If you are in
67 * extremely performance-critical code, you may want to be careful using this
68 * smart pointer as an argument type.
70 * RangedPtr<T> intentionally does not implicitly convert to T*. Use get() to
71 * explicitly convert to T*. Keep in mind that the raw pointer of course won't
72 * implement bounds checking in debug builds.
74 template <typename T>
75 class RangedPtr
77 T* ptr;
79 #ifdef DEBUG
80 T* const rangeStart;
81 T* const rangeEnd;
82 #endif
84 void checkSanity() {
85 MOZ_ASSERT(rangeStart <= ptr);
86 MOZ_ASSERT(ptr <= rangeEnd);
89 /* Creates a new pointer for |ptr|, restricted to this pointer's range. */
90 RangedPtr<T> create(T *ptr) const {
91 #ifdef DEBUG
92 return RangedPtr<T>(ptr, rangeStart, rangeEnd);
93 #else
94 return RangedPtr<T>(ptr, NULL, size_t(0));
95 #endif
98 public:
99 RangedPtr(T* p, T* start, T* end)
100 : ptr(p)
101 #ifdef DEBUG
102 , rangeStart(start), rangeEnd(end)
103 #endif
105 MOZ_ASSERT(rangeStart <= rangeEnd);
106 checkSanity();
108 RangedPtr(T* p, T* start, size_t length)
109 : ptr(p)
110 #ifdef DEBUG
111 , rangeStart(start), rangeEnd(start + length)
112 #endif
114 MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
115 MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
116 checkSanity();
119 /* Equivalent to RangedPtr(p, p, length). */
120 RangedPtr(T* p, size_t length)
121 : ptr(p)
122 #ifdef DEBUG
123 , rangeStart(p), rangeEnd(p + length)
124 #endif
126 MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
127 MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
128 checkSanity();
131 /* Equivalent to RangedPtr(arr, arr, N). */
132 template<size_t N>
133 RangedPtr(T arr[N])
134 : ptr(arr)
135 #ifdef DEBUG
136 , rangeStart(arr), rangeEnd(arr + N)
137 #endif
139 checkSanity();
142 T* get() const {
143 return ptr;
147 * You can only assign one RangedPtr into another if the two pointers have
148 * the same valid range:
150 * char arr1[] = "hi";
151 * char arr2[] = "bye";
152 * RangedPtr<char> p1(arr1, 2);
153 * p1 = RangedPtr<char>(arr1 + 1, arr1, arr1 + 2); // works
154 * p1 = RangedPtr<char>(arr2, 3); // asserts
156 RangedPtr<T>& operator=(const RangedPtr<T>& other) {
157 MOZ_ASSERT(rangeStart == other.rangeStart);
158 MOZ_ASSERT(rangeEnd == other.rangeEnd);
159 ptr = other.ptr;
160 checkSanity();
161 return *this;
164 RangedPtr<T> operator+(size_t inc) {
165 MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
166 MOZ_ASSERT(ptr + inc > ptr);
167 return create(ptr + inc);
170 RangedPtr<T> operator-(size_t dec) {
171 MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
172 MOZ_ASSERT(ptr - dec < ptr);
173 return create(ptr - dec);
177 * You can assign a raw pointer into a RangedPtr if the raw pointer is
178 * within the range specified at creation.
180 template <typename U>
181 RangedPtr<T>& operator=(U* p) {
182 *this = create(p);
183 return *this;
186 template <typename U>
187 RangedPtr<T>& operator=(const RangedPtr<U>& p) {
188 MOZ_ASSERT(rangeStart <= p.ptr);
189 MOZ_ASSERT(p.ptr <= rangeEnd);
190 ptr = p.ptr;
191 checkSanity();
192 return *this;
195 RangedPtr<T>& operator++() {
196 return (*this += 1);
199 RangedPtr<T> operator++(int) {
200 RangedPtr<T> rcp = *this;
201 ++*this;
202 return rcp;
205 RangedPtr<T>& operator--() {
206 return (*this -= 1);
209 RangedPtr<T> operator--(int) {
210 RangedPtr<T> rcp = *this;
211 --*this;
212 return rcp;
215 RangedPtr<T>& operator+=(size_t inc) {
216 this->operator=<T>(*this + inc);
217 return *this;
220 RangedPtr<T>& operator-=(size_t dec) {
221 this->operator=<T>(*this - dec);
222 return *this;
225 T& operator[](int index) const {
226 MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
227 return *create(ptr + index);
230 T& operator*() const {
231 return *ptr;
234 template <typename U>
235 bool operator==(const RangedPtr<U>& other) const {
236 return ptr == other.ptr;
238 template <typename U>
239 bool operator!=(const RangedPtr<U>& other) const {
240 return !(*this == other);
243 template<typename U>
244 bool operator==(const U* u) const {
245 return ptr == u;
247 template<typename U>
248 bool operator!=(const U* u) const {
249 return !(*this == u);
252 template <typename U>
253 bool operator<(const RangedPtr<U>& other) const {
254 return ptr < other.ptr;
256 template <typename U>
257 bool operator<=(const RangedPtr<U>& other) const {
258 return ptr <= other.ptr;
261 template <typename U>
262 bool operator>(const RangedPtr<U>& other) const {
263 return ptr > other.ptr;
265 template <typename U>
266 bool operator>=(const RangedPtr<U>& other) const {
267 return ptr >= other.ptr;
270 size_t operator-(const RangedPtr<T>& other) const {
271 MOZ_ASSERT(ptr >= other.ptr);
272 return PointerRangeSize(other.ptr, ptr);
275 private:
276 RangedPtr() MOZ_DELETE;
277 T* operator&() MOZ_DELETE;
278 operator T*() const MOZ_DELETE;
281 } /* namespace mozilla */
283 #endif /* mozilla_RangedPtr_h_ */