diff options
Diffstat (limited to 'libs/assimp/include/assimp/IOStreamBuffer.h')
-rw-r--r-- | libs/assimp/include/assimp/IOStreamBuffer.h | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/libs/assimp/include/assimp/IOStreamBuffer.h b/libs/assimp/include/assimp/IOStreamBuffer.h new file mode 100644 index 0000000..09ca1c9 --- /dev/null +++ b/libs/assimp/include/assimp/IOStreamBuffer.h @@ -0,0 +1,352 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2022, 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. + +---------------------------------------------------------------------- +*/ + +#pragma once +#ifndef AI_IOSTREAMBUFFER_H_INC +#define AI_IOSTREAMBUFFER_H_INC + +#ifdef __GNUC__ +#pragma GCC system_header +#endif + +#include <assimp/ParsingUtils.h> +#include <assimp/types.h> +#include <assimp/IOStream.hpp> + +#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> +AI_FORCE_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> +AI_FORCE_INLINE IOStreamBuffer<T>::~IOStreamBuffer() { + // empty +} + +template <class T> +AI_FORCE_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> +AI_FORCE_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> +AI_FORCE_INLINE + size_t + IOStreamBuffer<T>::size() const { + return m_filesize; +} + +template <class T> +AI_FORCE_INLINE + size_t + IOStreamBuffer<T>::cacheSize() const { + return m_cacheSize; +} + +template <class T> +AI_FORCE_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> +AI_FORCE_INLINE size_t IOStreamBuffer<T>::getNumBlocks() const { + return m_numBlocks; +} + +template <class T> +AI_FORCE_INLINE size_t IOStreamBuffer<T>::getCurrentBlockIndex() const { + return m_blockIdx; +} + +template <class T> +AI_FORCE_INLINE size_t IOStreamBuffer<T>::getFilePos() const { + return m_filePos; +} + +template <class T> +AI_FORCE_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; + } + } + + size_t i = 0; + for (;;) { + if (continuationToken == m_cache[m_cachePos] && IsLineEnd(m_cache[m_cachePos + 1])) { + ++m_cachePos; + while (m_cache[m_cachePos] != '\n') { + ++m_cachePos; + } + ++m_cachePos; + } else if (IsLineEnd(m_cache[m_cachePos])) { + break; + } + + buffer[i] = m_cache[m_cachePos]; + ++m_cachePos; + ++i; + + if(i == buffer.size()) { + buffer.resize(buffer.size() * 2); + } + + if (m_cachePos >= size()) { + break; + } + if (m_cachePos >= m_cacheSize) { + if (!readNextBlock()) { + return false; + } + } + } + + buffer[i] = '\n'; + ++m_cachePos; + + return true; +} + +static AI_FORCE_INLINE bool isEndOfCache(size_t pos, size_t cacheSize) { + return (pos == cacheSize); +} + +template <class T> +AI_FORCE_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(i == buffer.size()) { + buffer.resize(buffer.size() * 2); + } + + if (m_cachePos >= m_cacheSize) { + if (!readNextBlock()) { + return false; + } + } + } + buffer[i] = '\n'; + ++m_cachePos; + + return true; +} + +template <class T> +AI_FORCE_INLINE bool IOStreamBuffer<T>::getNextBlock(std::vector<T> &buffer) { + // Return the last block-value if getNextLine was used before + if (0 != m_cachePos) { + 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; +} + +} // namespace Assimp + +#endif // AI_IOSTREAMBUFFER_H_INC |