Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // Copyright (c) 2011, Google Inc. |
michael@0 | 2 | // All rights reserved. |
michael@0 | 3 | // |
michael@0 | 4 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | // modification, are permitted provided that the following conditions are |
michael@0 | 6 | // met: |
michael@0 | 7 | // |
michael@0 | 8 | // * Redistributions of source code must retain the above copyright |
michael@0 | 9 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | // * Redistributions in binary form must reproduce the above |
michael@0 | 11 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 12 | // in the documentation and/or other materials provided with the |
michael@0 | 13 | // distribution. |
michael@0 | 14 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 15 | // contributors may be used to endorse or promote products derived from |
michael@0 | 16 | // this software without specific prior written permission. |
michael@0 | 17 | // |
michael@0 | 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 29 | |
michael@0 | 30 | // memory_range.h: Define the google_breakpad::MemoryRange class, which |
michael@0 | 31 | // is a lightweight wrapper with a pointer and a length to encapsulate |
michael@0 | 32 | // a contiguous range of memory. |
michael@0 | 33 | |
michael@0 | 34 | #ifndef COMMON_MEMORY_RANGE_H_ |
michael@0 | 35 | #define COMMON_MEMORY_RANGE_H_ |
michael@0 | 36 | |
michael@0 | 37 | #include <stddef.h> |
michael@0 | 38 | |
michael@0 | 39 | #include "google_breakpad/common/breakpad_types.h" |
michael@0 | 40 | |
michael@0 | 41 | namespace google_breakpad { |
michael@0 | 42 | |
michael@0 | 43 | // A lightweight wrapper with a pointer and a length to encapsulate a |
michael@0 | 44 | // contiguous range of memory. It provides helper methods for checked |
michael@0 | 45 | // access of a subrange of the memory. Its implemementation does not |
michael@0 | 46 | // allocate memory or call into libc functions, and is thus safer to use |
michael@0 | 47 | // in a crashed environment. |
michael@0 | 48 | class MemoryRange { |
michael@0 | 49 | public: |
michael@0 | 50 | MemoryRange() : data_(NULL), length_(0) {} |
michael@0 | 51 | |
michael@0 | 52 | MemoryRange(const void* data, size_t length) { |
michael@0 | 53 | Set(data, length); |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | // Returns true if this memory range contains no data. |
michael@0 | 57 | bool IsEmpty() const { |
michael@0 | 58 | // Set() guarantees that |length_| is zero if |data_| is NULL. |
michael@0 | 59 | return length_ == 0; |
michael@0 | 60 | } |
michael@0 | 61 | |
michael@0 | 62 | // Resets to an empty range. |
michael@0 | 63 | void Reset() { |
michael@0 | 64 | data_ = NULL; |
michael@0 | 65 | length_ = 0; |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | // Sets this memory range to point to |data| and its length to |length|. |
michael@0 | 69 | void Set(const void* data, size_t length) { |
michael@0 | 70 | data_ = reinterpret_cast<const uint8_t*>(data); |
michael@0 | 71 | // Always set |length_| to zero if |data_| is NULL. |
michael@0 | 72 | length_ = data ? length : 0; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | // Returns true if this range covers a subrange of |sub_length| bytes |
michael@0 | 76 | // at |sub_offset| bytes of this memory range, or false otherwise. |
michael@0 | 77 | bool Covers(size_t sub_offset, size_t sub_length) const { |
michael@0 | 78 | // The following checks verify that: |
michael@0 | 79 | // 1. sub_offset is within [ 0 .. length_ - 1 ] |
michael@0 | 80 | // 2. sub_offset + sub_length is within |
michael@0 | 81 | // [ sub_offset .. length_ ] |
michael@0 | 82 | return sub_offset < length_ && |
michael@0 | 83 | sub_offset + sub_length >= sub_offset && |
michael@0 | 84 | sub_offset + sub_length <= length_; |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | // Returns a raw data pointer to a subrange of |sub_length| bytes at |
michael@0 | 88 | // |sub_offset| bytes of this memory range, or NULL if the subrange |
michael@0 | 89 | // is out of bounds. |
michael@0 | 90 | const void* GetData(size_t sub_offset, size_t sub_length) const { |
michael@0 | 91 | return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL; |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | // Same as the two-argument version of GetData() but uses sizeof(DataType) |
michael@0 | 95 | // as the subrange length and returns an |DataType| pointer for convenience. |
michael@0 | 96 | template <typename DataType> |
michael@0 | 97 | const DataType* GetData(size_t sub_offset) const { |
michael@0 | 98 | return reinterpret_cast<const DataType*>( |
michael@0 | 99 | GetData(sub_offset, sizeof(DataType))); |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | // Returns a raw pointer to the |element_index|-th element of an array |
michael@0 | 103 | // of elements of length |element_size| starting at |sub_offset| bytes |
michael@0 | 104 | // of this memory range, or NULL if the element is out of bounds. |
michael@0 | 105 | const void* GetArrayElement(size_t element_offset, |
michael@0 | 106 | size_t element_size, |
michael@0 | 107 | unsigned element_index) const { |
michael@0 | 108 | size_t sub_offset = element_offset + element_index * element_size; |
michael@0 | 109 | return GetData(sub_offset, element_size); |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | // Same as the three-argument version of GetArrayElement() but deduces |
michael@0 | 113 | // the element size using sizeof(ElementType) and returns an |ElementType| |
michael@0 | 114 | // pointer for convenience. |
michael@0 | 115 | template <typename ElementType> |
michael@0 | 116 | const ElementType* GetArrayElement(size_t element_offset, |
michael@0 | 117 | unsigned element_index) const { |
michael@0 | 118 | return reinterpret_cast<const ElementType*>( |
michael@0 | 119 | GetArrayElement(element_offset, sizeof(ElementType), element_index)); |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | // Returns a subrange of |sub_length| bytes at |sub_offset| bytes of |
michael@0 | 123 | // this memory range, or an empty range if the subrange is out of bounds. |
michael@0 | 124 | MemoryRange Subrange(size_t sub_offset, size_t sub_length) const { |
michael@0 | 125 | return Covers(sub_offset, sub_length) ? |
michael@0 | 126 | MemoryRange(data_ + sub_offset, sub_length) : MemoryRange(); |
michael@0 | 127 | } |
michael@0 | 128 | |
michael@0 | 129 | // Returns a pointer to the beginning of this memory range. |
michael@0 | 130 | const uint8_t* data() const { return data_; } |
michael@0 | 131 | |
michael@0 | 132 | // Returns the length, in bytes, of this memory range. |
michael@0 | 133 | size_t length() const { return length_; } |
michael@0 | 134 | |
michael@0 | 135 | private: |
michael@0 | 136 | // Pointer to the beginning of this memory range. |
michael@0 | 137 | const uint8_t* data_; |
michael@0 | 138 | |
michael@0 | 139 | // Length, in bytes, of this memory range. |
michael@0 | 140 | size_t length_; |
michael@0 | 141 | }; |
michael@0 | 142 | |
michael@0 | 143 | } // namespace google_breakpad |
michael@0 | 144 | |
michael@0 | 145 | #endif // COMMON_MEMORY_RANGE_H_ |