1 #include "otsdaq/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;
134 std::string StringMacros::encodeURIComponent(
const std::string& sourceStr)
136 std::string retStr =
"";
138 for(
const auto& c : sourceStr)
139 if((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9'))
143 sprintf(encodeStr,
"%%%2.2X", c);
154 std::string StringMacros::convertEnvironmentVariables(
const std::string& data)
156 size_t begin = data.find(
"$");
157 if(begin != std::string::npos)
160 std::string envVariable;
161 std::string converted = data;
163 if(data[begin + 1] ==
'{')
165 end = data.find(
"}", begin + 2);
166 envVariable = data.substr(begin + 2, end - begin - 2);
172 for(end = begin + 1; end < data.size(); ++end)
173 if(!((data[end] >=
'0' && data[end] <=
'9') ||
174 (data[end] >=
'A' && data[end] <=
'Z') ||
175 (data[end] >=
'a' && data[end] <=
'z') || data[end] ==
'-' ||
176 data[end] ==
'_' || data[end] ==
'.' || data[end] ==
':'))
178 envVariable = data.substr(begin + 1, end - begin - 1);
182 char* envResult = __ENV__(envVariable.c_str());
187 return convertEnvironmentVariables(
188 converted.replace(begin, end - begin, envResult));
192 __SS__ << (
"The environmental variable '" + envVariable +
193 "' is not set! Please make sure you set it before continuing!")
208 bool StringMacros::isNumber(
const std::string& s)
211 std::vector<std::string> numbers;
212 std::vector<char> ops;
214 StringMacros::getVectorFromString(
217 std::set<char>({
'+',
'-',
'*',
'/'}),
218 std::set<char>({
' ',
'\t',
'\n',
'\r'}),
224 for(
const auto& number : numbers)
226 if(number.size() == 0)
229 if(number.find(
"0x") == 0)
232 for(
unsigned int i = 2; i < number.size(); ++i)
234 if(!((number[i] >=
'0' && number[i] <=
'9') ||
235 (number[i] >=
'A' && number[i] <=
'F') ||
236 (number[i] >=
'a' && number[i] <=
'f')))
244 else if(number[0] ==
'b')
248 for(
unsigned int i = 1; i < number.size(); ++i)
250 if(!((number[i] >=
'0' && number[i] <=
'1')))
260 for(
unsigned int i = 0; i < number.size(); ++i)
261 if(!((number[i] >=
'0' && number[i] <=
'9') || number[i] ==
'.' ||
262 number[i] ==
'+' || number[i] ==
'-'))
282 std::string StringMacros::getNumberType(
const std::string& s)
285 std::vector<std::string> numbers;
286 std::vector<char> ops;
288 bool hasDecimal =
false;
290 StringMacros::getVectorFromString(
293 std::set<char>({
'+',
'-',
'*',
'/'}),
294 std::set<char>({
' ',
'\t',
'\n',
'\r'}),
300 for(
const auto& number : numbers)
302 if(number.size() == 0)
305 if(number.find(
"0x") == 0)
308 for(
unsigned int i = 2; i < number.size(); ++i)
310 if(!((number[i] >=
'0' && number[i] <=
'9') ||
311 (number[i] >=
'A' && number[i] <=
'F') ||
312 (number[i] >=
'a' && number[i] <=
'f')))
320 else if(number[0] ==
'b')
324 for(
unsigned int i = 1; i < number.size(); ++i)
326 if(!((number[i] >=
'0' && number[i] <=
'1')))
336 for(
unsigned int i = 0; i < number.size(); ++i)
337 if(!((number[i] >=
'0' && number[i] <=
'9') || number[i] ==
'.' ||
338 number[i] ==
'+' || number[i] ==
'-'))
340 else if(number[i] ==
'.')
353 return "unsigned long long";
362 bool StringMacros::getNumber(
const std::string& s,
bool& retValue)
366 __COUT_ERR__ <<
"Invalid empty bool string " << s << __E__;
371 if(s.find(
"1") != std::string::npos || s ==
"true" || s ==
"True" || s ==
"TRUE")
378 if(s.find(
"0") != std::string::npos || s ==
"false" || s ==
"False" || s ==
"FALSE")
384 __COUT_ERR__ <<
"Invalid bool string " << s << __E__;
393 std::string StringMacros::getTimestampString(
const std::string& linuxTimeInSeconds)
395 time_t timestamp(strtol(linuxTimeInSeconds.c_str(), 0, 10));
396 return getTimestampString(timestamp);
403 std::string StringMacros::getTimestampString(
const time_t& linuxTimeInSeconds)
405 std::string retValue(30,
'\0');
408 ::localtime_r(&linuxTimeInSeconds, &tmstruct);
409 ::strftime(&retValue[0], 30,
"%c %Z", &tmstruct);
410 retValue.resize(strlen(retValue.c_str()));
418 std::string StringMacros::validateValueForDefaultStringDataType(
419 const std::string& value,
bool doConvertEnvironmentVariables)
try
421 return doConvertEnvironmentVariables
422 ? StringMacros::convertEnvironmentVariables(value)
425 catch(
const std::runtime_error& e)
427 __SS__ <<
"Failed to validate value for default string data type. " << __E__
428 << e.what() << __E__;
436 void StringMacros::getSetFromString(
const std::string& inputString,
437 std::set<std::string>& setToReturn,
438 const std::set<char>& delimiter,
439 const std::set<char>& whitespace)
446 for(; j < inputString.size(); ++j)
447 if((whitespace.find(inputString[j]) !=
449 delimiter.find(inputString[j]) != delimiter.end()) &&
452 else if((whitespace.find(inputString[j]) !=
455 delimiter.find(inputString[j]) != delimiter.end()) &&
461 setToReturn.emplace(inputString.substr(i, j - i));
468 setToReturn.emplace(inputString.substr(i, j - i));
483 void StringMacros::getVectorFromString(
const std::string& inputString,
484 std::vector<std::string>& listToReturn,
485 const std::set<char>& delimiter,
486 const std::set<char>& whitespace,
487 std::vector<char>* listOfDelimiters)
492 std::set<char>::iterator delimeterSearchIt;
502 for(; c < inputString.size(); ++c)
506 delimeterSearchIt = delimiter.find(inputString[c]);
507 isDelimiter = delimeterSearchIt != delimiter.end();
512 if(whitespace.find(inputString[c]) !=
521 else if(whitespace.find(inputString[c]) != whitespace.end() &&
531 if(listOfDelimiters && listToReturn.size())
538 listOfDelimiters->push_back(lastDelimiter);
540 listToReturn.push_back(inputString.substr(i, j - i));
550 lastDelimiter = *delimeterSearchIt;
559 if(listOfDelimiters && listToReturn.size())
565 listOfDelimiters->push_back(lastDelimiter);
567 listToReturn.push_back(inputString.substr(i, j - i));
571 if(listOfDelimiters && listToReturn.size() - 1 != listOfDelimiters->size() &&
572 listToReturn.size() != listOfDelimiters->size())
574 __SS__ <<
"There is a mismatch in delimiters to entries (should be equal or one "
576 << listOfDelimiters->size() <<
" vs " << listToReturn.size() << __E__
577 <<
"Entries: " << StringMacros::vectorToString(listToReturn) << __E__
578 <<
"Delimiters: " << StringMacros::vectorToString(*listOfDelimiters)
597 std::vector<std::string> StringMacros::getVectorFromString(
598 const std::string& inputString,
599 const std::set<char>& delimiter,
600 const std::set<char>& whitespace,
601 std::vector<char>* listOfDelimiters)
603 std::vector<std::string> listToReturn;
605 StringMacros::getVectorFromString(
606 inputString, listToReturn, delimiter, whitespace, listOfDelimiters);
614 void StringMacros::getMapFromString(
const std::string& inputString,
615 std::map<std::string, std::string>& mapToReturn,
616 const std::set<char>& pairPairDelimiter,
617 const std::set<char>& nameValueDelimiter,
618 const std::set<char>& whitespace)
try
623 bool needValue =
false;
627 for(; j < inputString.size(); ++j)
630 if((whitespace.find(inputString[j]) !=
632 pairPairDelimiter.find(inputString[j]) != pairPairDelimiter.end()) &&
635 else if((whitespace.find(inputString[j]) !=
638 nameValueDelimiter.find(inputString[j]) !=
639 nameValueDelimiter.end()) &&
645 name = inputString.substr(i, j - i);
655 if((whitespace.find(inputString[j]) !=
657 nameValueDelimiter.find(inputString[j]) != nameValueDelimiter.end()) &&
660 else if((whitespace.find(inputString[j]) !=
663 pairPairDelimiter.find(inputString[j]) != pairPairDelimiter.end()) &&
670 mapToReturn.emplace(std::pair<std::string, std::string>(
672 validateValueForDefaultStringDataType(
673 inputString.substr(i, j - i))
676 if(!emplaceReturn.second)
678 __COUT__ <<
"Ignoring repetitive value ('"
679 << inputString.substr(i, j - i)
680 <<
"') and keeping current value ('"
681 << emplaceReturn.first->second <<
"'). " << __E__;
694 mapToReturn.emplace(std::pair<std::string, std::string>(
696 validateValueForDefaultStringDataType(
697 inputString.substr(i, j - i))
700 if(!emplaceReturn.second)
702 __COUT__ <<
"Ignoring repetitive value ('" << inputString.substr(i, j - i)
703 <<
"') and keeping current value ('" << emplaceReturn.first->second
708 catch(
const std::runtime_error& e)
710 __SS__ <<
"Error while extracting a map from the string '" << inputString
711 <<
"'... is it a valid map?" << __E__ << e.what() << __E__;
717 std::string StringMacros::mapToString(
const std::map<std::string, uint8_t>& mapToReturn,
718 const std::string& primaryDelimeter,
719 const std::string& secondaryDelimeter)
721 std::stringstream ss;
723 for(
auto& mapPair : mapToReturn)
728 ss << primaryDelimeter;
729 ss << mapPair.first << secondaryDelimeter << (
unsigned int)mapPair.second;
736 std::string StringMacros::setToString(
const std::set<uint8_t>& setToReturn,
737 const std::string& delimeter)
739 std::stringstream ss;
741 for(
auto& setValue : setToReturn)
747 ss << (
unsigned int)setValue;
754 std::string StringMacros::vectorToString(
const std::vector<uint8_t>& setToReturn,
755 const std::string& delimeter)
757 std::stringstream ss;
759 for(
auto& setValue : setToReturn)
765 ss << (
unsigned int)setValue;
773 std::string StringMacros::exec(
const char* cmd)
777 std::array<char, 128> buffer;
779 std::shared_ptr<FILE> pipe(popen(cmd,
"r"), pclose);
781 __THROW__(
"popen() failed!");
782 while(!feof(pipe.get()))
784 if(fgets(buffer.data(), 128, pipe.get()) !=
nullptr)
785 result += buffer.data();
795 #include <execinfo.h>
797 std::string StringMacros::stackTrace()
799 __SS__ <<
"ots::stackTrace:\n";
805 size = backtrace(array, 10);
809 char** messages = backtrace_symbols(array, size);
813 for(
unsigned int i = 1; i < size && messages != NULL; ++i)
826 char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
829 for(
char* p = messages[i]; *p; ++p)
847 if(mangled_name && offset_begin && offset_end && mangled_name < offset_begin)
849 *mangled_name++ =
'\0';
850 *offset_begin++ =
'\0';
851 *offset_end++ =
'\0';
854 char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
859 ss <<
"[" << i <<
"] " << messages[i] <<
" : " << real_name <<
"+"
860 << offset_begin << offset_end << std::endl;
865 ss <<
"[" << i <<
"] " << messages[i] <<
" : " << mangled_name <<
"+"
866 << offset_begin << offset_end << std::endl;
873 ss <<
"[" << i <<
"] " << messages[i] << std::endl;
891 char* StringMacros::otsGetEnvironmentVarable(
const char* name,
892 const std::string& location,
893 const unsigned int& line)
895 char* environmentVariablePtr = getenv(name);
896 if(!environmentVariablePtr)
898 __SS__ <<
"Environment variable '" << name <<
"' not defined at " << location
899 <<
"[" << line <<
"]" << __E__;
900 ss <<
"\n\n" << StringMacros::stackTrace() << __E__;
903 return environmentVariablePtr;
913 std::string StringMacros::demangleTypeName(
const char* name)
918 std::unique_ptr<char, void (*)(void*)> res{
919 abi::__cxa_demangle(name, NULL, NULL, &status), std::free};
921 return (status == 0) ? res.get() : name;
924 #else // does nothing if not g++
928 std::string StringMacros::demangleTypeName(
const char* name) {
return name; }