Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
LineEndings.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
6#include "Stroika/Foundation/Containers/Common.h"
8
10
11 /*
12 ********************************************************************************
13 ********************************** GetEOL **************************************
14 ********************************************************************************
15 */
16 template <IPossibleCharacterRepresentation T>
17 [[deprecated ("Since Stroika v3.0d7 - use kEOL")]] inline
18#if __cpp_constexpr >= 202211L
19 constexpr
20#endif
21 const T*
22 GetEOL ()
23 {
24 // note queer syntax for strings so works with many character types, including Characters::Character
25 if constexpr (qStroika_Foundation_Common_Platform_Windows) {
26 static constexpr T kResult_[] = {'\r', '\n', '\0'}; // "\r\n"
27 return kResult_;
28 }
29 else if constexpr (qStroika_Foundation_Common_Platform_POSIX) {
30 static constexpr T kResult_[] = {'\n', '\0'}; // "\n"
31 return kResult_;
32 }
33 else {
35 }
36 }
37
38 /*
39 ********************************************************************************
40 ************************ AssureHasLineTermination ******************************
41 ********************************************************************************
42 */
43 template <typename CHAR>
44 void AssureHasLineTermination (basic_string<CHAR>* text)
45 {
46 RequireNotNull (text);
47 const CHAR* eol = kEOL<CHAR>;
48 size_t eolLen = CString::Length (eol);
49 size_t len = text->length ();
50 bool already = false;
51 if (eolLen < len) {
52 already = (text->compare (len - eolLen, eolLen, eol) == 0);
53 }
54 if (not already) {
55 text->append (eol);
56 }
57 }
58
59 /*
60 ********************************************************************************
61 *********************************** CRLFToNL ***********************************
62 ********************************************************************************
63 */
64 template <typename TCHAR>
65 size_t CRLFToNL (const TCHAR* srcText, size_t srcTextBytes, TCHAR* outBuf, [[maybe_unused]] size_t outBufSize)
66 {
67 RequireNotNull (srcText);
68 RequireNotNull (outBuf);
69 TCHAR* outPtr = outBuf;
70 for (size_t i = 1; i <= srcTextBytes; ++i) {
71 TCHAR c = srcText[i - 1];
72 if (c == '\r') {
73 // peek at next character - and if we have a CRLF sequence - then advance pointer
74 // (so we skip next NL) and pretend this was an NL..
75 // NB: we DON'T map plain CR to NL - to get that to happen - use NormalizeTextToNL()
76 if (i < srcTextBytes and srcText[i] == '\n') {
77 c = '\n';
78 ++i;
79 }
80 }
81 *outPtr++ = c;
82 }
83 size_t nBytes = outPtr - outBuf;
84 Assert (nBytes <= outBufSize);
85 return nBytes;
86 }
87 template <typename TCHAR>
88 inline void CRLFToNL (basic_string<TCHAR>* text)
89 {
90 size_t origLen = text->length ();
91 size_t newLen = CRLFToNL (Containers::Start (*text), origLen, Containers::Start (*text), origLen);
92 Assert (newLen <= origLen);
93 text->resize (newLen);
94 }
95 template <typename TCHAR>
96 inline basic_string<TCHAR> CRLFToNL (const basic_string<TCHAR>& text)
97 {
98 basic_string<TCHAR> r = text;
99 CRLFToNL (&r);
100 return r;
101 }
102
103 /*
104 ********************************************************************************
105 *********************************** NLToCRLF ***********************************
106 ********************************************************************************
107 */
108 template <typename TCHAR>
109 size_t NLToCRLF (const TCHAR* srcText, size_t srcTextBytes, TCHAR* outBuf, [[maybe_unused]] size_t outBufSize)
110 {
111 Require (srcText != outBuf); // though we support this for the others - its too hard
112 // in this case for the PC...
113 TCHAR* outPtr = outBuf;
114 bool prevCharWasCR = false;
115 for (const TCHAR* i = srcText; i < srcText + srcTextBytes; ++i) {
116 Assert (outPtr < outBuf + outBufSize);
117 // prefix all LF with 'CR' so 'CRLF', unless it already WAS CRLF
118 if (*i == '\n' and not prevCharWasCR) {
119 *outPtr++ = '\r';
120 }
121 Assert (outPtr < outBuf + outBufSize);
122 *outPtr++ = *i;
123 prevCharWasCR == (*i == '\r');
124 }
125 size_t nBytes = outPtr - outBuf;
126 Assert (nBytes <= outBufSize);
127 return (nBytes);
128 }
129 template <typename TCHAR>
130 inline basic_string<TCHAR> NLToCRLF (const basic_string<TCHAR>& text)
131 {
132 size_t outBufSize = (text.length () + 1) * 2;
133 Memory::StackBuffer<TCHAR> outBuf{Memory::eUninitialized, outBufSize};
134 size_t newSize = NLToCRLF<TCHAR> (Containers::Start (text), text.length (), outBuf.begin (), outBufSize);
135 Assert (newSize < outBufSize);
136 outBuf[newSize] = '\0';
137 return basic_string<TCHAR> (outBuf);
138 }
139
140 /*
141 ********************************************************************************
142 ********************************* NativeToNL ***********************************
143 ********************************************************************************
144 */
145 template <typename TCHAR>
146 size_t NativeToNL (const TCHAR* srcText, size_t srcTextBytes, TCHAR* outBuf, [[maybe_unused]] size_t outBufSize)
147 {
148 TCHAR* outPtr = outBuf;
149 for (size_t i = 1; i <= srcTextBytes; ++i) {
150#if qStroika_Foundation_Common_Platform_MacOS
151 TCHAR c = (srcText[i - 1] == '\r') ? '\n' : srcText[i - 1];
152#elif qStroika_Foundation_Common_Platform_Windows
153 TCHAR c = srcText[i - 1];
154 if (c == '\r') {
155 // peek at next character - and if we have a CRLF sequence - then advance pointer
156 // (so we skip next NL) and pretend this was an NL..
157 // NB: we DON'T map plain CR to NL - to get that to happen - use Led_NormalizeTextToNL()
158 if (i < srcTextBytes and srcText[i] == '\n') {
159 c = '\n';
160 ++i;
161 }
162 }
163#else
164 TCHAR c = srcText[i - 1];
165#endif
166 *outPtr++ = c;
167 }
168 size_t nBytes = outPtr - outBuf;
169 Assert (nBytes <= outBufSize);
170 return nBytes;
171 }
172 template <typename TCHAR>
173 inline basic_string<TCHAR> NativeToNL (const basic_string<TCHAR>& text)
174 {
175 size_t outBufSize = text.length () + 1;
176 Memory::StackBuffer<TCHAR> outBuf{Memory::eUninitialized, outBufSize};
177 size_t newSize = NativeToNL<TCHAR> (Containers::Start (text), text.length (), outBuf.begin (), outBufSize);
178 Assert (newSize < outBufSize);
179 outBuf[newSize] = '\0';
180 return basic_string<TCHAR> (outBuf);
181 }
182
183 /*
184 ********************************************************************************
185 ********************************* NLToNative ***********************************
186 ********************************************************************************
187 */
188 template <typename TCHAR>
189 size_t NLToNative (const TCHAR* srcText, size_t srcTextBytes, TCHAR* outBuf, [[maybe_unused]] size_t outBufSize)
190 {
191 Require (srcText != outBuf); // though we support this for the others - its too hard
192 // in this case for the PC...
193 TCHAR* outPtr = outBuf;
194 for (size_t i = 1; i <= srcTextBytes; ++i) {
195 Assert (outPtr < outBuf + outBufSize);
196#if defined(macintosh)
197 TCHAR c = (srcText[i - 1] == '\n') ? '\r' : srcText[i - 1];
198#elif qStroika_Foundation_Common_Platform_Windows
199 TCHAR c = srcText[i - 1];
200 if (c == '\n') {
201 *outPtr++ = '\r';
202 }
203#else
204 // Unix
205 TCHAR c = srcText[i - 1];
206#endif
207 *outPtr++ = c;
208 }
209 size_t nBytes = outPtr - outBuf;
210 Assert (nBytes <= outBufSize);
211 return nBytes;
212 }
213 template <typename TCHAR>
214 inline basic_string<TCHAR> NLToNative (const basic_string<TCHAR>& text)
215 {
216 size_t outBufSize = (text.length () + 1) * 2;
217 Memory::StackBuffer<TCHAR> outBuf{Memory::eUninitialized, outBufSize};
218 size_t newSize = NLToNative<TCHAR> (Containers::Start (text), text.length (), outBuf.begin (), outBufSize);
219 Assert (newSize < outBufSize);
220 outBuf[newSize] = '\0';
221 return basic_string<TCHAR> (outBuf);
222 }
223
224 /*
225 ********************************************************************************
226 ************************** NormalizeTextToNL ***********************************
227 ********************************************************************************
228 */
229 template <typename TCHAR>
230 size_t NormalizeTextToNL (const TCHAR* srcText, size_t srcTextBytes, TCHAR* outBuf, [[maybe_unused]] size_t outBufSize)
231 {
232 Require (srcTextBytes == 0 or srcText != nullptr);
233 Require (outBufSize == 0 or outBuf != nullptr);
234 // Require outBufSize big enough to hold the converted srcTextBytes (best to just make sizes the same)
235
236 // NB: We DO Support the case where srcText == outBuf!!!!
237 TCHAR* outPtr = outBuf;
238 for (size_t i = 0; i < srcTextBytes; ++i) {
239 TCHAR c = srcText[i];
240 if (c == '\r') {
241 // peek at next character - and if we have a CRLF sequence - then advance pointer
242 // (so we skip next NL) and pretend this was an NL..
243 if (i + 1 < srcTextBytes and srcText[i + 1] == '\n') {
244 ++i;
245 }
246 c = '\n';
247 }
248 Assert (outPtr < outBuf + outBufSize);
249 *outPtr++ = c;
250 }
251 size_t nBytes = outPtr - outBuf;
252 Assert (nBytes <= outBufSize);
253 return nBytes;
254 }
255 template <typename TCHAR>
256 inline void NormalizeTextToNL (basic_string<TCHAR>* text)
257 {
258 RequireNotNull (text);
259 size_t origLen = text->length ();
260 size_t newLen = NormalizeTextToNL (static_cast<const TCHAR*> (Containers::Start (*text)), origLen,
261 static_cast<TCHAR*> (Containers::Start (*text)), origLen);
262 Assert (newLen <= origLen);
263 text->resize (newLen);
264 }
265 template <typename TCHAR>
266 inline basic_string<TCHAR> NormalizeTextToNL (const basic_string<TCHAR>& text)
267 {
268 basic_string<TCHAR> r = text;
270 return r;
271 }
272
273}
#define AssertNotImplemented()
Definition Assertions.h:401
#define RequireNotNull(p)
Definition Assertions.h:347
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
size_t NormalizeTextToNL(const TCHAR *srcText, size_t srcTextBytes, TCHAR *outBuf, size_t outBufSize)
size_t NLToCRLF(const TCHAR *srcText, size_t srcTextBytes, TCHAR *outBuf, size_t outBufSize)
Convert the argument srcText buffer from NL format line endings, to CRLF format line endings....
size_t CRLFToNL(const TCHAR *srcText, size_t srcTextBytes, TCHAR *outBuf, size_t outBufSize)
Convert the argument srcText buffer from CRLF format line endings, to NL format line endings.
CONTAINER::value_type * Start(CONTAINER &c)
For a contiguous container (such as a vector or basic_string) - find the pointer to the start of the ...