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 |
24 | namespace physx |
25 | { |
26 | #endif |
27 | |
28 | /** |
29 | \brief Iterator class for iterating over arrays of data that may be interleaved with other data. |
30 | |
31 | This class is used for iterating over arrays of elements that may have a larger element to element |
32 | offset, called the stride, than the size of the element itself (non-contiguous). |
33 | |
34 | The template parameter T denotes the type of the element accessed. The stride itself |
35 | is stored as a member field so multiple instances of a PxStrideIterator class can have |
36 | different strides. This is useful for cases were the stride depends on runtime configuration. |
37 | |
38 | The 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 |
47 | or 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 | |
58 | Two 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 | */ |
63 | template<typename T> |
64 | class 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 | |
81 | public: |
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 | |
327 | private: |
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 | */ |
351 | template<typename T> |
352 | PX_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 | */ |
361 | template<typename T> |
362 | PX_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 | */ |
370 | template<typename T> |
371 | PX_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 | |