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