From fa1710b5678ff24e16e246550c5e3542bb185749 Mon Sep 17 00:00:00 2001 From: osa Date: Wed, 24 Jul 2019 14:30:53 +0300 Subject: [PATCH] 0030830: Point Cloud Rendering - use temporary buffer to read lines from .pts and .ptx files Add Standard_ReadLineBuffer - auxiliary tool for buffered reading of lines from input stream. --- src/Standard/FILES | 1 + src/Standard/Standard_ReadLineBuffer.hxx | 198 +++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 src/Standard/Standard_ReadLineBuffer.hxx diff --git a/src/Standard/FILES b/src/Standard/FILES index 1199f5f973..01ca8000ee 100755 --- a/src/Standard/FILES +++ b/src/Standard/FILES @@ -77,6 +77,7 @@ Standard_PrimitiveTypes.hxx Standard_ProgramError.hxx Standard_RangeError.hxx Standard_ReadBuffer.hxx +Standard_ReadLineBuffer.hxx Standard_Real.cxx Standard_Real.hxx Standard_ShortReal.cxx diff --git a/src/Standard/Standard_ReadLineBuffer.hxx b/src/Standard/Standard_ReadLineBuffer.hxx new file mode 100644 index 0000000000..1029248d20 --- /dev/null +++ b/src/Standard/Standard_ReadLineBuffer.hxx @@ -0,0 +1,198 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Standard_ReadLineBuffer_HeaderFile +#define _Standard_ReadLineBuffer_HeaderFile + +#include +#include + +//! Auxiliary tool for buffered reading of lines from input stream. +class Standard_ReadLineBuffer +{ +public: + + //! Constructor with initialization. + //! @param theMaxBufferSizeBytes the length of buffer to read (in bytes) + Standard_ReadLineBuffer (size_t theMaxBufferSizeBytes) + : myUseReadBufferLastStr(false), + myBufferPos (0), + myBytesLastRead (0) + { + // allocate read buffer + myReadBuffer.resize (theMaxBufferSizeBytes); + } + + //! Destructor. + virtual ~Standard_ReadLineBuffer() {} + + //! Clear buffer and cached values. + void Clear() + { + myReadBufferLastStr.clear(); + myUseReadBufferLastStr = false; + myBufferPos = 0; + myBytesLastRead = 0; + } + + //! Read next line from the stream. + //! @return pointer to the line or NULL on error / end of reading buffer + //! (in case of NULL result theStream should be checked externally to identify the presence of errors). + //! Empty lines will be returned also with zero length. + //! @param theLineLength [out] - output parameter defined length of returned line. + template + const char* ReadLine (Stream_T& theStream, + size_t& theLineLength) + { + int64_t aReadData = 0; + return ReadLine (theStream, theLineLength, aReadData); + } + + //! Read next line from the stream. + //! @return pointer to the line or NULL on error / end of reading buffer + //! (in case of NULL result theStream should be checked externally to identify the presence of errors). + //! Empty lines will be returned also with zero length. + //! @param theLineLength [out] - output parameter defined length of returned line. + //! @param theReadData [out] - output parameter defined the number of elements successfully read from the stream during this call, + //! it can be zero if no data was read and the line is taken from the buffer. + template + const char* ReadLine (Stream_T& theStream, + size_t& theLineLength, + int64_t& theReadData) + { + char* aResultLine = NULL; + theLineLength = 0; + theReadData = 0; + + while (aResultLine == NULL) + { + if (myBufferPos == 0 || myBufferPos >= (myBytesLastRead)) + { + // read new chunk from the stream + if (!readStream (theStream, myReadBuffer.size(), myBytesLastRead)) + { + // error during file reading + break; + } + + theReadData = myBytesLastRead; + + if (myBytesLastRead > 0) + { + myBufferPos = 0; + } + else + { + // end of the stream + if (myUseReadBufferLastStr) + { + theLineLength = myReadBufferLastStr.size(); + aResultLine = myReadBufferLastStr.data(); + myUseReadBufferLastStr = false; + } + break; + } + } + + size_t aStartLinePos = myBufferPos; + bool isEndLineFound = false; + + // read next line from myReadBuffer + while (myBufferPos < myBytesLastRead) + { + if (myReadBuffer[myBufferPos] == '\n') + { + isEndLineFound = true; + } + + ++myBufferPos; + + if (isEndLineFound) break; + } + + if (isEndLineFound) + { + if (myUseReadBufferLastStr) + { + // append current string to the last "unfinished" string of the previous chunk + myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos); + myUseReadBufferLastStr = false; + theLineLength = myReadBufferLastStr.size(); + aResultLine = myReadBufferLastStr.data(); + } + else + { + if (myReadBufferLastStr.size() > 0) + { + myReadBufferLastStr.clear(); + } + theLineLength = myBufferPos - aStartLinePos; + aResultLine = myReadBuffer.data() + aStartLinePos; + } + // make string null terminated by replacing '\n' or '\r' (before '\n') symbol to null character. + if (theLineLength > 1 && aResultLine[theLineLength - 2] == '\r') + { + aResultLine[theLineLength - 2] = '\0'; + theLineLength -= 2; + } + else + { + aResultLine[theLineLength - 1] = '\0'; + theLineLength -= 1; + } + } + else + { + // save "unfinished" part of string to additional buffer + if (aStartLinePos != myBufferPos) + { + myReadBufferLastStr = std::vector(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos); + myUseReadBufferLastStr = true; + } + } + } + return aResultLine; + } + +protected: + + //! Read from stl stream. + //! @return true if reading was finished without errors. + bool readStream (std::istream& theStream, + size_t theLen, + size_t& theReadLen) + { + theReadLen = theStream.read (myReadBuffer.data(), theLen).gcount(); + return !theStream.bad(); + } + + //! Read from FILE stream. + //! @return true if reading was finished without errors. + bool readStream (FILE* theStream, + size_t theLen, + size_t& theReadLen) + { + theReadLen = ::fread (myReadBuffer.data(), 1, theLen, theStream); + return ::ferror (theStream) == 0; + } + +protected: + + std::vector myReadBuffer; //!< Temp read buffer + std::vector myReadBufferLastStr; //!< Part of last string of myReadBuffer + bool myUseReadBufferLastStr; //!< Flag to use myReadBufferLastStr during next line reading + size_t myBufferPos; //!< Current position in myReadBuffer + size_t myBytesLastRead; //!< The number of characters that were read last time from myReadBuffer. +}; + +#endif // _Standard_ReadLineBuffer_HeaderFile