4#include "Stroika/Foundation/StroikaPreComp.h"
11#if qCompilerAndStdLib_vswprintf_errantDependencyOnLocale_Buggy
16#if qCompilerAndStdLib_vswprintf_errantDependencyOnLocale_Buggy
20#include "Stroika/Foundation/Math/Common.h"
27using namespace Stroika::Foundation::Characters::CString;
34string Characters::CString::FormatV (
const char* format, va_list argsList)
42 va_copy (argListCopy, argsList);
44#if __STDC_WANT_SECURE_LIB__
45 while (::vsnprintf_s (msgBuf.data (), msgBuf.GetSize (), msgBuf.GetSize () - 1, format, argListCopy) < 0) {
46 msgBuf.GrowToSize_uninitialized (msgBuf.GetSize () * 2);
48 va_copy (argListCopy, argsList);
51 while (vsnprintf (msgBuf.data (), msgBuf.GetSize (), format, argListCopy) < 0) {
52 msgBuf.GrowToSize_uninitialized (msgBuf.GetSize () * 2);
54 va_copy (argListCopy, argsList);
58 Assert (::strlen (msgBuf.data ()) < msgBuf.GetSize ());
59 return string{msgBuf.data ()};
62u8string Characters::CString::FormatV (
const char8_t* format, va_list argsList)
70 va_copy (argListCopy, argsList);
72#if __STDC_WANT_SECURE_LIB__
73 while (::vsnprintf_s (
reinterpret_cast<char*
> (msgBuf.data ()), msgBuf.GetSize (), msgBuf.GetSize () - 1,
74 reinterpret_cast<const char*
> (format), argListCopy) < 0) {
75 msgBuf.GrowToSize_uninitialized (msgBuf.GetSize () * 2);
77 va_copy (argListCopy, argsList);
80 while (vsnprintf (
reinterpret_cast<char*
> (msgBuf.data ()), msgBuf.GetSize (),
reinterpret_cast<const char*
> (format), argListCopy) < 0) {
81 msgBuf.GrowToSize_uninitialized (msgBuf.GetSize () * 2);
83 va_copy (argListCopy, argsList);
87 Assert (::strlen (
reinterpret_cast<char*
> (msgBuf.data ())) < msgBuf.GetSize ());
88 return u8string{msgBuf.data ()};
92#if qCompilerAndStdLib_arm_asan_FaultStackUseAfterScope_Buggy
93Stroika_Foundation_Debug_ATTRIBUTE_NO_SANITIZE_ADDRESS
95 wstring Characters::CString::FormatV (
const wchar_t* format, va_list argsList)
99 const wchar_t* useFormat = format;
100 wchar_t newFormat[5 * 1024];
102 size_t origFormatLen = ::wcslen (format);
103 Require (origFormatLen < std::size (newFormat) / 2);
105 bool lookingAtFmtCvt =
false;
106 size_t newFormatIdx = 0;
107 for (
size_t i = 0; i < origFormatLen; ++i) {
108 if (lookingAtFmtCvt) {
111 lookingAtFmtCvt =
false;
114 newFormat[newFormatIdx] =
'l';
121 if (isdigit (format[i])) {
125 lookingAtFmtCvt =
false;
131 if (format[i] ==
'%') {
132 lookingAtFmtCvt =
true;
135 newFormat[newFormatIdx] = format[i];
138 Assert (newFormatIdx >= origFormatLen);
139 if (newFormatIdx > origFormatLen) {
140 newFormat[newFormatIdx] =
'\0';
141 useFormat = newFormat;
149 va_copy (argListCopy, argsList);
151#if qCompilerAndStdLib_vswprintf_errantDependencyOnLocale_Buggy
152 locale_t tmpLocale{};
153 locale_t prevLocale{};
154 [[maybe_unused]]
auto&& cleanup = Execution::Finally ([&tmpLocale, &prevLocale] ()
noexcept {
155 if (prevLocale !=
nullptr) {
156 ::uselocale (prevLocale);
158 if (tmpLocale !=
nullptr) {
159 ::freelocale (tmpLocale);
166 while (::vswprintf (msgBuf.data (), msgBuf.GetSize (), useFormat, argListCopy) < 0) {
167#if qCompilerAndStdLib_vswprintf_errantDependencyOnLocale_Buggy
168 if (errno == EILSEQ and tmpLocale ==
nullptr) {
169 tmpLocale = ::newlocale (LC_CTYPE,
"en_US.UTF-8", NULL);
170 prevLocale = ::uselocale (tmpLocale);
174 msgBuf.GrowToSize_uninitialized (msgBuf.GetSize () * 2);
175 va_end (argListCopy);
176 va_copy (argListCopy, argsList);
178 va_end (argListCopy);
179 Assert (::wcslen (msgBuf.data ()) < msgBuf.GetSize ());
180 return wstring{msgBuf.data ()};
182DISABLE_COMPILER_MSC_WARNING_END (6262)
189string Characters::CString::Format (const
char* format, ...)
192 va_start (argsList, format);
193 string tmp = FormatV (format, argsList);
198u8string Characters::CString::Format (
const char8_t* format, ...)
201 va_start (argsList, format);
202 u8string tmp = FormatV (format, argsList);
207wstring Characters::CString::Format (
const wchar_t* format, ...)
210 va_start (argsList, format);
211 wstring tmp = FormatV (format, argsList);
222 template <
typename STRING>
223 inline STRING LimitLength_HLPR_ (
const STRING& str,
size_t maxLen,
bool keepLeft,
const STRING& kELIPSIS)
225 if (str.length () <= maxLen) {
228 size_t useLen = maxLen;
229 if (useLen > kELIPSIS.length ()) {
230 useLen -= kELIPSIS.length ();
236 return str.substr (0, useLen) + kELIPSIS;
239 return kELIPSIS + str.substr (str.length () - useLen);
243string Characters::CString::LimitLength (
const string& str,
size_t maxLen,
bool keepLeft)
245 return LimitLength_HLPR_<string> (str, maxLen, keepLeft,
"...");
248wstring Characters::CString::LimitLength (
const wstring& str,
size_t maxLen,
bool keepLeft)
250 return LimitLength_HLPR_<wstring> (str, maxLen, keepLeft, L
"...");
259 template <
typename STRING>
260 inline STRING StripTrailingCharIfAny_HLPR_ (
const STRING& str,
typename STRING::value_type c)
262 if (str.size () > 0 and str[str.size () - 1] == c) {
264 tmp.erase (tmp.size () - 1);
271string Characters::CString::StripTrailingCharIfAny (
const string& s,
char c)
273 return StripTrailingCharIfAny_HLPR_ (s, c);
276wstring Characters::CString::StripTrailingCharIfAny (
const wstring& s,
wchar_t c)
278 return StripTrailingCharIfAny_HLPR_ (s, c);
286unsigned int Characters::CString::HexString2Int (
const string& s)
288 unsigned long l = strtoul (s.c_str (),
nullptr, 16);
289 if (l >= numeric_limits<unsigned int>::max ()) {
290 return numeric_limits<unsigned int>::max ();
295unsigned int Characters::CString::HexString2Int (
const wchar_t* s)
298 unsigned long l = wcstoul (s,
nullptr, 16);
299 if (l >= numeric_limits<unsigned int>::max ()) {
300 return numeric_limits<unsigned int>::max ();
305unsigned int Characters::CString::HexString2Int (
const wstring& s)
307 unsigned long l = wcstoul (s.c_str (),
nullptr, 16);
308 if (l >= numeric_limits<unsigned int>::max ()) {
309 return numeric_limits<unsigned int>::max ();
319long long int Characters::CString::Private_::String2Int_ (
const string& s)
322 return strtoll (s.c_str (),
nullptr, 10);
325long long int Characters::CString::Private_::String2Int_ (
const wstring& s)
327 unsigned long long int l = wcstoll (s.c_str (),
nullptr, 10);
336unsigned long long int Characters::CString::Private_::String2UInt_ (
const string& s)
339 unsigned long long int l = strtoull (s.c_str (),
nullptr, 10);
343unsigned long long int Characters::CString::Private_::String2UInt_ (
const wstring& s)
345 long long int l = wcstoull (s.c_str (),
nullptr, 10);
#define RequireNotNull(p)
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
DISABLE_COMPILER_MSC_WARNING_START(4996)