File indexing completed on 2025-02-21 09:30:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
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
0061
0062 template <class T>
0063 class IOStreamBuffer {
0064 public:
0065
0066 IOStreamBuffer(size_t cache = 4096 * 4096);
0067
0068
0069 ~IOStreamBuffer() = default;
0070
0071
0072
0073
0074 bool open(IOStream *stream);
0075
0076
0077
0078 bool close();
0079
0080
0081
0082 size_t size() const;
0083
0084
0085
0086 size_t cacheSize() const;
0087
0088
0089
0090 bool readNextBlock();
0091
0092
0093
0094 size_t getNumBlocks() const;
0095
0096
0097
0098 size_t getCurrentBlockIndex() const;
0099
0100
0101
0102 size_t getFilePos() const;
0103
0104
0105
0106
0107 bool getNextDataLine(std::vector<T> &buffer, T continuationToken);
0108
0109
0110
0111
0112 bool getNextLine(std::vector<T> &buffer);
0113
0114
0115
0116
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
0146 if (nullptr != m_stream) {
0147 return false;
0148 }
0149
0150
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
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
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
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 }
0348
0349 #endif