Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (c) 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_ReadLineBuffer_HeaderFile
0015 #define _Standard_ReadLineBuffer_HeaderFile
0016 
0017 #include <iostream>
0018 #include <vector>
0019 
0020 //! Auxiliary tool for buffered reading of lines from input stream.
0021 class Standard_ReadLineBuffer
0022 {
0023 public:
0024 
0025   //! Constructor with initialization.
0026   //! @param theMaxBufferSizeBytes the length of buffer to read (in bytes)
0027   Standard_ReadLineBuffer (size_t theMaxBufferSizeBytes)
0028   : myUseReadBufferLastStr(false),
0029     myIsMultilineMode     (false),
0030     myToPutGapInMultiline (true),
0031     myBufferPos           (0),
0032     myBytesLastRead       (0)
0033   {
0034     // allocate read buffer
0035     myReadBuffer.resize (theMaxBufferSizeBytes);
0036   }
0037 
0038   //! Destructor.
0039   virtual ~Standard_ReadLineBuffer() {}
0040 
0041   //! Clear buffer and cached values.
0042   void Clear()
0043   {
0044     myReadBufferLastStr.clear();
0045     myUseReadBufferLastStr = false;
0046     myIsMultilineMode = false;
0047     myToPutGapInMultiline = true;
0048     myBufferPos = 0;
0049     myBytesLastRead = 0;
0050   }
0051 
0052   //! Read next line from the stream.
0053   //! @return pointer to the line or NULL on error / end of reading buffer
0054   //!         (in case of NULL result theStream should be checked externally to identify the presence of errors).
0055   //!          Empty lines will be returned also with zero length.
0056   //! @param theStream [inout] - the stream to read from.
0057   //! @param theLineLength [out] - output parameter defined length of returned line.
0058   template<typename Stream_T>
0059   const char* ReadLine (Stream_T& theStream,
0060                         size_t& theLineLength)
0061   {
0062     int64_t aReadData = 0;
0063     return ReadLine (theStream, theLineLength, aReadData);
0064   }
0065 
0066   //! Read next line from the stream.
0067   //! @return pointer to the line or NULL on error / end of reading buffer
0068   //!         (in case of NULL result theStream should be checked externally to identify the presence of errors).
0069   //!          Empty lines will be returned also with zero length.
0070   //! @param theStream [inout] - the stream to read from.
0071   //! @param theLineLength [out] - output parameter defined length of returned line.
0072   //! @param theReadData   [out] - output parameter defined the number of elements successfully read from the stream during this call,
0073   //!                              it can be zero if no data was read and the line is taken from the buffer.
0074   template<typename Stream_T>
0075   const char* ReadLine (Stream_T& theStream,
0076                         size_t& theLineLength,
0077                         int64_t& theReadData)
0078   {
0079     char* aResultLine = NULL;
0080     bool isMultiline = false;
0081     theLineLength = 0;
0082     theReadData = 0;
0083 
0084     while (aResultLine == NULL)
0085     {
0086       if (myBufferPos == 0 || myBufferPos >= (myBytesLastRead))
0087       {
0088         // read new chunk from the stream
0089         if (!readStream (theStream, myReadBuffer.size(), myBytesLastRead))
0090         {
0091           // error during file reading
0092           break;
0093         }
0094 
0095         theReadData = myBytesLastRead;
0096 
0097         if (myBytesLastRead > 0)
0098         {
0099           myBufferPos = 0;
0100         }
0101         else
0102         {
0103           // end of the stream
0104           if (myUseReadBufferLastStr)
0105           {
0106             theLineLength = myReadBufferLastStr.size();
0107             aResultLine = &myReadBufferLastStr.front();
0108             myUseReadBufferLastStr = false;
0109           }
0110           break;
0111         }
0112       }
0113 
0114       size_t aStartLinePos = myBufferPos;
0115       bool isEndLineFound = false;
0116 
0117       // read next line from myReadBuffer
0118       while (myBufferPos < myBytesLastRead)
0119       {
0120         if (myIsMultilineMode
0121          && myReadBuffer[myBufferPos] == '\\')
0122         {
0123           // multi-line syntax
0124           if (myBufferPos + 1 == myBytesLastRead
0125            || (myBufferPos + 2 == myBytesLastRead
0126             && myReadBuffer[myBufferPos + 1] == '\r'))
0127           {
0128             isMultiline = true;
0129             if (myToPutGapInMultiline)
0130             {
0131               myReadBuffer[myBufferPos] = ' ';
0132               if (myBufferPos + 1 != myBytesLastRead)
0133               {
0134                 myReadBuffer[myBufferPos + 1] = ' ';
0135               }
0136             }
0137           }
0138           else if (myReadBuffer[myBufferPos + 1] == '\n'
0139                  ||(myReadBuffer[myBufferPos + 1] == '\r'
0140                  && myReadBuffer[myBufferPos + 2] == '\n'))
0141           {
0142             size_t aBufferPos = myBufferPos;
0143             myBufferPos = aBufferPos + (myReadBuffer[aBufferPos + 1] == '\r' ? 2 : 1);
0144             if (myToPutGapInMultiline)
0145             {
0146               myReadBuffer[aBufferPos] = ' ';
0147               ++aBufferPos;
0148             }
0149 
0150             if (myUseReadBufferLastStr)
0151             {
0152               myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + aBufferPos);
0153             }
0154             else
0155             {
0156               myReadBufferLastStr = std::vector<char>(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + aBufferPos);
0157               myUseReadBufferLastStr = true;
0158             }
0159 
0160             aStartLinePos = myBufferPos + 1;
0161           }
0162         }
0163         else if (myReadBuffer[myBufferPos] == '\n')
0164         {
0165           if (!isMultiline)
0166           {
0167             isEndLineFound = true;
0168           }
0169           else if (myBufferPos == 1 && myReadBuffer[0] == '\r')
0170           {
0171             myReadBufferLastStr.erase (myReadBufferLastStr.end() - 1);
0172             aStartLinePos += 2;
0173             isMultiline = false;
0174           }
0175           else if (myBufferPos == 0)
0176           {
0177             aStartLinePos += 1;
0178             if (myReadBufferLastStr[myReadBufferLastStr.size() - 1] == '\\')
0179             {
0180               myReadBufferLastStr.erase (myReadBufferLastStr.end() - 1);
0181             }
0182             else
0183             {
0184               myReadBufferLastStr.erase (myReadBufferLastStr.end() - 2, myReadBufferLastStr.end());
0185             }
0186             isMultiline = false;
0187           }
0188         }
0189 
0190         ++myBufferPos;
0191 
0192         if (isEndLineFound) break;
0193       }
0194 
0195       if (isEndLineFound)
0196       {
0197         if (myUseReadBufferLastStr)
0198         {
0199           // append current string to the last "unfinished" string of the previous chunk
0200           myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
0201           myUseReadBufferLastStr = false;
0202           theLineLength = myReadBufferLastStr.size();
0203           aResultLine = &myReadBufferLastStr.front();
0204         }
0205         else
0206         {
0207           if (myReadBufferLastStr.size() > 0)
0208           {
0209             myReadBufferLastStr.clear();
0210           }
0211           theLineLength = myBufferPos - aStartLinePos;
0212           aResultLine = &myReadBuffer.front() + aStartLinePos;
0213         }
0214         // make string null terminated by replacing '\n' or '\r' (before '\n') symbol to null character.
0215         if (theLineLength > 1 && aResultLine[theLineLength - 2] == '\r')
0216         {
0217           aResultLine[theLineLength - 2] = '\0';
0218           theLineLength -= 2;
0219         }
0220         else
0221         {
0222           aResultLine[theLineLength - 1] = '\0';
0223           theLineLength -= 1;
0224         }
0225       }
0226       else
0227       {
0228         // save "unfinished" part of string to additional buffer
0229         if (aStartLinePos != myBufferPos)
0230         {
0231           if (myUseReadBufferLastStr)
0232           {
0233             myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
0234           }
0235           else
0236           {
0237             myReadBufferLastStr = std::vector<char>(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
0238             myUseReadBufferLastStr = true;
0239           }
0240         }
0241       }
0242     }
0243     return aResultLine;
0244   }
0245 
0246   //! Returns TRUE when the Multiline Mode is on; FALSE by default.
0247   //! Multiline modes joins several lines in file having \ at the end of line:
0248   //! @code
0249   //!   Line starts here, \ // line continuation character without this comment
0250   //!   continues \         // line continuation character without this comment
0251   //!   and ends.
0252   //! @endcode
0253   bool IsMultilineMode() const { return myIsMultilineMode; }
0254 
0255   //! Put gap space while merging lines within multiline syntax, so that the following sample:
0256   //! @code
0257   //! 1/2/3\      // line continuation character without this comment
0258   //! 4/5/6
0259   //! @endcode
0260   //! Will become "1/2/3 4/5/6" when flag is TRUE, and "1/2/35/5/6" otherwise.
0261   bool ToPutGapInMultiline() const { return myToPutGapInMultiline; }
0262 
0263   //! Sets or unsets the multi-line mode.
0264   //! @param theMultilineMode [in] multiline mode flag
0265   //! @param theToPutGap      [in] put gap space while connecting lines (no gap otherwise)
0266   void SetMultilineMode (bool theMultilineMode,
0267                          bool theToPutGap = true)
0268   {
0269     myIsMultilineMode     = theMultilineMode;
0270     myToPutGapInMultiline = theToPutGap;
0271   }
0272 
0273 protected:
0274 
0275   //! Read from stl stream.
0276   //! @return true if reading was finished without errors.
0277   bool readStream (std::istream& theStream,
0278                    size_t theLen,
0279                    size_t& theReadLen)
0280   {
0281     theReadLen = (size_t )theStream.read (&myReadBuffer.front(), theLen).gcount();
0282     return !theStream.bad();
0283   }
0284 
0285   //! Read from FILE stream.
0286   //! @return true if reading was finished without errors.
0287   bool readStream (FILE* theStream,
0288                    size_t theLen,
0289                    size_t& theReadLen)
0290   {
0291     theReadLen = ::fread (&myReadBuffer.front(), 1, theLen, theStream);
0292     return ::ferror (theStream) == 0;
0293   }
0294 
0295 protected:
0296 
0297   std::vector<char> myReadBuffer;           //!< Temp read buffer
0298   std::vector<char> myReadBufferLastStr;    //!< Part of last string of myReadBuffer
0299   bool              myUseReadBufferLastStr; //!< Flag to use myReadBufferLastStr during next line reading
0300   bool              myIsMultilineMode;      //!< Flag to process of the special multi-line case at the end of the line
0301   bool              myToPutGapInMultiline;  //!< Flag to put gap space while joining lines in multi-line syntax
0302   size_t            myBufferPos;            //!< Current position in myReadBuffer
0303   size_t            myBytesLastRead;        //!< The number of characters that were read last time from myReadBuffer.
0304 };
0305 
0306 #endif // _Standard_ReadLineBuffer_HeaderFile