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
14namespace __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.
27template <typename T>
28class 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(N: 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(N: 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
111template <typename T>
112inline bool operator==(ArrayRef<T> lhs, ArrayRef<T> rhs) {
113 return lhs.equals(rhs);
114}
115
116template <typename T>
117inline 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