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