Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
StringUtils.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// Some static methods for string processing
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
26#include <iostream>
27#include <cstdio>
28#include <cstring>
29#include <regex>
30#ifdef WIN32
31#define NOMINMAX
32#include <windows.h>
33#undef NOMINMAX
34#else
35#include <unistd.h>
36#endif
37#include <xercesc/util/TransService.hpp>
38#include <xercesc/util/TranscodingException.hpp>
42#include "StringUtils.h"
43
44#define KM_PER_MILE 1.609344
45
46
47// ===========================================================================
48// static member definitions
49// ===========================================================================
50std::string StringUtils::emptyString;
51XERCES_CPP_NAMESPACE::XMLLCPTranscoder* StringUtils::myLCPTranscoder = nullptr;
52
53
54// ===========================================================================
55// method definitions
56// ===========================================================================
57std::string
58StringUtils::prune(const std::string& str) {
59 const std::string::size_type endpos = str.find_last_not_of(" \t\n\r");
60 if (std::string::npos != endpos) {
61 const int startpos = (int)str.find_first_not_of(" \t\n\r");
62 return str.substr(startpos, endpos - startpos + 1);
63 }
64 return "";
65}
66
67
68std::string
69StringUtils::pruneZeros(const std::string& str, int max) {
70 const std::string::size_type endpos = str.find_last_not_of("0");
71 if (endpos != std::string::npos && str.back() == '0') {
72 std::string res = str.substr(0, MAX2((int)str.size() - max, (int)endpos + 1));
73 return res;
74 }
75 return str;
76}
77
78std::string
79StringUtils::to_lower_case(const std::string& str) {
80 std::string s = str;
81 std::transform(s.begin(), s.end(), s.begin(), [](char c) {
82 return (char)::tolower(c);
83 });
84 return s;
85}
86
87
88std::string
90 // inspired by http://stackoverflow.com/questions/4059775/convert-iso-8859-1-strings-to-utf-8-in-c-c
91 std::string result;
92 for (const auto& c : str) {
93 const unsigned char uc = (unsigned char)c;
94 if (uc < 128) {
95 result += uc;
96 } else {
97 result += (char)(0xc2 + (uc > 0xbf));
98 result += (char)((uc & 0x3f) + 0x80);
99 }
100 }
101 return result;
102}
103
104
105std::string
107 str = replace(str, "\xE4", "ae");
108 str = replace(str, "\xC4", "Ae");
109 str = replace(str, "\xF6", "oe");
110 str = replace(str, "\xD6", "Oe");
111 str = replace(str, "\xFC", "ue");
112 str = replace(str, "\xDC", "Ue");
113 str = replace(str, "\xDF", "ss");
114 str = replace(str, "\xC9", "E");
115 str = replace(str, "\xE9", "e");
116 str = replace(str, "\xC8", "E");
117 str = replace(str, "\xE8", "e");
118 return str;
119}
120
121
122std::string
123StringUtils::replace(std::string str, const std::string& what, const std::string& by) {
124 std::string::size_type idx = str.find(what);
125 const int what_len = (int)what.length();
126 if (what_len > 0) {
127 const int by_len = (int)by.length();
128 while (idx != std::string::npos) {
129 str = str.replace(idx, what_len, by);
130 idx = str.find(what, idx + by_len);
131 }
132 }
133 return str;
134}
135
136
137std::string
138StringUtils::substituteEnvironment(const std::string& str, const std::chrono::time_point<std::chrono::system_clock>* const timeRef) {
139 std::string s = str;
140 if (timeRef != nullptr) {
141 const std::string::size_type localTimeIndex = str.find("${LOCALTIME}");
142 const std::string::size_type utcIndex = str.find("${UTC}");
143 const bool isUTC = utcIndex != std::string::npos;
144 if (localTimeIndex != std::string::npos || isUTC) {
145 const time_t rawtime = std::chrono::system_clock::to_time_t(*timeRef);
146 char buffer [80];
147 struct tm* timeinfo = isUTC ? gmtime(&rawtime) : localtime(&rawtime);
148 strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S.", timeinfo);
149 auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(*timeRef);
150 auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(*timeRef - seconds);
151 const std::string micro = buffer + toString(microseconds.count());
152 if (isUTC) {
153 s.replace(utcIndex, 6, micro);
154 } else {
155 s.replace(localTimeIndex, 12, micro);
156 }
157 }
158 }
159 const std::string::size_type pidIndex = str.find("${PID}");
160 if (pidIndex != std::string::npos) {
161#ifdef WIN32
162 s.replace(pidIndex, 6, toString(::GetCurrentProcessId()));
163#else
164 s.replace(pidIndex, 6, toString(::getpid()));
165#endif
166 }
167 if (std::getenv("SUMO_LOGO") == nullptr) {
168 s = replace(s, "${SUMO_LOGO}", "${SUMO_HOME}/data/logo/sumo-128x138.png");
169 }
170 const std::string::size_type tildeIndex = str.find("~");
171 if (tildeIndex == 0) {
172 s.replace(0, 1, "${HOME}");
173 }
174 s = replace(s, ",~", ",${HOME}");
175#ifdef WIN32
176 if (std::getenv("HOME") == nullptr) {
177 s = replace(s, "${HOME}", "${USERPROFILE}");
178 }
179#endif
180
181 // Expression for an environment variables, e.g. ${NAME}
182 // Note: - R"(...)" is a raw string literal syntax to simplify a regex declaration
183 // - .+? looks for the shortest match (non-greedy)
184 // - (.+?) defines a "subgroup" which is already stripped of the $ and {, }
185 std::regex envVarExpr(R"(\$\{(.+?)\})");
186
187 // Are there any variables in this string?
188 std::smatch match;
189 std::string strIter = s;
190
191 // Loop over the entire value string and look for variable names
192 while (std::regex_search(strIter, match, envVarExpr)) {
193 std::string varName = match[1];
194
195 // Find the variable in the environment and its value
196 std::string varValue;
197 if (std::getenv(varName.c_str()) != nullptr) {
198 varValue = std::getenv(varName.c_str());
199 }
200
201 // Replace the variable placeholder with its value in the original string
202 s = std::regex_replace(s, std::regex("\\$\\{" + varName + "\\}"), varValue);
203
204 // Continue the loop with the remainder of the string
205 strIter = match.suffix();
206 }
207 return s;
208}
209
210
211std::string
212StringUtils::isoTimeString(const std::chrono::time_point<std::chrono::system_clock>* const timeRef) {
213 const std::chrono::system_clock::time_point now = timeRef == nullptr ? std::chrono::system_clock::now() : *timeRef;
214 const auto now_seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
215 const std::time_t now_c = std::chrono::system_clock::to_time_t(now);
216 const auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(now - now_seconds).count();
217 std::tm local_tm = *std::localtime(&now_c);
218
219 // Get the time zone offset
220 std::time_t utc_time = std::time(nullptr);
221 std::tm utc_tm = *std::gmtime(&utc_time);
222 const double offset = std::difftime(std::mktime(&local_tm), std::mktime(&utc_tm)) / 3600.0;
223 const int hours_offset = static_cast<int>(offset);
224 const int minutes_offset = static_cast<int>((offset - hours_offset) * 60);
225
226 // Format the time
227 std::ostringstream oss;
228 char buf[32];
229 std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &local_tm);
230 oss << buf << "."
231 << std::setw(6) << std::setfill('0') << std::abs(microseconds)
232 << (hours_offset >= 0 ? "+" : "-")
233 << std::setw(2) << std::setfill('0') << std::abs(hours_offset) << ":"
234 << std::setw(2) << std::setfill('0') << std::abs(minutes_offset);
235 return oss.str();
236}
237
238
239bool
240StringUtils::startsWith(const std::string& str, const std::string prefix) {
241 return str.compare(0, prefix.length(), prefix) == 0;
242}
243
244
245bool
246StringUtils::endsWith(const std::string& str, const std::string suffix) {
247 if (str.length() >= suffix.length()) {
248 return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
249 } else {
250 return false;
251 }
252}
253
254
255std::string
256StringUtils::padFront(const std::string& str, int length, char padding) {
257 return std::string(MAX2(0, length - (int)str.size()), padding) + str;
258}
259
260
261std::string
262StringUtils::escapeXML(const std::string& orig, const bool maskDoubleHyphen) {
263 std::string result = replace(orig, "&", "&amp;");
264 result = replace(result, ">", "&gt;");
265 result = replace(result, "<", "&lt;");
266 result = replace(result, "\"", "&quot;");
267 if (maskDoubleHyphen) {
268 result = replace(result, "--", "&#45;&#45;");
269 }
270 for (char invalid = '\1'; invalid < ' '; invalid++) {
271 result = replace(result, std::string(1, invalid).c_str(), "");
272 }
273 return replace(result, "'", "&apos;");
274}
275
276
277std::string
278StringUtils::escapeShell(const std::string& orig) {
279 std::string result = replace(orig, "\"", "\\\"");
280 return result;
281}
282
283
284std::string
285StringUtils::urlEncode(const std::string& toEncode, const std::string encodeWhich) {
286 std::ostringstream out;
287
288 for (int i = 0; i < (int)toEncode.length(); ++i) {
289 const char t = toEncode.at(i);
290
291 if ((encodeWhich != "" && encodeWhich.find(t) == std::string::npos) ||
292 (encodeWhich == "" &&
293 ((t >= 45 && t <= 57) || // hyphen, period, slash, 0-9
294 (t >= 65 && t <= 90) || // A-Z
295 t == 95 || // underscore
296 (t >= 97 && t <= 122) || // a-z
297 t == 126)) // tilde
298 ) {
299 out << toEncode.at(i);
300 } else {
301 out << charToHex(toEncode.at(i));
302 }
303 }
304
305 return out.str();
306}
307
308
309std::string
310StringUtils::urlDecode(const std::string& toDecode) {
311 std::ostringstream out;
312
313 for (int i = 0; i < (int)toDecode.length(); ++i) {
314 if (toDecode.at(i) == '%') {
315 std::string str(toDecode.substr(i + 1, 2));
316 out << hexToChar(str);
317 i += 2;
318 } else {
319 out << toDecode.at(i);
320 }
321 }
322
323 return out.str();
324}
325
326std::string
327StringUtils::charToHex(unsigned char c) {
328 short i = c;
329
330 std::stringstream s;
331
332 s << "%" << std::setw(2) << std::setfill('0') << std::hex << i;
333
334 return s.str();
335}
336
337
338unsigned char
339StringUtils::hexToChar(const std::string& str) {
340 short c = 0;
341 if (!str.empty()) {
342 std::istringstream in(str);
343 in >> std::hex >> c;
344 if (in.fail()) {
345 throw NumberFormatException(str + " could not be interpreted as hex");
346 }
347 }
348 return static_cast<unsigned char>(c);
349}
350
351
352int
353StringUtils::toInt(const std::string& sData) {
354 long long int result = toLong(sData);
355 if (result > std::numeric_limits<int>::max() || result < std::numeric_limits<int>::min()) {
356 throw NumberFormatException(toString(result) + " int overflow");
357 }
358 return (int)result;
359}
360
361
362bool
363StringUtils::isInt(const std::string& sData) {
364 // first check if can be converted to long int
365 if (isLong(sData)) {
366 const long long int result = toLong(sData);
367 // now check if the result is in the range of an int
368 return ((result <= std::numeric_limits<int>::max()) && (result >= std::numeric_limits<int>::min()));
369 }
370 return false;
371}
372
373
374int
375StringUtils::toIntSecure(const std::string& sData, int def) {
376 if (sData.length() == 0) {
377 return def;
378 }
379 return toInt(sData);
380}
381
382
383long long int
384StringUtils::toLong(const std::string& sData) {
385 const char* const data = sData.c_str();
386 if (data == 0 || data[0] == 0) {
387 throw EmptyData();
388 }
389 char* end;
390 errno = 0;
391#ifdef _MSC_VER
392 long long int ret = _strtoi64(data, &end, 10);
393#else
394 long long int ret = strtoll(data, &end, 10);
395#endif
396 if (errno == ERANGE) {
397 errno = 0;
398 throw NumberFormatException("(long long integer range) " + sData);
399 }
400 if ((int)(end - data) != (int)strlen(data)) {
401 throw NumberFormatException("(long long integer format) " + sData);
402 }
403 return ret;
404}
405
406
407bool
408StringUtils::isLong(const std::string& sData) {
409 const char* const data = sData.c_str();
410 if (data == 0 || data[0] == 0) {
411 return false;
412 }
413 char* end;
414 // reset errno before parsing, to keep errors
415 errno = 0;
416 // continue depending of current plattform
417#ifdef _MSC_VER
418 _strtoi64(data, &end, 10);
419#else
420 strtoll(data, &end, 10);
421#endif
422 // check out of range
423 if (errno == ERANGE) {
424 return false;
425 }
426 // check length of converted data
427 if ((int)(end - data) != (int)strlen(data)) {
428 return false;
429 }
430 return true;
431}
432
433
434int
435StringUtils::hexToInt(const std::string& sData) {
436 if (sData.length() == 0) {
437 throw EmptyData();
438 }
439 size_t idx = 0;
440 int result;
441 try {
442 if (sData[0] == '#') { // for html color codes
443 result = std::stoi(sData.substr(1), &idx, 16);
444 idx++;
445 } else {
446 result = std::stoi(sData, &idx, 16);
447 }
448 } catch (...) {
449 throw NumberFormatException("(hex integer format) " + sData);
450 }
451 if (idx != sData.length()) {
452 throw NumberFormatException("(hex integer format) " + sData);
453 }
454 return result;
455}
456
457
458bool
459StringUtils::isHex(std::string sData) {
460 if (sData.length() == 0) {
461 return false;
462 }
463 // remove the first character (for HTML color codes)
464 if (sData[0] == '#') {
465 sData = sData.substr(1);
466 }
467 const char* sDataPtr = sData.c_str();
468 char* returnPtr;
469 // reset errno
470 errno = 0;
471 // call string to long (size 16) from standard library
472 strtol(sDataPtr, &returnPtr, 16);
473 // check out of range
474 if (errno == ERANGE) {
475 return false;
476 }
477 // check if there was an error converting sDataPtr to double,
478 if (sDataPtr == returnPtr) {
479 return false;
480 }
481 // compare size of start and end points
482 if (static_cast<size_t>(returnPtr - sDataPtr) != sData.size()) {
483 return false;
484 }
485 return true;
486}
487
488
489double
490StringUtils::toDouble(const std::string& sData) {
491 if (sData.size() == 0) {
492 throw EmptyData();
493 }
494 try {
495 size_t idx = 0;
496 const double result = std::stod(sData, &idx);
497 if (idx != sData.size()) {
498 throw NumberFormatException("(double format) " + sData);
499 } else {
500 return result;
501 }
502 } catch (...) {
503 // invalid_argument or out_of_range
504 throw NumberFormatException("(double) " + sData);
505 }
506}
507
508
509bool
510StringUtils::isDouble(const std::string& sData) {
511 if (sData.size() == 0) {
512 return false;
513 }
514 const char* sDataPtr = sData.c_str();
515 char* returnPtr;
516 // reset errno
517 errno = 0;
518 // call string to double from standard library
519 strtod(sDataPtr, &returnPtr);
520 // check out of range
521 if (errno == ERANGE) {
522 return false;
523 }
524 // check if there was an error converting sDataPtr to double,
525 if (sDataPtr == returnPtr) {
526 return false;
527 }
528 // compare size of start and end points
529 if (static_cast<size_t>(returnPtr - sDataPtr) != sData.size()) {
530 return false;
531 }
532 return true;
533}
534
535
536double
537StringUtils::toDoubleSecure(const std::string& sData, const double def) {
538 if (sData.length() == 0) {
539 return def;
540 }
541 return toDouble(sData);
542}
543
544
545bool
546StringUtils::toBool(const std::string& sData) {
547 if (sData.length() == 0) {
548 throw EmptyData();
549 }
550 const std::string s = to_lower_case(sData);
551 if (s == "1" || s == "yes" || s == "true" || s == "on" || s == "x" || s == "t") {
552 return true;
553 }
554 if (s == "0" || s == "no" || s == "false" || s == "off" || s == "-" || s == "f") {
555 return false;
556 }
557 throw BoolFormatException(s);
558}
559
560
561bool
562StringUtils::isBool(const std::string& sData) {
563 if (sData.length() == 0) {
564 return false;
565 }
566 const std::string s = to_lower_case(sData);
567 // check true values
568 if (s == "1" || s == "yes" || s == "true" || s == "on" || s == "x" || s == "t") {
569 return true;
570 }
571 // check false values
572 if (s == "0" || s == "no" || s == "false" || s == "off" || s == "-" || s == "f") {
573 return true;
574 }
575 // no valid true or false values
576 return false;
577}
578
579
581StringUtils::toVersion(const std::string& sData) {
582 std::vector<std::string> parts = StringTokenizer(sData, ".").getVector();
583 return MMVersion(toInt(parts.front()), toDouble(parts.back()));
584}
585
586
587double
588StringUtils::parseDist(const std::string& sData) {
589 if (sData.size() == 0) {
590 throw EmptyData();
591 }
592 try {
593 size_t idx = 0;
594 const double result = std::stod(sData, &idx);
595 if (idx != sData.size()) {
596 const std::string unit = prune(sData.substr(idx));
597 if (unit == "m" || unit == "metre" || unit == "meter" || unit == "metres" || unit == "meters") {
598 return result;
599 }
600 if (unit == "km" || unit == "kilometre" || unit == "kilometer" || unit == "kilometres" || unit == "kilometers") {
601 return result * 1000.;
602 }
603 if (unit == "mi" || unit == "mile" || unit == "miles") {
604 return result * 1000. * KM_PER_MILE;
605 }
606 if (unit == "nmi") {
607 return result * 1852.;
608 }
609 if (unit == "ft" || unit == "foot" || unit == "feet") {
610 return result * 12. * 0.0254;
611 }
612 if (unit == "\"" || unit == "in" || unit == "inch" || unit == "inches") {
613 return result * 0.0254;
614 }
615 if (unit[0] == '\'') {
616 double inches = 12 * result;
617 if (unit.length() > 1) {
618 inches += std::stod(unit.substr(1), &idx);
619 if (unit.substr(idx) == "\"") {
620 return inches * 0.0254;
621 }
622 }
623 }
624 throw NumberFormatException("(distance format) " + sData);
625 } else {
626 return result;
627 }
628 } catch (...) {
629 // invalid_argument or out_of_range
630 throw NumberFormatException("(double) " + sData);
631 }
632}
633
634
635double
636StringUtils::parseSpeed(const std::string& sData, const bool defaultKmph) {
637 if (sData.size() == 0) {
638 throw EmptyData();
639 }
640 try {
641 size_t idx = 0;
642 const double result = std::stod(sData, &idx);
643 if (idx != sData.size()) {
644 const std::string unit = prune(sData.substr(idx));
645 if (unit == "km/h" || unit == "kph" || unit == "kmh" || unit == "kmph") {
646 return result / 3.6;
647 }
648 if (unit == "m/s") {
649 return result;
650 }
651 if (unit == "mph") {
652 return result * KM_PER_MILE / 3.6;
653 }
654 if (unit == "knots") {
655 return result * 1.852 / 3.6;
656 }
657 throw NumberFormatException("(speed format) " + sData);
658 } else {
659 return defaultKmph ? result / 3.6 : result;
660 }
661 } catch (...) {
662 // invalid_argument or out_of_range
663 throw NumberFormatException("(double) " + sData);
664 }
665}
666
667
668std::string
669StringUtils::transcode(const XMLCh* const data, int length) {
670 if (data == 0) {
671 throw EmptyData();
672 }
673 if (length == 0) {
674 return "";
675 }
676#if _XERCES_VERSION < 30100
677 char* t = XERCES_CPP_NAMESPACE::XMLString::transcode(data);
678 std::string result(t);
679 XERCES_CPP_NAMESPACE::XMLString::release(&t);
680 return result;
681#else
682 try {
683 XERCES_CPP_NAMESPACE::TranscodeToStr utf8(data, "UTF-8");
684 return reinterpret_cast<const char*>(utf8.str());
685 } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {
686 return "?";
687 }
688#endif
689}
690
691
692std::string
693StringUtils::transcodeFromLocal(const std::string& localString) {
694#if _XERCES_VERSION > 30100
695 try {
696 if (myLCPTranscoder == nullptr) {
697 myLCPTranscoder = XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgMemoryManager);
698 }
699 if (myLCPTranscoder != nullptr) {
700 return transcode(myLCPTranscoder->transcode(localString.c_str()));
701 }
702 } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {}
703#endif
704 return localString;
705}
706
707
708std::string
709StringUtils::transcodeToLocal(const std::string& utf8String) {
710#if _XERCES_VERSION > 30100
711 try {
712 if (myLCPTranscoder == nullptr) {
713 myLCPTranscoder = XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgMemoryManager);
714 }
715 if (myLCPTranscoder != nullptr) {
716 XERCES_CPP_NAMESPACE::TranscodeFromStr utf8(reinterpret_cast<const XMLByte*>(utf8String.c_str()), utf8String.size(), "UTF-8");
717 return myLCPTranscoder->transcode(utf8.str());
718 }
719 } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {}
720#endif
721 return utf8String;
722}
723
724
725std::string
726StringUtils::trim_left(const std::string s, const std::string& t) {
727 std::string result = s;
728 result.erase(0, s.find_first_not_of(t));
729 return result;
730}
731
732std::string
733StringUtils::trim_right(const std::string s, const std::string& t) {
734 std::string result = s;
735 result.erase(s.find_last_not_of(t) + 1);
736 return result;
737}
738
739std::string
740StringUtils::trim(const std::string s, const std::string& t) {
741 return trim_right(trim_left(s, t), t);
742}
743
744
745std::string
746StringUtils::wrapText(const std::string s, int width) {
747 std::vector<std::string> parts = StringTokenizer(s).getVector();
748 std::string result;
749 std::string line;
750 bool firstLine = true;
751 bool firstWord = true;
752 for (std::string p : parts) {
753 if ((int)(line.size() + p.size()) < width || firstWord) {
754 if (firstWord) {
755 firstWord = false;
756 } else {
757 line += " ";
758 }
759 line = line + p;
760 } else {
761 if (firstLine) {
762 firstLine = false;
763 } else {
764 result += "\n";
765 }
766 result = result + line;
767 line.clear();
768 firstWord = true;
769 }
770 }
771 if (line.size() > 0) {
772 if (firstLine) {
773 firstLine = false;
774 } else {
775 result += "\n";
776 }
777 result = result + line;
778 }
779 return result;
780}
781
782
783void
787
788
789std::string
790StringUtils::adjustDecimalValue(double value, int precision) {
791 // obtain value in string format with 20 decimals precision
792 auto valueStr = toString(value, precision);
793 // now clear all zeros
794 while (valueStr.size() > 1) {
795 if (valueStr.back() == '0') {
796 valueStr.pop_back();
797 } else if (valueStr.back() == '.') {
798 valueStr.pop_back();
799 return valueStr;
800 } else {
801 return valueStr;
802 }
803 }
804 return valueStr;
805}
806
807/****************************************************************************/
std::pair< int, double > MMVersion
(M)ajor/(M)inor version for written networks and default version for loading
Definition StdDefs.h:71
T MAX2(T a, T b)
Definition StdDefs.h:86
#define KM_PER_MILE
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
std::vector< std::string > getVector()
return vector of strings
static std::string pruneZeros(const std::string &str, int max)
Removes trailing zeros (at most 'max')
static std::string urlEncode(const std::string &url, const std::string encodeWhich="")
encode url (stem from http://bogomip.net/blog/cpp-url-encoding-and-decoding/)
static bool isDouble(const std::string &sData)
check if the given sData can be conveted to double
static MMVersion toVersion(const std::string &sData)
parse a (network) version string
static bool isBool(const std::string &sData)
check if the given value can be converted to bool
static std::string charToHex(unsigned char c)
char to hexadecimal
static std::string urlDecode(const std::string &encoded)
decode url (stem from http://bogomip.net/blog/cpp-url-encoding-and-decoding/)
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
static double toDoubleSecure(const std::string &sData, const double def)
converts a string into the integer value described by it
static std::string trim(const std::string s, const std::string &t=" \t\n")
remove leading and trailing whitespace
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
static void resetTranscoder()
must be called when shutting down the xml subsystem
static XERCES_CPP_NAMESPACE::XMLLCPTranscoder * myLCPTranscoder
static std::string trim_right(const std::string s, const std::string &t=" \t\n")
remove trailing whitespace from string
static std::string trim_left(const std::string s, const std::string &t=" \t\n")
remove leading whitespace from string
static std::string escapeShell(const std::string &orig)
Escape special characters with backslash.
static std::string replace(std::string str, const std::string &what, const std::string &by)
Replaces all occurrences of the second string by the third string within the first string.
static int hexToInt(const std::string &sData)
converts a string with a hex value into the integer value described by it by calling the char-type co...
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static bool isHex(std::string sData)
check if the given string can be converted to hex
static std::string latin1_to_utf8(std::string str)
Transfers from Latin 1 (ISO-8859-1) to UTF-8.
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
static std::string padFront(const std::string &str, int length, char padding)
static std::string convertUmlaute(std::string str)
Converts german "Umlaute" to their latin-version.
static double parseDist(const std::string &sData)
parse a distance, length or width value with a unit
static std::string adjustDecimalValue(double value, int precision)
write with maximum precision if needed but remove trailing zeros
static unsigned char hexToChar(const std::string &str)
hexadecimal to char
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
static std::string wrapText(const std::string s, int width)
remove leading and trailing whitespace
static double parseSpeed(const std::string &sData, const bool defaultKmph=true)
parse a speed value with a unit
static std::string emptyString
An empty string.
Definition StringUtils.h:94
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static std::string substituteEnvironment(const std::string &str, const std::chrono::time_point< std::chrono::system_clock > *const timeRef=nullptr)
Replaces an environment variable with its value (similar to bash); syntax for a variable is ${NAME}.
static bool isLong(const std::string &sData)
Check if the given sData can be converted to long.
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage
static int toIntSecure(const std::string &sData, int def)
converts a string into the integer value described by it
static std::string isoTimeString(const std::chrono::time_point< std::chrono::system_clock > *const timeRef=nullptr)
Returns an ISO8601 formatted time string with microsecond precision.
static std::string transcodeFromLocal(const std::string &localString)
convert a string from the local codepage to UTF-8
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool isInt(const std::string &sData)
check if the given sData can be converted to int
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter