6 #include <boost/exception/all.hpp> 7 #include <boost/math/constants/constants.hpp> 8 #include <boost/tokenizer.hpp> 9 #include <boost/lexical_cast.hpp> 10 #include <boost/algorithm/string/trim.hpp> 14 #include "../icedb/splitSet.hpp" 15 #include "../icedb/error.hpp" 17 #pragma warning( disable : 4244 ) // lots of template math involves doubles, and I'm sick of static casting 24 const std::string &Tspecializer, std::string &out)
28 os << Tstart <<
":" << Tinterval <<
":" << Tend <<
":" 33 #define DOTYPES(f) f(int); f(float); f(double); f(long); f(long long); \ 34 f(unsigned int); f(unsigned long); f(unsigned long long); 38 const T &Tstart,
const T &Tend,
const T &Tinterval,
39 const std::string &Tspecializer,
40 std::set<T> &expanded)
43 double start, end, interval;
44 start = boost::lexical_cast<
double>(Tstart);
45 end = boost::lexical_cast<
double>(Tend);
46 interval = boost::lexical_cast<
double>(Tinterval);
47 std::string specializer(Tspecializer);
48 std::transform(specializer.begin(),specializer.end(),specializer.begin(),::tolower);
54 .add<std::string>(
"range-name", srange)
55 .add<std::string>(
"specializer-type", specializer)
56 .add<
double>(
"interval", interval)
57 .
template add<T>(
"Tstart", Tstart)
58 .template add<T>(
"Tend", Tend)
59 .
template add<T>(
"Tinterval", Tinterval);
62 if (specializer ==
"")
64 if ((start > end && interval > 0) || (start < end && interval < 0))
67 .add<std::string>(
"range-name", srange)
68 .add<std::string>(
"specializer-type", specializer)
69 .add<
double>(
"interval", interval)
70 .
template add<T>(
"Tstart", Tstart)
71 .template add<T>(
"Tend", Tend)
72 .
template add<T>(
"Tinterval", Tinterval);
74 for (
double j=start;j<=end+(interval/100.0);j+=interval)
76 if (expanded.count((T) j) == 0)
77 expanded.insert((T) j);
79 }
else if (specializer ==
"lin") {
81 double increment = (end - start) / (interval);
82 if (!increment) expanded.insert((T) start);
83 for (
double j=start+(increment/2.0); j<end+(increment/100.0);j+=increment)
85 if (expanded.count((T) j) == 0)
86 expanded.insert((T) j);
88 }
else if (specializer ==
"log") {
89 if (start == 0 || end == 0)
91 .add<std::string>(
"range-name", srange)
92 .add<std::string>(
"specializer-type", specializer)
93 .add<
double>(
"interval", interval)
94 .
template add<T>(
"Tstart", Tstart)
95 .template add<T>(
"Tend", Tend)
96 .
template add<T>(
"Tinterval", Tinterval);
97 double is = log10( (
double) start);
98 double ie = log10( (
double) end);
99 double increment = (ie - is) / (interval);
100 if (!increment) expanded.insert((T) start);
101 for (
double j=is+(increment/2.0); j<ie+(increment/100.0);j+=increment)
103 double k = pow((
double) 10.0, (
double) j);
104 if (expanded.count((T) k) == 0)
105 expanded.insert((T) k);
107 }
else if (specializer ==
"inv") {
108 if (start == 0 || end == 0)
110 .add<std::string>(
"range-name", srange)
111 .add<std::string>(
"specializer-type", specializer)
112 .add<
double>(
"interval", interval)
113 .
template add<T>(
"Tstart", Tstart)
114 .template add<T>(
"Tend", Tend)
115 .
template add<T>(
"Tinterval", Tinterval);
116 double is = 1.0 / start;
117 double ie = 1.0 / end;
118 double increment = (is - ie) / (interval);
119 if (!increment) expanded.insert((T) start);
120 for (
double j=ie+(increment/2.0); j<is+(increment/100.0);j+=increment)
122 double k = (1.0) / j;
123 if (expanded.count((T) k) == 0)
124 expanded.insert((T) k);
126 }
else if (specializer ==
"cos") {
129 const double pi = boost::math::constants::pi<double>();
130 int ai = (int) (interval) % 2;
131 double cs = cos(start * pi / 180.0);
132 double ce = cos(end * pi / 180.0);
133 double increment = (ai) ? (ce - cs) / (interval-1) : (ce - cs) / (interval);
134 if (increment == 0) expanded.insert(start);
135 if (increment != increment)
137 expanded.insert(start);
148 if (!ai) cs += increment/2.0;
149 for (
double j=cs; j<ce+(increment/10.0);j+=increment)
152 double k = (acos((
double) max(min(j,1.0),-1.0)) * 180.0 / pi);
153 if (expanded.count((T) k) == 0)
154 expanded.insert((T) k);
158 .add<std::string>(
"range-name", srange)
159 .add<std::string>(
"specializer-type", specializer)
160 .add<
double>(
"interval", interval)
161 .
template add<T>(
"Tstart", Tstart)
162 .template add<T>(
"Tend", Tend)
163 .
template add<T>(
"Tinterval", Tinterval);
167 #define SPEC_SPLITSET_A(T) \ 168 template DL_ICEDB void splitSet<T>(const T&, const T&, \ 169 const T&, const std::string&, std::set<T> &); 181 const std::string &instr,
182 T &start, T &end, T &interval,
size_t &num, std::string &specializer)
186 typedef boost::tokenizer<boost::char_separator<char> >
188 boost::char_separator<char> seprange(
":/");
189 bool isRange =
false;
190 if (instr.find(
'/') != string::npos) { isRange =
true; specializer =
"range"; }
191 tokenizer trange(instr,seprange);
194 for (
auto rt = trange.begin(); rt != trange.end(); rt++, i++)
198 boost::algorithm::trim(s);
201 range.push_back(boost::lexical_cast<T>(s));
209 .add<std::string>(
"range-name", instr)
210 .add<std::string>(
"specializer-type", specializer)
211 .add<
double>(
"interval", interval)
212 .
template add<T>(
"Tstart", start)
213 .template add<T>(
"Tend", end)
214 .
template add<size_t>(
"num", num);
219 if (range.size() == 1)
227 end = range[range.size()-1];
229 if (specializer.size())
231 if (range.size() > 2) num = (
size_t) range[1];
233 if (range.size() > 2) interval = range[1];
235 num = (size_t) ( ( (end - start) / interval) + 1);
240 #define SPEC_SPLITSET_INTERVAL(T) \ 241 template DL_ICEDB void extractInterval<T>( \ 242 const std::string&, T&, T&, T&, size_t&, std::string&); 254 void splitSet(
const std::string &instr, std::set<T> &expanded,
255 const std::map<std::string, std::string> *aliases)
259 typedef boost::tokenizer<boost::char_separator<char> >
261 boost::char_separator<char> sep(
",");
262 boost::char_separator<char> seprange(
":");
264 tokenizer tcom(instr,sep);
265 for (
auto ot = tcom.begin(); ot != tcom.end(); ot++)
270 std::map<std::string, std::string> defaliases;
271 if (!aliases) aliases = &defaliases;
273 if (aliases->count(*ot))
275 ssubst = aliases->at(*ot);
277 splitSet<T>(ssubst, expanded, aliases);
280 tokenizer trange(*ot,seprange);
284 for (
auto rt = trange.begin(); rt != trange.end(); rt++, i++)
288 boost::algorithm::trim(s);
291 range.push_back(boost::lexical_cast<T>(s));
299 .add<std::string>(
"range-name", instr);
304 if (range.size() == 1)
306 if (expanded.count(range[0]) == 0)
307 expanded.insert(range[0]);
309 double start, end = 0, interval = 1;
310 start = (double) range[0];
311 end = (double) range[range.size()-1];
312 if (range.size() > 2) interval = (
double) range[1];
316 splitSet<T>(start, end, interval, specializer, expanded);
323 template <>
void splitSet<std::string>(
const std::string &instr, std::set<std::string> &expanded,
324 const std::map<std::string, std::string> *aliases)
328 typedef boost::tokenizer<boost::char_separator<char> >
330 boost::char_separator<char> sep(
",;");
334 std::map<std::string, std::string> defaliases;
335 if (!aliases) aliases = &defaliases;
337 tokenizer tcom(instr,sep);
338 for (
auto ot = tcom.begin(); ot != tcom.end(); ot++)
340 if (aliases->count(*ot))
342 ssubst = aliases->at(*ot);
344 splitSet<std::string>(ssubst, expanded, aliases);
346 if (expanded.count(*ot) == 0)
347 expanded.insert(*ot);
352 #define SPEC_SPLITSET(T) \ 353 template DL_ICEDB void splitSet<T>(const std::string &instr, std::set<T> &expanded, \ 354 const std::map<std::string, std::string> *aliases); 366 const std::string &instr, std::vector<std::string> &out,
char delim)
370 if (!instr.size())
return;
373 const char* start = instr.data();
374 const char* stop = instr.data() + instr.size();
378 const char* sep = start;
379 sep = std::find(start, stop, delim);
385 out.push_back(std::string(start, sep));
391 const std::string &instr, std::map<std::string, std::string> &out)
394 if (!instr.size())
return;
397 const char* start = instr.data();
398 const char* stop = instr.data() + instr.size();
402 const char* sep = start;
403 sep = std::find(start, stop,
'\0');
411 const char* sepc = std::find(start, sep,
'=');
413 std::string key(start, sepc);
421 val = std::string(sepc + 1, sep);
422 out.insert(std::make_pair(key, val));
439 const std::map<std::string, std::string> *aliases)
441 std::vector<std::string> splits;
444 for (
const auto &s : splits)
446 std::map<std::string, std::string> defaliases;
447 if (!aliases) aliases = &defaliases;
449 if (aliases->count(s))
451 std::string ssubst = aliases->at(s);
453 append(ssubst, aliases);
456 T start, end, interval;
458 std::string specializer;
459 bool isRange =
false;
461 if (specializer ==
"range")
463 ranges.push_back(std::pair<T, T>(start, end));
464 }
else if (start == end) {
465 ranges.push_back(std::pair<T, T>(start, end));
467 splitSet(start, end, interval, specializer, vals);
471 for (
const auto &v : vals)
473 ranges.push_back(std::pair<T, T>(v, v));
479 const std::map<std::string, std::string> *aliases)
481 for (
const auto &str : s) append(str, aliases);
487 ranges.insert(ranges.end(), src.
ranges.begin(), src.
ranges.end());
492 for (
const auto &r : ranges)
494 if (val >= r.first && val < r.second)
return true;
495 if (r.first == r.second) {
496 if (val == r.first)
return true;
504 for (
const auto &r : ranges)
506 T lower = (r.first * (
static_cast<T
>(1) - factorSep)) - linSep,
507 upper = (r.second * (static_cast<T>(1) + factorSep)) + linSep;
508 if (val >= lower && val < upper)
return true;
513 #define IMPL_INTS(T) template class DL_ICEDB intervals < T >; bool isNear(const T &val, const T &linSep, const T &factorSep) const
void extractInterval(const std::string &instr, T &start, T &end, T &interval, size_t &num, std::string &specializer)
Extracts ICEDB_LOG_INFOrmation from interval notation.
#define SPEC_SPLITSET_INTERVAL(T)
Class to define and search on intervals.
void splitSet(const std::string &instr, std::set< T > &expanded, const std::map< std::string, std::string > *aliases)
intervals(const std::string &s="")
void splitNullMap(const std::string &instr, std::map< std::string, std::string > &out)
Convenience function to split a null-separated string list into a map of strings. ...
void append(const std::string &instr, const std::map< std::string, std::string > *aliases=nullptr)
void splitVector(const std::string &instr, std::vector< std::string > &out, char delim)
Convenience function to split a null-separated string list into a vector of strings.
void splitSet(const T &Tstart, const T &Tend, const T &Tinterval, const std::string &Tspecializer, std::set< T > &expanded)
Shortcut that already passes parsed ICEDB_LOG_INFOrmation.
void stringifyRange(const T &Tstart, const T &Tend, const T &Tinterval, const std::string &Tspecializer, std::string &out)
#define SPEC_SPLITSET_A(T)
bool inRange(const T &val) const
std::vector< std::pair< T, T > > ranges