~ubuntu-branches/ubuntu/precise/enigmail/precise-security

« back to all changes in this revision

Viewing changes to mfbt/RangedPtr.h

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2012-11-12 16:36:01 UTC
  • mfrom: (0.12.15)
  • Revision ID: package-import@ubuntu.com-20121112163601-t8e8skdfi3ni9iqp
Tags: 2:1.4.6-0ubuntu0.12.04.1
* New upstream release v1.4.6
  - see LP: #1080212 for USN information
* Drop unneeded patches
  - remove debian/patches/correct-version-number.diff
  - remove debian/patches/dont_register_cids_multiple_times.diff
  - update debian/patches/series
* Support building in an objdir
  - update debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
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:
3
 
 *
4
 
 * ***** BEGIN LICENSE BLOCK *****
5
 
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
 
 *
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/
11
 
 *
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.
16
 
 *
17
 
 * The Original Code is Mozilla Code.
18
 
 *
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.
23
 
 *
24
 
 * Contributor(s):
25
 
 *   Jeff Walden <jwalden+code@mit.edu> (original author)
26
 
 *
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.
38
 
 *
39
 
 * ***** END LICENSE BLOCK ***** */
40
 
 
41
 
/*
42
 
 * Implements a smart pointer asserted to remain within a range specified at
43
 
 * construction.
44
 
 */
45
 
 
46
 
#ifndef mozilla_RangedPtr_h_
47
 
#define mozilla_RangedPtr_h_
48
 
 
49
 
#include "mozilla/Assertions.h"
50
 
#include "mozilla/Attributes.h"
51
 
#include "mozilla/Util.h"
52
 
 
53
 
namespace mozilla {
54
 
 
55
 
/*
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.
63
 
 *
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.
69
 
 *
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.
73
 
 */
74
 
template <typename T>
75
 
class RangedPtr
76
 
{
77
 
    T* ptr;
78
 
 
79
 
#ifdef DEBUG
80
 
    T* const rangeStart;
81
 
    T* const rangeEnd;
82
 
#endif
83
 
 
84
 
    void checkSanity() {
85
 
        MOZ_ASSERT(rangeStart <= ptr);
86
 
        MOZ_ASSERT(ptr <= rangeEnd);
87
 
    }
88
 
 
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
96
 
    }
97
 
 
98
 
  public:
99
 
    RangedPtr(T* p, T* start, T* end)
100
 
      : ptr(p)
101
 
#ifdef DEBUG
102
 
      , rangeStart(start), rangeEnd(end)
103
 
#endif
104
 
    {
105
 
        MOZ_ASSERT(rangeStart <= rangeEnd);
106
 
        checkSanity();
107
 
    }
108
 
    RangedPtr(T* p, T* start, size_t length)
109
 
      : ptr(p)
110
 
#ifdef DEBUG
111
 
      , rangeStart(start), rangeEnd(start + length)
112
 
#endif
113
 
    {
114
 
        MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
115
 
        MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
116
 
        checkSanity();
117
 
    }
118
 
 
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
125
 
    {
126
 
        MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
127
 
        MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
128
 
        checkSanity();
129
 
    }
130
 
 
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
138
 
    {
139
 
      checkSanity();
140
 
    }
141
 
 
142
 
    T* get() const {
143
 
        return ptr;
144
 
    }
145
 
 
146
 
    /*
147
 
     * You can only assign one RangedPtr into another if the two pointers have
148
 
     * the same valid range:
149
 
     *
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
155
 
     */
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;
162
 
    }
163
 
 
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);
168
 
    }
169
 
 
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);
174
 
    }
175
 
 
176
 
    /*
177
 
     * You can assign a raw pointer into a RangedPtr if the raw pointer is
178
 
     * within the range specified at creation.
179
 
     */
180
 
    template <typename U>
181
 
    RangedPtr<T>& operator=(U* p) {
182
 
        *this = create(p);
183
 
        return *this;
184
 
    }
185
 
 
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;
193
 
    }
194
 
 
195
 
    RangedPtr<T>& operator++() {
196
 
        return (*this += 1);
197
 
    }
198
 
 
199
 
    RangedPtr<T> operator++(int) {
200
 
        RangedPtr<T> rcp = *this;
201
 
        ++*this;
202
 
        return rcp;
203
 
    }
204
 
 
205
 
    RangedPtr<T>& operator--() {
206
 
        return (*this -= 1);
207
 
    }
208
 
 
209
 
    RangedPtr<T> operator--(int) {
210
 
        RangedPtr<T> rcp = *this;
211
 
        --*this;
212
 
        return rcp;
213
 
    }
214
 
 
215
 
    RangedPtr<T>& operator+=(size_t inc) {
216
 
        this->operator=<T>(*this + inc);
217
 
        return *this;
218
 
    }
219
 
 
220
 
    RangedPtr<T>& operator-=(size_t dec) {
221
 
        this->operator=<T>(*this - dec);
222
 
        return *this;
223
 
    }
224
 
 
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);
228
 
    }
229
 
 
230
 
    T& operator*() const {
231
 
        return *ptr;
232
 
    }
233
 
 
234
 
    template <typename U>
235
 
    bool operator==(const RangedPtr<U>& other) const {
236
 
        return ptr == other.ptr;
237
 
    }
238
 
    template <typename U>
239
 
    bool operator!=(const RangedPtr<U>& other) const {
240
 
        return !(*this == other);
241
 
    }
242
 
 
243
 
    template<typename U>
244
 
    bool operator==(const U* u) const {
245
 
        return ptr == u;
246
 
    }
247
 
    template<typename U>
248
 
    bool operator!=(const U* u) const {
249
 
        return !(*this == u);
250
 
    }
251
 
 
252
 
    template <typename U>
253
 
    bool operator<(const RangedPtr<U>& other) const {
254
 
        return ptr < other.ptr;
255
 
    }
256
 
    template <typename U>
257
 
    bool operator<=(const RangedPtr<U>& other) const {
258
 
        return ptr <= other.ptr;
259
 
    }
260
 
 
261
 
    template <typename U>
262
 
    bool operator>(const RangedPtr<U>& other) const {
263
 
        return ptr > other.ptr;
264
 
    }
265
 
    template <typename U>
266
 
    bool operator>=(const RangedPtr<U>& other) const {
267
 
        return ptr >= other.ptr;
268
 
    }
269
 
 
270
 
    size_t operator-(const RangedPtr<T>& other) const {
271
 
        MOZ_ASSERT(ptr >= other.ptr);
272
 
        return PointerRangeSize(other.ptr, ptr);
273
 
    }
274
 
 
275
 
  private:
276
 
    RangedPtr() MOZ_DELETE;
277
 
    T* operator&() MOZ_DELETE;
278
 
    operator T*() const MOZ_DELETE;
279
 
};
280
 
 
281
 
} /* namespace mozilla */
282
 
 
283
 
#endif  /* mozilla_RangedPtr_h_ */