Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*
0002 Open Asset Import Library (assimp)
0003 ----------------------------------------------------------------------
0004 
0005 Copyright (c) 2006-2024, assimp team
0006 
0007 All rights reserved.
0008 
0009 Redistribution and use of this software in source and binary forms,
0010 with or without modification, are permitted provided that the
0011 following conditions are met:
0012 
0013 * Redistributions of source code must retain the above
0014 copyright notice, this list of conditions and the
0015 following disclaimer.
0016 
0017 * Redistributions in binary form must reproduce the above
0018 copyright notice, this list of conditions and the
0019 following disclaimer in the documentation and/or other
0020 materials provided with the distribution.
0021 
0022 * Neither the name of the assimp team, nor the names of its
0023 contributors may be used to endorse or promote products
0024 derived from this software without specific prior
0025 written permission of the assimp team.
0026 
0027 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0028 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0029 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0030 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0031 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0032 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0033 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0034 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0035 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0036 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0037 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0038 
0039 ----------------------------------------------------------------------
0040 */
0041 
0042 #pragma once
0043 #ifndef AI_IOSTREAMBUFFER_H_INC
0044 #define AI_IOSTREAMBUFFER_H_INC
0045 
0046 #ifdef __GNUC__
0047 #pragma GCC system_header
0048 #endif
0049 
0050 #include <assimp/ParsingUtils.h>
0051 #include <assimp/types.h>
0052 #include <assimp/IOStream.hpp>
0053 
0054 #include <vector>
0055 
0056 namespace Assimp {
0057 
0058 // ---------------------------------------------------------------------------
0059 /**
0060  *  Implementation of a cached stream buffer.
0061  */
0062 template <class T>
0063 class IOStreamBuffer {
0064 public:
0065     /// @brief  The class constructor.
0066     IOStreamBuffer(size_t cache = 4096 * 4096);
0067 
0068     /// @brief  The class destructor.
0069     ~IOStreamBuffer() = default;
0070 
0071     /// @brief  Will open the cached access for a given stream.
0072     /// @param  stream      The stream to cache.
0073     /// @return true if successful.
0074     bool open(IOStream *stream);
0075 
0076     /// @brief  Will close the cached access.
0077     /// @return true if successful.
0078     bool close();
0079 
0080     /// @brief  Returns the file-size.
0081     /// @return The file-size.
0082     size_t size() const;
0083 
0084     /// @brief  Returns the cache size.
0085     /// @return The cache size.
0086     size_t cacheSize() const;
0087 
0088     /// @brief  Will read the next block.
0089     /// @return true if successful.
0090     bool readNextBlock();
0091 
0092     /// @brief  Returns the number of blocks to read.
0093     /// @return The number of blocks.
0094     size_t getNumBlocks() const;
0095 
0096     /// @brief  Returns the current block index.
0097     /// @return The current block index.
0098     size_t getCurrentBlockIndex() const;
0099 
0100     /// @brief  Returns the current file pos.
0101     /// @return The current file pos.
0102     size_t getFilePos() const;
0103 
0104     /// @brief  Will read the next line.
0105     /// @param  buffer      The buffer for the next line.
0106     /// @return true if successful.
0107     bool getNextDataLine(std::vector<T> &buffer, T continuationToken);
0108 
0109     /// @brief  Will read the next line ascii or binary end line char.
0110     /// @param  buffer      The buffer for the next line.
0111     /// @return true if successful.
0112     bool getNextLine(std::vector<T> &buffer);
0113 
0114     /// @brief  Will read the next block.
0115     /// @param  buffer      The buffer for the next block.
0116     /// @return true if successful.
0117     bool getNextBlock(std::vector<T> &buffer);
0118 
0119 private:
0120     IOStream *m_stream;
0121     size_t m_filesize;
0122     size_t m_cacheSize;
0123     size_t m_numBlocks;
0124     size_t m_blockIdx;
0125     std::vector<T> m_cache;
0126     size_t m_cachePos;
0127     size_t m_filePos;
0128 };
0129 
0130 template <class T>
0131 AI_FORCE_INLINE IOStreamBuffer<T>::IOStreamBuffer(size_t cache) :
0132         m_stream(nullptr),
0133         m_filesize(0),
0134         m_cacheSize(cache),
0135         m_numBlocks(0),
0136         m_blockIdx(0),
0137         m_cachePos(0),
0138         m_filePos(0) {
0139     m_cache.resize(cache);
0140     std::fill(m_cache.begin(), m_cache.end(), '\n');
0141 }
0142 
0143 template <class T>
0144 AI_FORCE_INLINE bool IOStreamBuffer<T>::open(IOStream *stream) {
0145     //  file still opened!
0146     if (nullptr != m_stream) {
0147         return false;
0148     }
0149 
0150     //  Invalid stream pointer
0151     if (nullptr == stream) {
0152         return false;
0153     }
0154 
0155     m_stream = stream;
0156     m_filesize = m_stream->FileSize();
0157     if (m_filesize == 0) {
0158         return false;
0159     }
0160     if (m_filesize < m_cacheSize) {
0161         m_cacheSize = m_filesize;
0162     }
0163 
0164     m_numBlocks = m_filesize / m_cacheSize;
0165     if ((m_filesize % m_cacheSize) > 0) {
0166         m_numBlocks++;
0167     }
0168 
0169     return true;
0170 }
0171 
0172 template <class T>
0173 AI_FORCE_INLINE bool IOStreamBuffer<T>::close() {
0174     if (nullptr == m_stream) {
0175         return false;
0176     }
0177 
0178     // init counters and state vars
0179     m_stream = nullptr;
0180     m_filesize = 0;
0181     m_numBlocks = 0;
0182     m_blockIdx = 0;
0183     m_cachePos = 0;
0184     m_filePos = 0;
0185 
0186     return true;
0187 }
0188 
0189 template <class T>
0190 AI_FORCE_INLINE
0191         size_t
0192         IOStreamBuffer<T>::size() const {
0193     return m_filesize;
0194 }
0195 
0196 template <class T>
0197 AI_FORCE_INLINE
0198         size_t
0199         IOStreamBuffer<T>::cacheSize() const {
0200     return m_cacheSize;
0201 }
0202 
0203 template <class T>
0204 AI_FORCE_INLINE bool IOStreamBuffer<T>::readNextBlock() {
0205     m_stream->Seek(m_filePos, aiOrigin_SET);
0206     size_t readLen = m_stream->Read(&m_cache[0], sizeof(T), m_cacheSize);
0207     if (readLen == 0) {
0208         return false;
0209     }
0210     if (readLen < m_cacheSize) {
0211         m_cacheSize = readLen;
0212     }
0213     m_filePos += m_cacheSize;
0214     m_cachePos = 0;
0215     m_blockIdx++;
0216 
0217     return true;
0218 }
0219 
0220 template <class T>
0221 AI_FORCE_INLINE size_t IOStreamBuffer<T>::getNumBlocks() const {
0222     return m_numBlocks;
0223 }
0224 
0225 template <class T>
0226 AI_FORCE_INLINE size_t IOStreamBuffer<T>::getCurrentBlockIndex() const {
0227     return m_blockIdx;
0228 }
0229 
0230 template <class T>
0231 AI_FORCE_INLINE size_t IOStreamBuffer<T>::getFilePos() const {
0232     return m_filePos;
0233 }
0234 
0235 template <class T>
0236 AI_FORCE_INLINE bool IOStreamBuffer<T>::getNextDataLine(std::vector<T> &buffer, T continuationToken) {
0237     buffer.resize(m_cacheSize);
0238     if (m_cachePos >= m_cacheSize || 0 == m_filePos) {
0239         if (!readNextBlock()) {
0240             return false;
0241         }
0242     }
0243 
0244     size_t i = 0;
0245     for (;;) {
0246         if (continuationToken == m_cache[m_cachePos] && IsLineEnd(m_cache[m_cachePos + 1])) {
0247             ++m_cachePos;
0248             while (m_cache[m_cachePos] != '\n') {
0249                 ++m_cachePos;
0250             }
0251             ++m_cachePos;
0252         } else if (IsLineEnd(m_cache[m_cachePos])) {
0253             break;
0254         }
0255 
0256         buffer[i] = m_cache[m_cachePos];
0257         ++m_cachePos;
0258         ++i;
0259 
0260         if(i == buffer.size()) {
0261             buffer.resize(buffer.size() * 2);
0262         }
0263 
0264         if (m_cachePos >= size()) {
0265             break;
0266         }
0267         if (m_cachePos >= m_cacheSize) {
0268             if (!readNextBlock()) {
0269                 return false;
0270             }
0271         }
0272     }
0273 
0274     buffer[i] = '\n';
0275     ++m_cachePos;
0276 
0277     return true;
0278 }
0279 
0280 static AI_FORCE_INLINE bool isEndOfCache(size_t pos, size_t cacheSize) {
0281     return (pos == cacheSize);
0282 }
0283 
0284 template <class T>
0285 AI_FORCE_INLINE bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
0286     buffer.resize(m_cacheSize);
0287     if (m_cachePos >= m_cacheSize || 0 == m_filePos) {
0288         if (!readNextBlock()) {
0289             return false;
0290         }
0291     }
0292 
0293     if (IsLineEnd(m_cache[m_cachePos])) {
0294         // skip line end
0295         while (m_cache[m_cachePos] != '\n') {
0296             ++m_cachePos;
0297         }
0298         ++m_cachePos;
0299         if (isEndOfCache(m_cachePos, m_cacheSize)) {
0300             if (!readNextBlock()) {
0301                 return false;
0302             }
0303         }
0304     }
0305 
0306     size_t i(0);
0307     while (!IsLineEnd(m_cache[m_cachePos])) {
0308         buffer[i] = m_cache[m_cachePos];
0309         ++m_cachePos;
0310         ++i;
0311 
0312         if(i == buffer.size()) {
0313             buffer.resize(buffer.size() * 2);
0314         }
0315 
0316         if (m_cachePos >= m_cacheSize) {
0317             if (!readNextBlock()) {
0318                 return false;
0319             }
0320         }
0321     }
0322     buffer[i] = '\n';
0323     while (m_cachePos < m_cacheSize && (m_cache[m_cachePos] == '\r' || m_cache[m_cachePos] == '\n')) {
0324         ++m_cachePos;
0325     }
0326 
0327     return true;
0328 }
0329 
0330 template <class T>
0331 AI_FORCE_INLINE bool IOStreamBuffer<T>::getNextBlock(std::vector<T> &buffer) {
0332     // Return the last block-value if getNextLine was used before
0333     if (0 != m_cachePos) {
0334         buffer = std::vector<T>(m_cache.begin() + m_cachePos, m_cache.end());
0335         m_cachePos = 0;
0336     } else {
0337         if (!readNextBlock()) {
0338             return false;
0339         }
0340 
0341         buffer = std::vector<T>(m_cache.begin(), m_cache.end());
0342     }
0343 
0344     return true;
0345 }
0346 
0347 } // namespace Assimp
0348 
0349 #endif // AI_IOSTREAMBUFFER_H_INC