35#include <fmt/chrono.h>
51 bool inOverbar =
false;
54 if( aOldStr == wxT(
"~" ) )
57 newStr.reserve( aOldStr.length() );
59 for( wxString::const_iterator chIt = aOldStr.begin(); chIt != aOldStr.end(); ++chIt )
63 wxString::const_iterator lookahead = chIt + 1;
65 if( lookahead != aOldStr.end() && *lookahead ==
'~' )
67 if( ++lookahead != aOldStr.end() && *lookahead ==
'{' )
71 newStr << wxT(
"~~{}" );
80 else if( lookahead != aOldStr.end() && *lookahead ==
'{' )
95 newStr << wxT(
"~{" );
102 else if( ( *chIt ==
' ' || *chIt ==
'}' || *chIt ==
')' ) && inOverbar )
105 newStr << wxT(
"}" );
114 newStr << wxT(
"}" );
124 for( wxString::iterator ii = aString->begin(); ii != aString->end(); ++ii )
126 if( *ii == L
'\u00B4' || *ii == L
'\u2018' || *ii == L
'\u2019' )
131 if( *ii == L
'\u201C' || *ii == L
'\u201D' )
136 if( *ii == L
'\u2013' || *ii == L
'\u2014' )
150 std::vector<bool> braceStack;
152 converted.reserve( aSource.length() );
154 for( wxUniChar c: aSource )
159 converted += wxT(
"{slash}" );
160 else if( c ==
'\n' || c ==
'\r' )
161 converted += wxEmptyString;
169 converted += wxT(
"{slash}" );
171 converted += wxT(
"{backslash}" );
173 converted += wxT(
"{lt}" );
175 converted += wxT(
"{gt}" );
177 converted += wxT(
"{colon}" );
179 converted += wxT(
"{dblquote}" );
180 else if( c ==
'\n' || c ==
'\r' )
181 converted += wxEmptyString;
188 converted += wxT(
"{slash}" );
190 converted += wxT(
"{comma}" );
192 converted += wxT(
"{dblquote}" );
199 converted += wxT(
"{dblquote}" );
205 if( c >= 0x7F || c ==
'\'' || c ==
'\\' || c ==
'(' || c ==
')' )
207 unsigned int code = c;
209 snprintf( buffer,
sizeof(buffer),
"\\u%4.4X", code );
219 if( c ==
'\n' || c ==
'\r' )
220 converted += wxT(
"{return}" );
227 converted += wxT(
"{slash}" );
229 converted += wxT(
"{backslash}" );
231 converted += wxT(
"{dblquote}" );
233 converted += wxT(
"{lt}" );
235 converted += wxT(
"{gt}" );
237 converted += wxT(
"{bar}" );
239 converted += wxT(
"{colon}" );
241 converted += wxT(
"{tab}" );
242 else if( c ==
'\n' || c ==
'\r' )
243 converted += wxT(
"{return}" );
250 converted += wxT(
"{space}" );
257 converted += wxT(
"{comma}" );
258 else if( c ==
'\n' || c ==
'\r' )
259 converted += wxT(
"{return}" );
275 size_t sourceLen = aSource.length();
284 newbuf.reserve( sourceLen );
289 for(
size_t i = 0; i < sourceLen; ++i )
298 bool terminated =
false;
300 for( i = i + 1; i < sourceLen; ++i )
324 else if( prev ==
'$' || prev ==
'~' || prev ==
'^' || prev ==
'_' )
328 else if( token == wxT(
"dblquote" ) ) newbuf << wxT(
"\"" );
329 else if( token == wxT(
"quote" ) ) newbuf << wxT(
"'" );
330 else if( token == wxT(
"lt" ) ) newbuf << wxT(
"<" );
331 else if( token == wxT(
"gt" ) ) newbuf << wxT(
">" );
332 else if( token == wxT(
"backslash" ) ) newbuf << wxT(
"\\" );
333 else if( token == wxT(
"slash" ) ) newbuf << wxT(
"/" );
334 else if( token == wxT(
"bar" ) ) newbuf << wxT(
"|" );
335 else if( token == wxT(
"comma" ) ) newbuf << wxT(
"," );
336 else if( token == wxT(
"colon" ) ) newbuf << wxT(
":" );
337 else if( token == wxT(
"space" ) ) newbuf << wxT(
" " );
338 else if( token == wxT(
"dollar" ) ) newbuf << wxT(
"$" );
339 else if( token == wxT(
"tab" ) ) newbuf << wxT(
"\t" );
340 else if( token == wxT(
"return" ) ) newbuf << wxT(
"\n" );
341 else if( token == wxT(
"brace" ) ) newbuf << wxT(
"{" );
364 result.reserve( aString.length() );
366 for(
const wxString& word : words )
368 if( !result.IsEmpty() )
369 result += wxT(
" " );
371 result += word.Capitalize();
382 const char* start = aSource;
385 while( (cc = *aSource++) != 0 )
405 if( cc !=
'"' && cc !=
'\\' )
419 return aSource - start;
429 const char* start = aSource;
430 char* limit = aDest + aDestSize - 1;
433 while( (cc = *aSource++) != 0 && aDest < limit )
453 if( cc !=
'"' && cc !=
'\\' )
468 return aSource - start;
474 wxString str = aString;
477 str.Replace( wxT(
"\r\n" ), wxT(
"\r" ) );
478 str.Replace( wxT(
"\n" ), wxT(
"\r" ) );
480 std::string utf8 =
TO_UTF8( aString );
484 ret.reserve( utf8.length() + 2 );
488 for( std::string::const_iterator it = utf8.begin(); it!=utf8.end(); ++it )
496 else if( *it ==
'\\' )
517 converted.reserve( aString.length() );
519 for( wxUniChar c : aString )
522 converted += wxT(
""" );
524 converted += wxT(
"'" );
526 converted += wxT(
"&" );
528 converted += wxT(
"<" );
530 converted += wxT(
">" );
541 wxString converted = aString;
543 converted.Replace( wxS(
""" ), wxS(
"\"" ) );
544 converted.Replace( wxS(
"'" ), wxS(
"'" ) );
545 converted.Replace( wxS(
"&" ), wxS(
"&" ) );
546 converted.Replace( wxS(
"<" ), wxS(
"<" ) );
547 converted.Replace( wxS(
">" ), wxS(
">" ) );
553 wxRegEx regex(
"&#(\\d*);" );
558 wxString str = aString;
560 while( regex.Matches( str ) )
562 std::vector<wxString> matches;
563 regex.GetMatch( &start, &len );
565 result << str.Left( start );
567 unsigned long codeVal = 0;
568 wxString code = regex.GetMatch( str, 1 );
569 code.ToCULong( &codeVal );
572 result << wxUniChar( codeVal );
574 str = str.Mid( start + len );
585 wxString str = aInput;
586 wxRegEx( wxS(
"<[^>]*>" ) ).ReplaceAll( &str, wxEmptyString );
594 wxRegEx regex( wxS(
"\\b(https?|ftp|file)://([-\\w+&@#/%?=~|!:,.;]*[^.,:;<>\\s\u00b6])" ),
597 regex.ReplaceAll( &aStr,
"<a href=\"\\0\">\\0</a>" );
605 wxString tmp = aString;
607 return tmp.Trim(
true ).Trim(
false ).IsEmpty();
618 int overbarDepth = -1;
619 int superSubDepth = -1;
620 int braceNesting = 0;
622 for(
auto chIt = aString.begin(), end = aString.end(); chIt < end; ++chIt )
630 else if( *chIt ==
'^' && superSubDepth == -1 )
632 auto lookahead = chIt;
634 if( ++lookahead != end && *lookahead ==
'{' )
637 superSubDepth = braceNesting;
642 else if( *chIt ==
'_' && superSubDepth == -1 )
644 auto lookahead = chIt;
646 if( ++lookahead != end && *lookahead ==
'{' )
649 superSubDepth = braceNesting;
654 else if( *chIt ==
'~' && overbarDepth == -1 )
656 auto lookahead = chIt;
658 if( ++lookahead != end && *lookahead ==
'{' )
661 overbarDepth = braceNesting;
666 else if( *chIt ==
'{' )
670 else if( *chIt ==
'}' )
672 if( braceNesting > 0 )
675 if( braceNesting == superSubDepth )
681 if( braceNesting == overbarDepth )
697 static const char whitespace[] =
" \t\n\r\f\v";
701 while( *
text && strchr( whitespace, *
text ) )
704 char* cp =
text + strlen(
text ) - 1;
706 while( cp >=
text && strchr( whitespace, *cp ) )
714char*
GetLine( FILE* File,
char* Line,
int* LineNum,
int SizeLine )
717 if( fgets( Line, SizeLine, File ) ==
nullptr )
723 }
while( Line[0] ==
'#' || Line[0] ==
'\n' || Line[0] ==
'\r' || Line[0] == 0 );
725 strtok( Line,
"\n\r" );
736#if defined(__MINGW32__) && !defined(_UCRT)
737 return fmt::format(
"{:%FT%T}", fmt::localtime( std::time(
nullptr ) ) );
739 return fmt::format(
"{:%FT%T%z}", fmt::localtime( std::time(
nullptr ) ) );
744int StrNumCmp(
const wxString& aString1,
const wxString& aString2,
bool aIgnoreCase )
746 int nb1 = 0, nb2 = 0;
748 auto str1 = aString1.begin();
749 auto str2 = aString2.begin();
751 while( str1 != aString1.end() && str2 != aString2.end() )
753 wxUniChar c1 = *str1;
754 wxUniChar c2 = *str2;
756 if( wxIsdigit( c1 ) && wxIsdigit( c2 ) )
764 nb1 = nb1 * 10 + (int) c1 -
'0';
766 }
while( str1 != aString1.end() && wxIsdigit( *str1 ) );
771 nb2 = nb2 * 10 + (int) c2 -
'0';
773 }
while( str2 != aString2.end() && wxIsdigit( *str2 ) );
781 c1 = ( str1 != aString1.end() ) ? *str1 : wxUniChar( 0 );
782 c2 = ( str2 != aString2.end() ) ? *str2 : wxUniChar( 0 );
790 wxUniChar uc1 = wxToupper( c1 );
791 wxUniChar uc2 = wxToupper( c2 );
794 return uc1 < uc2 ? -1 : 1;
806 if( str1 != aString1.end() )
809 if( str2 != aString2.end() )
813 if( str1 == aString1.end() && str2 != aString2.end() )
817 else if( str1 != aString1.end() && str2 == aString2.end() )
827 bool case_sensitive )
829 const wxChar* cp =
nullptr;
830 const wxChar* mp =
nullptr;
831 const wxChar* wild =
nullptr;
832 const wxChar* str =
nullptr;
833 wxString _pattern, _string_to_tst;
837 wild = pattern.GetData();
838 str = string_to_tst.GetData();
843 _pattern.MakeUpper();
844 _string_to_tst = string_to_tst;
845 _string_to_tst.MakeUpper();
846 wild = _pattern.GetData();
847 str = _string_to_tst.GetData();
850 while( ( *str ) && ( *wild !=
'*' ) )
852 if( ( *wild != *str ) && ( *wild !=
'?' ) )
869 else if( ( *wild == *str ) || ( *wild ==
'?' ) )
881 while( *wild ==
'*' )
893 static const wxString modifiers( wxT(
"pnuµμmkKM" ) );
895 if( !aString.length() )
901 if( modifiers.Find( aString[ 0 ] ) >= 0 )
903 modifier = aString[ 0 ];
904 units = aString.Mid( 1 ).Trim();
909 units = aString.Mid( 0 ).Trim();
913 && !units.IsSameAs( wxT(
"F" ),
false )
914 && !units.IsSameAs( wxT(
"hz" ),
false )
915 && !units.IsSameAs( wxT(
"W" ),
false )
916 && !units.IsSameAs( wxT(
"V" ),
false )
917 && !units.IsSameAs( wxT(
"A" ),
false )
918 && !units.IsSameAs( wxT(
"H" ),
false ) )
923 if( modifier ==
'p' )
925 if( modifier ==
'n' )
927 else if( modifier ==
'u' || modifier == wxS(
"µ" )[0] || modifier == wxS(
"μ" )[0] )
929 else if( modifier ==
'm' )
931 else if( modifier ==
'k' || modifier ==
'K' )
933 else if( modifier ==
'M' )
935 else if( modifier ==
'G' )
955 value->Replace( wxS(
" " ), wxEmptyString );
957 wxChar ambiguousSeparator =
'?';
958 wxChar thousandsSeparator =
'?';
959 bool thousandsSeparatorFound =
false;
960 wxChar decimalSeparator =
'?';
961 bool decimalSeparatorFound =
false;
964 for(
int ii = (
int) value->length() - 1; ii >= 0; --ii )
966 wxChar c = value->GetChar( ii );
968 if( c >=
'0' && c <=
'9' )
972 else if( c ==
'.' || c ==
',' )
974 if( decimalSeparator !=
'?' || thousandsSeparator !=
'?' )
978 if( c == decimalSeparator )
980 if( thousandsSeparatorFound )
982 else if( decimalSeparatorFound )
985 decimalSeparatorFound =
true;
987 else if( c == thousandsSeparator )
992 thousandsSeparatorFound =
true;
995 else if( ambiguousSeparator !=
'?' )
999 if( c == ambiguousSeparator )
1002 thousandsSeparator = ambiguousSeparator;
1003 thousandsSeparatorFound =
true;
1004 decimalSeparator = c ==
'.' ?
',' :
'.';
1009 decimalSeparator = ambiguousSeparator;
1010 decimalSeparatorFound =
true;
1011 thousandsSeparator = c;
1012 thousandsSeparatorFound =
true;
1024 if( ( ii == 1 && value->GetChar( 0 ) ==
'0' ) || digits != 3 )
1026 decimalSeparator = c;
1027 decimalSeparatorFound =
true;
1028 thousandsSeparator = c ==
'.' ?
',' :
'.';
1032 ambiguousSeparator = c;
1045 if( decimalSeparator ==
'?' && thousandsSeparator ==
'?' )
1047 const struct lconv* lc = localeconv();
1049 decimalSeparator = lc->decimal_point[0];
1050 thousandsSeparator = decimalSeparator ==
'.' ?
',' :
'.';
1054 value->Replace( thousandsSeparator, wxEmptyString );
1055 value->Replace( decimalSeparator,
'.' );
1068 wxString strFWordBeg, strFWordMid, strFWordEnd;
1069 wxString strSWordBeg, strSWordMid, strSWordEnd;
1072 SplitString( fWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
1073 SplitString( sWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
1076 int isEqual = strFWordBeg.CmpNoCase( strSWordBeg );
1082 else if( isEqual < 0 )
1089 double lFirstNumber = 0;
1090 double lSecondNumber = 0;
1091 bool endingIsModifier =
false;
1098 strFWordMid.ToDouble( &lFirstNumber );
1099 strSWordMid.ToDouble( &lSecondNumber );
1101 endingIsModifier |=
ApplyModifier( lFirstNumber, strFWordEnd );
1102 endingIsModifier |=
ApplyModifier( lSecondNumber, strSWordEnd );
1104 if( lFirstNumber > lSecondNumber )
1106 else if( lFirstNumber < lSecondNumber )
1109 else if( !endingIsModifier )
1110 return strFWordEnd.CmpNoCase( strSWordEnd );
1119 wxString* strBeginning,
1120 wxString* strDigits,
1123 static const wxString separators( wxT(
".," ) );
1126 strBeginning->Empty();
1131 if( strToSplit.length() == 0 )
1137 for( ii = (strToSplit.length() - 1); ii >= 0; ii-- )
1139 if( wxIsdigit( strToSplit[ii] ) )
1146 *strBeginning = strToSplit;
1151 *strEnd = strToSplit.substr( ii + 1 );
1154 int position = ii + 1;
1156 for( ; ii >= 0; ii-- )
1158 if( !wxIsdigit( strToSplit[ii] ) && separators.Find( strToSplit[ii] ) < 0 )
1164 *strDigits = strToSplit.substr( 0, position );
1170 *strDigits = strToSplit.substr( ii + 1, position - ii - 1 );
1171 *strBeginning = strToSplit.substr( 0, ii + 1 );
1185 int index = aStr.Len() - 1;
1189 const char chr = aStr.GetChar( index );
1191 if( chr <
'0' || chr >
'9' )
1194 number += ( chr -
'0' ) * base;
1211 bool changed =
false;
1213 result.reserve( aName->length() );
1215 for( std::string::iterator it = aName->begin(); it != aName->end(); ++it )
1220 StrPrintf( &result,
"%c", aReplaceChar );
1241 bool changed =
false;
1243 result.reserve( aName.Length() );
1246 for( wxString::iterator it = aName.begin(); it != aName.end(); ++it )
1248 if( illWChars.Find( *it ) != wxNOT_FOUND )
1251 result += aReplaceChar;
1253 result += wxString::Format(
"%%%02x", *it );
1270void wxStringSplit(
const wxString& aText, wxArrayString& aStrings, wxChar aSplitter )
1274 for(
unsigned ii = 0; ii < aText.Length(); ii++ )
1276 if( aText[ii] == aSplitter )
1278 aStrings.Add( tmp );
1287 if( !tmp.IsEmpty() )
1288 aStrings.Add( tmp );
1294 struct lconv* lc = localeconv();
1295 char sep = lc->decimal_point[0];
1296 unsigned sep_pos = aStringValue.Find( sep );
1301 unsigned min_len = sep_pos + aTrailingZeroAllowed + 1;
1303 while( aStringValue.Len() > min_len )
1305 if( aStringValue.Last() ==
'0' )
1306 aStringValue.RemoveLast();
1318 if( aValue != 0.0 && std::fabs( aValue ) <= 0.0001 )
1320 buf = fmt::format(
"{:.16f}", aValue );
1323 while( !buf.empty() && buf[buf.size() - 1] ==
'0' )
1330 if( buf[buf.size() - 1] ==
'.' )
1337 buf = fmt::format(
"{:.10g}", aValue );
1349 if( aValue != 0.0 && std::fabs( aValue ) <= 0.0001 )
1353 len = snprintf( buf,
sizeof(buf),
"%.16f", aValue );
1355 while( --len > 0 && buf[len] ==
'0' )
1358 if( buf[len] ==
'.' || buf[len] ==
',' )
1367 len = snprintf( buf,
sizeof(buf),
"%.10g", aValue );
1370 return std::string( buf, len );
1377 wxString line = wxString::FromUTF8( cstring );
1379 if( line.IsEmpty() )
1381 line = wxConvCurrent->cMB2WC( cstring );
1383 if( line.IsEmpty() )
1384 line = wxString::From8BitData( cstring );
1394 wxString line = wxString::FromUTF8( aString );
1396 if( line.IsEmpty() )
1398 line = wxConvCurrent->cMB2WC( aString.c_str() );
1400 if( line.IsEmpty() )
1401 line = wxString::From8BitData( aString.c_str() );
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
This file contains miscellaneous commonly used macros and functions.
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
wxString RemoveHTMLTags(const wxString &aInput)
Removes HTML tags from a string.
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
int GetTrailingInt(const wxString &aStr)
Gets the trailing int, if any, from a string.
wxString UnescapeString(const wxString &aSource)
static const char illegalFileNameChars[]
Illegal file name characters used to ensure file names will be valid on all supported platforms.
wxString LinkifyHTML(wxString aStr)
Wraps links in HTML tags.
bool convertSeparators(wxString *value)
wxString GetIllegalFileNameWxChars()
wxString From_UTF8(const char *cstring)
bool ConvertSmartQuotesAndDashes(wxString *aString)
Convert curly quotes and em/en dashes to straight quotes and dashes.
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
int ReadDelimitedText(wxString *aDest, const char *aSource)
Copy bytes from aSource delimited string segment to aDest wxString.
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
wxString TitleCaps(const wxString &aString)
Capitalize the first letter in each word.
std::string UIDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 We want to avoid scientific ...
std::string FormatDouble2Str(double aValue)
Print a float number without using scientific notation and no trailing 0 This function is intended in...
int PrintableCharCount(const wxString &aString)
Return the number of printable (ie: non-formatting) chars.
std::string EscapedUTF8(const wxString &aString)
Return an 8 bit UTF8 string given aString in Unicode form.
char * GetLine(FILE *File, char *Line, int *LineNum, int SizeLine)
Read one line line from aFile.
bool ApplyModifier(double &value, const wxString &aString)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
wxString GetISO8601CurrentDateTime()
int ValueStringCompare(const wxString &strFWord, const wxString &strSWord)
Compare strings like the strcmp function but handle numbers and modifiers within the string text corr...
int SplitString(const wxString &strToSplit, wxString *strBeginning, wxString *strDigits, wxString *strEnd)
Break a string into three parts: he alphabetic preamble, the numeric part, and any alphabetic ending.
void StripTrailingZeros(wxString &aStringValue, unsigned aTrailingZeroAllowed)
Remove trailing zeros from a string containing a converted float number.
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
bool NoPrintableChars(const wxString &aString)
Return true if the string is empty or contains only whitespace.
wxString UnescapeHTML(const wxString &aString)
Return a new wxString unescaped from HTML format.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
ESCAPE_CONTEXT
Escape/Unescape routines to safely encode reserved-characters in various contexts.