xref: /freebsd/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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