Stroika Library 3.0d23x
 
Loading...
Searching...
No Matches
SDKString.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
5#include "Stroika/Foundation/Containers/Common.h"
6
8 [[noreturn]] void ThrowSystemErrNo ();
9 [[noreturn]] void ThrowSystemErrNo (int sysErr);
10}
11
13
14 /*
15 ********************************************************************************
16 ***************** Characters::AdjustNulTerminatedStringSpan ********************
17 ********************************************************************************
18 */
19 template <typename CHAR_T, size_t EXTENT>
20 requires (same_as<remove_cv_t<CHAR_T>, char> or same_as<remove_cv_t<CHAR_T>, SDKChar>)
21 span<CHAR_T, EXTENT> AdjustNulTerminatedStringSpan (span<CHAR_T, EXTENT> s)
22 {
23 if constexpr (same_as<CHAR_T, char>) {
24 size_t l = ::strlen (s.data ());
25 Require (s.size () > l); // typically greater by one
26 return s.subspan (0, l);
27 }
28 else if constexpr (same_as<CHAR_T, wchar_t>) {
29 size_t l = ::wcslen (s.data ());
30 Require (s.size () > l); // typically greater by one
31 return s.subspan (0, l);
32 }
33 }
34
35 /*
36 ********************************************************************************
37 ***************************** Characters::Narrow2SDK ***************************
38 ********************************************************************************
39 */
40 inline SDKString Narrow2SDK (span<const char> s)
41 {
42#if qTargetPlatformSDKUseswchar_t
43#if qStroika_Foundation_Common_Platform_Windows
44 static constexpr DWORD kFLAGS_ = MB_ERR_INVALID_CHARS;
45 int stringLength = ::MultiByteToWideChar (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), nullptr, 0);
46 if (stringLength == 0 and s.size () != 0) {
47 Execution::ThrowSystemErrNo ();
48 }
49 SDKString result;
50 result.resize (stringLength);
51 Verify (::MultiByteToWideChar (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), Containers::Start (result), stringLength) == stringLength);
52 return result;
53#else
54 AssertNotImplemented (); // nobody but windows uses wchar_t as far as I know
55#endif
56#else
57 return SDKString{s.begin (), s.end ()};
58#endif
59 }
60 inline SDKString Narrow2SDK (const string& s)
61 {
62#if qTargetPlatformSDKUseswchar_t
63 return Narrow2SDK (span{s}); // delegate work
64#else
65 return s; // short-circuit so optimizer opportunity
66#endif
67 }
68 inline SDKString Narrow2SDK (span<const char> s, AllowMissingCharacterErrorsFlag)
69 {
70#if qTargetPlatformSDKUseswchar_t
71#if qStroika_Foundation_Common_Platform_Windows
72 static constexpr DWORD kFLAGS_ = 0;
73 int stringLength = ::MultiByteToWideChar (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), nullptr, 0);
74 if (stringLength == 0 and s.size () != 0) {
75 Execution::ThrowSystemErrNo ();
76 }
77 SDKString result;
78 result.resize (stringLength);
79 Verify (::MultiByteToWideChar (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), Containers::Start (result), stringLength) == stringLength);
80 return result;
81#else
82 AssertNotImplemented (); // nobody but windows uses wchar_t as far as I know
83#endif
84#else
85 return SDKString{s.begin (), s.end ()};
86#endif
87 }
88 inline SDKString Narrow2SDK (const string& s, [[maybe_unused]] AllowMissingCharacterErrorsFlag allow)
89 {
90#if qTargetPlatformSDKUseswchar_t
91 return Narrow2SDK (span{s}, allow); // delegate work
92#else
93 return s; // short-circuit so optimizer opportunity
94#endif
95 }
96
97 /*
98 ********************************************************************************
99 **************************** Characters::NarrowSDK2Wide ************************
100 ********************************************************************************
101 */
102 inline wstring NarrowSDK2Wide (span<const char> s)
103 {
104 // No need to special case qTargetPlatformSDKUseswchar_t cuz SDK2Wide is a no-op inlinable in that case
105 return SDK2Wide (Narrow2SDK (s));
106 }
107 inline wstring NarrowSDK2Wide (const string& s)
108 {
109 return NarrowSDK2Wide (span{s});
110 }
111 inline wstring NarrowSDK2Wide (span<const char> s, AllowMissingCharacterErrorsFlag allow)
112 {
113 // No need to special case qTargetPlatformSDKUseswchar_t cuz SDK2Wide is a no-op inlinable in that case
114 return SDK2Wide (Narrow2SDK (s, allow), allow);
115 }
116 inline wstring NarrowSDK2Wide (const string& s, AllowMissingCharacterErrorsFlag allow)
117 {
118 return NarrowSDK2Wide (span{s}, allow);
119 }
120
121 /*
122 ********************************************************************************
123 ***************************** Characters::SDK2Narrow ***************************
124 ********************************************************************************
125 */
126 inline string SDK2Narrow (span<const SDKChar> s)
127 {
128#if qTargetPlatformSDKUseswchar_t
129#if qStroika_Foundation_Common_Platform_Windows
130 static constexpr DWORD kFLAGS_ = 0; // WC_ERR_INVALID_CHARS doesn't work (https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte), so must use lpUsedDefaultChar
131 int stringLength = ::WideCharToMultiByte (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), nullptr, 0, nullptr, nullptr);
132 if (stringLength == 0 and s.size () != 0) {
133 Execution::ThrowSystemErrNo ();
134 }
135 string result;
136 result.resize (stringLength);
137 BOOL usedDefaultChar{false};
138 Verify (::WideCharToMultiByte (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), Containers::Start (result), stringLength,
139 nullptr, &usedDefaultChar) == stringLength);
140 if (usedDefaultChar) {
141 Execution::ThrowSystemErrNo (ERROR_NO_UNICODE_TRANSLATION);
142 }
143 return result;
144#else
145 AssertNotImplemented (); // nobody but windows uses wchar_t as far as I know
146#endif
147#else
148 return string{s.begin (), s.end ()};
149#endif
150 }
151 inline string SDK2Narrow (const SDKString& s)
152 {
153#if qTargetPlatformSDKUseswchar_t
154 return SDK2Narrow (span{s}); // delegate work
155#else
156 return s; // short-circuit so optimizer opportunity
157#endif
158 }
159 inline string SDK2Narrow (span<const SDKChar> s, AllowMissingCharacterErrorsFlag)
160 {
161#if qTargetPlatformSDKUseswchar_t
162#if qStroika_Foundation_Common_Platform_Windows
163 static constexpr DWORD kFLAGS_ = 0; // NOTE NOT specifying WC_ERR_INVALID_CHARS so map bad/missing UNICODE characters to some system default char
164 int stringLength = ::WideCharToMultiByte (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), nullptr, 0, nullptr, nullptr);
165 if (stringLength == 0 and s.size () != 0) {
166 Execution::ThrowSystemErrNo ();
167 }
168 string result;
169 result.resize (stringLength);
170 Verify (::WideCharToMultiByte (CP_ACP, kFLAGS_, s.data (), static_cast<int> (s.size ()), Containers::Start (result), stringLength,
171 nullptr, nullptr) == stringLength);
172 return result;
173#else
175#endif
176#else
177 return string{s.begin (), s.end ()};
178#endif
179 }
180 inline string SDK2Narrow (const SDKString& s, [[maybe_unused]] AllowMissingCharacterErrorsFlag allowMissing)
181 {
182#if qTargetPlatformSDKUseswchar_t
183 return SDK2Narrow (span{s}, allowMissing); // delegate work
184#else
185 return s; // short-circuit so optimizer opportunity
186#endif
187 }
188
189 /*
190 ********************************************************************************
191 ******************************* Characters::SDK2Wide ***************************
192 ********************************************************************************
193 */
194#if qTargetPlatformSDKUseswchar_t
195 inline wstring SDK2Wide (span<const SDKChar> s)
196 {
197 return wstring{s.begin (), s.end ()};
198 }
199#endif
200 inline wstring SDK2Wide (const SDKString& s)
201 {
202#if qTargetPlatformSDKUseswchar_t
203 return s; // short-circuit so optimizer opportunity
204#else
205 return SDK2Wide (span{s}); // delegate work
206#endif
207 }
208#if qTargetPlatformSDKUseswchar_t
209 inline wstring SDK2Wide (span<const SDKChar> s, AllowMissingCharacterErrorsFlag)
210 {
211 return wstring{s.begin (), s.end ()};
212 }
213#endif
214 inline wstring SDK2Wide (const SDKString& s, [[maybe_unused]] AllowMissingCharacterErrorsFlag allow)
215 {
216#if qTargetPlatformSDKUseswchar_t
217 return s; // short-circuit so optimizer opportunity
218#else
219 return SDK2Wide (span{s}, allow); // delegate work
220#endif
221 }
222
223 /*
224 ********************************************************************************
225 ******************************* Characters::Wide2SDK ***************************
226 ********************************************************************************
227 */
228#if qTargetPlatformSDKUseswchar_t
229 inline SDKString Wide2SDK (span<const SDKChar> s)
230 {
231 return SDKString{s.begin (), s.end ()};
232 }
233#endif
234 inline SDKString Wide2SDK (const wstring& s)
235 {
236#if qTargetPlatformSDKUseswchar_t
237 return s; // short-circuit so optimizer opportunity
238#else
239 return Wide2SDK (span{s});
240#endif
241 }
242#if qTargetPlatformSDKUseswchar_t
243 inline SDKString Wide2SDK (span<const SDKChar> s, AllowMissingCharacterErrorsFlag)
244 {
245 return SDKString{s.begin (), s.end ()};
246 }
247#endif
248 inline SDKString Wide2SDK (const wstring& s, [[maybe_unused]] AllowMissingCharacterErrorsFlag allow)
249 {
250#if qTargetPlatformSDKUseswchar_t
251 return s; // short-circuit so optimizer opportunity
252#else
253 return Wide2SDK (span{s}, allow);
254#endif
255 }
256
257 /// <summary>
258 //////////////////////////// DEPRECATED BELOW.../////////////////////////////
259 /// </summary>
260
262 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
263 [[deprecated (
264 "Since Stroika v3.0d1 use String::FromNarrowSDKString (s).As<wstring> () - less efficent but this is never used")]] inline wstring
265 NarrowSDKStringToWide (const string& s)
266 {
267#ifdef CP_ACP
268 Assert (CP_ACP == 0);
269#else
270 const unsigned char CP_ACP = 0;
271#endif
272 return NarrowStringToWide (s, CP_ACP);
273 }
274 [[deprecated ("Since Stroika v3.0d1 use String (s).AsNarrowSDKString () - less efficent but this is never used")]] inline string
275 WideStringToNarrowSDKString (const wstring& ws)
276 {
277#ifdef CP_ACP
278 Assert (CP_ACP == 0);
279#else
280 const unsigned char CP_ACP = 0;
281#endif
282 return WideStringToNarrow (ws, CP_ACP);
283 }
284 [[deprecated (
285 "Since Stroika v3.0d1 use String::FromSDKString (s).AsNarrowSDKString () - less efficent but this is never used")]] inline string
286 SDKString2NarrowSDK (const SDKString& s)
287 {
288#if qTargetPlatformSDKUseswchar_t
289 return WideStringToNarrowSDKString (s);
290#else
291 return s;
292#endif
293 }
294 [[deprecated (
295 "Since Stroika v3.0d1 use String::FromNarrowSDKString (s).AsSDKString () - less efficent but this is never used")]] inline SDKString
296 NarrowSDK2SDKString (const string& s)
297 {
298#if qTargetPlatformSDKUseswchar_t
299 return NarrowSDKStringToWide (s);
300#else
301 return s;
302#endif
303 }
304 [[deprecated ("Since Stroika v3.0d1 use String{s}.AsSDKString () - less efficent but this is never used")]] inline SDKString
305 Wide2SDKString (const wstring& s)
306 {
307#if qTargetPlatformSDKUseswchar_t
308 return s;
309#else
310 return WideStringToNarrowSDKString (s);
311#endif
312 }
313 [[deprecated ("Since Stroika v3.0d1 - just use String::FromNarrowSDKString (s).AsSDKString ()")]] inline SDKString ToSDKString (const string& s)
314 {
315 return NarrowSDK2SDKString (s);
316 }
317 [[deprecated ("Since Stroika v3.0d1 - just use String(s).AsSDKString ()")]] inline SDKString ToSDKString (const wstring& s)
318 {
319 return Wide2SDKString (s);
320 }
321 DISABLE_COMPILER_MSC_WARNING_END (4996);
322 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"");
323
324}
#define AssertNotImplemented()
Definition Assertions.h:401
#define Verify(c)
Definition Assertions.h:419
wstring NarrowSDK2Wide(span< const char > s)
SDKString Wide2SDK(span< const wchar_t > s)
Definition SDKString.cpp:58
wstring SDK2Wide(span< const SDKChar > s)
conditional_t< qTargetPlatformSDKUseswchar_t, wchar_t, char > SDKChar
Definition SDKChar.h:71
basic_string< SDKChar > SDKString
Definition SDKString.h:38
SDKString Narrow2SDK(span< const char > s)
Definition SDKString.inl:40
span< CHAR_T, EXTENT > AdjustNulTerminatedStringSpan(span< CHAR_T, EXTENT > s)
often apply this adjustment to return the non-nul string prefix from a span of characters.
Definition SDKString.inl:21
string SDK2Narrow(span< const SDKChar > s)
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 ...