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