1 #ifndef _ots_String_Macros_h_
2 #define _ots_String_Macros_h_
4 #include "otsdaq-core/Macros/CoutMacros.h"
39 static bool wildCardMatch (
const std::string& needle,
const std::string& haystack,
unsigned int* priorityIndex = 0);
40 static bool inWildCardSet (
const std::string needle,
const std::set<std::string>& haystack);
48 static const T& getWildCardMatchFromMap (
const std::string needle,
const std::map<std::string,T>& haystack)
50 unsigned int matchPriority, bestMatchPriority = 0;
54 __SS__ <<
"Needle '" << needle <<
"' not found in EMPTY wildcard haystack:" << __E__;
55 throw std::runtime_error(ss.str());
60 std::string bestMatchKey;
61 for(
const auto& haystackPair : haystack)
64 if(StringMacros::wildCardMatch(haystackPair.first,needle,
67 if(matchPriority == 1)
68 return haystackPair.second;
70 if(!bestMatchPriority || matchPriority < bestMatchPriority)
73 bestMatchPriority = matchPriority;
74 bestMatchKey = haystackPair.first;
83 return haystack.at(bestMatchKey);
86 __SS__ <<
"Needle '" << needle <<
"' not found in wildcard haystack:" << __E__;
88 for(
const auto& haystackPair : haystack)
91 ss <<
", " << haystackPair.first;
95 ss <<
", " << haystackPair.first;
96 throw std::runtime_error(ss.str());
99 static std::string decodeURIComponent (
const std::string& data);
100 static std::string convertEnvironmentVariables (
const std::string& data);
101 static bool isNumber (
const std::string& s);
104 static bool getNumber (
const std::string& s, T& retValue)
107 std::vector<std::string> numbers;
108 std::vector<char> ops;
110 StringMacros::getVectorFromString(s,numbers,
111 std::set<char>({
'+',
'-',
'*',
'/'}),
112 std::set<char>({
' ',
'\t',
'\n',
'\r'}),
120 for(
const auto& number:numbers)
122 if(number.size() == 0)
continue;
131 if(
typeid(
unsigned int) ==
typeid(retValue) ||
132 typeid(
int) ==
typeid(retValue) ||
133 typeid(
unsigned long long) ==
typeid(retValue) ||
134 typeid(
long long) ==
typeid(retValue) ||
135 typeid(
unsigned long) ==
typeid(retValue) ||
136 typeid(
long) ==
typeid(retValue) ||
137 typeid(
unsigned short) ==
typeid(retValue) ||
138 typeid(
short) ==
typeid(retValue) ||
139 typeid(uint8_t) ==
typeid(retValue))
141 if(number.find(
"0x") == 0)
144 for(
unsigned int i=2;i<number.size();++i)
146 if(!((number[i] >=
'0' && number[i] <=
'9') ||
147 (number[i] >=
'A' && number[i] <=
'F') ||
148 (number[i] >=
'a' && number[i] <=
'f')
157 else if(number[0] ==
'b')
161 for(
unsigned int i=1;i<number.size();++i)
163 if(!((number[i] >=
'0' && number[i] <=
'1')
176 for(
unsigned int i=0;i<number.size();++i)
177 if(!((number[i] >=
'0' && number[i] <=
'9') ||
185 if(
typeid(
double) ==
typeid(retValue))
186 tmpValue = strtod(number.c_str(),0);
187 else if(
typeid(
float) ==
typeid(retValue))
188 tmpValue = strtof(number.c_str(),0);
189 else if(
typeid(
unsigned int) ==
typeid(retValue) ||
190 typeid(
int) ==
typeid(retValue) ||
191 typeid(
unsigned long long) ==
typeid(retValue) ||
192 typeid(
long long) ==
typeid(retValue) ||
193 typeid(
unsigned long) ==
typeid(retValue) ||
194 typeid(
long) ==
typeid(retValue) ||
195 typeid(
unsigned short) ==
typeid(retValue) ||
196 typeid(
short) ==
typeid(retValue) ||
197 typeid(uint8_t) ==
typeid(retValue))
199 if(number.size() > 2 && number[1] ==
'x')
200 tmpValue = (T)strtol(number.c_str(),0,16);
201 else if(number.size() > 1 && number[0] ==
'b')
202 tmpValue = (T)strtol(number.substr(1).c_str(),0,2);
204 tmpValue = (T)strtol(number.c_str(),0,10);
208 __SS__ <<
"Invalid type '" <<
209 StringMacros::demangleTypeName(
typeid(retValue).name()) <<
210 "' requested for a numeric string. Data was '" <<
211 number <<
"'" << __E__;
222 __COUTV__(StringMacros::vectorToString(numbers));
223 __COUTV__(StringMacros::vectorToString(ops));
230 retValue += tmpValue;
233 retValue -= tmpValue;
236 retValue *= tmpValue;
239 retValue /= tmpValue;
242 __SS__ <<
"Unrecognized operation '" << ops[i-1] <<
"' found!" << __E__ <<
244 StringMacros::vectorToString(numbers) << __E__ <<
246 StringMacros::vectorToString(ops) << __E__;
261 static T validateValueForDefaultStringDataType (
const std::string& value,
bool doConvertEnvironmentVariables=
true)
267 std::string data = doConvertEnvironmentVariables?convertEnvironmentVariables(value):
271 if(StringMacros::getNumber(data,retValue))
275 __SS__ <<
"Invalid type '" <<
276 StringMacros::demangleTypeName(
typeid(retValue).name()) <<
277 "' requested for a non-numeric string (must request std::string). Data was '" <<
278 data <<
"'" << __E__;
282 catch(
const std::runtime_error& e)
284 __SS__ <<
"Failed to validate the string value for the data type '" <<
285 StringMacros::demangleTypeName(
typeid(retValue).name()) <<
286 "' requested. " << __E__ << e.what() << __E__;
290 static std::string validateValueForDefaultStringDataType (
const std::string& value,
bool doConvertEnvironmentVariables=
true);
293 static void getSetFromString (
const std::string& inputString, std::set<std::string>& setToReturn,
const std::set<char>& delimiter = {
',',
'|',
'&'},
const std::set<char>& whitespace = {
' ',
'\t',
'\n',
'\r'});
294 static void getVectorFromString (
const std::string& inputString, std::vector<std::string>& listToReturn,
const std::set<char>& delimiter = {
',',
'|',
'&'},
const std::set<char>& whitespace = {
' ',
'\t',
'\n',
'\r'}, std::vector<char>* listOfDelimiters = 0);
296 static void getMapFromString (
const std::string& inputString, std::map<std::string,T>& mapToReturn,
const std::set<char>& pairPairDelimiter = {
',',
'|',
'&'},
const std::set<char>& nameValueDelimiter = {
'=',
':'},
const std::set<char>& whitespace = {
' ',
'\t',
'\n',
'\r'})
302 bool needValue =
false;
306 for(;j<inputString.size();++j)
309 if((whitespace.find(inputString[j]) != whitespace.end() ||
310 pairPairDelimiter.find(inputString[j]) != pairPairDelimiter.end())
313 else if((whitespace.find(inputString[j]) != whitespace.end() ||
314 nameValueDelimiter.find(inputString[j]) != nameValueDelimiter.end())
320 name = inputString.substr(i,j-i);
330 if((whitespace.find(inputString[j]) != whitespace.end() ||
331 nameValueDelimiter.find(inputString[j]) != nameValueDelimiter.end())
334 else if((whitespace.find(inputString[j]) != whitespace.end() ||
335 pairPairDelimiter.find(inputString[j]) != pairPairDelimiter.end())
341 auto emplaceReturn = mapToReturn.emplace(std::pair<std::string,T>(
343 validateValueForDefaultStringDataType<T>(
344 inputString.substr(i,j-i))
347 if(!emplaceReturn.second)
349 __COUT__ <<
"Ignoring repetitive value ('" << inputString.substr(i,j-i) <<
350 "') and keeping current value ('" << emplaceReturn.first->second <<
"'). " << __E__;
362 auto emplaceReturn = mapToReturn.emplace(std::pair<std::string,T>(
364 validateValueForDefaultStringDataType<T>(
365 inputString.substr(i,j-i))
368 if(!emplaceReturn.second)
370 __COUT__ <<
"Ignoring repetitive value ('" << inputString.substr(i,j-i) <<
371 "') and keeping current value ('" << emplaceReturn.first->second <<
"'). " << __E__;
375 catch(
const std::runtime_error &e)
377 __SS__ <<
"Error while extracting a map from the string '" <<
378 inputString <<
"'... is it a valid map?" << __E__ << e.what() << __E__;
382 static void getMapFromString (
const std::string& inputString, std::map<std::string,std::string>& mapToReturn,
const std::set<char>& pairPairDelimiter = {
',',
'|',
'&'},
const std::set<char>& nameValueDelimiter = {
'=',
':'},
const std::set<char>& whitespace = {
' ',
'\t',
'\n',
'\r'});
384 static std::string mapToString (
const std::map<std::string,T>& mapToReturn,
const std::string& primaryDelimeter =
",",
const std::string& secondaryDelimeter =
": ")
386 std::stringstream ss;
388 for(
auto& mapPair:mapToReturn)
390 if(first) first =
false;
391 else ss << primaryDelimeter;
392 ss << mapPair.first << secondaryDelimeter <<
397 static std::string mapToString (
const std::map<std::string,uint8_t>& mapToReturn,
const std::string& primaryDelimeter =
",",
const std::string& secondaryDelimeter =
": ");
399 static std::string setToString (
const std::set<T>& setToReturn,
const std::string& delimeter =
",")
401 std::stringstream ss;
403 for(
auto& setValue:setToReturn)
405 if(first) first =
false;
406 else ss << delimeter;
411 static std::string setToString (
const std::set<uint8_t>& setToReturn,
const std::string& delimeter =
",");
413 static std::string vectorToString (
const std::vector<T>& setToReturn,
const std::string& delimeter =
",")
415 std::stringstream ss;
417 for(
auto& setValue:setToReturn)
419 if(first) first =
false;
420 else ss << delimeter;
425 static std::string vectorToString (
const std::vector<uint8_t>& setToReturn,
const std::string& delimeter =
",");
427 static std::string demangleTypeName (
const char* name);