Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:21:32

0001 // Copyright (c) 2017-2019 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement..
0013 
0014 #ifndef _Standard_ReadBuffer_HeaderFile
0015 #define _Standard_ReadBuffer_HeaderFile
0016 
0017 #include <Standard_ProgramError.hxx>
0018 
0019 #include <iostream>
0020 
0021 //! Auxiliary tool for buffered reading from input stream within chunks of constant size.
0022 class Standard_ReadBuffer
0023 {
0024 public:
0025   //! Constructor with initialization.
0026   Standard_ReadBuffer(int64_t theDataLen, size_t theChunkLen, bool theIsPartialPayload = false)
0027       : myBufferPtr(nullptr),
0028         myBufferEnd(nullptr),
0029         myDataLen(0),
0030         myDataRead(0),
0031         myChunkLen(0),
0032         myNbChunks(0),
0033         myBufferLen(0)
0034   {
0035     Init(theDataLen, theChunkLen, theIsPartialPayload);
0036   }
0037 
0038   //! Initialize the buffer.
0039   //! @param[in] theDataLen   the full length of input data to read from stream.
0040   //! @param[in] theChunkLen  the length of single chunk to read
0041   //! @param[in] theIsPartialPayload  when FALSE, theDataLen will be automatically aligned to the
0042   //! multiple of theChunkLen;
0043   //!                                 when TRUE, last chunk will be read from stream exactly till
0044   //!                                 theDataLen allowing portion of chunk to be uninitialized
0045   //!                                 (useful for interleaved data)
0046   void Init(int64_t theDataLen, size_t theChunkLen, bool theIsPartialPayload = false)
0047   {
0048     myDataRead = 0;
0049     if (theIsPartialPayload)
0050     {
0051       myDataLen = theDataLen;
0052     }
0053     else
0054     {
0055       myDataLen = theDataLen - theDataLen % int64_t(theChunkLen);
0056     }
0057     myChunkLen  = theChunkLen;
0058     myNbChunks  = sizeof(myBuffer) / theChunkLen;
0059     myBufferLen = theChunkLen * myNbChunks;
0060 
0061     myBufferEnd = myBuffer + sizeof(myBuffer);
0062     myBufferPtr = myBuffer + sizeof(myBuffer);
0063     memset(myBuffer, 0, sizeof(myBuffer));
0064 
0065     if (theChunkLen > sizeof(myBuffer))
0066     {
0067       throw Standard_ProgramError(
0068         "Internal error - chunk size is greater then preallocated buffer");
0069     }
0070   }
0071 
0072   //! Return TRUE if amount of read bytes is equal to requested length of entire data.
0073   bool IsDone() const { return myDataRead == myDataLen; }
0074 
0075   //! Read next chunk.
0076   //! @return pointer to the chunk or NULL on error / end of reading buffer
0077   template <typename Chunk_T, typename Stream_T>
0078   Chunk_T* ReadChunk(Stream_T& theStream)
0079   {
0080     return reinterpret_cast<Chunk_T*>(readRawDataChunk(theStream));
0081   }
0082 
0083   //! Read next chunk.
0084   //! @return pointer to the chunk or NULL on error / end of reading buffer
0085   template <typename Stream_T>
0086   char* ReadDataChunk(Stream_T& theStream)
0087   {
0088     return readRawDataChunk(theStream);
0089   }
0090 
0091 private:
0092   //! Read next chunk.
0093   //! @return pointer to the chunk or NULL on error / end of reading buffer
0094   template <typename Stream_T>
0095   char* readRawDataChunk(Stream_T& theStream)
0096   {
0097     if (myBufferPtr == nullptr)
0098     {
0099       return nullptr;
0100     }
0101 
0102     myBufferPtr += myChunkLen;
0103     if (myBufferPtr < myBufferEnd)
0104     {
0105       return myBufferPtr;
0106     }
0107 
0108     const int64_t aDataLeft = myDataLen - myDataRead;
0109     if (aDataLeft <= 0) // myDataLen is normally multiple of myChunkLen, but can be smaller in
0110                         // interleaved data
0111     {
0112       myBufferPtr = nullptr;
0113       return nullptr;
0114     }
0115 
0116     const size_t aDataToRead = int64_t(myBufferLen) > aDataLeft ? size_t(aDataLeft) : myBufferLen;
0117     if (!readStream(theStream, aDataToRead))
0118     {
0119       myBufferPtr = nullptr;
0120       return nullptr;
0121     }
0122 
0123     myBufferPtr = myBuffer;
0124     myBufferEnd = myBuffer + aDataToRead;
0125     myDataRead += aDataToRead;
0126     return myBufferPtr;
0127   }
0128 
0129   //! Read from stl stream.
0130   bool readStream(std::istream& theStream, size_t theLen)
0131   {
0132     theStream.read(myBuffer, theLen);
0133     return theStream.good();
0134   }
0135 
0136   //! Read from FILE stream.
0137   bool readStream(FILE* theStream, size_t theLen)
0138   {
0139     return ::fread(myBuffer, 1, theLen, theStream) == theLen;
0140   }
0141 
0142 private:
0143   char        myBuffer[4096]; //!< data cache
0144   char*       myBufferPtr;    //!< current position within the buffer
0145   const char* myBufferEnd;    //!< end of the buffer
0146   int64_t     myDataLen;      //!< length of entire data to read
0147   int64_t     myDataRead;     //!< amount of data already processed
0148   // clang-format off
0149   size_t      myChunkLen;     //!< length of single chunk that caller would like to read (e.g. iterator increment)
0150   size_t      myNbChunks;     //!< number of cached chunks
0151   size_t      myBufferLen;    //!< effective length of the buffer to be read at once (multiple of chunk length)
0152   // clang-format on
0153 };
0154 
0155 #endif // _Standard_ReadBuffer_HeaderFile