NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
stringtools.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2021 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "stringtools.hpp"
20#include "../settings.hpp"
21#include "../structures.hpp"
23
24#include <cstring>
25#include <sstream>
26#include <iomanip>
27
28// Forward declarations
29std::string getNextArgument(std::string& sArgList, bool bCut);
30double intPower(double, int);
31
32// toString function implementations
33// There's an overwrite for mostly every variable type
34//
43std::string toString(int nNumber, const Settings& _option)
44{
45 return toString((double)nNumber, _option); // Unnoetig das nochmal zu schreiben. Rufen wir die andere Funktion mit einer expliziten Konvertierung auf
46}
47
48
58std::string toString(double dNumber, const Settings& _option)
59{
60 return toString(dNumber, _option.getPrecision()); // Auf den eigentlichen string wird dann mit der Methode ostringstream::str() zugegriffen
61}
62
63
73std::string toString(double dNumber, int nPrecision)
74{
75 std::ostringstream Temp;
76 Temp.precision(nPrecision);
77 Temp << dNumber;
78 return Temp.str();
79}
80
90std::string toString(const std::complex<double>& dNumber, int nPrecision)
91{
92 if (std::isnan(dNumber.real()) && std::isnan(dNumber.imag()))
93 return "nan";
94
95 std::ostringstream Temp;
96 Temp.precision(std::rint(nPrecision / (dNumber.real() != 0.0 && dNumber.imag() != 0.0 && !std::isnan(dNumber.imag()) ? 2 : 1)));
97
98 if (dNumber.real() || !dNumber.imag())
99 Temp << dNumber.real();
100
101 if (dNumber.imag())
102 {
103 if ((dNumber.imag() > 0.0 || std::isnan(dNumber.imag())) && dNumber.real() != 0.0)
104 Temp << "+";
105
106 Temp << dNumber.imag() << (std::isnan(dNumber.imag()) || std::isinf(dNumber.imag()) ? " i" : "i");
107 }
108
109 return Temp.str();
110}
111
112
121std::string toString(int nNumber)
122{
123 return toString((long long int)nNumber);
124}
125
126
135std::string toString(size_t nNumber)
136{
137 return toString((long long int)nNumber);
138}
139
140
150std::string toString(__time64_t tTime, int timeStampFlags)
151{
152 tm* ltm = _localtime64(&tTime);
153
154 if (!ltm)
155 return "";
156
158
159 std::ostringstream timeStream;
160
161 if (!(timeStampFlags & GET_ONLY_TIME))
162 {
163 timeStream << 1900+ltm->tm_year << "-"; //YYYY-
164 timeStream << std::setfill('0') << std::setw(2) << ltm->tm_mon + 1 << "-"; // MM-
165 timeStream << std::setfill('0') << std::setw(2) << ltm->tm_mday; // DD
166
167 if (timeStampFlags & GET_AS_TIMESTAMP)
168 timeStream << "_";
169 else
170 {
171 timeStream << ", "; // Komma im regulaeren Datum
172
173 if (timeStampFlags & GET_WITH_TEXT)
174 {
175 if (_lang.get("TOOLS_TIMESTAMP_AT") == "TOOLS_TIMESTAMP_AT")
176 timeStream << "at ";
177 else
178 timeStream << _lang.get("TOOLS_TIMESTAMP_AT") << " ";
179 }
180 }
181 }
182
183 if (timeStampFlags & GET_ONLY_TIME)
184 timeStream << std::setfill('0') << std::setw(2) << ltm->tm_hour + tz.Bias.count()/60; // hh
185 else
186 timeStream << std::setfill('0') << std::setw(2) << ltm->tm_hour; // hh
187
188 if (!(timeStampFlags & GET_AS_TIMESTAMP))
189 timeStream << ":"; // ':' im regulaeren Datum
190
191 timeStream << std::setfill('0') << std::setw(2) << ltm->tm_min; // mm
192
193 if (!(timeStampFlags & GET_AS_TIMESTAMP))
194 timeStream << ":";
195
196 timeStream << std::setfill('0') << std::setw(2) << ltm->tm_sec; // ss
197
198 return timeStream.str();
199}
200
201
210std::string toString(sys_time_point tp, int timeStampFlags)
211{
214 std::ostringstream timeStream;
215
216 if (!(timeStampFlags & GET_ONLY_TIME))
217 {
218 timeStream << ltm.m_ymd.year() << "-"; //YYYY-
219 timeStream << std::setfill('0') << std::setw(2) << unsigned(ltm.m_ymd.month()) << "-"; // MM-
220 timeStream << ltm.m_ymd.day(); // DD
221
222 if (timeStampFlags & GET_AS_TIMESTAMP)
223 timeStream << "_";
224 else
225 {
226 timeStream << ", "; // Komma im regulaeren Datum
227
228 if (timeStampFlags & GET_WITH_TEXT)
229 {
230 if (_lang.get("TOOLS_TIMESTAMP_AT") == "TOOLS_TIMESTAMP_AT")
231 timeStream << "at ";
232 else
233 timeStream << _lang.get("TOOLS_TIMESTAMP_AT") << " ";
234 }
235 }
236 }
237
238 if (timeStampFlags & GET_ONLY_TIME)
239 timeStream << std::setfill('0') << std::setw(2) << ltm.m_hours.count() + (tz.Bias + tz.DayLightBias).count()/60; // hh
240 else
241 timeStream << std::setfill('0') << std::setw(2) << ltm.m_hours.count(); // hh
242
243 if (!(timeStampFlags & GET_AS_TIMESTAMP))
244 timeStream << ":"; // ':' im regulaeren Datum
245
246 timeStream << std::setfill('0') << std::setw(2) << ltm.m_minutes.count(); // mm
247
248 if (!(timeStampFlags & GET_AS_TIMESTAMP))
249 timeStream << ":";
250
251 timeStream << std::setfill('0') << std::setw(2) << ltm.m_seconds.count(); // ss
252
253 if (!(timeStampFlags & GET_AS_TIMESTAMP))
254 {
255 if (timeStampFlags & (GET_MILLISECONDS | GET_FULL_PRECISION)
256 || ltm.m_millisecs.count())
257 timeStream << "." << std::setfill('0') << std::setw(3) << ltm.m_millisecs.count();
258
259 if (timeStampFlags & GET_FULL_PRECISION)
260 timeStream << std::setfill('0') << std::setw(3) << ltm.m_microsecs.count();
261 }
262
263 return timeStream.str();
264}
265
266
274std::string toString(long long int nNumber)
275{
276 std::ostringstream Temp;
277 Temp << nNumber;
278 return Temp.str();
279}
280
281
291std::string toString(bool bBoolean)
292{
293 if (bBoolean)
294 return "true";
295 else
296 return "false";
297}
298
299
308std::string toCmdString(double dNumber)
309{
310 std::ostringstream Temp;
311 Temp.precision(20);
312 Temp << dNumber;
313 return Temp.str();
314}
315
316
325std::string toCmdString(const std::complex<double>& dNumber)
326{
327 return toString(dNumber, 20);
328}
329
330
339std::string toHexString(int nNumber)
340{
341 std::ostringstream Temp;
342 Temp << std::hex << nNumber;
343 return "0x" + Temp.str();
344}
345
346
356std::vector<std::string> toStrVector(std::string sString)
357{
358 std::vector<std::string> vVector;
359
360 if (sString == "{}" || !sString.length())
361 return vVector;
362
363 if (sString.front() == '{' && sString.back() == '}')
364 {
365 sString.erase(0, 1);
366 sString.pop_back();
367 }
368
369 while (sString.length())
370 {
371 vVector.push_back(getNextArgument(sString, true));
372 }
373
374 return vVector;
375}
376
377
387std::vector<int> toIntVector(std::string sString)
388{
389 std::vector<int> vVector;
390 std::vector<std::string> vStrVect = toStrVector(sString);
391
392 if (!vStrVect.size())
393 return vVector;
394
395 for (const auto& s : vStrVect)
396 {
397 vVector.push_back(StrToInt(s));
398 }
399
400 return vVector;
401}
402
403
412std::string condenseText(const std::string& sText)
413{
414 std::string sReturn = sText;
415 static std::string sToErase = " AaEeIiOoUuÄäÖöÜüßYy";
416 for (unsigned int i = 0; i < sReturn.length(); i++)
417 {
418 if (sToErase.find(sReturn[i]) != std::string::npos
419 || sReturn[i] == 142
420 || sReturn[i] == 132
421 || sReturn[i] == 153
422 || sReturn[i] == 148
423 || sReturn[i] == 154
424 || sReturn[i] == 129
425 || sReturn[i] == 225)
426 {
427 sReturn.erase(i, 1);
428 i--;
429 }
430 }
431 return sReturn;
432}
433
434
446std::string truncString(const std::string& sText, size_t nMaxChars)
447{
448 if (sText.length() <= nMaxChars)
449 return sText;
450
451 return sText.substr(0, nMaxChars-3) + "...";
452}
453
454
463void StripSpaces(std::string& sToStrip)
464{
465 if (!sToStrip.length())
466 return;
467
468 sToStrip.erase(0, sToStrip.find_first_not_of(" \t"));
469
470 if (sToStrip.length() && (sToStrip.back() == ' ' || sToStrip.back() == '\t'))
471 sToStrip.erase(sToStrip.find_last_not_of(" \t") + 1);
472}
473
474
482int StrToInt(const std::string& sString)
483{
484 return atoi(sString.c_str());
485}
486
487
495double StrToDb(const std::string& sString)
496{
497 return atof(sString.c_str());
498}
499
500
509double StrToLogical(const std::string& sString)
510{
511 if (toLowerCase(sString) == "true" || sString == "1")
512 return 1.0;
513 else if (toLowerCase(sString) == "false" || sString == "0")
514 return 0.0;
515
516 return StrToCmplx(sString).real();
517}
518
519
528std::complex<double> StrToCmplx(const std::string& sString)
529{
530 double re, im;
531
532 //if (!isConvertible(sString, CONVTYPE_VALUE) || sString == "---") <-- Should be obsolete due to the fact that it should be checked in advance
533 if (sString == "---"
534 || (sString.length() < 4 && (toLowerCase(sString) == "na" || toLowerCase(sString) == "n/a")))
535 return NAN;
536
537 const char* pStart = sString.c_str();
538 const char* pEnd = pStart + sString.length();
539 int oprt = 0;
540
541 // check whether next char is 'i' and advance
542 // over all whitespaces
543 while (pStart < pEnd && (*pStart == ' ' || *pStart == '+'))
544 pStart++;
545
546 if (pStart >= pEnd)
547 return NAN; // End of Input
548
549 // read 1st value
551
552 // Error code might imply "i" or "-i"
553 if (res.ec == std::errc::invalid_argument)
554 {
555 // Check, if there are other characters
556 while (res.ptr < pEnd && (*res.ptr == '-' || *res.ptr == ' ' || tolower(*res.ptr) == 'i'))
557 res.ptr++;
558
559 // Did we find any? If no, it is +/-i
560 if (res.ptr >= pEnd)
561 return std::complex<double>(0, *pStart == '-' ? -1 : 1);
562
563 // We did find other character sequences
564 return NAN;
565 }
566
567 // check whether next char is 'i' and advance
568 // over all whitespaces
569 while (res.ptr < pEnd && *res.ptr == ' ')
570 res.ptr++;
571
572 if (res.ptr >= pEnd)
573 return re; // End of Input
574
575 if (*res.ptr == '-' || *res.ptr == '+')
576 {
577 oprt = *res.ptr == '-' ? -1 : 1;
578 res.ptr++;
579 }
580
581 // check whether next char is 'i' and advance
582 // over all whitespaces
583 while (res.ptr < pEnd && *res.ptr == ' ')
584 res.ptr++;
585
586 if (res.ptr >= pEnd)
587 return re; // End of Input
588
589 // Is it the actual imaginary value?
590 if (tolower(*res.ptr) == 'i'
591 && oprt
592 && (res.ptr+1 >= pEnd || tolower(*(res.ptr+1)) != 'n'))
593 return std::complex<double>(re, oprt);
594
595 if ((tolower(*res.ptr) == 'i' && (res.ptr+1 >= pEnd || tolower(*(res.ptr+1)) != 'n')) || *res.ptr == '*')
596 return std::complex<double>(0.0, re);
597
598 // read 2nd value
599 res = fast_float::from_chars(res.ptr, pEnd, im);
600
601 // Error
602 if (res.ec == std::errc::invalid_argument)
603 return re;
604
605 // check whether next char is 'i' and advance
606 // over all whitespaces
607 while (res.ptr < pEnd && *res.ptr == ' ')
608 res.ptr++;
609
610 if (tolower(*res.ptr) != 'i' && *res.ptr != '*')
611 { // ERROR or premature end of input
612 return re;
613 }
614
615 return std::complex<double>(re, oprt*im);
616}
617
618
626sys_time_point StrToTime(const std::string& sString)
627{
628 int format = detectTimeDateFormat(sString);
629
630 if (format == TD_NONE)
631 return sys_time_point();
632
633 // Try to detect dates
634 size_t pos = sString.find_first_not_of(" \t");
635
637 timeStruct.m_hours = std::chrono::hours::zero();
638 timeStruct.m_minutes = std::chrono::minutes::zero();
639 timeStruct.m_seconds = std::chrono::seconds::zero();
640 timeStruct.m_millisecs = std::chrono::milliseconds::zero();
641 timeStruct.m_microsecs = std::chrono::microseconds::zero();
642
643 const char* DIGITS = "0123456789";
644
645 // Contains time
646 if (format & TD_HHMM || format & TD_HHMMSS)
647 {
648 std::vector<std::string> toks = split(sString, ':');
649
650 bool isFirst = sString.find(':') < 3 + pos;
651
652 for (size_t i = 0; i < toks.size(); i++)
653 {
654 // Catch milliseconds written as s.i or ss.iii
655 StripSpaces(toks[i]);
656
657 if (i == 2 && toks[i].length() >= 3 && (toks[i][1] == '.' || toks[i][2] == '.'))
658 {
659 size_t dot = toks[i].find('.');
660 toks.insert(toks.begin()+i+1, toks[i].substr(dot+1));
661 toks[i].erase(dot);
662 }
663
664 // Remove leading of trailing non-time characters
665 if (toks[i].find_first_not_of(DIGITS) != std::string::npos)
666 {
667 if ((isFirst && i+1 != toks.size()) || (!isFirst && i))
668 break;
669
670 if (isFirst)
671 toks[i].erase(toks[i].find_first_not_of(DIGITS));
672 else
673 toks[i].erase(0, toks[i].find_last_not_of(DIGITS)+1);
674 }
675
676 if (!i)
677 timeStruct.m_hours = std::chrono::hours(StrToInt(toks[i]));
678 else if (i == 1)
679 timeStruct.m_minutes = std::chrono::minutes(StrToInt(toks[i]));
680 else if (i == 2 && format & TD_HHMMSS)
681 timeStruct.m_seconds = std::chrono::seconds(StrToInt(toks[i]));
682 else if (i == 3 && format & TD_HHMMSS)
683 timeStruct.m_millisecs = std::chrono::milliseconds(int(StrToInt(toks[i])*intPower(10.0, 3-toks[i].length()))); // scaling due to possible missing trailing zeros
684 }
685 }
686
687 // Contains DD.MM.YY or DD/MM/YYYY
688 if (format & TD_DDMM || format & TD_DDMMYY)
689 {
690 std::vector<std::string> toks = split(sString, format & TD_SEP_SLASH ? '/' : '.');
691 date::year y(timeStruct.m_ymd.year());
692 date::month m(0);
693 date::day d(0);
694
695 bool isFirst = sString.find(format & TD_SEP_SLASH ? '/' : '.') < 3 + pos;
696
697 for (size_t i = 0; i < toks.size(); i++)
698 {
699 StripSpaces(toks[i]);
700
701 // Remove leading or trailing non-date chars
702 if (toks[i].find_first_not_of(DIGITS) != std::string::npos)
703 {
704 // Obscure logic needed because msecs are also
705 // separated by a dot
706 if ((isFirst && i < bool(format & TD_DDMMYY) + 1) || (!isFirst && i))
707 break;
708
709 if (isFirst)
710 toks[i].erase(toks[i].find_first_not_of(DIGITS));
711 else
712 toks[i].erase(0, toks[i].find_last_not_of(DIGITS)+1);
713 }
714
715 if (!i)
716 d = date::day(StrToInt(toks[i]));
717 else if (i == 1)
718 m = date::month(StrToInt(toks[i]));
719 else if (i == 2 && format & TD_DDMMYY)
720 {
721 if (toks[i].length() > 2)
722 y = date::year(StrToInt(toks[i]));
723 else
724 y = date::year(StrToInt(toks[i]) + 2000);
725 }
726 }
727
728 timeStruct.m_ymd = date::year_month_day(y,m,d);
729 }
730
731 // Contains YY-MM-DD or YY/MM/DD
732 if (format & TD_YYMMDD)
733 {
734 std::vector<std::string> toks;
735 bool isFirst;
736 date::year y(0);
737 date::month m(0);
738 date::day d(0);
739
740 if (format & TD_SEP_MINUS)
741 {
742 toks = split(sString, '-');
743 isFirst = sString.find('-') < 5 + pos;
744 }
745 else
746 {
747 toks = split(sString, '/');
748 isFirst = sString.find('/') < 5 + pos;
749 }
750
751 for (size_t i = 0; i < toks.size(); i++)
752 {
753 StripSpaces(toks[i]);
754
755 // Remove leading or trailing non-date chars
756 if (toks[i].find_first_not_of(DIGITS) != std::string::npos)
757 {
758 if ((isFirst && i+1 != toks.size()) || (!isFirst && i))
759 break;
760
761 if (isFirst)
762 toks[i].erase(toks[i].find_first_not_of(DIGITS));
763 else
764 toks[i].erase(0, toks[i].find_last_not_of(DIGITS)+1);
765 }
766
767 if (!i)
768 {
769 if (toks[i].length() > 2)
770 y = date::year(StrToInt(toks[i]));
771 else
772 y = date::year(StrToInt(toks[i]) + 2000);
773 }
774 else if (i == 1)
775 m = date::month(StrToInt(toks[i]));
776 else if (i == 2)
777 d = date::day(StrToInt(toks[i]));
778 }
779
780 timeStruct.m_ymd = date::year_month_day(y,m,d);
781 }
782
783 return getTimePointFromTimeStamp(timeStruct);
784}
785
786
795size_t versionToInt(std::string sVersion)
796{
797 size_t nVOffset = 0;
798
799 if (sVersion.front() == 'v')
800 nVOffset = 1;
801
802 replaceAll(sVersion, ".", "");
803 return StrToInt(sVersion.substr(nVOffset));
804}
805
806
815std::string intToVersion(size_t nVersionDigits)
816{
817 std::string _sVer = toString(nVersionDigits);
818
819 // Prepend zeroes, if the length is shorter than
820 // three
821 if (_sVer.length() < 3)
822 _sVer.insert(0, 3-_sVer.length(), '0');
823
824 // Convert the version string into the M.m.b format
825 for (size_t n = 1; n < _sVer.length(); n++)
826 {
827 if (n % 2)
828 _sVer.insert(n, 1, '.');
829 }
830
831 return _sVer;
832}
833
834
844std::string toInternalString(std::string sStr)
845{
846 if (sStr.front() == '"' && sStr.back() == '"')
847 sStr = sStr.substr(1, sStr.length()-2);
848
849 for (size_t i = 0; i < sStr.length(); i++)
850 {
851 if (sStr.compare(i, 2, "\\t") == 0
852 && sStr.compare(i, 4, "\\tau") != 0
853 && sStr.compare(i, 6, "\\theta") != 0
854 && sStr.compare(i, 6, "\\times") != 0)
855 sStr.replace(i, 2, "\t");
856
857 if (sStr.compare(i, 2, "\\n") == 0
858 && sStr.compare(i, 3, "\\nu") != 0
859 && sStr.compare(i, 4, "\\neq") != 0)
860 sStr.replace(i, 2, "\n");
861
862 if (sStr.compare(i, 2, "\\\"") == 0)
863 sStr.replace(i, 2, "\"");
864
865 if (sStr.compare(i, 2, "\\ ") == 0)
866 sStr.replace(i, 2, "\\");
867 }
868
869 return sStr;
870}
871
872
881std::string toExternalString(std::string sStr)
882{
883 replaceAll(sStr, "\"", "\\\"");
884 return "\"" + sStr + "\"";
885}
886
887
896std::string toLowerCase(const std::string& sUpperCase)
897{
898 std::string sLowerCase = sUpperCase;
899 for (unsigned int i = 0; i < sLowerCase.length(); i++)
900 {
901 // --> Laufe alle Zeichen im String ab und pruefe, ob ihr CHAR-Wert zwischen A und Z liegt
902 if ((int)sLowerCase[i] >= (int)'A' && (int)sLowerCase[i] <= (int)'Z')
903 {
904 // --> Falls ja, verschiebe den CHAR-Wert um die Differenz aus A und a <--
905 sLowerCase[i] = (char)((int)sLowerCase[i] + ((int)'a' - (int)'A'));
906 }
907 if (sLowerCase[i] == 'Ä')
908 sLowerCase[i] = 'ä';
909 else if (sLowerCase[i] == 'Ö')
910 sLowerCase[i] = 'ö';
911 else if (sLowerCase[i] == 'Ü')
912 sLowerCase[i] = 'ü';
913 else if (sLowerCase[i] == (char)142)
914 sLowerCase[i] = (char)132;
915 else if (sLowerCase[i] == (char)153)
916 sLowerCase[i] = (char)148;
917 else if (sLowerCase[i] == (char)154)
918 sLowerCase[i] = (char)129;
919 }
920 return sLowerCase;
921}
922
923
932std::string toUpperCase(const std::string& sLowerCase)
933{
934 std::string sUpperCase = sLowerCase;
935 for (unsigned int i = 0; i < sUpperCase.length(); i++)
936 {
937 // Handle escape characters like linebreaks or tabulator characters
938 if ((!i || sUpperCase[i - 1] != '\\') && (sUpperCase.substr(i, 2) == "\\n" || sUpperCase.substr(i, 2) == "\\t"))
939 {
940 i++;
941 continue;
942 }
943 else if (sUpperCase.substr(i, 2) == "\\n")
944 {
945 sUpperCase.replace(i, 2, "N");
946 }
947 else if (sUpperCase.substr(i, 2) == "\\t")
948 {
949 sUpperCase.replace(i, 2, "T");
950 }
951 // --> Laufe alle Zeichen im String ab und pruefe, ob ihr CHAR-Wert zwischen a und z liegt
952 if ((int)sUpperCase[i] >= (int)'a' && (int)sLowerCase[i] <= (int)'z')
953 {
954 // --> Falls ja, verschiebe den CHAR-Wert um die Differenz aus a und A <--
955 sUpperCase[i] = (char)((int)sUpperCase[i] + ((int)'A' - (int)'a'));
956 }
957 if (sUpperCase[i] == 'ä')
958 sUpperCase[i] = 'Ä';
959 else if (sUpperCase[i] == 'ö')
960 sUpperCase[i] = 'Ö';
961 else if (sUpperCase[i] == 'ü')
962 sUpperCase[i] = 'Ü';
963 else if (sUpperCase[i] == (char)132)
964 sUpperCase[i] = (char)142;
965 else if (sUpperCase[i] == (char)148)
966 sUpperCase[i] = (char)153;
967 else if (sUpperCase[i] == (char)129)
968 sUpperCase[i] = (char)154;
969 }
970 return sUpperCase;
971}
972
973
984static bool isDateTimePattern(const std::string& sStr, size_t pos)
985{
986 if (pos
987 && isdigit(sStr[pos-1])
988 && isdigit(sStr[pos+1])
989 && ((pos+3 < sStr.length() && sStr[pos+3] == sStr[pos])
990 || (pos+2 < sStr.length() && sStr[pos+2] == sStr[pos])
991 || sStr[pos] == ':'
992 || (sStr[pos] == '.' && pos > 6 && sStr[pos-2] == ':')))
993 return true;
994
995 return false;
996}
997
998
1009bool isConvertible(const std::string& sStr, ConvertibleType type)
1010{
1011 if (type == CONVTYPE_VALUE)
1012 {
1013 // Apply the simplest heuristic: mostly every numerical valid character
1014 // and ignore characters, which cannot represent a value by themselves
1015 if (sStr.find_first_not_of(" 0123456789.,eianfEIANF+-*/\t") != std::string::npos
1016 || (sStr.find_first_not_of("+-* .,\teE") == std::string::npos && sStr.find("---") == std::string::npos))
1017 return false;
1018
1019 // Eliminate invalid character positions
1020 if (tolower(sStr.front()) == 'e'
1021 || tolower(sStr.front()) == 'a'
1022 || tolower(sStr.front()) == 'f'
1023 || tolower(sStr.back()) == 'e')
1024 return false;
1025
1026 // Try to detect dates
1027 return !isConvertible(sStr, CONVTYPE_DATE_TIME);
1028 }
1029 else if (type == CONVTYPE_LOGICAL)
1030 {
1031 // Apply the simplest heuristic: mostly every numerical valid character
1032 // and ignore characters, which cannot represent a value by themselves
1033 if (toLowerCase(sStr) == "true"
1034 || toLowerCase(sStr) == "false"
1035 || sStr == "0"
1036 || sStr == "1")
1037 return true;
1038
1039 // Try to detect values
1040 return isConvertible(sStr, CONVTYPE_VALUE);
1041 }
1042 else if (type == CONVTYPE_DATE_TIME)
1043 {
1044 // Apply the simplest heuristic: only digits and separators
1045 // and ignore characters, which cannot represent a date by themselves
1046 if (sStr.find_first_not_of(" 0123456789,.:-/\tTZ") != std::string::npos
1047 || sStr.find_first_not_of(" \t,.:-/TZ") == std::string::npos)
1048 return false;
1049
1050 // Try to detect dates
1051 size_t pos = sStr.find_first_not_of(" \t");
1052
1053 if (sStr.length() >= pos+3 && isdigit(sStr[pos]))
1054 {
1055 for (size_t i = pos; i < sStr.length()-1; i++)
1056 {
1057 // Detects these candidates:
1058 // (YY)YY-MM-DD, DD.MM.YY(YY), (yy)yy-m-d, d.m.yy(yy),
1059 // d.m., dd.mm., (YY)YY/MM/DD, (YY)YY/M/D,
1060 // hh:mm:ss, h:mm:ss, h:mm, hh:mm
1061 // hh:mm:ss:iii, h:mm:ss:iii, hh:mm:ss.iii, h:mm:ss.iii
1062 // YYYY-MM-DDThh:mm:ss.iiiZ
1063 if (sStr[i] == '-' || sStr[i] == '.' || sStr[i] == '/' || sStr[i] == ':')
1064 {
1065 if (isDateTimePattern(sStr, i))
1066 return true;
1067
1068 return false;
1069 }
1070 }
1071 }
1072 }
1073
1074 return false;
1075}
1076
1077
1088static int isDatePattern_US(const std::string& sStr, size_t i)
1089{
1090 // Surrounded by digits?
1091 if (!i || !isdigit(sStr[i-1]) || !isdigit(sStr[i+1]))
1092 return TD_NONE;
1093
1094 // Detects these candidates:
1095 // YY-MM-DD, yy-m-d, YY/MM/DD, YY/M/D, DD/MM/YYYY, D/M/YY(YY)
1096 if ((i+3 < sStr.length() && sStr[i+3] == sStr[i])
1097 || (i+2 < sStr.length() && sStr[i+2] == sStr[i]))
1098 {
1099 // Special case for DD/MM/YYYY, D/M/YY(YY) (note that the year has more characters)
1100 if ((sStr[i+3] == '/' && i+6 < sStr.length() && isdigit(sStr[i+6]))
1101 || (sStr[i+2] == '/' && i+4 < sStr.length() && isdigit(sStr[i+4])))
1102 return TD_DDMMYY | TD_SEP_SLASH;
1103
1104 return TD_YYMMDD | (sStr[i] == '-' ? TD_SEP_MINUS : TD_SEP_SLASH);
1105 }
1106
1107 return TD_NONE;
1108}
1109
1110
1121static int isDatePattern_DE(const std::string& sStr, size_t i)
1122{
1123 // Surrounded by digits?
1124 if (!i || !isdigit(sStr[i-1]) || !isdigit(sStr[i+1]))
1125 return TD_NONE;
1126
1127 // Detects these candidates:
1128 // DD.MM.YY, d.m.yy
1129 if ((i+4 < sStr.length() && sStr[i+3] == sStr[i] && isdigit(sStr[i+4]))
1130 || (i+3 < sStr.length() && sStr[i+2] == sStr[i] && isdigit(sStr[i+3])))
1131 return TD_DDMMYY | TD_SEP_DOT;
1132 // d.m., dd.mm.
1133 else if ((i+3 < sStr.length() && sStr[i+3] == sStr[i])
1134 || (i+2 < sStr.length() && sStr[i+2] == sStr[i]))
1135 return TD_DDMM | TD_SEP_DOT;
1136
1137 return TD_NONE;
1138}
1139
1140
1150static int isTimePattern(const std::string& sStr, size_t i)
1151{
1152 // Surrounded by digits?
1153 if (!i || !isdigit(sStr[i-1]) || !isdigit(sStr[i+1]))
1154 return TD_NONE;
1155
1156 // Detects these candidates:
1157 // hh:mm:ss, h:mm:ss, hh:mm:ss:iii, h:mm:ss:iii, hh:mm:ss.iii, h:mm:ss.iii
1158 if ((i+3 < sStr.length() && sStr[i+3] == sStr[i])
1159 || (i+2 < sStr.length() && sStr[i+2] == sStr[i]))
1160 return TD_HHMMSS | TD_SEP_COLON;
1161
1162 // h:mm, hh:mm
1163 return TD_HHMM | TD_SEP_COLON;
1164}
1165
1166
1175int detectTimeDateFormat(const std::string& sStr)
1176{
1177 if (sStr.find_first_not_of(" 0123456789,.:-/\tTZ") != std::string::npos || sStr.find_first_not_of(" \t") == std::string::npos)
1178 return TD_NONE;
1179
1180 // Try to detect dates
1181 size_t pos = sStr.find_first_not_of(" \t");
1182 int format = TD_NONE;
1183
1184 if (sStr.length() >= pos+3 && isdigit(sStr[pos]))
1185 {
1186 for (size_t i = pos; i < sStr.length()-1; i++)
1187 {
1188 // Detects these candidates:
1189 // (YY)YY-MM-DD, (yy)yy-m-d, (YY)YY/MM/DD, (YY)YY/M/D, DD/MM/YYYY, D/M/YYYY
1190 if (sStr[i] == '-' || sStr[i] == '/')
1191 format |= isDatePattern_US(sStr, i);
1192 // DD.MM.YY(YY), d.m.yy(yy), d.m., dd.mm.
1193 else if (sStr[i] == '.')
1194 format |= isDatePattern_DE(sStr, i);
1195 // hh:mm:ss, h:mm:ss, h:mm, hh:mm
1196 // hh:mm:ss:iii, h:mm:ss:iii, hh:mm:ss.iii, h:mm:ss.iii
1197 else if (sStr[i] == ':')
1198 format |= isTimePattern(sStr, i);
1199 }
1200 }
1201
1202 // If we have the dashed american theme and T and Z,
1203 // then we have a full UTC time stamp
1205 && sStr.find('T') != std::string::npos
1206 && sStr.find('Z') != std::string::npos)
1207 format |= TD_UTC;
1208
1209 return format;
1210}
1211
1212
1222std::string wcstombs(const std::wstring& wStr)
1223{
1224 std::string sReturn;
1225
1226 // provide a target character array
1227 char* cBuf = new char[wStr.length() * 2 + 1];
1228
1229 // transform the wstring into the target array
1230 unsigned int nRet = wcstombs(cBuf, wStr.c_str(), wStr.length() * 2 + 1);
1231
1232 // Write the zero character and copy the contents of the character
1233 // array to the target string
1234 if (nRet == wStr.length() * 2 + 1)
1235 cBuf[wStr.length() * 2] = '\0';
1236 if (nRet)
1237 sReturn = cBuf;
1238
1239 // Clear the memory and return the string
1240 delete[] cBuf;
1241 return sReturn;
1242}
1243
1244
1253std::string toSystemCodePage(std::string sOutput)
1254{
1255 return sOutput;
1256}
1257
1258
1267std::string fromSystemCodePage(std::string sOutput)
1268{
1269 for (unsigned int i = 0; i < sOutput.length(); i++)
1270 {
1271 if (sOutput[i] == (char)142)
1272 sOutput[i] = 'Ä';
1273 else if (sOutput[i] == (char)132)
1274 sOutput[i] = 'ä';
1275 else if (sOutput[i] == (char)153)
1276 sOutput[i] = 'Ö';
1277 else if (sOutput[i] == (char)148)
1278 sOutput[i] = 'ö';
1279 else if (sOutput[i] == (char)154)
1280 sOutput[i] = 'Ü';
1281 else if (sOutput[i] == (char)129)
1282 sOutput[i] = 'ü';
1283 else if (sOutput[i] == (char)225)
1284 sOutput[i] = 'ß';
1285 else if (sOutput[i] == (char)248)
1286 sOutput[i] = '°';
1287 else if (sOutput[i] == (char)174)
1288 sOutput[i] = (char)171;
1289 else if (sOutput[i] == (char)175)
1290 sOutput[i] = (char)187;
1291 else
1292 continue;
1293 }
1294 return sOutput;
1295}
1296
1297
1307std::string utf8parser(const std::string& sString)
1308{
1309 std::string sReturn = sString;
1310 if (sReturn.length() < 2)
1311 return sReturn;
1312
1313 // Go through the complete string
1314 for (unsigned int i = 0; i < sReturn.length() - 1; i++)
1315 {
1316 // UTF-8 encoded characters are more than one byte in length
1317 if (sReturn[i] == (char)195)
1318 {
1319 if (sReturn[i + 1] == (char)132) //Ä
1320 {
1321 sReturn.erase(i, 1);
1322 sReturn[i] = (char)142;
1323 }
1324 else if (sReturn[i + 1] == (char)164) //ä
1325 {
1326 sReturn.erase(i, 1);
1327 sReturn[i] = (char)132;
1328 }
1329 else if (sReturn[i + 1] == (char)150) //Ö
1330 {
1331 sReturn.erase(i, 1);
1332 sReturn[i] = (char)153;
1333 }
1334 else if (sReturn[i + 1] == (char)182) //ö
1335 {
1336 sReturn.erase(i, 1);
1337 sReturn[i] = (char)148;
1338 }
1339 else if (sReturn[i + 1] == (char)156) //Ü
1340 {
1341 sReturn.erase(i, 1);
1342 sReturn[i] = (char)154;
1343 }
1344 else if (sReturn[i + 1] == (char)188) //ü
1345 {
1346 sReturn.erase(i, 1);
1347 sReturn[i] = (char)129;
1348 }
1349 else if (sReturn[i + 1] == (char)159) //ß
1350 {
1351 sReturn.erase(i, 1);
1352 sReturn[i] = (char)225;
1353 }
1354 }
1355 if (sReturn[i] == (char)194 && sReturn[i + 1] == (char)176)
1356 {
1357 sReturn.erase(i, 1);
1358 sReturn[i] = (char)248;
1359 }
1360 }
1361 return sReturn;
1362}
1363
1364
1373std::string getTimeStamp(bool bGetStamp)
1374{
1375 return toString(_time64(0), bGetStamp ? GET_AS_TIMESTAMP : GET_WITH_TEXT);
1376}
1377
1378
1388std::vector<std::string> split(const std::string& sStr, char cSplit)
1389{
1390 std::vector<std::string> vSplit;
1391 size_t lastPos = 0;
1392
1393 for (size_t i = 1; i < sStr.length(); i++)
1394 {
1395 if (sStr[i] == cSplit)
1396 {
1397 vSplit.push_back(sStr.substr(lastPos, i - lastPos));
1398 lastPos = i+1;
1399 }
1400 }
1401
1402 if (lastPos < sStr.length())
1403 vSplit.push_back(sStr.substr(lastPos));
1404
1405 return vSplit;
1406}
1407
1408
1420std::string ellipsize(const std::string& sLongString, size_t nMaxStringLength)
1421{
1422 if (sLongString.length() > nMaxStringLength)
1423 return sLongString.substr(0, nMaxStringLength/2-2) + "[...]" + sLongString.substr(sLongString.length()-nMaxStringLength+2);
1424
1425 return sLongString;
1426}
1427
1428
1443void replaceAll(std::string& sToModify, const char* sToRep, const char* sNewValue, size_t nStart /*= 0*/, size_t nEnd /*= string::npos*/)
1444{
1445 size_t nRepLength = strlen(sToRep);
1446 size_t nNewLength = strlen(sNewValue);
1447 int nOffSet = nNewLength - nRepLength;
1448 // Ensure the values are correct
1449 if (!sToModify.length() || !nRepLength)
1450 return;
1451
1452 // check the boundaries
1453 if ((size_t)nStart > sToModify.length())
1454 return;
1455
1456 if (nEnd == std::string::npos)
1457 nEnd = sToModify.length();
1458
1459 // Process the replacing
1460 for (size_t i = nStart; i <= nEnd-nRepLength; i++)
1461 {
1462 if (i >= sToModify.length())
1463 break;
1464
1465 if (!sToModify.compare(i, nRepLength, sToRep))
1466 {
1467 sToModify.replace(i, nRepLength, sNewValue);
1468 nEnd += nOffSet;
1469 i += nNewLength - 1;
1470 }
1471 }
1472}
1473
1474
1490void replaceAll(std::string& sToModify, const std::string& sToRep, const std::string& sNewValue, size_t nStart /*= 0*/, size_t nEnd /*= string::npos*/)
1491{
1492 size_t nRepLength = sToRep.length();
1493 size_t nNewLength = sNewValue.length();
1494 int nOffSet = nNewLength - nRepLength;
1495 // Ensure the values are correct
1496 if (!sToModify.length() || !nRepLength)
1497 return;
1498
1499 // check the boundaries
1500 if ((size_t)nStart > sToModify.length())
1501 return;
1502
1503 if (nEnd == std::string::npos)
1504 nEnd = sToModify.length();
1505
1506 // Process the replacing
1507 for (size_t i = nStart; i <= nEnd-nRepLength; i++)
1508 {
1509 if (i >= sToModify.length())
1510 break;
1511
1512 if (!sToModify.compare(i, nRepLength, sToRep))
1513 {
1514 sToModify.replace(i, nRepLength, sNewValue);
1515 nEnd += nOffSet;
1516 i += nNewLength - 1;
1517 }
1518 }
1519}
1520
1521
1531std::string replaceControlCharacters(std::string sToModify)
1532{
1533 replaceAll(sToModify, "\n", "\\n");
1534 replaceAll(sToModify, "\t", "\\t");
1535
1536 return sToModify;
1537}
1538
1539
1548std::string replacePathSeparator(const std::string& __sPath)
1549{
1550 std::string sPath = __sPath;
1551
1552 // Go through the whole string
1553 for (unsigned int i = 0; i < sPath.length(); i++)
1554 {
1555 // Replace the backslash
1556 if (sPath[i] == '\\')
1557 sPath[i] = '/';
1558 }
1559
1560 return sPath;
1561}
1562
1563
1575{
1576 str1.strip();
1577 str2.strip();
1578
1579 return str1 == str2;
1580}
1581
1582
const std::string sVersion
std::string get(const std::string &sMessage, const std::vector< std::string > &vTokens) const
This member function returns the language string for the passed language identifier and replaces all ...
Definition: language.cpp:292
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
size_t getPrecision() const
Returns the precision for displaying floating numbers in the terminal. This value determines the numb...
Definition: settings.hpp:1000
void strip()
This member function shrinks the viewed section to remove all leading or trailing whitespace characte...
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
CONSTCD11 date::year year() const NOEXCEPT
Definition: date.h:2928
CONSTCD11 date::day day() const NOEXCEPT
Definition: date.h:2930
CONSTCD11 date::month month() const NOEXCEPT
Definition: date.h:2929
Language _lang
Definition: kernel.cpp:39
sys_time_point sys_time_now()
Returns the current time as a sys_time_point (i.e. a std::chrono::time_point with microseconds precis...
time_stamp getTimeStampFromTimePoint(sys_time_point tp)
Return a time_stamp instance converted from the passed sys_time_point.
time_zone getCurrentTimeZone()
Return the current time_zone of the system.
sys_time_point getTimePointFromTimeStamp(const time_stamp &ts)
Convert a time_stamp to a sys_time_point.
std::chrono::time_point< std::chrono::system_clock, std::chrono::microseconds > sys_time_point
This is a typedef for a custom system_clock time_point with microseconds precision.
auto format(const std::locale &loc, const CharT *fmt, const Streamable &tp) -> decltype(to_stream(std::declval< std::basic_ostream< CharT > & >(), fmt, tp), std::basic_string< CharT >{})
Definition: date.h:6249
from_chars_result from_chars(const char *first, const char *last, T &value, chars_format fmt=chars_format::general) noexcept
Definition: parse_number.h:66
bool isnan(const value_type &v)
Definition: muParserDef.h:379
bool isinf(const value_type &v)
Definition: muParserDef.h:374
value_type rint(value_type v)
static int isTimePattern(const std::string &sStr, size_t i)
Returns a formatting flag combination, if the string is a time pattern or TD_NONE.
std::vector< int > toIntVector(std::string sString)
This function converts a std::string into a std::vector, where the string shall be passed as "{x,...
std::vector< std::string > toStrVector(std::string sString)
This function converts a std::string into a std::vector, where the string shall be passed as "{x,...
std::string toInternalString(std::string sStr)
Converts a string literal to the internal representation in tables and clusters.
std::string toString(int nNumber, const Settings &_option)
Converts an integer to a string.
Definition: stringtools.cpp:43
std::string toHexString(int nNumber)
Converts an integer to a hexadecimal number printed as string.
void StripSpaces(std::string &sToStrip)
Removes leading and trailing white spaces and tabulator characters.
std::string truncString(const std::string &sText, size_t nMaxChars)
This function truncates the string to the passed max length (including a trailing ellipsis) or return...
double intPower(double, int)
This function calculates the power of a value with the specialization that the exponent is an integer...
Definition: tools.cpp:3607
static bool isDateTimePattern(const std::string &sStr, size_t pos)
Static function to determine, whether the character at passed position fits the pattern needed for a ...
std::string toLowerCase(const std::string &sUpperCase)
Converts uppercase to lowercase letters.
int detectTimeDateFormat(const std::string &sStr)
Detects the contained date-time format and returns it as a bitflag composition.
int StrToInt(const std::string &sString)
Converts a string into an integer.
std::string replaceControlCharacters(std::string sToModify)
This function is a simple wrapper for replaceAll() and specialized to remove control characters from ...
std::vector< std::string > split(const std::string &sStr, char cSplit)
Splits a vector at the selected characters.
std::string toExternalString(std::string sStr)
Converts an internal string to the external representation in the terminal.
double StrToDb(const std::string &sString)
Converts a string into a double.
sys_time_point StrToTime(const std::string &sString)
Convert a string to a sys_time_point.
double StrToLogical(const std::string &sString)
Converts a string into a double considering logical values.
static int isDatePattern_DE(const std::string &sStr, size_t i)
Returns a formatting flag combination, if the string is a DE-specific date pattern or TD_NONE.
size_t versionToInt(std::string sVersion)
Converts a version string into a multi-digit integer.
std::string ellipsize(const std::string &sLongString, size_t nMaxStringLength)
Shortens the passed string by introducing a ellipsis in the middle of the string, if the string is lo...
std::string intToVersion(size_t nVersionDigits)
Converts a multi-digit integer into a verison string.
bool isConvertible(const std::string &sStr, ConvertibleType type)
This function checks, whether a string can be converted to the selected ConvertibleType.
bool isEqualStripped(StringView str1, StringView str2)
Returns true, if the contents of the strings are equal, if all surrounding whitespaces will be stripp...
std::string fromSystemCodePage(std::string sOutput)
Transforms the system code page to the internal one.
std::complex< double > StrToCmplx(const std::string &sString)
Converts a string into a complex number.
std::string utf8parser(const std::string &sString)
Transforms a UTF8 encoded string into a standard ASCII string in the internal code page representatio...
std::string toUpperCase(const std::string &sLowerCase)
Converts lowercase letters to uppercase ones.
std::string toCmdString(double dNumber)
Converts a numerical value into a "full" precision string.
std::string toSystemCodePage(std::string sOutput)
Converts an internal to an external string. Does nothing currently.
std::string getNextArgument(std::string &sArgList, bool bCut)
Definition: tools.cpp:2294
static int isDatePattern_US(const std::string &sStr, size_t i)
Returns a formatting flag combination, if the string is a US-specific date pattern or TD_NONE.
std::string replacePathSeparator(const std::string &__sPath)
This function replaces the Windows style path sparators to UNIX style.
std::string condenseText(const std::string &sText)
Removes vowels and umlauts from the passed string.
std::string wcstombs(const std::wstring &wStr)
This function is a wrapper for the usual wcstombs function, which can handle wstrings.
void replaceAll(std::string &sToModify, const char *sToRep, const char *sNewValue, size_t nStart, size_t nEnd)
This function replaces all occurences of the string sToRep in the string sToModify with the new value...
std::string getTimeStamp(bool bGetStamp)
This function simple returns the current time as a default timestamp.
@ TD_YYMMDD
Definition: stringtools.hpp:55
@ TD_SEP_SLASH
Definition: stringtools.hpp:64
@ TD_DDMM
Definition: stringtools.hpp:57
@ TD_SEP_COLON
Definition: stringtools.hpp:61
@ TD_HHMM
Definition: stringtools.hpp:53
@ TD_SEP_DOT
Definition: stringtools.hpp:62
@ TD_HHMMSS
Definition: stringtools.hpp:52
@ TD_UTC
Definition: stringtools.hpp:59
@ TD_NONE
Definition: stringtools.hpp:51
@ TD_SEP_MINUS
Definition: stringtools.hpp:63
@ TD_DDMMYY
Definition: stringtools.hpp:56
ConvertibleType
Definition: stringtools.hpp:42
@ CONVTYPE_DATE_TIME
Definition: stringtools.hpp:45
@ CONVTYPE_LOGICAL
Definition: stringtools.hpp:46
@ CONVTYPE_VALUE
Definition: stringtools.hpp:44
@ GET_AS_TIMESTAMP
Definition: stringtools.hpp:35
@ GET_ONLY_TIME
Definition: stringtools.hpp:34
@ GET_FULL_PRECISION
Definition: stringtools.hpp:38
@ GET_MILLISECONDS
Definition: stringtools.hpp:37
@ GET_WITH_TEXT
Definition: stringtools.hpp:36
This structure defines all fields necessary to create a time stamp or a formatted date.
date::year_month_day m_ymd
std::chrono::microseconds m_microsecs
std::chrono::minutes m_minutes
std::chrono::seconds m_seconds
std::chrono::hours m_hours
std::chrono::milliseconds m_millisecs
This structure defines the information for a time zone.