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