master
  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(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 __sanitizer
122
123#endif  // SANITIZER_ARRAY_REF_H