1/*
2 * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
3 *
4 * NVIDIA CORPORATION and its licensors retain all intellectual property
5 * and proprietary rights in and to this software, related documentation
6 * and any modifications thereto. Any use, reproduction, disclosure or
7 * distribution of this software and related documentation without an express
8 * license agreement from NVIDIA CORPORATION is strictly prohibited.
9 */
10// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
11// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
12
13
14#ifndef PX_FOUNDATION_PX_STRIDE_ITERATOR_H
15#define PX_FOUNDATION_PX_STRIDE_ITERATOR_H
16
17#include "foundation/PxAssert.h"
18
19/** \addtogroup foundation
20 @{
21*/
22
23#ifndef PX_DOXYGEN
24namespace physx
25{
26#endif
27
28/**
29\brief Iterator class for iterating over arrays of data that may be interleaved with other data.
30
31This class is used for iterating over arrays of elements that may have a larger element to element
32offset, called the stride, than the size of the element itself (non-contiguous).
33
34The template parameter T denotes the type of the element accessed. The stride itself
35is stored as a member field so multiple instances of a PxStrideIterator class can have
36different strides. This is useful for cases were the stride depends on runtime configuration.
37
38The stride iterator can be used for index based access, e.g.:
39\code
40 PxStrideIterator<PxVec3> strideArray(...);
41 for (unsigned i = 0; i < 10; ++i)
42 {
43 PxVec3& vec = strideArray[i];
44 ...
45 }
46\endcode
47or iteration by increment, e.g.:
48\code
49 PxStrideIterator<PxVec3> strideBegin(...);
50 PxStrideIterator<PxVec3> strideEnd(strideBegin + 10);
51 for (PxStrideIterator<PxVec3> it = strideBegin; it < strideEnd; ++it)
52 {
53 PxVec3& vec = *it;
54 ...
55 }
56\endcode
57
58Two special cases:
59- A stride of sizeof(T) represents a regular c array of type T.
60- A stride of 0 can be used to describe re-occurrence of the same element multiple times.
61
62*/
63template<typename T>
64class PxStrideIterator
65{
66
67#ifndef PX_DOXYGEN
68 template <typename X>
69 struct StripConst
70 {
71 typedef X Type;
72 };
73
74 template <typename X>
75 struct StripConst<const X>
76 {
77 typedef X Type;
78 };
79#endif
80
81public:
82
83 /**
84 \brief Constructor.
85
86 Optionally takes a pointer to an element and a stride.
87
88 \param[in] ptr pointer to element, defaults to NULL.
89 \param[in] stride stride for accessing consecutive elements, defaults to the size of one element.
90 */
91 explicit PX_INLINE PxStrideIterator(T* ptr = NULL, PxU32 stride = sizeof(T)) :
92 mPtr(ptr), mStride(stride)
93 {
94 PX_ASSERT(mStride == 0 || sizeof(T) <= mStride);
95 }
96
97 /**
98 \brief Copy constructor.
99
100 \param[in] strideIterator PxStrideIterator to be copied.
101 */
102 PX_INLINE PxStrideIterator(const PxStrideIterator<typename StripConst<T>::Type>& strideIterator) :
103 mPtr(strideIterator.ptr()), mStride(strideIterator.stride())
104 {
105 PX_ASSERT(mStride == 0 || sizeof(T) <= mStride);
106 }
107
108 /**
109 \brief Get pointer to element.
110 */
111 PX_INLINE T* ptr() const
112 {
113 return mPtr;
114 }
115
116 /**
117 \brief Get stride.
118 */
119 PX_INLINE PxU32 stride() const
120 {
121 return mStride;
122 }
123
124 /**
125 \brief Indirection operator.
126 */
127 PX_INLINE T& operator*() const
128 {
129 return *mPtr;
130 }
131
132 /**
133 \brief Dereferencing operator.
134 */
135 PX_INLINE T* operator->() const
136 {
137 return mPtr;
138 }
139
140 /**
141 \brief Indexing operator.
142 */
143 PX_INLINE T& operator[](unsigned int i) const
144 {
145 return *byteAdd(mPtr, i * stride());
146 }
147
148 /**
149 \brief Indexing operator.
150 */
151 PX_DEPRECATED PX_INLINE T& operator[](int i) const
152 {
153 PX_ASSERT(i >= 0);
154 return this->operator[]((unsigned int)i);
155 }
156
157 /**
158 \brief Pre-increment operator.
159 */
160 PX_INLINE PxStrideIterator& operator++()
161 {
162 mPtr = byteAdd(mPtr, stride());
163 return *this;
164 }
165
166 /**
167 \brief Post-increment operator.
168 */
169 PX_INLINE PxStrideIterator operator++(int)
170 {
171 PxStrideIterator tmp = *this;
172 mPtr = byteAdd(mPtr, stride());
173 return tmp;
174 }
175
176 /**
177 \brief Pre-decrement operator.
178 */
179 PX_INLINE PxStrideIterator& operator--()
180 {
181 mPtr = byteSub(mPtr, stride());
182 return *this;
183 }
184
185 /**
186 \brief Post-decrement operator.
187 */
188 PX_INLINE PxStrideIterator operator--(int)
189 {
190 PxStrideIterator tmp = *this;
191 mPtr = byteSub(mPtr, stride());
192 return tmp;
193 }
194
195 /**
196 \brief Addition operator.
197 */
198 PX_INLINE PxStrideIterator operator+(unsigned int i) const
199 {
200 return PxStrideIterator(byteAdd(mPtr, i * stride()), stride());
201 }
202
203 /**
204 \brief Addition operator.
205 */
206 PX_DEPRECATED PX_INLINE PxStrideIterator operator+(int i) const
207 {
208 return PxStrideIterator(byteAdd(mPtr, i * stride()), stride());
209 }
210
211 /**
212 \brief Subtraction operator.
213 */
214 PX_INLINE PxStrideIterator operator-(unsigned int i) const
215 {
216 return PxStrideIterator(byteSub(mPtr, i * stride()), stride());
217 }
218
219 /**
220 \brief Subtraction operator.
221 */
222 PX_DEPRECATED PX_INLINE PxStrideIterator operator-(int i) const
223 {
224 return PxStrideIterator(byteSub(mPtr, i * stride()), stride());
225 }
226
227 /**
228 \brief Addition compound assignment operator.
229 */
230 PX_INLINE PxStrideIterator& operator+=(unsigned int i)
231 {
232 mPtr = byteAdd(mPtr, i * stride());
233 return *this;
234 }
235
236 /**
237 \brief Addition compound assignment operator.
238 */
239 PX_DEPRECATED PX_INLINE PxStrideIterator& operator+=(int i)
240 {
241 mPtr = byteAdd(mPtr, i * stride());
242 return *this;
243 }
244
245 /**
246 \brief Subtraction compound assignment operator.
247 */
248 PX_INLINE PxStrideIterator& operator-=(unsigned int i)
249 {
250 mPtr = byteSub(mPtr, i * stride());
251 return *this;
252 }
253
254 /**
255 \brief Subtraction compound assignment operator.
256 */
257 PX_DEPRECATED PX_INLINE PxStrideIterator& operator-=(int i)
258 {
259 mPtr = byteSub(mPtr, i * stride());
260 return *this;
261 }
262
263 /**
264 \brief Iterator difference.
265 */
266 PX_INLINE int operator-(const PxStrideIterator& other) const
267 {
268 PX_ASSERT(isCompatible(other));
269 int byteDiff = static_cast<int>(reinterpret_cast<const PxU8*>(mPtr) - reinterpret_cast<const PxU8*>(other.mPtr));
270 return byteDiff / static_cast<int>(stride());
271 }
272
273 /**
274 \brief Equality operator.
275 */
276 PX_INLINE bool operator==(const PxStrideIterator& other) const
277 {
278 PX_ASSERT(isCompatible(other));
279 return mPtr == other.mPtr;
280 }
281
282 /**
283 \brief Inequality operator.
284 */
285 PX_INLINE bool operator!=(const PxStrideIterator& other) const
286 {
287 PX_ASSERT(isCompatible(other));
288 return mPtr != other.mPtr;
289 }
290
291 /**
292 \brief Less than operator.
293 */
294 PX_INLINE bool operator<(const PxStrideIterator& other) const
295 {
296 PX_ASSERT(isCompatible(other));
297 return mPtr < other.mPtr;
298 }
299
300 /**
301 \brief Greater than operator.
302 */
303 PX_INLINE bool operator>(const PxStrideIterator& other) const
304 {
305 PX_ASSERT(isCompatible(other));
306 return mPtr > other.mPtr;
307 }
308
309 /**
310 \brief Less or equal than operator.
311 */
312 PX_INLINE bool operator<=(const PxStrideIterator& other) const
313 {
314 PX_ASSERT(isCompatible(other));
315 return mPtr <= other.mPtr;
316 }
317
318 /**
319 \brief Greater or equal than operator.
320 */
321 PX_INLINE bool operator>=(const PxStrideIterator& other) const
322 {
323 PX_ASSERT(isCompatible(other));
324 return mPtr >= other.mPtr;
325 }
326
327private:
328 PX_INLINE static T* byteAdd(T* ptr, PxU32 bytes)
329 {
330 return const_cast<T*>(reinterpret_cast<const T*>(reinterpret_cast<const PxU8*>(ptr) + bytes));
331 }
332
333 PX_INLINE static T* byteSub(T* ptr, PxU32 bytes)
334 {
335 return const_cast<T*>(reinterpret_cast<const T*>(reinterpret_cast<const PxU8*>(ptr) - bytes));
336 }
337
338 PX_INLINE bool isCompatible(const PxStrideIterator& other) const
339 {
340 int byteDiff = static_cast<int>(reinterpret_cast<const PxU8*>(mPtr) - reinterpret_cast<const PxU8*>(other.mPtr));
341 return (stride() == other.stride()) && (abs(byteDiff) % stride() == 0);
342 }
343
344 T* mPtr;
345 PxU32 mStride;
346};
347
348/**
349\brief Addition operator.
350*/
351template<typename T>
352PX_INLINE PxStrideIterator<T> operator+(int i, PxStrideIterator<T> it)
353{
354 it += i;
355 return it;
356}
357
358/**
359\brief Stride iterator factory function which infers the iterator type.
360*/
361template<typename T>
362PX_INLINE PxStrideIterator<T> PxMakeIterator(T* ptr, PxU32 stride = sizeof(T))
363{
364 return PxStrideIterator<T>(ptr, stride);
365}
366
367/**
368\brief Stride iterator factory function which infers the iterator type.
369*/
370template<typename T>
371PX_INLINE PxStrideIterator<const T> PxMakeIterator(const T* ptr, PxU32 stride = sizeof(T))
372{
373 return PxStrideIterator<const T>(ptr, stride);
374}
375
376#ifndef PX_DOXYGEN
377} // namespace physx
378#endif
379
380 /** @} */
381#endif // PX_FOUNDATION_PX_STRIDE_ITERATOR_H
382