1 // Copyright (c) 2019 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #ifndef _Standard_ReadLineBuffer_HeaderFile
15 #define _Standard_ReadLineBuffer_HeaderFile
20 //! Auxiliary tool for buffered reading of lines from input stream.
21 class Standard_ReadLineBuffer
25 //! Constructor with initialization.
26 //! @param theMaxBufferSizeBytes the length of buffer to read (in bytes)
27 Standard_ReadLineBuffer (size_t theMaxBufferSizeBytes)
28 : myUseReadBufferLastStr(false),
32 // allocate read buffer
33 myReadBuffer.resize (theMaxBufferSizeBytes);
37 virtual ~Standard_ReadLineBuffer() {}
39 //! Clear buffer and cached values.
42 myReadBufferLastStr.clear();
43 myUseReadBufferLastStr = false;
48 //! Read next line from the stream.
49 //! @return pointer to the line or NULL on error / end of reading buffer
50 //! (in case of NULL result theStream should be checked externally to identify the presence of errors).
51 //! Empty lines will be returned also with zero length.
52 //! @param theLineLength [out] - output parameter defined length of returned line.
53 template<typename Stream_T>
54 const char* ReadLine (Stream_T& theStream,
55 size_t& theLineLength)
57 int64_t aReadData = 0;
58 return ReadLine (theStream, theLineLength, aReadData);
61 //! Read next line from the stream.
62 //! @return pointer to the line or NULL on error / end of reading buffer
63 //! (in case of NULL result theStream should be checked externally to identify the presence of errors).
64 //! Empty lines will be returned also with zero length.
65 //! @param theLineLength [out] - output parameter defined length of returned line.
66 //! @param theReadData [out] - output parameter defined the number of elements successfully read from the stream during this call,
67 //! it can be zero if no data was read and the line is taken from the buffer.
68 template<typename Stream_T>
69 const char* ReadLine (Stream_T& theStream,
70 size_t& theLineLength,
73 char* aResultLine = NULL;
77 while (aResultLine == NULL)
79 if (myBufferPos == 0 || myBufferPos >= (myBytesLastRead))
81 // read new chunk from the stream
82 if (!readStream (theStream, myReadBuffer.size(), myBytesLastRead))
84 // error during file reading
88 theReadData = myBytesLastRead;
90 if (myBytesLastRead > 0)
97 if (myUseReadBufferLastStr)
99 theLineLength = myReadBufferLastStr.size();
100 aResultLine = myReadBufferLastStr.data();
101 myUseReadBufferLastStr = false;
107 size_t aStartLinePos = myBufferPos;
108 bool isEndLineFound = false;
110 // read next line from myReadBuffer
111 while (myBufferPos < myBytesLastRead)
113 if (myReadBuffer[myBufferPos] == '\n')
115 isEndLineFound = true;
120 if (isEndLineFound) break;
125 if (myUseReadBufferLastStr)
127 // append current string to the last "unfinished" string of the previous chunk
128 myReadBufferLastStr.insert (myReadBufferLastStr.end(), myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
129 myUseReadBufferLastStr = false;
130 theLineLength = myReadBufferLastStr.size();
131 aResultLine = myReadBufferLastStr.data();
135 if (myReadBufferLastStr.size() > 0)
137 myReadBufferLastStr.clear();
139 theLineLength = myBufferPos - aStartLinePos;
140 aResultLine = myReadBuffer.data() + aStartLinePos;
142 // make string null terminated by replacing '\n' or '\r' (before '\n') symbol to null character.
143 if (theLineLength > 1 && aResultLine[theLineLength - 2] == '\r')
145 aResultLine[theLineLength - 2] = '\0';
150 aResultLine[theLineLength - 1] = '\0';
156 // save "unfinished" part of string to additional buffer
157 if (aStartLinePos != myBufferPos)
159 myReadBufferLastStr = std::vector<char>(myReadBuffer.begin() + aStartLinePos, myReadBuffer.begin() + myBufferPos);
160 myUseReadBufferLastStr = true;
169 //! Read from stl stream.
170 //! @return true if reading was finished without errors.
171 bool readStream (std::istream& theStream,
175 theReadLen = (size_t )theStream.read (myReadBuffer.data(), theLen).gcount();
176 return !theStream.bad();
179 //! Read from FILE stream.
180 //! @return true if reading was finished without errors.
181 bool readStream (FILE* theStream,
185 theReadLen = ::fread (myReadBuffer.data(), 1, theLen, theStream);
186 return ::ferror (theStream) == 0;
191 std::vector<char> myReadBuffer; //!< Temp read buffer
192 std::vector<char> myReadBufferLastStr; //!< Part of last string of myReadBuffer
193 bool myUseReadBufferLastStr; //!< Flag to use myReadBufferLastStr during next line reading
194 size_t myBufferPos; //!< Current position in myReadBuffer
195 size_t myBytesLastRead; //!< The number of characters that were read last time from myReadBuffer.
198 #endif // _Standard_ReadLineBuffer_HeaderFile