• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_ADT_ARRAYREF_H
11 #define LLVM_ADT_ARRAYREF_H
12 
13 #include "llvm/ADT/SmallVector.h"
14 #include <vector>
15 
16 namespace llvm {
17 
18   /// ArrayRef - Represent a constant reference to an array (0 or more elements
19   /// consecutively in memory), i.e. a start pointer and a length.  It allows
20   /// various APIs to take consecutive elements easily and conveniently.
21   ///
22   /// This class does not own the underlying data, it is expected to be used in
23   /// situations where the data resides in some other buffer, whose lifetime
24   /// extends past that of the ArrayRef. For this reason, it is not in general
25   /// safe to store an ArrayRef.
26   ///
27   /// This is intended to be trivially copyable, so it should be passed by
28   /// value.
29   template<typename T>
30   class ArrayRef {
31   public:
32     typedef const T *iterator;
33     typedef const T *const_iterator;
34     typedef size_t size_type;
35 
36   private:
37     /// The start of the array, in an external buffer.
38     const T *Data;
39 
40     /// The number of elements.
41     size_type Length;
42 
43   public:
44     /// @name Constructors
45     /// @{
46 
47     /// Construct an empty ArrayRef.
ArrayRef()48     /*implicit*/ ArrayRef() : Data(0), Length(0) {}
49 
50     /// Construct an ArrayRef from a single element.
ArrayRef(const T & OneElt)51     /*implicit*/ ArrayRef(const T &OneElt)
52       : Data(&OneElt), Length(1) {}
53 
54     /// Construct an ArrayRef from a pointer and length.
ArrayRef(const T * data,size_t length)55     /*implicit*/ ArrayRef(const T *data, size_t length)
56       : Data(data), Length(length) {}
57 
58     /// Construct an ArrayRef from a range.
ArrayRef(const T * begin,const T * end)59     ArrayRef(const T *begin, const T *end)
60       : Data(begin), Length(end - begin) {}
61 
62     /// Construct an ArrayRef from a SmallVector. This is templated in order to
63     /// avoid instantiating SmallVectorTemplateCommon<T> whenever we
64     /// copy-construct an ArrayRef.
65     template<typename U>
ArrayRef(const SmallVectorTemplateCommon<T,U> & Vec)66     /*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec)
67       : Data(Vec.data()), Length(Vec.size()) {
68     }
69 
70     /// Construct an ArrayRef from a std::vector.
71     template<typename A>
ArrayRef(const std::vector<T,A> & Vec)72     /*implicit*/ ArrayRef(const std::vector<T, A> &Vec)
73       : Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
74 
75     /// Construct an ArrayRef from a C array.
76     template <size_t N>
ArrayRef(const T (& Arr)[N])77     /*implicit*/ ArrayRef(const T (&Arr)[N])
78       : Data(Arr), Length(N) {}
79 
80     /// @}
81     /// @name Simple Operations
82     /// @{
83 
begin()84     iterator begin() const { return Data; }
end()85     iterator end() const { return Data + Length; }
86 
87     /// empty - Check if the array is empty.
empty()88     bool empty() const { return Length == 0; }
89 
data()90     const T *data() const { return Data; }
91 
92     /// size - Get the array size.
size()93     size_t size() const { return Length; }
94 
95     /// front - Get the first element.
front()96     const T &front() const {
97       assert(!empty());
98       return Data[0];
99     }
100 
101     /// back - Get the last element.
back()102     const T &back() const {
103       assert(!empty());
104       return Data[Length-1];
105     }
106 
107     /// equals - Check for element-wise equality.
equals(ArrayRef RHS)108     bool equals(ArrayRef RHS) const {
109       if (Length != RHS.Length)
110         return false;
111       for (size_type i = 0; i != Length; i++)
112         if (Data[i] != RHS.Data[i])
113           return false;
114       return true;
115     }
116 
117     /// slice(n) - Chop off the first N elements of the array.
slice(unsigned N)118     ArrayRef<T> slice(unsigned N) const {
119       assert(N <= size() && "Invalid specifier");
120       return ArrayRef<T>(data()+N, size()-N);
121     }
122 
123     /// slice(n, m) - Chop off the first N elements of the array, and keep M
124     /// elements in the array.
slice(unsigned N,unsigned M)125     ArrayRef<T> slice(unsigned N, unsigned M) const {
126       assert(N+M <= size() && "Invalid specifier");
127       return ArrayRef<T>(data()+N, M);
128     }
129 
130     /// @}
131     /// @name Operator Overloads
132     /// @{
133     const T &operator[](size_t Index) const {
134       assert(Index < Length && "Invalid index!");
135       return Data[Index];
136     }
137 
138     /// @}
139     /// @name Expensive Operations
140     /// @{
vec()141     std::vector<T> vec() const {
142       return std::vector<T>(Data, Data+Length);
143     }
144 
145     /// @}
146     /// @name Conversion operators
147     /// @{
148     operator std::vector<T>() const {
149       return std::vector<T>(Data, Data+Length);
150     }
151 
152     /// @}
153   };
154 
155   /// MutableArrayRef - Represent a mutable reference to an array (0 or more
156   /// elements consecutively in memory), i.e. a start pointer and a length.  It
157   /// allows various APIs to take and modify consecutive elements easily and
158   /// conveniently.
159   ///
160   /// This class does not own the underlying data, it is expected to be used in
161   /// situations where the data resides in some other buffer, whose lifetime
162   /// extends past that of the MutableArrayRef. For this reason, it is not in
163   /// general safe to store a MutableArrayRef.
164   ///
165   /// This is intended to be trivially copyable, so it should be passed by
166   /// value.
167   template<typename T>
168   class MutableArrayRef : public ArrayRef<T> {
169   public:
170     typedef T *iterator;
171 
172     /// Construct an empty ArrayRef.
MutableArrayRef()173     /*implicit*/ MutableArrayRef() : ArrayRef<T>() {}
174 
175     /// Construct an MutableArrayRef from a single element.
MutableArrayRef(T & OneElt)176     /*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
177 
178     /// Construct an MutableArrayRef from a pointer and length.
MutableArrayRef(T * data,size_t length)179     /*implicit*/ MutableArrayRef(T *data, size_t length)
180       : ArrayRef<T>(data, length) {}
181 
182     /// Construct an MutableArrayRef from a range.
MutableArrayRef(T * begin,T * end)183     MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
184 
185     /// Construct an MutableArrayRef from a SmallVector.
MutableArrayRef(SmallVectorImpl<T> & Vec)186     /*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec)
187     : ArrayRef<T>(Vec) {}
188 
189     /// Construct a MutableArrayRef from a std::vector.
MutableArrayRef(std::vector<T> & Vec)190     /*implicit*/ MutableArrayRef(std::vector<T> &Vec)
191     : ArrayRef<T>(Vec) {}
192 
193     /// Construct an MutableArrayRef from a C array.
194     template <size_t N>
MutableArrayRef(T (& Arr)[N])195     /*implicit*/ MutableArrayRef(T (&Arr)[N])
196       : ArrayRef<T>(Arr) {}
197 
data()198     T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }
199 
begin()200     iterator begin() const { return data(); }
end()201     iterator end() const { return data() + this->size(); }
202 
203     /// front - Get the first element.
front()204     T &front() const {
205       assert(!this->empty());
206       return data()[0];
207     }
208 
209     /// back - Get the last element.
back()210     T &back() const {
211       assert(!this->empty());
212       return data()[this->size()-1];
213     }
214 
215     /// slice(n) - Chop off the first N elements of the array.
slice(unsigned N)216     MutableArrayRef<T> slice(unsigned N) const {
217       assert(N <= this->size() && "Invalid specifier");
218       return MutableArrayRef<T>(data()+N, this->size()-N);
219     }
220 
221     /// slice(n, m) - Chop off the first N elements of the array, and keep M
222     /// elements in the array.
slice(unsigned N,unsigned M)223     MutableArrayRef<T> slice(unsigned N, unsigned M) const {
224       assert(N+M <= this->size() && "Invalid specifier");
225       return MutableArrayRef<T>(data()+N, M);
226     }
227 
228     /// @}
229     /// @name Operator Overloads
230     /// @{
231     T &operator[](size_t Index) const {
232       assert(Index < this->size() && "Invalid index!");
233       return data()[Index];
234     }
235   };
236 
237   /// @name ArrayRef Convenience constructors
238   /// @{
239 
240   /// Construct an ArrayRef from a single element.
241   template<typename T>
makeArrayRef(const T & OneElt)242   ArrayRef<T> makeArrayRef(const T &OneElt) {
243     return OneElt;
244   }
245 
246   /// Construct an ArrayRef from a pointer and length.
247   template<typename T>
makeArrayRef(const T * data,size_t length)248   ArrayRef<T> makeArrayRef(const T *data, size_t length) {
249     return ArrayRef<T>(data, length);
250   }
251 
252   /// Construct an ArrayRef from a range.
253   template<typename T>
makeArrayRef(const T * begin,const T * end)254   ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
255     return ArrayRef<T>(begin, end);
256   }
257 
258   /// Construct an ArrayRef from a SmallVector.
259   template <typename T>
makeArrayRef(const SmallVectorImpl<T> & Vec)260   ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
261     return Vec;
262   }
263 
264   /// Construct an ArrayRef from a SmallVector.
265   template <typename T, unsigned N>
makeArrayRef(const SmallVector<T,N> & Vec)266   ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
267     return Vec;
268   }
269 
270   /// Construct an ArrayRef from a std::vector.
271   template<typename T>
makeArrayRef(const std::vector<T> & Vec)272   ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
273     return Vec;
274   }
275 
276   /// Construct an ArrayRef from a C array.
277   template<typename T, size_t N>
makeArrayRef(const T (& Arr)[N])278   ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
279     return ArrayRef<T>(Arr);
280   }
281 
282   /// @}
283   /// @name ArrayRef Comparison Operators
284   /// @{
285 
286   template<typename T>
287   inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) {
288     return LHS.equals(RHS);
289   }
290 
291   template<typename T>
292   inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
293     return !(LHS == RHS);
294   }
295 
296   /// @}
297 
298   // ArrayRefs can be treated like a POD type.
299   template <typename T> struct isPodLike;
300   template <typename T> struct isPodLike<ArrayRef<T> > {
301     static const bool value = true;
302   };
303 }
304 
305 #endif
306