diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-05-06 09:07:44 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2022-05-06 09:07:44 +0000 |
commit | dfc91d326993c6a382d07a9524f8484faacf2d3c (patch) | |
tree | 0fa50ae66c09be0c0d2c4cf76f4350093b0d20c1 /vespalib | |
parent | c7079415d0ad26115a57b2279d8dc1411f961932 (diff) |
Use raw buffer ptr for (Const)ArrayRef ctors instead of going via subscript operator
Avoids triggering technically undefined behavior when creating an array
ref for a nullptr range, since the subscript operators will take a reference
to the underlying nullptr.
Diffstat (limited to 'vespalib')
-rw-r--r-- | vespalib/src/vespa/vespalib/util/arrayref.h | 50 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/small_vector.h | 2 |
2 files changed, 28 insertions, 24 deletions
diff --git a/vespalib/src/vespa/vespalib/util/arrayref.h b/vespalib/src/vespa/vespalib/util/arrayref.h index 337833d2457..cbfea3c21bd 100644 --- a/vespalib/src/vespa/vespalib/util/arrayref.h +++ b/vespalib/src/vespa/vespalib/util/arrayref.h @@ -14,19 +14,21 @@ namespace vespalib { template <typename T> class ArrayRef { public: - ArrayRef() noexcept : _v(nullptr), _sz(0) { } - ArrayRef(T * v, size_t sz) noexcept : _v(v), _sz(sz) { } + constexpr ArrayRef() noexcept : _v(nullptr), _sz(0) { } + constexpr ArrayRef(T * v, size_t sz) noexcept : _v(v), _sz(sz) { } template<typename A=std::allocator<T>> - ArrayRef(std::vector<T, A> & v) noexcept : _v(&v[0]), _sz(v.size()) { } + ArrayRef(std::vector<T, A> & v) noexcept : _v(v.data()), _sz(v.size()) { } template<size_t N> - ArrayRef(SmallVector<T, N> &v) noexcept : _v(&v[0]), _sz(v.size()) { } - ArrayRef(Array<T> &v) noexcept : _v(&v[0]), _sz(v.size()) { } - T & operator [] (size_t i) { return _v[i]; } - const T & operator [] (size_t i) const { return _v[i]; } - size_t size() const { return _sz; } - bool empty() const { return _sz == 0; } - T *begin() { return _v; } - T *end() { return _v + _sz; } + ArrayRef(SmallVector<T, N> &v) noexcept : _v(v.data()), _sz(v.size()) { } + ArrayRef(Array<T> &v) noexcept : _v(v.data()), _sz(v.size()) { } + T & operator [] (size_t i) noexcept { return _v[i]; } + const T & operator [] (size_t i) const noexcept { return _v[i]; } + T * data() noexcept { return _v; } + const T * data() const noexcept { return _v; } + [[nodiscard]] size_t size() const noexcept { return _sz; } + [[nodiscard]] bool empty() const noexcept { return _sz == 0; } + T *begin() noexcept { return _v; } + T *end() noexcept { return _v + _sz; } private: T * _v; size_t _sz; @@ -35,21 +37,21 @@ private: template <typename T> class ConstArrayRef { public: - ConstArrayRef(const T *v, size_t sz) noexcept : _v(v), _sz(sz) { } + constexpr ConstArrayRef(const T *v, size_t sz) noexcept : _v(v), _sz(sz) { } template<typename A=std::allocator<T>> - ConstArrayRef(const std::vector<T, A> & v) noexcept : _v(&v[0]), _sz(v.size()) { } + ConstArrayRef(const std::vector<T, A> & v) noexcept : _v(v.data()), _sz(v.size()) { } template<size_t N> - ConstArrayRef(const SmallVector<T, N> &v) noexcept : _v(&v[0]), _sz(v.size()) { } - ConstArrayRef(const ArrayRef<T> & v) noexcept : _v(&v[0]), _sz(v.size()) { } - ConstArrayRef(const Array<T> &v) noexcept : _v(&v[0]), _sz(v.size()) { } + ConstArrayRef(const SmallVector<T, N> &v) noexcept : _v(v.data()), _sz(v.size()) { } + ConstArrayRef(const ArrayRef<T> & v) noexcept : _v(v.data()), _sz(v.size()) { } + ConstArrayRef(const Array<T> &v) noexcept : _v(v.data()), _sz(v.size()) { } constexpr ConstArrayRef() noexcept : _v(nullptr), _sz(0) {} - const T & operator [] (size_t i) const { return _v[i]; } - size_t size() const { return _sz; } - bool empty() const { return _sz == 0; } - const T *cbegin() const { return _v; } - const T *cend() const { return _v + _sz; } - const T *begin() const { return _v; } - const T *end() const { return _v + _sz; } + const T & operator [] (size_t i) const noexcept { return _v[i]; } + [[nodiscard]] size_t size() const noexcept { return _sz; } + [[nodiscard]] bool empty() const noexcept { return _sz == 0; } + const T *cbegin() const noexcept { return _v; } + const T *cend() const noexcept { return _v + _sz; } + const T *begin() const noexcept { return _v; } + const T *end() const noexcept { return _v + _sz; } const T *data() const noexcept { return _v; } private: const T *_v; @@ -59,7 +61,7 @@ private: // const-cast for array references; use with care template <typename T> ArrayRef<T> unconstify(const ConstArrayRef<T> &ref) { - return ArrayRef<T>(const_cast<T*>(&ref[0]), ref.size()); + return ArrayRef<T>(const_cast<T*>(ref.data()), ref.size()); } } diff --git a/vespalib/src/vespa/vespalib/util/small_vector.h b/vespalib/src/vespa/vespalib/util/small_vector.h index c1549ef725d..54711623440 100644 --- a/vespalib/src/vespa/vespalib/util/small_vector.h +++ b/vespalib/src/vespa/vespalib/util/small_vector.h @@ -186,6 +186,8 @@ public: const T *end() const { return (_data + _size); } T &operator[](size_t idx) { return _data[idx]; } const T &operator[](size_t idx) const { return _data[idx]; } + T *data() noexcept { return _data; } + const T *data() const noexcept { return _data; } T &back() { return _data[_size - 1]; } const T &back() const { return _data[_size - 1]; } void clear() { |