Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:59

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 
0026   //! Constructor with initialization.
0027   Standard_ReadBuffer (int64_t theDataLen,
0028                        size_t  theChunkLen,
0029                        bool theIsPartialPayload = false)
0030   : myBufferPtr(NULL),
0031     myBufferEnd(NULL),
0032     myDataLen  (0),
0033     myDataRead (0),
0034     myChunkLen (0),
0035     myNbChunks (0),
0036     myBufferLen(0)
0037   {
0038     Init (theDataLen, theChunkLen, theIsPartialPayload);
0039   }
0040 
0041   //! Initialize the buffer.
0042   //! @param theDataLen  [in] the full length of input data to read from stream.
0043   //! @param theChunkLen [in] the length of single chunk to read
0044   //! @param theIsPartialPayload [in] when FALSE, theDataLen will be automatically aligned to the multiple of theChunkLen;
0045   //!                                 when TRUE, last chunk will be read from stream exactly till theDataLen
0046   //!                                 allowing portion of chunk to be uninitialized (useful for interleaved data)
0047   void Init (int64_t theDataLen,
0048              size_t  theChunkLen,
0049              bool theIsPartialPayload = false)
0050   {
0051     myDataRead  = 0;
0052     if (theIsPartialPayload)
0053     {
0054       myDataLen = theDataLen;
0055     }
0056     else
0057     {
0058       myDataLen = theDataLen - theDataLen % int64_t(theChunkLen);
0059     }
0060     myChunkLen  = theChunkLen;
0061     myNbChunks  = sizeof(myBuffer) / theChunkLen;
0062     myBufferLen = theChunkLen * myNbChunks;
0063 
0064     myBufferEnd = myBuffer + sizeof(myBuffer);
0065     myBufferPtr = myBuffer + sizeof(myBuffer);
0066     memset (myBuffer, 0, sizeof(myBuffer));
0067 
0068     if (theChunkLen > sizeof(myBuffer))
0069     {
0070       Standard_ProgramError::Raise ("Internal error - chunk size is greater then preallocated buffer");
0071     }
0072   }
0073 
0074   //! Return TRUE if amount of read bytes is equal to requested length of entire data.
0075   bool IsDone() const
0076   {
0077     return myDataRead == myDataLen;
0078   }
0079 
0080   //! Read next chunk.
0081   //! @return pointer to the chunk or NULL on error / end of reading buffer
0082   template<typename Chunk_T, typename Stream_T>
0083   Chunk_T* ReadChunk (Stream_T& theStream)
0084   {
0085     return reinterpret_cast<Chunk_T*> (readRawDataChunk (theStream));
0086   }
0087 
0088   //! Read next chunk.
0089   //! @return pointer to the chunk or NULL on error / end of reading buffer
0090   template<typename Stream_T>
0091   char* ReadDataChunk (Stream_T& theStream)
0092   {
0093     return readRawDataChunk (theStream);
0094   }
0095 
0096 private:
0097 
0098   //! Read next chunk.
0099   //! @return pointer to the chunk or NULL on error / end of reading buffer
0100   template<typename Stream_T>
0101   char* readRawDataChunk (Stream_T& theStream)
0102   {
0103     if (myBufferPtr == NULL)
0104     {
0105       return NULL;
0106     }
0107 
0108     myBufferPtr += myChunkLen;
0109     if (myBufferPtr < myBufferEnd)
0110     {
0111       return myBufferPtr;
0112     }
0113 
0114     const int64_t aDataLeft = myDataLen - myDataRead;
0115     if (aDataLeft <= 0) // myDataLen is normally multiple of myChunkLen, but can be smaller in interleaved data
0116     {
0117       myBufferPtr = NULL;
0118       return NULL;
0119     }
0120 
0121     const size_t aDataToRead = int64_t(myBufferLen) > aDataLeft ? size_t(aDataLeft) : myBufferLen;
0122     if (!readStream (theStream, aDataToRead))
0123     {
0124       myBufferPtr = NULL;
0125       return NULL;
0126     }
0127 
0128     myBufferPtr = myBuffer;
0129     myBufferEnd = myBuffer + aDataToRead;
0130     myDataRead += aDataToRead;
0131     return myBufferPtr;
0132   }
0133 
0134   //! Read from stl stream.
0135   bool readStream (std::istream& theStream,
0136                    size_t theLen)
0137   {
0138     theStream.read (myBuffer, theLen);
0139     return theStream.good();
0140   }
0141 
0142   //! Read from FILE stream.
0143   bool readStream (FILE* theStream,
0144                    size_t theLen)
0145   {
0146     return ::fread (myBuffer, 1, theLen, theStream) == theLen;
0147   }
0148 
0149 private:
0150 
0151   char        myBuffer[4096]; //!< data cache
0152   char*       myBufferPtr;    //!< current position within the buffer
0153   const char* myBufferEnd;    //!< end of the buffer
0154   int64_t     myDataLen;      //!< length of entire data to read
0155   int64_t     myDataRead;     //!< amount of data already processed
0156   size_t      myChunkLen;     //!< length of single chunk that caller would like to read (e.g. iterator increment)
0157   size_t      myNbChunks;     //!< number of cached chunks
0158   size_t      myBufferLen;    //!< effective length of the buffer to be read at once (multiple of chunk length)
0159 
0160 };
0161 
0162 #endif // _Standard_ReadBuffer_HeaderFile