1 | // |
2 | // Redistribution and use in source and binary forms, with or without |
3 | // modification, are permitted provided that the following conditions |
4 | // are met: |
5 | // * Redistributions of source code must retain the above copyright |
6 | // notice, this list of conditions and the following disclaimer. |
7 | // * Redistributions in binary form must reproduce the above copyright |
8 | // notice, this list of conditions and the following disclaimer in the |
9 | // documentation and/or other materials provided with the distribution. |
10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
11 | // contributors may be used to endorse or promote products derived |
12 | // from this software without specific prior written permission. |
13 | // |
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | // |
26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
29 | |
30 | #ifndef PXFOUNDATION_PXSTRIDEITERATOR_H |
31 | #define PXFOUNDATION_PXSTRIDEITERATOR_H |
32 | |
33 | #include "foundation/Px.h" |
34 | #include "foundation/PxSharedAssert.h" |
35 | |
36 | /** \addtogroup foundation |
37 | @{ |
38 | */ |
39 | |
40 | #if !PX_DOXYGEN |
41 | namespace physx |
42 | { |
43 | #endif |
44 | |
45 | /** |
46 | \brief Iterator class for iterating over arrays of data that may be interleaved with other data. |
47 | |
48 | This class is used for iterating over arrays of elements that may have a larger element to element |
49 | offset, called the stride, than the size of the element itself (non-contiguous). |
50 | |
51 | The template parameter T denotes the type of the element accessed. The stride itself |
52 | is stored as a member field so multiple instances of a PxStrideIterator class can have |
53 | different strides. This is useful for cases were the stride depends on runtime configuration. |
54 | |
55 | The stride iterator can be used for index based access, e.g.: |
56 | \code |
57 | PxStrideIterator<PxVec3> strideArray(...); |
58 | for (unsigned i = 0; i < 10; ++i) |
59 | { |
60 | PxVec3& vec = strideArray[i]; |
61 | ... |
62 | } |
63 | \endcode |
64 | or iteration by increment, e.g.: |
65 | \code |
66 | PxStrideIterator<PxVec3> strideBegin(...); |
67 | PxStrideIterator<PxVec3> strideEnd(strideBegin + 10); |
68 | for (PxStrideIterator<PxVec3> it = strideBegin; it < strideEnd; ++it) |
69 | { |
70 | PxVec3& vec = *it; |
71 | ... |
72 | } |
73 | \endcode |
74 | |
75 | Two special cases: |
76 | - A stride of sizeof(T) represents a regular c array of type T. |
77 | - A stride of 0 can be used to describe re-occurrence of the same element multiple times. |
78 | |
79 | */ |
80 | template <typename T> |
81 | class PxStrideIterator |
82 | { |
83 | |
84 | #if !PX_DOXYGEN |
85 | template <typename X> |
86 | struct StripConst |
87 | { |
88 | typedef X Type; |
89 | }; |
90 | |
91 | template <typename X> |
92 | struct StripConst<const X> |
93 | { |
94 | typedef X Type; |
95 | }; |
96 | #endif |
97 | |
98 | public: |
99 | /** |
100 | \brief Constructor. |
101 | |
102 | Optionally takes a pointer to an element and a stride. |
103 | |
104 | \param[in] ptr pointer to element, defaults to NULL. |
105 | \param[in] stride stride for accessing consecutive elements, defaults to the size of one element. |
106 | */ |
107 | explicit PX_INLINE PxStrideIterator(T* ptr = NULL, PxU32 stride = sizeof(T)) : mPtr(ptr), mStride(stride) |
108 | { |
109 | PX_SHARED_ASSERT(mStride == 0 || sizeof(T) <= mStride); |
110 | } |
111 | |
112 | /** |
113 | \brief Copy constructor. |
114 | |
115 | \param[in] strideIterator PxStrideIterator to be copied. |
116 | */ |
117 | PX_INLINE PxStrideIterator(const PxStrideIterator<typename StripConst<T>::Type>& strideIterator) |
118 | : mPtr(strideIterator.ptr()), mStride(strideIterator.stride()) |
119 | { |
120 | PX_SHARED_ASSERT(mStride == 0 || sizeof(T) <= mStride); |
121 | } |
122 | |
123 | /** |
124 | \brief Get pointer to element. |
125 | */ |
126 | PX_INLINE T* ptr() const |
127 | { |
128 | return mPtr; |
129 | } |
130 | |
131 | /** |
132 | \brief Get stride. |
133 | */ |
134 | PX_INLINE PxU32 stride() const |
135 | { |
136 | return mStride; |
137 | } |
138 | |
139 | /** |
140 | \brief Indirection operator. |
141 | */ |
142 | PX_INLINE T& operator*() const |
143 | { |
144 | return *mPtr; |
145 | } |
146 | |
147 | /** |
148 | \brief Dereferencing operator. |
149 | */ |
150 | PX_INLINE T* operator->() const |
151 | { |
152 | return mPtr; |
153 | } |
154 | |
155 | /** |
156 | \brief Indexing operator. |
157 | */ |
158 | PX_INLINE T& operator[](unsigned int i) const |
159 | { |
160 | return *byteAdd(ptr: mPtr, bytes: i * stride()); |
161 | } |
162 | |
163 | /** |
164 | \brief Pre-increment operator. |
165 | */ |
166 | PX_INLINE PxStrideIterator& operator++() |
167 | { |
168 | mPtr = byteAdd(ptr: mPtr, bytes: stride()); |
169 | return *this; |
170 | } |
171 | |
172 | /** |
173 | \brief Post-increment operator. |
174 | */ |
175 | PX_INLINE PxStrideIterator operator++(int) |
176 | { |
177 | PxStrideIterator tmp = *this; |
178 | mPtr = byteAdd(ptr: mPtr, bytes: stride()); |
179 | return tmp; |
180 | } |
181 | |
182 | /** |
183 | \brief Pre-decrement operator. |
184 | */ |
185 | PX_INLINE PxStrideIterator& operator--() |
186 | { |
187 | mPtr = byteSub(ptr: mPtr, bytes: stride()); |
188 | return *this; |
189 | } |
190 | |
191 | /** |
192 | \brief Post-decrement operator. |
193 | */ |
194 | PX_INLINE PxStrideIterator operator--(int) |
195 | { |
196 | PxStrideIterator tmp = *this; |
197 | mPtr = byteSub(ptr: mPtr, bytes: stride()); |
198 | return tmp; |
199 | } |
200 | |
201 | /** |
202 | \brief Addition operator. |
203 | */ |
204 | PX_INLINE PxStrideIterator operator+(unsigned int i) const |
205 | { |
206 | return PxStrideIterator(byteAdd(ptr: mPtr, bytes: i * stride()), stride()); |
207 | } |
208 | |
209 | /** |
210 | \brief Subtraction operator. |
211 | */ |
212 | PX_INLINE PxStrideIterator operator-(unsigned int i) const |
213 | { |
214 | return PxStrideIterator(byteSub(ptr: mPtr, bytes: i * stride()), stride()); |
215 | } |
216 | |
217 | /** |
218 | \brief Addition compound assignment operator. |
219 | */ |
220 | PX_INLINE PxStrideIterator& operator+=(unsigned int i) |
221 | { |
222 | mPtr = byteAdd(ptr: mPtr, bytes: i * stride()); |
223 | return *this; |
224 | } |
225 | |
226 | /** |
227 | \brief Subtraction compound assignment operator. |
228 | */ |
229 | PX_INLINE PxStrideIterator& operator-=(unsigned int i) |
230 | { |
231 | mPtr = byteSub(ptr: mPtr, bytes: i * stride()); |
232 | return *this; |
233 | } |
234 | |
235 | /** |
236 | \brief Iterator difference. |
237 | */ |
238 | PX_INLINE int operator-(const PxStrideIterator& other) const |
239 | { |
240 | PX_SHARED_ASSERT(isCompatible(other)); |
241 | int byteDiff = static_cast<int>(reinterpret_cast<const PxU8*>(mPtr) - reinterpret_cast<const PxU8*>(other.mPtr)); |
242 | return byteDiff / static_cast<int>(stride()); |
243 | } |
244 | |
245 | /** |
246 | \brief Equality operator. |
247 | */ |
248 | PX_INLINE bool operator==(const PxStrideIterator& other) const |
249 | { |
250 | PX_SHARED_ASSERT(isCompatible(other)); |
251 | return mPtr == other.mPtr; |
252 | } |
253 | |
254 | /** |
255 | \brief Inequality operator. |
256 | */ |
257 | PX_INLINE bool operator!=(const PxStrideIterator& other) const |
258 | { |
259 | PX_SHARED_ASSERT(isCompatible(other)); |
260 | return mPtr != other.mPtr; |
261 | } |
262 | |
263 | /** |
264 | \brief Less than operator. |
265 | */ |
266 | PX_INLINE bool operator<(const PxStrideIterator& other) const |
267 | { |
268 | PX_SHARED_ASSERT(isCompatible(other)); |
269 | return mPtr < other.mPtr; |
270 | } |
271 | |
272 | /** |
273 | \brief Greater than operator. |
274 | */ |
275 | PX_INLINE bool operator>(const PxStrideIterator& other) const |
276 | { |
277 | PX_SHARED_ASSERT(isCompatible(other)); |
278 | return mPtr > other.mPtr; |
279 | } |
280 | |
281 | /** |
282 | \brief Less or equal than operator. |
283 | */ |
284 | PX_INLINE bool operator<=(const PxStrideIterator& other) const |
285 | { |
286 | PX_SHARED_ASSERT(isCompatible(other)); |
287 | return mPtr <= other.mPtr; |
288 | } |
289 | |
290 | /** |
291 | \brief Greater or equal than operator. |
292 | */ |
293 | PX_INLINE bool operator>=(const PxStrideIterator& other) const |
294 | { |
295 | PX_SHARED_ASSERT(isCompatible(other)); |
296 | return mPtr >= other.mPtr; |
297 | } |
298 | |
299 | private: |
300 | PX_INLINE static T* byteAdd(T* ptr, PxU32 bytes) |
301 | { |
302 | return const_cast<T*>(reinterpret_cast<const T*>(reinterpret_cast<const PxU8*>(ptr) + bytes)); |
303 | } |
304 | |
305 | PX_INLINE static T* byteSub(T* ptr, PxU32 bytes) |
306 | { |
307 | return const_cast<T*>(reinterpret_cast<const T*>(reinterpret_cast<const PxU8*>(ptr) - bytes)); |
308 | } |
309 | |
310 | PX_INLINE bool isCompatible(const PxStrideIterator& other) const |
311 | { |
312 | int byteDiff = static_cast<int>(reinterpret_cast<const PxU8*>(mPtr) - reinterpret_cast<const PxU8*>(other.mPtr)); |
313 | return (stride() == other.stride()) && (abs(x: byteDiff) % stride() == 0); |
314 | } |
315 | |
316 | T* mPtr; |
317 | PxU32 mStride; |
318 | }; |
319 | |
320 | /** |
321 | \brief Addition operator. |
322 | */ |
323 | template <typename T> |
324 | PX_INLINE PxStrideIterator<T> operator+(int i, PxStrideIterator<T> it) |
325 | { |
326 | it += i; |
327 | return it; |
328 | } |
329 | |
330 | /** |
331 | \brief Stride iterator factory function which infers the iterator type. |
332 | */ |
333 | template <typename T> |
334 | PX_INLINE PxStrideIterator<T> PxMakeIterator(T* ptr, PxU32 stride = sizeof(T)) |
335 | { |
336 | return PxStrideIterator<T>(ptr, stride); |
337 | } |
338 | |
339 | /** |
340 | \brief Stride iterator factory function which infers the iterator type. |
341 | */ |
342 | template <typename T> |
343 | PX_INLINE PxStrideIterator<const T> PxMakeIterator(const T* ptr, PxU32 stride = sizeof(T)) |
344 | { |
345 | return PxStrideIterator<const T>(ptr, stride); |
346 | } |
347 | |
348 | #if !PX_DOXYGEN |
349 | } // namespace physx |
350 | #endif |
351 | |
352 | /** @} */ |
353 | #endif // PXFOUNDATION_PXSTRIDEITERATOR_H |
354 | |