1 #include "otsdaq-core/Macros/StringMacros.h"
16 bool StringMacros::wildCardMatch(
const std::string& needle,
17 const std::string& haystack,
18 unsigned int* priorityIndex)
try
25 if(needle.size() == 0)
41 if(needle == haystack)
49 if(needle[needle.size() - 1] ==
'*' &&
50 needle.substr(0, needle.size() - 1) == haystack.substr(0, needle.size() - 1))
58 if(needle[0] ==
'*' &&
59 needle.substr(1) == haystack.substr(haystack.size() - (needle.size() - 1)))
67 if(needle[0] ==
'*' && needle[needle.size() - 1] ==
'*' &&
68 std::string::npos != haystack.find(needle.substr(1, needle.size() - 2)))
90 bool StringMacros::inWildCardSet(
const std::string& needle,
91 const std::set<std::string>& haystack)
93 for(
const auto& haystackString : haystack)
96 if(StringMacros::wildCardMatch(haystackString, needle))
104 std::string StringMacros::decodeURIComponent(
const std::string& data)
106 std::string decodeURIString(data.size(), 0);
108 for(
unsigned int i = 0; i < data.size(); ++i, ++j)
113 if(data[i + 1] >
'9')
114 decodeURIString[j] += (data[i + 1] - 55) * 16;
116 decodeURIString[j] += (data[i + 1] - 48) * 16;
119 if(data[i + 2] >
'9')
120 decodeURIString[j] += (data[i + 2] - 55);
122 decodeURIString[j] += (data[i + 2] - 48);
127 decodeURIString[j] = data[i];
129 decodeURIString.resize(j);
130 return decodeURIString;
138 std::string StringMacros::convertEnvironmentVariables(
const std::string& data)
140 size_t begin = data.find(
"$");
141 if(begin != std::string::npos)
144 std::string envVariable;
145 std::string converted = data;
147 if(data[begin + 1] ==
'{')
149 end = data.find(
"}", begin + 2);
150 envVariable = data.substr(begin + 2, end - begin - 2);
156 for(end = begin + 1; end < data.size(); ++end)
157 if(!((data[end] >=
'0' && data[end] <=
'9') ||
158 (data[end] >=
'A' && data[end] <=
'Z') ||
159 (data[end] >=
'a' && data[end] <=
'z') || data[end] ==
'-' ||
160 data[end] ==
'_' || data[end] ==
'.' || data[end] ==
':'))
162 envVariable = data.substr(begin + 1, end - begin - 1);
166 char* envResult = __ENV__(envVariable.c_str());
171 return convertEnvironmentVariables(
172 converted.replace(begin, end - begin, envResult));
176 __SS__ << (
"The environmental variable '" + envVariable +
177 "' is not set! Please make sure you set it before continuing!")
192 bool StringMacros::isNumber(
const std::string& s)
195 std::vector<std::string> numbers;
196 std::vector<char> ops;
198 StringMacros::getVectorFromString(
201 std::set<char>({
'+',
'-',
'*',
'/'}),
202 std::set<char>({
' ',
'\t',
'\n',
'\r'}),
208 for(
const auto& number : numbers)
210 if(number.size() == 0)
213 if(number.find(
"0x") == 0)
216 for(
unsigned int i = 2; i < number.size(); ++i)
218 if(!((number[i] >=
'0' && number[i] <=
'9') ||
219 (number[i] >=
'A' && number[i] <=
'F') ||
220 (number[i] >=
'a' && number[i] <=
'f')))
228 else if(number[0] ==
'b')
232 for(
unsigned int i = 1; i < number.size(); ++i)
234 if(!((number[i] >=
'0' && number[i] <=
'1')))
244 for(
unsigned int i = 0; i < number.size(); ++i)
245 if(!((number[i] >=
'0' && number[i] <=
'9') || number[i] ==
'.' ||
246 number[i] ==
'+' || number[i] ==
'-'))
264 std::string StringMacros::getTimestampString(
const std::string& linuxTimeInSeconds)
266 time_t timestamp(strtol(linuxTimeInSeconds.c_str(), 0, 10));
267 return getTimestampString(timestamp);
274 std::string StringMacros::getTimestampString(
const time_t& linuxTimeInSeconds)
276 std::string retValue(30,
'\0');
279 ::localtime_r(&linuxTimeInSeconds, &tmstruct);
280 ::strftime(&retValue[0], 30,
"%c %Z", &tmstruct);
281 retValue.resize(strlen(retValue.c_str()));
289 std::string StringMacros::validateValueForDefaultStringDataType(
290 const std::string& value,
bool doConvertEnvironmentVariables)
try
292 return doConvertEnvironmentVariables
293 ? StringMacros::convertEnvironmentVariables(value)
296 catch(
const std::runtime_error& e)
298 __SS__ <<
"Failed to validate value for default string data type. " << __E__
299 << e.what() << __E__;
307 void StringMacros::getSetFromString(
const std::string& inputString,
308 std::set<std::string>& setToReturn,
309 const std::set<char>& delimiter,
310 const std::set<char>& whitespace)
317 for(; j < inputString.size(); ++j)
318 if((whitespace.find(inputString[j]) !=
320 delimiter.find(inputString[j]) != delimiter.end()) &&
323 else if((whitespace.find(inputString[j]) !=
326 delimiter.find(inputString[j]) != delimiter.end()) &&
332 setToReturn.emplace(inputString.substr(i, j - i));
339 setToReturn.emplace(inputString.substr(i, j - i));
354 void StringMacros::getVectorFromString(
const std::string& inputString,
355 std::vector<std::string>& listToReturn,
356 const std::set<char>& delimiter,
357 const std::set<char>& whitespace,
358 std::vector<char>* listOfDelimiters)
363 std::set<char>::iterator delimeterSearchIt;
373 for(; c < inputString.size(); ++c)
377 delimeterSearchIt = delimiter.find(inputString[c]);
378 isDelimiter = delimeterSearchIt != delimiter.end();
383 if(whitespace.find(inputString[c]) !=
392 else if(whitespace.find(inputString[c]) != whitespace.end() &&
402 if(listOfDelimiters && listToReturn.size())
409 listOfDelimiters->push_back(lastDelimiter);
411 listToReturn.push_back(inputString.substr(i, j - i));
421 lastDelimiter = *delimeterSearchIt;
430 if(listOfDelimiters && listToReturn.size())
436 listOfDelimiters->push_back(lastDelimiter);
438 listToReturn.push_back(inputString.substr(i, j - i));
442 if(listOfDelimiters && listToReturn.size() - 1 != listOfDelimiters->size() &&
443 listToReturn.size() != listOfDelimiters->size())
445 __SS__ <<
"There is a mismatch in delimiters to entries (should be equal or one "
447 << listOfDelimiters->size() <<
" vs " << listToReturn.size() << __E__
448 <<
"Entries: " << StringMacros::vectorToString(listToReturn) << __E__
449 <<
"Delimiters: " << StringMacros::vectorToString(*listOfDelimiters)
460 void StringMacros::getMapFromString(
const std::string& inputString,
461 std::map<std::string, std::string>& mapToReturn,
462 const std::set<char>& pairPairDelimiter,
463 const std::set<char>& nameValueDelimiter,
464 const std::set<char>& whitespace)
try
469 bool needValue =
false;
473 for(; j < inputString.size(); ++j)
476 if((whitespace.find(inputString[j]) !=
478 pairPairDelimiter.find(inputString[j]) != pairPairDelimiter.end()) &&
481 else if((whitespace.find(inputString[j]) !=
484 nameValueDelimiter.find(inputString[j]) !=
485 nameValueDelimiter.end()) &&
491 name = inputString.substr(i, j - i);
501 if((whitespace.find(inputString[j]) !=
503 nameValueDelimiter.find(inputString[j]) != nameValueDelimiter.end()) &&
506 else if((whitespace.find(inputString[j]) !=
509 pairPairDelimiter.find(inputString[j]) != pairPairDelimiter.end()) &&
516 mapToReturn.emplace(std::pair<std::string, std::string>(
518 validateValueForDefaultStringDataType(
519 inputString.substr(i, j - i))
522 if(!emplaceReturn.second)
524 __COUT__ <<
"Ignoring repetitive value ('"
525 << inputString.substr(i, j - i)
526 <<
"') and keeping current value ('"
527 << emplaceReturn.first->second <<
"'). " << __E__;
540 mapToReturn.emplace(std::pair<std::string, std::string>(
542 validateValueForDefaultStringDataType(
543 inputString.substr(i, j - i))
546 if(!emplaceReturn.second)
548 __COUT__ <<
"Ignoring repetitive value ('" << inputString.substr(i, j - i)
549 <<
"') and keeping current value ('" << emplaceReturn.first->second
554 catch(
const std::runtime_error& e)
556 __SS__ <<
"Error while extracting a map from the string '" << inputString
557 <<
"'... is it a valid map?" << __E__ << e.what() << __E__;
563 std::string StringMacros::mapToString(
const std::map<std::string, uint8_t>& mapToReturn,
564 const std::string& primaryDelimeter,
565 const std::string& secondaryDelimeter)
567 std::stringstream ss;
569 for(
auto& mapPair : mapToReturn)
574 ss << primaryDelimeter;
575 ss << mapPair.first << secondaryDelimeter << (
unsigned int)mapPair.second;
582 std::string StringMacros::setToString(
const std::set<uint8_t>& setToReturn,
583 const std::string& delimeter)
585 std::stringstream ss;
587 for(
auto& setValue : setToReturn)
593 ss << (
unsigned int)setValue;
600 std::string StringMacros::vectorToString(
const std::vector<uint8_t>& setToReturn,
601 const std::string& delimeter)
603 std::stringstream ss;
605 for(
auto& setValue : setToReturn)
611 ss << (
unsigned int)setValue;
619 std::string StringMacros::exec(
const char* cmd)
623 std::array<char, 128> buffer;
625 std::shared_ptr<FILE> pipe(popen(cmd,
"r"), pclose);
627 __THROW__(
"popen() failed!");
628 while(!feof(pipe.get()))
630 if(fgets(buffer.data(), 128, pipe.get()) !=
nullptr)
631 result += buffer.data();
641 #include <execinfo.h>
642 std::string StringMacros::stackTrace()
644 __SS__ <<
"ots::stackTrace:\n";
650 size = backtrace(array, 10);
654 char** messages = backtrace_symbols(array, size);
658 for(
unsigned int i = 1; i < size && messages != NULL; ++i)
671 char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
674 for(
char* p = messages[i]; *p; ++p)
692 if(mangled_name && offset_begin && offset_end && mangled_name < offset_begin)
694 *mangled_name++ =
'\0';
695 *offset_begin++ =
'\0';
696 *offset_end++ =
'\0';
699 char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
704 ss <<
"[" << i <<
"] " << messages[i] <<
" : " << real_name <<
"+"
705 << offset_begin << offset_end << std::endl;
710 ss <<
"[" << i <<
"] " << messages[i] <<
" : " << mangled_name <<
"+"
711 << offset_begin << offset_end << std::endl;
718 ss <<
"[" << i <<
"] " << messages[i] << std::endl;
733 char* StringMacros::otsGetEnvironmentVarable(
const char* name,
734 const std::string& location,
735 const unsigned int& line)
737 char* environmentVariablePtr = getenv(name);
738 if(!environmentVariablePtr)
740 __SS__ <<
"Environment variable '" << name <<
"' not defined at " << location
741 <<
"[" << line <<
"]" << __E__;
742 ss <<
"\n\n" << StringMacros::stackTrace() << __E__;
745 return environmentVariablePtr;
755 std::string StringMacros::demangleTypeName(
const char* name)
760 std::unique_ptr<char, void (*)(void*)> res{
761 abi::__cxa_demangle(name, NULL, NULL, &status), std::free};
763 return (status == 0) ? res.get() : name;
766 #else // does nothing if not g++
770 std::string StringMacros::demangleTypeName(
const char* name) {
return name; }