4 * @brief Implementation of LineInfo class.
21 , m_dwRevisionNumber(0)
25 LineInfo::LineInfo(const tchar_t* pszLine, size_t nLength)
31 , m_dwRevisionNumber(0)
33 Create(pszLine, nLength);
36 LineInfo::LineInfo(const LineInfo& li)
37 : m_pcLine(new tchar_t[li.m_nMax])
38 , m_nLength(li.m_nLength)
40 , m_nEolChars(li.m_nEolChars)
41 , m_dwFlags(li.m_dwFlags)
42 , m_dwRevisionNumber(li.m_dwRevisionNumber)
44 memcpy (m_pcLine, li.m_pcLine, sizeof (tchar_t) * m_nMax);
47 LineInfo::LineInfo(LineInfo&& li) noexcept
51 *this = std::move(li);
59 LineInfo& LineInfo::operator=(const LineInfo& li)
61 m_pcLine = new tchar_t[li.m_nMax];
62 m_nLength = li.m_nLength;
64 m_nEolChars = li.m_nEolChars;
65 m_dwFlags = li.m_dwFlags;
66 m_dwRevisionNumber = li.m_dwRevisionNumber;
67 memcpy (m_pcLine, li.m_pcLine, sizeof (tchar_t) * m_nMax);
71 LineInfo& LineInfo::operator=(LineInfo&& li) noexcept
73 m_pcLine = li.m_pcLine;
74 m_nLength = li.m_nLength;
76 m_nEolChars = li.m_nEolChars;
77 m_dwFlags = li.m_dwFlags;
78 m_dwRevisionNumber = li.m_dwRevisionNumber;
79 li.m_pcLine = nullptr;
86 * Frees buffer, sets members to initial values.
88 void LineInfo::Clear()
90 if (m_pcLine != nullptr)
98 m_dwRevisionNumber = 0;
103 * @brief Free reserved memory.
104 * Frees reserved memory, but does not clear flags.
106 void LineInfo::FreeBuffer()
108 if (m_pcLine != nullptr)
119 * @brief Create a line.
120 * @param [in] pszLine Line data.
121 * @param [in] nLength Line length.
123 void LineInfo::Create(const tchar_t* pszLine, size_t nLength)
131 assert (nLength <= INT_MAX); // assert "positive int"
133 m_nMax = ALIGN_BUF_SIZE (m_nLength + 1);
134 assert (m_nMax < INT_MAX);
135 assert (m_nMax >= m_nLength + 1);
136 if (m_pcLine != nullptr)
138 m_pcLine = new tchar_t[m_nMax];
139 memset(m_pcLine, 0, m_nMax * sizeof(tchar_t));
140 const size_t dwLen = sizeof (tchar_t) * m_nLength;
141 memcpy (m_pcLine, pszLine, dwLen);
142 m_pcLine[m_nLength] = '\0';
145 if (nLength > 1 && IsDosEol(&pszLine[nLength - 2]))
147 else if (IsEol(pszLine[nLength - 1]))
149 assert (static_cast<size_t>(nEols) <= m_nLength);
155 * @brief Create an empty line.
157 void LineInfo::CreateEmpty()
161 m_nMax = ALIGN_BUF_SIZE (m_nLength + 1);
163 m_pcLine = new tchar_t[m_nMax];
164 memset (m_pcLine, 0, m_nMax * sizeof(tchar_t));
168 * @brief Append a text to the line.
169 * @param [in] pszChars String to append to the line.
170 * @param [in] nLength Length of the string to append.
172 void LineInfo::Append(const tchar_t* pszChars, size_t nLength, bool bDetectEol)
174 assert (nLength <= INT_MAX); // assert "positive int"
175 size_t nBufNeeded = m_nLength + m_nEolChars + nLength + 1;
176 if (nBufNeeded > m_nMax)
178 m_nMax = ALIGN_BUF_SIZE (nBufNeeded);
179 assert (m_nMax < INT_MAX);
180 assert (m_nMax >= m_nLength + nLength);
181 tchar_t *pcNewBuf = new tchar_t[m_nMax];
182 if (FullLength() > 0)
183 memcpy (pcNewBuf, m_pcLine, sizeof (tchar_t) * (FullLength() + 1));
188 memcpy (m_pcLine + m_nLength + m_nEolChars, pszChars, sizeof (tchar_t) * nLength);
189 m_nLength += nLength + m_nEolChars;
190 m_pcLine[m_nLength] = '\0';
195 // Did line gain eol ? (We asserted above that it had none at start)
196 if (nLength > 1 && IsDosEol(&m_pcLine[m_nLength - 2]))
200 else if (LineInfo::IsEol(m_pcLine[m_nLength - 1]))
204 assert (static_cast<size_t>(m_nEolChars) <= m_nLength);
205 m_nLength -= m_nEolChars;
206 assert (m_nLength + m_nEolChars <= m_nMax);
210 * @brief Get line's EOL bytes.
211 * @return EOL bytes, or `nullptr` if no EOL bytes.
213 const tchar_t* LineInfo::GetEol() const
216 return &m_pcLine[Length()];
222 * @brief Change line's EOL.
223 * @param [in] lpEOL New EOL bytes.
224 * @return true if succeeded, false if failed (nothing to change).
226 bool LineInfo::ChangeEol(const tchar_t* lpEOL)
228 const int nNewEolChars = (int) tc::tcslen(lpEOL);
230 // Check if we really are changing EOL.
231 if (nNewEolChars == m_nEolChars)
232 if (tc::tcscmp(m_pcLine + Length(), lpEOL) == 0)
235 size_t nBufNeeded = m_nLength + nNewEolChars+1;
236 assert (nBufNeeded < INT_MAX);
237 if (nBufNeeded > m_nMax)
239 m_nMax = ALIGN_BUF_SIZE (nBufNeeded);
240 assert (m_nMax >= nBufNeeded);
241 tchar_t *pcNewBuf = new tchar_t[m_nMax];
242 if (FullLength() > 0)
243 memcpy (pcNewBuf, m_pcLine, sizeof (tchar_t) * (FullLength() + 1));
248 // copy also the 0 to zero-terminate the line
249 memcpy (m_pcLine + m_nLength, lpEOL, sizeof (tchar_t) * (nNewEolChars + 1));
250 m_nEolChars = nNewEolChars;
255 * @brief Delete part of the line.
256 * @param [in] nStartChar Start position for removal.
257 * @param [in] nEndChar End position for removal.
259 void LineInfo::Delete(size_t nStartChar, size_t nEndChar)
261 if (nEndChar < Length() || m_nEolChars)
263 // preserve characters after deleted range by shifting up
264 memcpy (m_pcLine + nStartChar, m_pcLine + nEndChar,
265 sizeof (tchar_t) * (FullLength() - nEndChar));
267 size_t nDelete = (nEndChar - nStartChar);
268 if (nDelete <= m_nLength)
270 m_nLength -= nDelete;
274 assert( (m_nLength + m_nEolChars) <= nDelete );
275 nDelete -= m_nLength;
277 m_nEolChars -= static_cast<int>(nDelete);
279 assert (m_nLength <= INT_MAX); // assert "positive int"
280 if (m_pcLine != nullptr)
281 m_pcLine[FullLength()] = '\0';
285 * @brief Delete line contents from given index to the end.
286 * @param [in] Index of first character to remove.
288 void LineInfo::DeleteEnd(size_t nStartChar)
290 m_nLength = nStartChar;
291 assert (m_nLength <= INT_MAX); // assert "positive int"
292 if (m_pcLine != nullptr)
293 m_pcLine[nStartChar] = 0;
298 * @brief Remove EOL from line.
300 void LineInfo::RemoveEol()
304 m_pcLine[m_nLength] = '\0';