1*06c3fb27SDimitry Andric //===-- sanitizer_array_ref.h -----------------------------------*- C++ -*-===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #ifndef SANITIZER_ARRAY_REF_H 10*06c3fb27SDimitry Andric #define SANITIZER_ARRAY_REF_H 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric #include "sanitizer_internal_defs.h" 13*06c3fb27SDimitry Andric 14*06c3fb27SDimitry Andric namespace __sanitizer { 15*06c3fb27SDimitry Andric 16*06c3fb27SDimitry Andric /// ArrayRef - Represent a constant reference to an array (0 or more elements 17*06c3fb27SDimitry Andric /// consecutively in memory), i.e. a start pointer and a length. It allows 18*06c3fb27SDimitry Andric /// various APIs to take consecutive elements easily and conveniently. 19*06c3fb27SDimitry Andric /// 20*06c3fb27SDimitry Andric /// This class does not own the underlying data, it is expected to be used in 21*06c3fb27SDimitry Andric /// situations where the data resides in some other buffer, whose lifetime 22*06c3fb27SDimitry Andric /// extends past that of the ArrayRef. For this reason, it is not in general 23*06c3fb27SDimitry Andric /// safe to store an ArrayRef. 24*06c3fb27SDimitry Andric /// 25*06c3fb27SDimitry Andric /// This is intended to be trivially copyable, so it should be passed by 26*06c3fb27SDimitry Andric /// value. 27*06c3fb27SDimitry Andric template <typename T> 28*06c3fb27SDimitry Andric class ArrayRef { 29*06c3fb27SDimitry Andric public: ArrayRef()30*06c3fb27SDimitry Andric constexpr ArrayRef() {} ArrayRef(const T * begin,const T * end)31*06c3fb27SDimitry Andric constexpr ArrayRef(const T *begin, const T *end) : begin_(begin), end_(end) { 32*06c3fb27SDimitry Andric DCHECK(empty() || begin); 33*06c3fb27SDimitry Andric } ArrayRef(const T * data,uptr length)34*06c3fb27SDimitry Andric constexpr ArrayRef(const T *data, uptr length) 35*06c3fb27SDimitry Andric : ArrayRef(data, data + length) {} 36*06c3fb27SDimitry Andric template <uptr N> ArrayRef(const T (& src)[N])37*06c3fb27SDimitry Andric constexpr ArrayRef(const T (&src)[N]) : ArrayRef(src, src + N) {} 38*06c3fb27SDimitry Andric template <typename C> ArrayRef(const C & src)39*06c3fb27SDimitry Andric constexpr ArrayRef(const C &src) 40*06c3fb27SDimitry Andric : ArrayRef(src.data(), src.data() + src.size()) {} ArrayRef(const T & one_elt)41*06c3fb27SDimitry Andric ArrayRef(const T &one_elt) : ArrayRef(&one_elt, &one_elt + 1) {} 42*06c3fb27SDimitry Andric data()43*06c3fb27SDimitry Andric const T *data() const { return empty() ? nullptr : begin_; } 44*06c3fb27SDimitry Andric begin()45*06c3fb27SDimitry Andric const T *begin() const { return begin_; } end()46*06c3fb27SDimitry Andric const T *end() const { return end_; } 47*06c3fb27SDimitry Andric empty()48*06c3fb27SDimitry Andric bool empty() const { return begin_ == end_; } 49*06c3fb27SDimitry Andric size()50*06c3fb27SDimitry Andric uptr size() const { return end_ - begin_; } 51*06c3fb27SDimitry Andric 52*06c3fb27SDimitry Andric /// equals - Check for element-wise equality. equals(ArrayRef rhs)53*06c3fb27SDimitry Andric bool equals(ArrayRef rhs) const { 54*06c3fb27SDimitry Andric if (size() != rhs.size()) 55*06c3fb27SDimitry Andric return false; 56*06c3fb27SDimitry Andric auto r = rhs.begin(); 57*06c3fb27SDimitry Andric for (auto &l : *this) { 58*06c3fb27SDimitry Andric if (!(l == *r)) 59*06c3fb27SDimitry Andric return false; 60*06c3fb27SDimitry Andric ++r; 61*06c3fb27SDimitry Andric } 62*06c3fb27SDimitry Andric return true; 63*06c3fb27SDimitry Andric } 64*06c3fb27SDimitry Andric 65*06c3fb27SDimitry Andric /// slice(n, m) - Chop off the first N elements of the array, and keep M 66*06c3fb27SDimitry Andric /// elements in the array. slice(uptr N,uptr M)67*06c3fb27SDimitry Andric ArrayRef<T> slice(uptr N, uptr M) const { 68*06c3fb27SDimitry Andric DCHECK_LE(N + M, size()); 69*06c3fb27SDimitry Andric return ArrayRef<T>(data() + N, M); 70*06c3fb27SDimitry Andric } 71*06c3fb27SDimitry Andric 72*06c3fb27SDimitry Andric /// slice(n) - Chop off the first N elements of the array. slice(uptr N)73*06c3fb27SDimitry Andric ArrayRef<T> slice(uptr N) const { return slice(N, size() - N); } 74*06c3fb27SDimitry Andric 75*06c3fb27SDimitry Andric /// Drop the first \p N elements of the array. 76*06c3fb27SDimitry Andric ArrayRef<T> drop_front(uptr N = 1) const { 77*06c3fb27SDimitry Andric DCHECK_GE(size(), N); 78*06c3fb27SDimitry Andric return slice(N, size() - N); 79*06c3fb27SDimitry Andric } 80*06c3fb27SDimitry Andric 81*06c3fb27SDimitry Andric /// Drop the last \p N elements of the array. 82*06c3fb27SDimitry Andric ArrayRef<T> drop_back(uptr N = 1) const { 83*06c3fb27SDimitry Andric DCHECK_GE(size(), N); 84*06c3fb27SDimitry Andric return slice(0, size() - N); 85*06c3fb27SDimitry Andric } 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric /// Return a copy of *this with only the first \p N elements. 88*06c3fb27SDimitry Andric ArrayRef<T> take_front(uptr N = 1) const { 89*06c3fb27SDimitry Andric if (N >= size()) 90*06c3fb27SDimitry Andric return *this; 91*06c3fb27SDimitry Andric return drop_back(size() - N); 92*06c3fb27SDimitry Andric } 93*06c3fb27SDimitry Andric 94*06c3fb27SDimitry Andric /// Return a copy of *this with only the last \p N elements. 95*06c3fb27SDimitry Andric ArrayRef<T> take_back(uptr N = 1) const { 96*06c3fb27SDimitry Andric if (N >= size()) 97*06c3fb27SDimitry Andric return *this; 98*06c3fb27SDimitry Andric return drop_front(size() - N); 99*06c3fb27SDimitry Andric } 100*06c3fb27SDimitry Andric 101*06c3fb27SDimitry Andric const T &operator[](uptr index) const { 102*06c3fb27SDimitry Andric DCHECK_LT(index, size()); 103*06c3fb27SDimitry Andric return begin_[index]; 104*06c3fb27SDimitry Andric } 105*06c3fb27SDimitry Andric 106*06c3fb27SDimitry Andric private: 107*06c3fb27SDimitry Andric const T *begin_ = nullptr; 108*06c3fb27SDimitry Andric const T *end_ = nullptr; 109*06c3fb27SDimitry Andric }; 110*06c3fb27SDimitry Andric 111*06c3fb27SDimitry Andric template <typename T> 112*06c3fb27SDimitry Andric inline bool operator==(ArrayRef<T> lhs, ArrayRef<T> rhs) { 113*06c3fb27SDimitry Andric return lhs.equals(rhs); 114*06c3fb27SDimitry Andric } 115*06c3fb27SDimitry Andric 116*06c3fb27SDimitry Andric template <typename T> 117*06c3fb27SDimitry Andric inline bool operator!=(ArrayRef<T> lhs, ArrayRef<T> rhs) { 118*06c3fb27SDimitry Andric return !(lhs == rhs); 119*06c3fb27SDimitry Andric } 120*06c3fb27SDimitry Andric 121*06c3fb27SDimitry Andric } // namespace __sanitizer 122*06c3fb27SDimitry Andric 123*06c3fb27SDimitry Andric #endif // SANITIZER_ARRAY_REF_H 124