![]() |
|
|||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |