Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 09:30:10

0001 /*
0002 ---------------------------------------------------------------------------
0003 Open Asset Import Library (assimp)
0004 ---------------------------------------------------------------------------
0005 
0006 Copyright (c) 2006-2024, assimp team
0007 
0008 All rights reserved.
0009 
0010 Redistribution and use of this software in source and binary forms,
0011 with or without modification, are permitted provided that the following
0012 conditions are met:
0013 
0014 * Redistributions of source code must retain the above
0015   copyright notice, this list of conditions and the
0016   following disclaimer.
0017 
0018 * Redistributions in binary form must reproduce the above
0019   copyright notice, this list of conditions and the
0020   following disclaimer in the documentation and/or other
0021   materials provided with the distribution.
0022 
0023 * Neither the name of the assimp team, nor the names of its
0024   contributors may be used to endorse or promote products
0025   derived from this software without specific prior
0026   written permission of the assimp team.
0027 
0028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0029 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0030 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0031 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0032 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0033 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0034 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0035 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0036 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0038 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0039 ---------------------------------------------------------------------------
0040 */
0041 
0042 /** @file Defines the StreamWriter class which writes data to
0043  *  a binary stream with a well-defined endianness. */
0044 #pragma once
0045 #ifndef AI_STREAMWRITER_H_INCLUDED
0046 #define AI_STREAMWRITER_H_INCLUDED
0047 
0048 #ifdef __GNUC__
0049 #   pragma GCC system_header
0050 #endif
0051 
0052 #include <assimp/ByteSwapper.h>
0053 #include <assimp/IOStream.hpp>
0054 
0055 #include <memory>
0056 #include <vector>
0057 
0058 namespace Assimp {
0059 
0060 // --------------------------------------------------------------------------------------------
0061 /** Wrapper class around IOStream to allow for consistent writing of binary data in both
0062  *  little and big endian format. Don't attempt to instance the template directly. Use
0063  *  StreamWriterLE to write to a little-endian stream and StreamWriterBE to write to a
0064  *  BE stream. Alternatively, there is StreamWriterAny if the endianness of the output
0065  *  stream is to be determined at runtime.
0066  */
0067 // --------------------------------------------------------------------------------------------
0068 template <bool SwapEndianness = false, bool RuntimeSwitch = false>
0069 class StreamWriter {
0070     enum {
0071         INITIAL_CAPACITY = 1024
0072     };
0073 
0074 public:
0075 
0076     // ---------------------------------------------------------------------
0077     /** Construction from a given stream with a well-defined endianness.
0078      *
0079      *  The StreamReader holds a permanent strong reference to the
0080      *  stream, which is released upon destruction.
0081      *  @param stream Input stream. The stream is not re-seeked and writing
0082           continues at the current position of the stream cursor.
0083      *  @param le If @c RuntimeSwitch is true: specifies whether the
0084      *    stream is in little endian byte order. Otherwise the
0085      *    endianness information is defined by the @c SwapEndianness
0086      *    template parameter and this parameter is meaningless.  */
0087     StreamWriter(std::shared_ptr<IOStream> stream, bool le = false)
0088         : stream(stream)
0089         , le(le)
0090         , cursor()
0091     {
0092         ai_assert(stream);
0093         buffer.reserve(INITIAL_CAPACITY);
0094     }
0095 
0096     // ---------------------------------------------------------------------
0097     StreamWriter(IOStream* stream, bool le = false)
0098         : stream(std::shared_ptr<IOStream>(stream))
0099         , le(le)
0100         , cursor()
0101     {
0102         ai_assert(stream);
0103         buffer.reserve(INITIAL_CAPACITY);
0104     }
0105 
0106     // ---------------------------------------------------------------------
0107     ~StreamWriter() {
0108         stream->Write(buffer.data(), 1, buffer.size());
0109         stream->Flush();
0110     }
0111 
0112 public:
0113 
0114     // ---------------------------------------------------------------------
0115     /** Flush the contents of the internal buffer, and the output IOStream */
0116     void Flush()
0117     {
0118         stream->Write(buffer.data(), 1, buffer.size());
0119         stream->Flush();
0120         buffer.clear();
0121         cursor = 0;
0122     }
0123 
0124     // ---------------------------------------------------------------------
0125     /** Seek to the given offset / origin in the output IOStream.
0126      *
0127      *  Flushes the internal buffer and the output IOStream prior to seeking. */
0128     aiReturn Seek(size_t pOffset, aiOrigin pOrigin=aiOrigin_SET)
0129     {
0130         Flush();
0131         return stream->Seek(pOffset, pOrigin);
0132     }
0133 
0134     // ---------------------------------------------------------------------
0135     /** Tell the current position in the output IOStream.
0136      *
0137      *  First flushes the internal buffer and the output IOStream. */
0138     size_t Tell()
0139     {
0140         Flush();
0141         return stream->Tell();
0142     }
0143 
0144 public:
0145 
0146     // ---------------------------------------------------------------------
0147     /** Write a float to the stream  */
0148     void PutF4(float f)
0149     {
0150         Put(f);
0151     }
0152 
0153     // ---------------------------------------------------------------------
0154     /** Write a double to the stream  */
0155     void PutF8(double d)    {
0156         Put(d);
0157     }
0158 
0159     // ---------------------------------------------------------------------
0160     /** Write a signed 16 bit integer to the stream */
0161     void PutI2(int16_t n)   {
0162         Put(n);
0163     }
0164 
0165     // ---------------------------------------------------------------------
0166     /** Write a signed 8 bit integer to the stream */
0167     void PutI1(int8_t n)    {
0168         Put(n);
0169     }
0170 
0171     // ---------------------------------------------------------------------
0172     /** Write an signed 32 bit integer to the stream */
0173     void PutI4(int32_t n)   {
0174         Put(n);
0175     }
0176 
0177     // ---------------------------------------------------------------------
0178     /** Write a signed 64 bit integer to the stream */
0179     void PutI8(int64_t n)   {
0180         Put(n);
0181     }
0182 
0183     // ---------------------------------------------------------------------
0184     /** Write a unsigned 16 bit integer to the stream */
0185     void PutU2(uint16_t n)  {
0186         Put(n);
0187     }
0188 
0189     // ---------------------------------------------------------------------
0190     /** Write a unsigned 8 bit integer to the stream */
0191     void PutU1(uint8_t n)   {
0192         Put(n);
0193     }
0194 
0195     // ---------------------------------------------------------------------
0196     /** Write an unsigned 32 bit integer to the stream */
0197     void PutU4(uint32_t n)  {
0198         Put(n);
0199     }
0200 
0201     // ---------------------------------------------------------------------
0202     /** Write a unsigned 64 bit integer to the stream */
0203     void PutU8(uint64_t n)  {
0204         Put(n);
0205     }
0206 
0207     // ---------------------------------------------------------------------
0208     /** Write a single character to the stream */
0209     void PutChar(char c)    {
0210         Put(c);
0211     }
0212 
0213     // ---------------------------------------------------------------------
0214     /** Write an aiString to the stream */
0215     void PutString(const aiString& s)
0216     {
0217         // as Put(T f) below
0218         if (cursor + s.length >= buffer.size()) {
0219             buffer.resize(cursor + s.length);
0220         }
0221         void* dest = &buffer[cursor];
0222         ::memcpy(dest, s.C_Str(), s.length);
0223         cursor += s.length;
0224     }
0225 
0226     // ---------------------------------------------------------------------
0227     /** Write a std::string to the stream */
0228     void PutString(const std::string& s)
0229     {
0230         // as Put(T f) below
0231         if (cursor + s.size() >= buffer.size()) {
0232             buffer.resize(cursor + s.size());
0233         }
0234         void* dest = &buffer[cursor];
0235         ::memcpy(dest, s.c_str(), s.size());
0236         cursor += s.size();
0237     }
0238 
0239 public:
0240 
0241     // ---------------------------------------------------------------------
0242     /** overload operator<< and allow chaining of MM ops. */
0243     template <typename T>
0244     StreamWriter& operator << (T f) {
0245         Put(f);
0246         return *this;
0247     }
0248 
0249     // ---------------------------------------------------------------------
0250     std::size_t GetCurrentPos() const {
0251         return cursor;
0252     }
0253 
0254     // ---------------------------------------------------------------------
0255     void SetCurrentPos(std::size_t new_cursor) {
0256         cursor = new_cursor;
0257     }
0258 
0259     // ---------------------------------------------------------------------
0260     /** Generic write method. ByteSwap::Swap(T*) *must* be defined */
0261     template <typename T>
0262     void Put(T f)   {
0263         Intern :: Getter<SwapEndianness,T,RuntimeSwitch>() (&f, le);
0264 
0265         if (cursor + sizeof(T) >= buffer.size()) {
0266             buffer.resize(cursor + sizeof(T));
0267         }
0268 
0269         void* dest = &buffer[cursor];
0270 
0271         // reinterpret_cast + assignment breaks strict aliasing rules
0272         // and generally causes trouble on platforms such as ARM that
0273         // do not silently ignore alignment faults.
0274         ::memcpy(dest, &f, sizeof(T));
0275         cursor += sizeof(T);
0276     }
0277 
0278 private:
0279 
0280     std::shared_ptr<IOStream> stream;
0281     bool le;
0282 
0283     std::vector<uint8_t> buffer;
0284     std::size_t cursor;
0285 };
0286 
0287 
0288 // --------------------------------------------------------------------------------------------
0289 // `static` StreamWriter. Their byte order is fixed and they might be a little bit faster.
0290 #ifdef AI_BUILD_BIG_ENDIAN
0291     typedef StreamWriter<true>  StreamWriterLE;
0292     typedef StreamWriter<false> StreamWriterBE;
0293 #else
0294     typedef StreamWriter<true>  StreamWriterBE;
0295     typedef StreamWriter<false> StreamWriterLE;
0296 #endif
0297 
0298 // `dynamic` StreamWriter. The byte order of the input data is specified in the
0299 // c'tor. This involves runtime branching and might be a little bit slower.
0300 typedef StreamWriter<true,true> StreamWriterAny;
0301 
0302 } // end namespace Assimp
0303 
0304 #endif // !! AI_STREAMWriter_H_INCLUDED