LCOV - app.info - objdir/dist/include/mozilla/RangedPtr.h

LCOV - code coverage report
| Current view: | directory - objdir/dist/include/mozilla - RangedPtr.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 78 | 78 | 100.0 %
| Date: | 2012-04-07 | Functions: | 43 | 43 | 100.0 %

           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       606428774 :     void checkSanity() {
          85       606428774 :         MOZ_ASSERT(rangeStart <= ptr);
          86       606428774 :         MOZ_ASSERT(ptr <= rangeEnd);
          87       606428774 :     }
          88                 :
          89                 :     /* Creates a new pointer for |ptr|, restricted to this pointer's range. */
          90       303180352 :     RangedPtr<T> create(T *ptr) const {
          91                 : #ifdef DEBUG
          92       303180352 :         return RangedPtr<T>(ptr, rangeStart, rangeEnd);
          93                 : #else
          94                 :         return RangedPtr<T>(ptr, NULL, size_t(0));
          95                 : #endif
          96                 :     }
          97                 :
          98                 :   public:
          99       303180585 :     RangedPtr(T* p, T* start, T* end)
         100                 :       : ptr(p)
         101                 : #ifdef DEBUG
         102       303180585 :       , rangeStart(start), rangeEnd(end)
         103                 : #endif
         104                 :     {
         105       303180585 :         MOZ_ASSERT(rangeStart <= rangeEnd);
         106       303180585 :         checkSanity();
         107       303180585 :     }
         108        39167390 :     RangedPtr(T* p, T* start, size_t length)
         109                 :       : ptr(p)
         110                 : #ifdef DEBUG
         111        39167390 :       , rangeStart(start), rangeEnd(start + length)
         112                 : #endif
         113                 :     {
         114        39028689 :         MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
         115        39167390 :         MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
         116        39167390 :         checkSanity();
         117        39167390 :     }
         118                 :
         119                 :     /* Equivalent to RangedPtr(p, p, length). */
         120          213063 :     RangedPtr(T* p, size_t length)
         121                 :       : ptr(p)
         122                 : #ifdef DEBUG
         123          213063 :       , rangeStart(p), rangeEnd(p + length)
         124                 : #endif
         125                 :     {
         126          213063 :         MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
         127          213063 :         MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
         128          213063 :         checkSanity();
         129          213063 :     }
         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        39072518 :     T* get() const {
         143        39072518 :         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          136132 :     RangedPtr<T>& operator=(const RangedPtr<T>& other) {
         157          136132 :         MOZ_ASSERT(rangeStart == other.rangeStart);
         158          136132 :         MOZ_ASSERT(rangeEnd == other.rangeEnd);
         159          136132 :         ptr = other.ptr;
         160          136132 :         checkSanity();
         161          136132 :         return *this;
         162                 :     }
         163                 :
         164         2000701 :     RangedPtr<T> operator+(size_t inc) {
         165         2000701 :         MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
         166         2000701 :         MOZ_ASSERT(ptr + inc > ptr);
         167         2000701 :         return create(ptr + inc);
         168                 :     }
         169                 :
         170       300682889 :     RangedPtr<T> operator-(size_t dec) {
         171       300154662 :         MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
         172       300682889 :         MOZ_ASSERT(ptr - dec < ptr);
         173       300682889 :         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       263731604 :     RangedPtr<T>& operator=(const RangedPtr<U>& p) {
         188       263731604 :         MOZ_ASSERT(rangeStart <= p.ptr);
         189       263731604 :         MOZ_ASSERT(p.ptr <= rangeEnd);
         190       263731604 :         ptr = p.ptr;
         191       263731604 :         checkSanity();
         192       263731604 :         return *this;
         193                 :     }
         194                 :
         195         2000260 :     RangedPtr<T>& operator++() {
         196         2000260 :         return (*this += 1);
         197                 :     }
         198                 :
         199         1927021 :     RangedPtr<T> operator++(int) {
         200         1927021 :         RangedPtr<T> rcp = *this;
         201         1927021 :         ++*this;
         202                 :         return rcp;
         203                 :     }
         204                 :
         205       261730903 :     RangedPtr<T>& operator--() {
         206       261730903 :         return (*this -= 1);
         207                 :     }
         208                 :
         209                 :     RangedPtr<T> operator--(int) {
         210                 :         RangedPtr<T> rcp = *this;
         211                 :         --*this;
         212                 :         return rcp;
         213                 :     }
         214                 :
         215         2000701 :     RangedPtr<T>& operator+=(size_t inc) {
         216         2000701 :         this->operator=<T>(*this + inc);
         217         2000701 :         return *this;
         218                 :     }
         219                 :
         220       261730903 :     RangedPtr<T>& operator-=(size_t dec) {
         221       261730903 :         this->operator=<T>(*this - dec);
         222       261730903 :         return *this;
         223                 :     }
         224                 :
         225          496762 :     T& operator[](int index) const {
         226          496762 :         MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
         227          496762 :         return *create(ptr + index);
         228                 :     }
         229                 :
         230       344390165 :     T& operator*() const {
         231       344390165 :         return *ptr;
         232                 :     }
         233                 :
         234                 :     template <typename U>
         235          304626 :     bool operator==(const RangedPtr<U>& other) const {
         236          304626 :         return ptr == other.ptr;
         237                 :     }
         238                 :     template <typename U>
         239          207847 :     bool operator!=(const RangedPtr<U>& other) const {
         240          207847 :         return !(*this == other);
         241                 :     }
         242                 :
         243                 :     template<typename U>
         244           25088 :     bool operator==(const U* u) const {
         245           25088 :         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         1459442 :     bool operator<(const RangedPtr<U>& other) const {
         254         1459442 :         return ptr < other.ptr;
         255                 :     }
         256                 :     template <typename U>
         257            5216 :     bool operator<=(const RangedPtr<U>& other) const {
         258            5216 :         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          238716 :     bool operator>=(const RangedPtr<U>& other) const {
         267          238716 :         return ptr >= other.ptr;
         268                 :     }
         269                 :
         270        38885021 :     size_t operator-(const RangedPtr<T>& other) const {
         271        38885021 :         MOZ_ASSERT(ptr >= other.ptr);
         272        38885021 :         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_ */

Generated by: LCOV version 1.7