diff options
Diffstat (limited to 'src/3rdparty/assimp/code/IOStreamBuffer.h')
-rw-r--r-- | src/3rdparty/assimp/code/IOStreamBuffer.h | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/src/3rdparty/assimp/code/IOStreamBuffer.h b/src/3rdparty/assimp/code/IOStreamBuffer.h new file mode 100644 index 000000000..d7528de7e --- /dev/null +++ b/src/3rdparty/assimp/code/IOStreamBuffer.h @@ -0,0 +1,350 @@ +#pragma once + +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#include <assimp/types.h> +#include <assimp/IOStream.hpp> +#include "ParsingUtils.h" + +#include <vector> + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** + * Implementation of a cached stream buffer. + */ +template<class T> +class IOStreamBuffer { +public: + /// @brief The class constructor. + IOStreamBuffer( size_t cache = 4096 * 4096 ); + + /// @brief The class destructor. + ~IOStreamBuffer(); + + /// @brief Will open the cached access for a given stream. + /// @param stream The stream to cache. + /// @return true if successful. + bool open( IOStream *stream ); + + /// @brief Will close the cached access. + /// @return true if successful. + bool close(); + + /// @brief Returns the file-size. + /// @return The file-size. + size_t size() const; + + /// @brief Returns the cache size. + /// @return The cache size. + size_t cacheSize() const; + + /// @brief Will read the next block. + /// @return true if successful. + bool readNextBlock(); + + /// @brief Returns the number of blocks to read. + /// @return The number of blocks. + size_t getNumBlocks() const; + + /// @brief Returns the current block index. + /// @return The current block index. + size_t getCurrentBlockIndex() const; + + /// @brief Returns the current file pos. + /// @return The current file pos. + size_t getFilePos() const; + + /// @brief Will read the next line. + /// @param buffer The buffer for the next line. + /// @return true if successful. + bool getNextDataLine( std::vector<T> &buffer, T continuationToken ); + + /// @brief Will read the next line ascii or binary end line char. + /// @param buffer The buffer for the next line. + /// @return true if successful. + bool getNextLine(std::vector<T> &buffer); + + /// @brief Will read the next block. + /// @param buffer The buffer for the next block. + /// @return true if successful. + bool getNextBlock( std::vector<T> &buffer ); + +private: + IOStream *m_stream; + size_t m_filesize; + size_t m_cacheSize; + size_t m_numBlocks; + size_t m_blockIdx; + std::vector<T> m_cache; + size_t m_cachePos; + size_t m_filePos; +}; + +template<class T> +inline +IOStreamBuffer<T>::IOStreamBuffer( size_t cache ) +: m_stream( nullptr ) +, m_filesize( 0 ) +, m_cacheSize( cache ) +, m_numBlocks( 0 ) +, m_blockIdx( 0 ) +, m_cachePos( 0 ) +, m_filePos( 0 ) { + m_cache.resize( cache ); + std::fill( m_cache.begin(), m_cache.end(), '\n' ); +} + +template<class T> +inline +IOStreamBuffer<T>::~IOStreamBuffer() { + // empty +} + +template<class T> +inline +bool IOStreamBuffer<T>::open( IOStream *stream ) { + // file still opened! + if ( nullptr != m_stream ) { + return false; + } + + // Invalid stream pointer + if ( nullptr == stream ) { + return false; + } + + m_stream = stream; + m_filesize = m_stream->FileSize(); + if ( m_filesize == 0 ) { + return false; + } + if ( m_filesize < m_cacheSize ) { + m_cacheSize = m_filesize; + } + + m_numBlocks = m_filesize / m_cacheSize; + if ( ( m_filesize % m_cacheSize ) > 0 ) { + m_numBlocks++; + } + + return true; +} + +template<class T> +inline +bool IOStreamBuffer<T>::close() { + if ( nullptr == m_stream ) { + return false; + } + + // init counters and state vars + m_stream = nullptr; + m_filesize = 0; + m_numBlocks = 0; + m_blockIdx = 0; + m_cachePos = 0; + m_filePos = 0; + + return true; +} + +template<class T> +inline +size_t IOStreamBuffer<T>::size() const { + return m_filesize; +} + +template<class T> +inline +size_t IOStreamBuffer<T>::cacheSize() const { + return m_cacheSize; +} + +template<class T> +inline +bool IOStreamBuffer<T>::readNextBlock() { + m_stream->Seek( m_filePos, aiOrigin_SET ); + size_t readLen = m_stream->Read( &m_cache[ 0 ], sizeof( T ), m_cacheSize ); + if ( readLen == 0 ) { + return false; + } + if ( readLen < m_cacheSize ) { + m_cacheSize = readLen; + } + m_filePos += m_cacheSize; + m_cachePos = 0; + m_blockIdx++; + + return true; +} + +template<class T> +inline +size_t IOStreamBuffer<T>::getNumBlocks() const { + return m_numBlocks; +} + +template<class T> +inline +size_t IOStreamBuffer<T>::getCurrentBlockIndex() const { + return m_blockIdx; +} + +template<class T> +inline +size_t IOStreamBuffer<T>::getFilePos() const { + return m_filePos; +} + +template<class T> +inline +bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) { + buffer.resize( m_cacheSize ); + if ( m_cachePos == m_cacheSize || 0 == m_filePos ) { + if ( !readNextBlock() ) { + return false; + } + } + + bool continuationFound( false ), endOfDataLine( false ); + size_t i = 0; + while ( !endOfDataLine ) { + if ( continuationToken == m_cache[ m_cachePos ] ) { + continuationFound = true; + ++m_cachePos; + } + if ( IsLineEnd( m_cache[ m_cachePos ] ) ) { + if ( !continuationFound ) { + // the end of the data line + break; + } else { + // skip line end + while ( m_cache[m_cachePos] != '\n') { + ++m_cachePos; + } + ++m_cachePos; + continuationFound = false; + } + } + + buffer[ i ] = m_cache[ m_cachePos ]; + m_cachePos++; + i++; + if ( m_cachePos >= m_cacheSize ) { + if ( !readNextBlock() ) { + return false; + } + } + } + + buffer[ i ] = '\n'; + m_cachePos++; + + return true; +} + +static +inline +bool isEndOfCache( size_t pos, size_t cacheSize ) { + return ( pos == cacheSize ); +} + +template<class T> +inline +bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) { + buffer.resize(m_cacheSize); + if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) { + if (!readNextBlock()) { + return false; + } + } + + if (IsLineEnd(m_cache[m_cachePos])) { + // skip line end + while (m_cache[m_cachePos] != '\n') { + ++m_cachePos; + } + ++m_cachePos; + if ( isEndOfCache( m_cachePos, m_cacheSize ) ) { + if ( !readNextBlock() ) { + return false; + } + } + } + + size_t i = 0; + while (!IsLineEnd(m_cache[ m_cachePos ])) { + buffer[i] = m_cache[ m_cachePos ]; + m_cachePos++; + i++; + if (m_cachePos >= m_cacheSize) { + if (!readNextBlock()) { + return false; + } + } + } + buffer[i] = '\n'; + m_cachePos++; + + return true; +} + +template<class T> +inline +bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) { + //just return the last blockvalue if getNextLine was used before + if ( m_cachePos != 0) { + buffer = std::vector<T>(m_cache.begin() + m_cachePos, m_cache.end()); + m_cachePos = 0; + } + else { + if ( !readNextBlock() ) + return false; + + buffer = std::vector<T>(m_cache.begin(), m_cache.end()); + } + return true; +} + +} // !ns Assimp |