diff options
Diffstat (limited to 'Source/JavaScriptCore/wtf/BoundsCheckedPointer.h')
-rw-r--r-- | Source/JavaScriptCore/wtf/BoundsCheckedPointer.h | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h b/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h new file mode 100644 index 000000000..d5d42fc1c --- /dev/null +++ b/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WTF_BoundsCheckedPointer_h +#define WTF_BoundsCheckedPointer_h + +#include "Assertions.h" +#include "UnusedParam.h" + +namespace WTF { + +// Useful for when you'd like to do pointer arithmetic on a buffer, but +// you'd also like to get some ASSERT()'s that prevent you from overflowing. +// This should be performance-neutral in release builds, while providing +// you with strong assertions in debug builds. Note that all of the +// asserting happens when you actually access the pointer. You are allowed +// to overflow or underflow with arithmetic so long as no accesses are +// performed. + +template<typename T> +class BoundsCheckedPointer { +public: + BoundsCheckedPointer() + : m_pointer(0) +#if !ASSERT_DISABLED + , m_begin(0) + , m_end(0) +#endif + { + } + + BoundsCheckedPointer(T* pointer, size_t numElements) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(pointer) + , m_end(pointer + numElements) +#endif + { + UNUSED_PARAM(numElements); + } + + BoundsCheckedPointer(T* pointer, T* end) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(pointer) + , m_end(end) +#endif + { + UNUSED_PARAM(end); + } + + BoundsCheckedPointer(T* pointer, T* begin, size_t numElements) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(begin) + , m_end(begin + numElements) +#endif + { + UNUSED_PARAM(begin); + UNUSED_PARAM(numElements); + } + + BoundsCheckedPointer(T* pointer, T* begin, T* end) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(begin) + , m_end(end) +#endif + { + UNUSED_PARAM(begin); + UNUSED_PARAM(end); + } + + BoundsCheckedPointer& operator=(T* value) + { + m_pointer = value; + return *this; + } + + BoundsCheckedPointer& operator+=(ptrdiff_t amount) + { + m_pointer += amount; + return *this; + } + + BoundsCheckedPointer& operator-=(ptrdiff_t amount) + { + m_pointer -= amount; + return *this; + } + + BoundsCheckedPointer operator+(ptrdiff_t amount) const + { + BoundsCheckedPointer result = *this; + result.m_pointer += amount; + return result; + } + + BoundsCheckedPointer operator-(ptrdiff_t amount) const + { + BoundsCheckedPointer result = *this; + result.m_pointer -= amount; + return result; + } + + BoundsCheckedPointer operator++() // prefix + { + m_pointer++; + return *this; + } + + BoundsCheckedPointer operator--() // prefix + { + m_pointer--; + return *this; + } + + BoundsCheckedPointer operator++(int) // postfix + { + BoundsCheckedPointer result = *this; + m_pointer++; + return result; + } + + BoundsCheckedPointer operator--(int) // postfix + { + BoundsCheckedPointer result = *this; + m_pointer--; + return result; + } + + bool operator<(T* other) const + { + return m_pointer < other; + } + + bool operator<=(T* other) const + { + return m_pointer <= other; + } + + bool operator>(T* other) const + { + return m_pointer > other; + } + + bool operator>=(T* other) const + { + return m_pointer >= other; + } + + bool operator==(T* other) const + { + return m_pointer == other; + } + + bool operator!=(T* other) const + { + return m_pointer != other; + } + + bool operator<(BoundsCheckedPointer other) const + { + return m_pointer < other.m_pointer; + } + + bool operator<=(BoundsCheckedPointer other) const + { + return m_pointer <= other.m_pointer; + } + + bool operator>(BoundsCheckedPointer other) const + { + return m_pointer > other.m_pointer; + } + + bool operator>=(BoundsCheckedPointer other) const + { + return m_pointer >= other.m_pointer; + } + + bool operator==(BoundsCheckedPointer other) const + { + return m_pointer == other.m_pointer; + } + + bool operator!=(BoundsCheckedPointer other) const + { + return m_pointer != other.m_pointer; + } + + BoundsCheckedPointer operator!() + { + return !m_pointer; + } + + T* get() + { + return m_pointer; + } + + T& operator*() + { + validate(); + return *m_pointer; + } + + const T& operator*() const + { + validate(); + return *m_pointer; + } + + T& operator[](ptrdiff_t index) + { + validate(m_pointer + index); + return m_pointer[index]; + } + + const T& operator[](ptrdiff_t index) const + { + validate(m_pointer + index); + return m_pointer[index]; + } + + // The only thing this has in common with strcat() is that it + // keeps appending from the given pointer until reaching 0. + BoundsCheckedPointer& strcat(const T* source) + { + while (*source) + *(*this)++ = *source++; + return *this; + } + +private: + void validate(T* pointer) const + { + ASSERT_UNUSED(pointer, pointer >= m_begin); + + // This guard is designed to protect against the misaligned case. + // A simple pointer < m_end would miss the case if, for example, + // T = int16_t and pointer is 1 byte less than m_end. + ASSERT_UNUSED(pointer, pointer + 1 <= m_end); + } + + void validate() const + { + validate(m_pointer); + } + + T* m_pointer; +#if !ASSERT_DISABLED + T* m_begin; + T* m_end; +#endif +}; + +} // namespace WTF + +using WTF::BoundsCheckedPointer; + +#endif // WTF_BoundsCheckedPointer_h |