Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreStreamSerialiser.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

File size: 15.3 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2013 Torus Knot Software Ltd
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25THE SOFTWARE.
26-----------------------------------------------------------------------------
27*/
28#ifndef __StreamSerialiser_H__
29#define __StreamSerialiser_H__
30
31#include "OgrePrerequisites.h"
32#include "OgreDataStream.h"
33#include "OgreHeaderPrefix.h"
34
35namespace Ogre
36{
37        /** \addtogroup Core
38        *  @{
39        */
40        /** \addtogroup Resources
41        *  @{
42        */
43
44        /** Utility class providing helper methods for reading / writing
45                structured data held in a DataStream.
46        @remarks
47                The structure of a file read / written by this class is a series of
48                'chunks'. A chunk-based format has the advantage of being extensible later,
49                and it's robust, in that a reader can skip chunks that they are not
50                able (or willing) to process.
51        @par
52                Chunks are contained serially in the file, but they can also be
53                nested in order both to provide context, and to group chunks together for
54                potential skipping.
55        @par
56                The data format of a chunk is as follows:
57                -# Chunk ID (32-bit uint). This can be any number unique in a context, except the numbers 0x0000, 0x0001 and 0x1000, which are reserved for Ogre's use
58                -# Chunk version (16-bit uint). Chunks can change over time so this version number reflects that
59                -# Length (32-bit uint). The length of the chunk data section, including nested chunks. Note that
60                        this length excludes this header, but includes the header of any nested chunks.
61                -# Checksum (32-bit uint). Checksum value generated from the above - basically lets us check this is a valid chunk.
62                -# Chunk data
63                The 'Chunk data' section will contain chunk-specific data, which may include
64                other nested chunks.
65        */
66        class _OgreExport StreamSerialiser : public StreamAlloc
67        {
68        public:
69                /// The endianness of files
70                enum Endian
71                {
72                        /// Automatically determine endianness
73                        ENDIAN_AUTO,
74                        /// Use big endian (0x1000 is serialised as 0x10 0x00)
75                        ENDIAN_BIG,
76                        /// Use little endian (0x1000 is serialised as 0x00 0x10)
77                        ENDIAN_LITTLE
78                };
79
80                /// The storage format of Real values
81                enum RealStorageFormat
82                {
83                        /// Real is stored as float, reducing precision if you're using OGRE_DOUBLE_PRECISION
84                        REAL_FLOAT,
85                        /// Real as stored as double, not useful unless you're using OGRE_DOUBLE_PRECISION
86                        REAL_DOUBLE
87                };
88
89
90                /// Definition of a chunk of data in a file
91                struct Chunk : public StreamAlloc
92                {
93                        /// Identifier of the chunk (for example from makeIdentifier)  (stored)
94                        uint32 id;
95                        /// Version of the chunk (stored)
96                        uint16 version;
97                        /// Length of the chunk data in bytes, excluding the header of this chunk (stored)
98                        uint32 length;
99                        /// Location of the chunk (header) in bytes from the start of a stream (derived)
100                        uint32 offset;
101
102                        Chunk() : id(0), version(1), length(0), offset(0) {}
103                };
104
105                /** Constructor.
106                @param stream The stream on which you will read / write data.
107                @param endianMode The endian mode in which to read / writedata. If left at
108                        the default, when writing the endian mode will be the native platform mode,
109                        and when reading it's expected that the first chunk encountered will be
110                        the header chunk, which will determine the endian mode.
111                @param autoHeader If true, the first write or read to this stream will
112                        automatically read / write the header too. This is required if you
113                        set endianMode to ENDIAN_AUTO, but if you manually set the endian mode,
114                        then you can skip writing / reading the header if you wish, if for example
115                        this stream is midway through a file which has already included header
116                        information.
117                @param realFormat Set the format you want to write reals in. Only useful for files that
118                        you're writing (since when reading this is picked up from the file),
119                        and can only be changed if autoHeader is true, since real format is stored in the header.
120                        Defaults to float unless you're using OGRE_DOUBLE_PRECISION.
121                */
122                StreamSerialiser(const DataStreamPtr& stream, Endian endianMode = ENDIAN_AUTO, 
123                        bool autoHeader = true, 
124#if OGRE_DOUBLE_PRECISION
125                        RealStorageFormat realFormat = REAL_DOUBLE
126#else
127                        RealStorageFormat realFormat = REAL_FLOAT
128#endif
129                        );
130                virtual ~StreamSerialiser();
131
132                /** Get the endian mode.
133                @remarks
134                        If the result is ENDIAN_AUTO, this mode will change when the first piece of
135                        data is read / written.
136                */
137                virtual Endian getEndian() const { return mEndian; }
138
139                /** Pack a 4-character code into a 32-bit identifier.
140                @remarks
141                        You can use this to generate id's for your chunks based on friendlier
142                        4-character codes rather than assigning numerical IDs, if you like.
143                @param code String to pack - must be 4 characters.
144                */
145                static uint32 makeIdentifier(const String& code);
146
147                /** Report the current depth of the chunk nesting, whether reading or writing.
148                @remarks
149                        Returns how many levels of nested chunks are currently being processed,
150                        either writing or reading. In order to tidily finish, you must call
151                        read/writeChunkEnd this many times.
152                */
153                size_t getCurrentChunkDepth() const { return mChunkStack.size(); }
154
155                /** Get the ID of the chunk that's currently being read/written, if any.
156                @return The id of the current chunk being read / written (at the tightest
157                        level of nesting), or zero if no chunk is being processed.
158                */
159                uint32 getCurrentChunkID() const;
160
161                /** Get the current byte position relative to the start of the data section
162                        of the last chunk that was read or written.
163                @return the offset. Note that a return value of 0 means that either the
164                        position is at the start of the chunk data section (ie right after the
165                        header), or that no chunk is currently active. Use getCurrentChunkID
166                        or getCurrentChunkDepth to determine if a chunk is active.
167                */
168                size_t getOffsetFromChunkStart() const;
169
170                /** Reads the start of the next chunk in the file.
171                @remarks
172                        Files are serialised in a chunk-based manner, meaning that each section
173                        of data is prepended by a chunk header. After reading this chunk header,
174                        the next set of data is available directly afterwards.
175                @note
176                        When you have finished with this chunk, you should call readChunkEnd.
177                        This will perform a bit of validation and clear the chunk from
178                        the stack.
179                @return The Chunk that comes next
180                */
181                virtual const Chunk* readChunkBegin();
182
183                /** Reads the start of the next chunk so long as it's of a given ID and version.
184                @remarks
185                        This method operates like readChunkBegin, except it checks the ID and
186                        version.
187                @param id The ID you're expecting. If the next chunk isn't of this ID, then
188                        the chunk read is undone and the method returns null.
189                @param maxVersion The maximum version you're able to process. If the ID is correct
190                        but the version exceeds what is passed in here, the chunk is skipped over,
191                        the problem logged and null is returned.
192                @param msg Descriptive text added to the log if versions are not compatible
193                @return The chunk if it passes the validation.
194                */
195                virtual const Chunk* readChunkBegin(uint32 id, uint16 maxVersion, const String& msg = StringUtil::BLANK);
196
197                /** Call this to 'rewind' the stream to just before the start of the current
198                        chunk.
199                @remarks
200                        The most common case of wanting to use this is if you'd calledReadChunkBegin(),
201                        but the chunk you read wasn't one you wanted to process, and rather than
202                        skipping over it (which readChunkEnd() would do), you want to backtrack
203                        and give something else an opportunity to read it.
204                @param id The id of the chunk that you were reading (for validation purposes)
205                */
206                virtual void undoReadChunk(uint32 id);
207
208                /** Call this to 'peek' at the next chunk ID without permanently moving the stream pointer. */
209                virtual uint32 peekNextChunkID(); 
210
211                /** Finish the reading of a chunk.
212                @remarks
213                        You can call this method at any point after calling readChunkBegin, even
214                        if you didn't read all the rest of the data in the chunk. If you did
215                        not read to the end of a chunk, this method will automatically skip
216                        over the remainder of the chunk and position the stream just after it.
217                @param id The id of the chunk that you were reading (for validation purposes)
218                */
219                virtual void readChunkEnd(uint32 id);
220
221                /** Return whether the current data pointer is at the end of the current chunk.
222                @param id The id of the chunk that you were reading (for validation purposes)
223                */
224                virtual bool isEndOfChunk(uint32 id);
225
226                /// Reports whether the stream is at the end of file
227                virtual bool eof() const;
228
229                /** Get the definition of the current chunk being read (if any). */
230                virtual const Chunk* getCurrentChunk() const;
231
232                /** Begin writing a new chunk.
233                @remarks
234                        This starts the process of writing a new chunk to the stream. This will
235                        write the chunk header for you, and store a pointer so that the
236                        class can automatically go back and fill in the size for you later
237                        should you need it to. If you have already begun a chunk without ending
238                        it, then this method will start a nested chunk within it. Once written,
239                        you can then start writing chunk-specific data into your stream.
240                @note If this is the first chunk in the file
241                @param id The identifier of the new chunk. Any value that's unique in the
242                        file context is valid, except for the numbers 0x0001 and 0x1000 which are reserved
243                        for internal header identification use.
244                @param version The version of the chunk you're writing
245                */
246                virtual void writeChunkBegin(uint32 id, uint16 version = 1);
247                /** End writing a chunk.
248                @param id The identifier of the chunk - this is really just a safety check,
249                        since you can only end the chunk you most recently started.
250                */
251                virtual void writeChunkEnd(uint32 id);
252
253                /** Write arbitrary data to a stream.
254                @param buf Pointer to bytes
255                @param size The size of each element to write; each will be endian-flipped if
256                        necessary
257                @param count The number of elements to write
258                */
259                virtual void writeData(const void* buf, size_t size, size_t count);
260
261                /** Catch-all method to write primitive types. */
262                template <typename T>
263                void write(const T* pT, size_t count = 1)
264                {
265                        writeData(pT, sizeof(T), count);
266                }
267
268                // Special-case Real since we need to deal with single/double precision
269                virtual void write(const Real* val, size_t count = 1);
270
271                virtual void write(const Vector2* vec, size_t count = 1);
272                virtual void write(const Vector3* vec, size_t count = 1);
273                virtual void write(const Vector4* vec, size_t count = 1);
274                virtual void write(const Quaternion* q, size_t count = 1);
275                virtual void write(const Matrix3* m, size_t count = 1);
276                virtual void write(const Matrix4* m, size_t count = 1);
277                virtual void write(const String* string);
278                virtual void write(const AxisAlignedBox* aabb, size_t count = 1);
279                virtual void write(const Sphere* sphere, size_t count = 1);
280                virtual void write(const Plane* plane, size_t count = 1);
281                virtual void write(const Ray* ray, size_t count = 1);
282                virtual void write(const Radian* angle, size_t count = 1);
283                virtual void write(const Node* node, size_t count = 1);
284                virtual void write(const bool* boolean, size_t count = 1);
285
286
287                /** Read arbitrary data from a stream.
288                @param buf Pointer to bytes
289                @param size The size of each element to read; each will be endian-flipped if
290                necessary
291                @param count The number of elements to read
292                */
293                virtual void readData(void* buf, size_t size, size_t count);
294
295                /** Catch-all method to read primitive types. */
296                template <typename T>
297                void read(T* pT, size_t count = 1)
298                {
299                        readData(pT, sizeof(T), count);
300                }
301
302                // Special case Real, single/double-precision issues
303                virtual void read(Real* val, size_t count = 1);
304
305                /// read a Vector3
306                virtual void read(Vector2* vec, size_t count = 1);
307                virtual void read(Vector3* vec, size_t count = 1);
308                virtual void read(Vector4* vec, size_t count = 1);
309                virtual void read(Quaternion* q, size_t count = 1);
310                virtual void read(Matrix3* m, size_t count = 1);
311                virtual void read(Matrix4* m, size_t count = 1);
312                virtual void read(String* string);
313                virtual void read(AxisAlignedBox* aabb, size_t count = 1);
314                virtual void read(Sphere* sphere, size_t count = 1);
315                virtual void read(Plane* plane, size_t count = 1);
316                virtual void read(Ray* ray, size_t count = 1);
317                virtual void read(Radian* angle, size_t count = 1);
318                virtual void read(Node* node, size_t count = 1);
319                virtual void read(bool* val, size_t count = 1);
320
321                /** Start (un)compressing data
322                @param avail_in Available bytes for uncompressing
323                */
324                virtual void startDeflate(size_t avail_in = 0);
325                /** Stop (un)compressing data
326                */
327                virtual void stopDeflate();
328        protected:
329                DataStreamPtr mStream;
330                DataStreamPtr mOriginalStream;
331                Endian mEndian;
332                bool mFlipEndian;
333                bool mReadWriteHeader;
334                RealStorageFormat mRealFormat;
335                typedef deque<Chunk*>::type ChunkStack;
336                /// Current list of open chunks
337                ChunkStack mChunkStack;
338
339                static uint32 HEADER_ID;
340                static uint32 REVERSE_HEADER_ID;
341                static uint32 CHUNK_HEADER_SIZE;
342
343                virtual Chunk* readChunkImpl();
344                virtual void writeChunkImpl(uint32 id, uint16 version);
345                virtual void readHeader();
346                virtual void writeHeader();
347                virtual uint32 calculateChecksum(Chunk* c);
348                virtual void checkStream(bool failOnEof = false, 
349                        bool validateReadable = false, bool validateWriteable = false) const;
350
351                virtual void flipEndian(void * pData, size_t size, size_t count);
352                virtual void flipEndian(void * pData, size_t size);
353                virtual void determineEndianness();
354                virtual Chunk* popChunk(uint id);
355
356                virtual void writeFloatsAsDoubles(const float* val, size_t count);
357                virtual void writeDoublesAsFloats(const double* val, size_t count);
358                virtual void readFloatsAsDoubles(double* val, size_t count);
359                virtual void readDoublesAsFloats(float* val, size_t count);
360                template <typename T, typename U>
361                void writeConverted(const T* src, U typeToWrite, size_t count)
362                {
363                        U* tmp = OGRE_ALLOC_T(U, count, MEMCATEGORY_GENERAL);
364                        U* pDst = tmp;
365                        const T* pSrc = src;
366                        for (size_t i = 0; i < count; ++i)
367                                *pDst++ = static_cast<U>(*pSrc++);
368                       
369                        writeData(tmp, sizeof(U), count);
370
371                        OGRE_FREE(tmp, MEMCATEGORY_GENERAL);
372                }
373                template <typename T, typename U>
374                void readConverted(T* dst, U typeToRead, size_t count)
375                {
376                        U* tmp = OGRE_ALLOC_T(U, count, MEMCATEGORY_GENERAL);
377                        readData(tmp, sizeof(U), count);
378
379                        T* pDst = dst;
380                        const U* pSrc = tmp;
381                        for (size_t i = 0; i < count; ++i)
382                                *pDst++ = static_cast<T>(*pSrc++);
383
384
385                        OGRE_FREE(tmp, MEMCATEGORY_GENERAL);
386                }
387
388        };
389        /** @} */
390        /** @} */
391}
392
393#include "OgreHeaderSuffix.h"
394
395#endif
396
Note: See TracBrowser for help on using the repository browser.