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 | |
31 | #ifndef PSFILEBUFFER_PXFILEBUF_H |
32 | #define PSFILEBUFFER_PXFILEBUF_H |
33 | |
34 | #include "foundation/PxSimpleTypes.h" |
35 | |
36 | /** \addtogroup foundation |
37 | @{ |
38 | */ |
39 | |
40 | #if !PX_DOXYGEN |
41 | namespace physx |
42 | { |
43 | |
44 | namespace general_PxIOStream2 |
45 | { |
46 | #endif |
47 | |
48 | PX_PUSH_PACK_DEFAULT |
49 | |
50 | /** |
51 | \brief Callback class for data serialization. |
52 | |
53 | The user needs to supply an PxFileBuf implementation to a number of methods to allow the SDK to read or write |
54 | chunks of binary data. This allows flexibility for the source/destination of the data. For example the PxFileBuf |
55 | could store data in a file, memory buffer or custom file format. |
56 | |
57 | \note It is the users responsibility to ensure that the data is written to the appropriate offset. |
58 | |
59 | */ |
60 | class PxFileBuf |
61 | { |
62 | public: |
63 | |
64 | enum EndianMode |
65 | { |
66 | ENDIAN_NONE = 0, // do no conversion for endian mode |
67 | ENDIAN_BIG = 1, // always read/write data as natively big endian (Power PC, etc.) |
68 | ENDIAN_LITTLE = 2 // always read/write data as natively little endian (Intel, etc.) Default Behavior! |
69 | }; |
70 | |
71 | PxFileBuf(EndianMode mode=ENDIAN_LITTLE) |
72 | { |
73 | setEndianMode(mode); |
74 | } |
75 | |
76 | virtual ~PxFileBuf(void) |
77 | { |
78 | |
79 | } |
80 | |
81 | /** |
82 | \brief Declares a constant to seek to the end of the stream. |
83 | * |
84 | * Does not support streams longer than 32 bits |
85 | */ |
86 | static const uint32_t STREAM_SEEK_END=0xFFFFFFFF; |
87 | |
88 | enum OpenMode |
89 | { |
90 | OPEN_FILE_NOT_FOUND, |
91 | OPEN_READ_ONLY, // open file buffer stream for read only access |
92 | OPEN_WRITE_ONLY, // open file buffer stream for write only access |
93 | OPEN_READ_WRITE_NEW, // open a new file for both read/write access |
94 | OPEN_READ_WRITE_EXISTING // open an existing file for both read/write access |
95 | }; |
96 | |
97 | virtual OpenMode getOpenMode(void) const = 0; |
98 | |
99 | bool isOpen(void) const |
100 | { |
101 | return getOpenMode()!=OPEN_FILE_NOT_FOUND; |
102 | } |
103 | |
104 | enum SeekType |
105 | { |
106 | SEEKABLE_NO = 0, |
107 | SEEKABLE_READ = 0x1, |
108 | SEEKABLE_WRITE = 0x2, |
109 | SEEKABLE_READWRITE = 0x3 |
110 | }; |
111 | |
112 | virtual SeekType isSeekable(void) const = 0; |
113 | |
114 | void setEndianMode(EndianMode e) |
115 | { |
116 | mEndianMode = e; |
117 | if ( (e==ENDIAN_BIG && !isBigEndian() ) || |
118 | (e==ENDIAN_LITTLE && isBigEndian() ) ) |
119 | { |
120 | mEndianSwap = true; |
121 | } |
122 | else |
123 | { |
124 | mEndianSwap = false; |
125 | } |
126 | } |
127 | |
128 | EndianMode getEndianMode(void) const |
129 | { |
130 | return mEndianMode; |
131 | } |
132 | |
133 | virtual uint32_t getFileLength(void) const = 0; |
134 | |
135 | /** |
136 | \brief Seeks the stream to a particular location for reading |
137 | * |
138 | * If the location passed exceeds the length of the stream, then it will seek to the end. |
139 | * Returns the location it ended up at (useful if you seek to the end) to get the file position |
140 | */ |
141 | virtual uint32_t seekRead(uint32_t loc) = 0; |
142 | |
143 | /** |
144 | \brief Seeks the stream to a particular location for writing |
145 | * |
146 | * If the location passed exceeds the length of the stream, then it will seek to the end. |
147 | * Returns the location it ended up at (useful if you seek to the end) to get the file position |
148 | */ |
149 | virtual uint32_t seekWrite(uint32_t loc) = 0; |
150 | |
151 | /** |
152 | \brief Reads from the stream into a buffer. |
153 | |
154 | \param[out] mem The buffer to read the stream into. |
155 | \param[in] len The number of bytes to stream into the buffer |
156 | |
157 | \return Returns the actual number of bytes read. If not equal to the length requested, then reached end of stream. |
158 | */ |
159 | virtual uint32_t read(void *mem,uint32_t len) = 0; |
160 | |
161 | |
162 | /** |
163 | \brief Reads from the stream into a buffer but does not advance the read location. |
164 | |
165 | \param[out] mem The buffer to read the stream into. |
166 | \param[in] len The number of bytes to stream into the buffer |
167 | |
168 | \return Returns the actual number of bytes read. If not equal to the length requested, then reached end of stream. |
169 | */ |
170 | virtual uint32_t peek(void *mem,uint32_t len) = 0; |
171 | |
172 | /** |
173 | \brief Writes a buffer of memory to the stream |
174 | |
175 | \param[in] mem The address of a buffer of memory to send to the stream. |
176 | \param[in] len The number of bytes to send to the stream. |
177 | |
178 | \return Returns the actual number of bytes sent to the stream. If not equal to the length specific, then the stream is full or unable to write for some reason. |
179 | */ |
180 | virtual uint32_t write(const void *mem,uint32_t len) = 0; |
181 | |
182 | /** |
183 | \brief Reports the current stream location read aqccess. |
184 | |
185 | \return Returns the current stream read location. |
186 | */ |
187 | virtual uint32_t tellRead(void) const = 0; |
188 | |
189 | /** |
190 | \brief Reports the current stream location for write access. |
191 | |
192 | \return Returns the current stream write location. |
193 | */ |
194 | virtual uint32_t tellWrite(void) const = 0; |
195 | |
196 | /** |
197 | \brief Causes any temporarily cached data to be flushed to the stream. |
198 | */ |
199 | virtual void flush(void) = 0; |
200 | |
201 | /** |
202 | \brief Close the stream. |
203 | */ |
204 | virtual void close(void) {} |
205 | |
206 | void release(void) |
207 | { |
208 | delete this; |
209 | } |
210 | |
211 | static PX_INLINE bool isBigEndian() |
212 | { |
213 | int32_t i = 1; |
214 | return *(reinterpret_cast<char*>(&i))==0; |
215 | } |
216 | |
217 | PX_INLINE void swap2Bytes(void* _data) const |
218 | { |
219 | char *data = static_cast<char *>(_data); |
220 | char one_byte; |
221 | one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; |
222 | } |
223 | |
224 | PX_INLINE void swap4Bytes(void* _data) const |
225 | { |
226 | char *data = static_cast<char *>(_data); |
227 | char one_byte; |
228 | one_byte = data[0]; data[0] = data[3]; data[3] = one_byte; |
229 | one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; |
230 | } |
231 | |
232 | PX_INLINE void swap8Bytes(void *_data) const |
233 | { |
234 | char *data = static_cast<char *>(_data); |
235 | char one_byte; |
236 | one_byte = data[0]; data[0] = data[7]; data[7] = one_byte; |
237 | one_byte = data[1]; data[1] = data[6]; data[6] = one_byte; |
238 | one_byte = data[2]; data[2] = data[5]; data[5] = one_byte; |
239 | one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; |
240 | } |
241 | |
242 | |
243 | PX_INLINE void storeDword(uint32_t v) |
244 | { |
245 | if ( mEndianSwap ) |
246 | swap4Bytes(data: &v); |
247 | |
248 | write(mem: &v,len: sizeof(v)); |
249 | } |
250 | |
251 | PX_INLINE void storeFloat(float v) |
252 | { |
253 | if ( mEndianSwap ) |
254 | swap4Bytes(data: &v); |
255 | write(mem: &v,len: sizeof(v)); |
256 | } |
257 | |
258 | PX_INLINE void storeDouble(double v) |
259 | { |
260 | if ( mEndianSwap ) |
261 | swap8Bytes(data: &v); |
262 | write(mem: &v,len: sizeof(v)); |
263 | } |
264 | |
265 | PX_INLINE void storeByte(uint8_t b) |
266 | { |
267 | write(mem: &b,len: sizeof(b)); |
268 | } |
269 | |
270 | PX_INLINE void storeWord(uint16_t w) |
271 | { |
272 | if ( mEndianSwap ) |
273 | swap2Bytes(data: &w); |
274 | write(mem: &w,len: sizeof(w)); |
275 | } |
276 | |
277 | uint8_t readByte(void) |
278 | { |
279 | uint8_t v=0; |
280 | read(mem: &v,len: sizeof(v)); |
281 | return v; |
282 | } |
283 | |
284 | uint16_t readWord(void) |
285 | { |
286 | uint16_t v=0; |
287 | read(mem: &v,len: sizeof(v)); |
288 | if ( mEndianSwap ) |
289 | swap2Bytes(data: &v); |
290 | return v; |
291 | } |
292 | |
293 | uint32_t readDword(void) |
294 | { |
295 | uint32_t v=0; |
296 | read(mem: &v,len: sizeof(v)); |
297 | if ( mEndianSwap ) |
298 | swap4Bytes(data: &v); |
299 | return v; |
300 | } |
301 | |
302 | float readFloat(void) |
303 | { |
304 | float v=0; |
305 | read(mem: &v,len: sizeof(v)); |
306 | if ( mEndianSwap ) |
307 | swap4Bytes(data: &v); |
308 | return v; |
309 | } |
310 | |
311 | double readDouble(void) |
312 | { |
313 | double v=0; |
314 | read(mem: &v,len: sizeof(v)); |
315 | if ( mEndianSwap ) |
316 | swap8Bytes(data: &v); |
317 | return v; |
318 | } |
319 | |
320 | private: |
321 | bool mEndianSwap; // whether or not the endian should be swapped on the current platform |
322 | EndianMode mEndianMode; // the current endian mode behavior for the stream |
323 | }; |
324 | |
325 | PX_POP_PACK |
326 | |
327 | #if !PX_DOXYGEN |
328 | } // end of namespace |
329 | |
330 | using namespace general_PxIOStream2; |
331 | |
332 | namespace general_PxIOStream = general_PxIOStream2; |
333 | |
334 | } // end of namespace |
335 | #endif |
336 | |
337 | /** @} */ |
338 | |
339 | #endif // PSFILEBUFFER_PXFILEBUF_H |
340 | |