124 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef SANITIZER_ARRAY_REF_H10#define SANITIZER_ARRAY_REF_H11 12#include "sanitizer_internal_defs.h"13 14namespace __sanitizer {15 16/// ArrayRef - Represent a constant reference to an array (0 or more elements17/// consecutively in memory), i.e. a start pointer and a length. It allows18/// 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 in21/// situations where the data resides in some other buffer, whose lifetime22/// extends past that of the ArrayRef. For this reason, it is not in general23/// safe to store an ArrayRef.24///25/// This is intended to be trivially copyable, so it should be passed by26/// 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 M66 /// 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 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 __sanitizer122 123#endif // SANITIZER_ARRAY_REF_H124