icedb  version 0.5.1
Snow particle scattering database API
Classes | Functions
icedb::splitSet Namespace Reference

Classes

class  intervals
 Class to define and search on intervals. More...
 

Functions

template<class T >
void stringifyRange (const T &Tstart, const T &Tend, const T &Tinterval, const std::string &Tspecializer, std::string &out)
 
template<class T >
void splitSet (const T &start, const T &end, const T &interval, const std::string &specializer, std::set< T > &expanded)
 Shortcut that already passes parsed ICEDB_LOG_INFOrmation. More...
 
 DOTYPES (SPEC_SPLITSET_A)
 
template<class T >
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. More...
 
 DOTYPES (SPEC_SPLITSET_INTERVAL)
 
template<class T >
void splitSet (const std::string &instr, std::set< T > &expanded, const std::map< std::string, std::string > *aliases)
 
template<>
void splitSet< std::string > (const std::string &instr, std::set< std::string > &expanded, const std::map< std::string, std::string > *aliases)
 
 DOTYPES (SPEC_SPLITSET)
 
void splitVector (const std::string &instr, std::vector< std::string > &out, char delim='\0')
 Convenience function to split a null-separated string list into a vector of strings. More...
 
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. More...
 
 DOTYPES (IMPL_INTS)
 
void splitNullVector (const std::string &instr, std::vector< std::string > &out)
 

Function Documentation

◆ DOTYPES() [1/4]

icedb::splitSet::DOTYPES ( SPEC_SPLITSET_A  )

◆ DOTYPES() [2/4]

icedb::splitSet::DOTYPES ( SPEC_SPLITSET_INTERVAL  )

◆ DOTYPES() [3/4]

icedb::splitSet::DOTYPES ( SPEC_SPLITSET  )

◆ DOTYPES() [4/4]

icedb::splitSet::DOTYPES ( IMPL_INTS  )

◆ extractInterval()

template<class T >
void icedb::splitSet::extractInterval ( const std::string &  instr,
T &  start,
T &  end,
T &  interval,
size_t &  num,
std::string &  specializer 
)

Extracts ICEDB_LOG_INFOrmation from interval notation.

Definition at line 180 of file splitSet.cpp.

References ICEDB_throw, and icedb::error::xInvalidRange.

Referenced by icedb::splitSet::intervals< T >::append().

183  {
184  using namespace std;
185  // Prepare tokenizer
186  typedef boost::tokenizer<boost::char_separator<char> >
187  tokenizer;
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);
192  vector<T> range;
193  size_t i = 0;
194  for (auto rt = trange.begin(); rt != trange.end(); rt++, i++)
195  {
196  try {
197  string s = *rt;
198  boost::algorithm::trim(s);
199  if (i < 3)
200  {
201  range.push_back(boost::lexical_cast<T>(s));
202  } else {
203  specializer = s;
204  }
205  }
206  catch (...)
207  {
208  ICEDB_throw(error::error_types::xInvalidRange)
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);
215  }
216  }
217  // Look at range. If one element, just add it. If two or
218  // three, calculate the inclusive interval
219  if (range.size() == 1)
220  {
221  start = range[0];
222  end = range[0];
223  interval = 0;
224  num = 1;
225  } else {
226  start = range[0];
227  end = range[range.size()-1];
228  interval = 0;
229  if (specializer.size())
230  {
231  if (range.size() > 2) num = (size_t) range[1];
232  } else {
233  if (range.size() > 2) interval = range[1];
234  // Linear spacing, starting at start.
235  num = (size_t) ( ( (end - start) / interval) + 1);
236  }
237  }
238  }
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88
Here is the caller graph for this function:

◆ splitNullMap()

void icedb::splitSet::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.

Commonly-used to split up the results of a Ryan_Debug::ProcessICEDB_LOG_INFO environment structure.

Definition at line 390 of file splitSet.cpp.

Referenced by splitNullVector().

392  {
393  using namespace std;
394  if (!instr.size()) return;
395 
396  // Fast string splitting based on null values.
397  const char* start = instr.data();
398  const char* stop = instr.data() + instr.size();
399  while (start < stop)
400  {
401  // Find the next null character
402  const char* sep = start;
403  sep = std::find(start, stop, '\0');
404  if (*start == '\0')
405  {
406  start = sep+1;
407  continue;
408  }
409  // Split based on location of equal sign
410  //out.push_back(std::string(start, sep - 1));
411  const char* sepc = std::find(start, sep, '=');
412  // If the = cannot be found, then it is a key with an empty value.
413  std::string key(start, sepc);
414  if (!key.size())
415  {
416  start = sep+1;
417  continue;
418  }
419  std::string val;
420  if (sepc < sep)
421  val = std::string(sepc + 1, sep);
422  out.insert(std::make_pair(key, val));
423  start = sep+1;
424  }
425  }
STL namespace.
Here is the caller graph for this function:

◆ splitNullVector()

void icedb::splitSet::splitNullVector ( const std::string &  instr,
std::vector< std::string > &  out 
)
inline

Definition at line 46 of file splitSet.hpp.

References splitNullMap(), and splitVector().

47  { splitVector(instr, out); }
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.
Definition: splitSet.cpp:365
Here is the call graph for this function:

◆ splitSet() [1/2]

template<class T >
void icedb::splitSet::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.

Definition at line 37 of file splitSet.cpp.

References ICEDB_throw, stringifyRange(), icedb::error::xDivByZero, and icedb::error::xInvalidRange.

Referenced by icedb::splitSet::intervals< T >::append().

41  {
42  using namespace std;
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);
49  std::string srange;
50  stringifyRange(Tstart,Tend,Tinterval,Tspecializer,srange);
51 
52  if (interval < 0) {
53  ICEDB_throw(error::error_types::xInvalidRange)
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);
60  }
61 
62  if (specializer == "")
63  {
64  if ((start > end && interval > 0) || (start < end && interval < 0))
65  {
66  ICEDB_throw(error::error_types::xInvalidRange)
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);
73  }
74  for (double j=start;j<=end+(interval/100.0);j+=interval)
75  {
76  if (expanded.count((T) j) == 0)
77  expanded.insert((T) j);
78  }
79  } else if (specializer == "lin") {
80  // Linear spacing
81  double increment = (end - start) / (interval); // so interval of 1 gives midpoint
82  if (!increment) expanded.insert((T) start);
83  for (double j=start+(increment/2.0); j<end+(increment/100.0);j+=increment)
84  {
85  if (expanded.count((T) j) == 0)
86  expanded.insert((T) j);
87  }
88  } else if (specializer == "log") {
89  if (start == 0 || end == 0)
90  ICEDB_throw(error::error_types::xDivByZero)
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)
102  {
103  double k = pow((double) 10.0, (double) j);
104  if (expanded.count((T) k) == 0)
105  expanded.insert((T) k);
106  }
107  } else if (specializer == "inv") {
108  if (start == 0 || end == 0)
109  ICEDB_throw(error::error_types::xDivByZero)
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)
121  {
122  double k = (1.0) / j;
123  if (expanded.count((T) k) == 0)
124  expanded.insert((T) k);
125  }
126  } else if (specializer == "cos") {
127  // Linear in cos
128  // start, end are in degrees
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) // nan check - occurs when selecting only one value, and bounds are the same
136  {
137  expanded.insert(start);
138  return;
139  }
140  if (increment < 0)
141  {
142  increment *= -1.0;
143  std::swap(cs,ce);
144  }
145  // For even n, divide into intervals and use the midpoint of the interval.
146  // For odd n, use the endpoints. Note that the weights for orientations
147  // (not computed here) will be different for the two choices.
148  if (!ai) cs += increment/2.0;
149  for (double j=cs; j<ce+(increment/10.0);j+=increment)
150  {
151  // max and min to avoid j>1 and j<-1 error from rounding
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);
155  }
156  } else {
157  ICEDB_throw(error::error_types::xInvalidRange)
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);
164  }
165  }
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88
void stringifyRange(const T &Tstart, const T &Tend, const T &Tinterval, const std::string &Tspecializer, std::string &out)
Definition: splitSet.cpp:23
Here is the call graph for this function:
Here is the caller graph for this function:

◆ splitSet() [2/2]

template<class T >
void icedb::splitSet::splitSet ( const std::string &  instr,
std::set< T > &  expanded,
const std::map< std::string, std::string > *  aliases = nullptr 
)

Function that expands sets of numbers with separators of commas, dashes and colons.

Definition at line 254 of file splitSet.cpp.

References ICEDB_throw, and icedb::error::xInvalidRange.

256  {
257  using namespace std;
258  // Prepare tokenizer
259  typedef boost::tokenizer<boost::char_separator<char> >
260  tokenizer;
261  boost::char_separator<char> sep(",");
262  boost::char_separator<char> seprange(":");
263  {
264  tokenizer tcom(instr,sep);
265  for (auto ot = tcom.begin(); ot != tcom.end(); ot++)
266  {
267  // At this junction, do any alias substitution
268  std::string ssubst;
269 
270  std::map<std::string, std::string> defaliases;
271  if (!aliases) aliases = &defaliases; // Provides a convenient default
272 
273  if (aliases->count(*ot))
274  {
275  ssubst = aliases->at(*ot);
276  // Recursively call splitSet to handle bundles of aliases
277  splitSet<T>(ssubst, expanded, aliases);
278  } else {
279  // Separated based on commas. Expand for dashes and colons
280  tokenizer trange(*ot,seprange);
281  vector<T> range;
282  string specializer;
283  size_t i = 0;
284  for (auto rt = trange.begin(); rt != trange.end(); rt++, i++)
285  {
286  try {
287  string s = *rt;
288  boost::algorithm::trim(s);
289  if (i < 3)
290  {
291  range.push_back(boost::lexical_cast<T>(s));
292  } else {
293  specializer = s;
294  }
295  }
296  catch (...)
297  {
298  ICEDB_throw(error::error_types::xInvalidRange)
299  .add<std::string>("range-name", instr);
300  }
301  }
302  // Look at range. If one element, just add it. If two or
303  // three, calculate the inclusive interval
304  if (range.size() == 1)
305  {
306  if (expanded.count(range[0]) == 0)
307  expanded.insert(range[0]);
308  } else {
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];
313 
314  // I'm moving the logic to the other template definition, as it
315  // let's me split stuff without casts back to strings.
316  splitSet<T>(start, end, interval, specializer, expanded);
317  }
318  }
319  }
320  }
321  }
STL namespace.
#define ICEDB_throw(x)
Definition: error.hpp:88

◆ splitSet< std::string >()

template<>
void icedb::splitSet::splitSet< std::string > ( const std::string &  instr,
std::set< std::string > &  expanded,
const std::map< std::string, std::string > *  aliases 
)

Specialization for splitting strings. These objects have no ranges to be compared against.

Definition at line 323 of file splitSet.cpp.

325  {
326  using namespace std;
327  // Prepare tokenizer
328  typedef boost::tokenizer<boost::char_separator<char> >
329  tokenizer;
330  boost::char_separator<char> sep(",;");
331 
332  std::string ssubst;
333 
334  std::map<std::string, std::string> defaliases;
335  if (!aliases) aliases = &defaliases; // Provides a convenient default
336 
337  tokenizer tcom(instr,sep);
338  for (auto ot = tcom.begin(); ot != tcom.end(); ot++)
339  {
340  if (aliases->count(*ot))
341  {
342  ssubst = aliases->at(*ot);
343  // Recursively call splitSet to handle bundles of aliases
344  splitSet<std::string>(ssubst, expanded, aliases);
345  } else {
346  if (expanded.count(*ot) == 0)
347  expanded.insert(*ot);
348  }
349  }
350  }
STL namespace.

◆ splitVector()

void icedb::splitSet::splitVector ( const std::string &  instr,
std::vector< std::string > &  out,
char  delim = '\0' 
)

Convenience function to split a null-separated string list into a vector of strings.

Commonly-used to split up the results of a Ryan_Debug::ProcessICEDB_LOG_INFO command-line structure.

Definition at line 365 of file splitSet.cpp.

Referenced by icedb::splitSet::intervals< T >::append(), and splitNullVector().

367  {
368  using namespace std;
369  //out.clear();
370  if (!instr.size()) return;
371 
372  // Fast string splitting based on null values.
373  const char* start = instr.data();
374  const char* stop = instr.data() + instr.size();
375  while (start < stop)
376  {
377  // Find the next null character
378  const char* sep = start;
379  sep = std::find(start, stop, delim);
380  if (*start == delim)
381  {
382  start = sep+1;
383  continue;
384  }
385  out.push_back(std::string(start, sep));
386  start = sep+1;
387  }
388  }
STL namespace.
Here is the caller graph for this function:

◆ stringifyRange()

template<class T >
void icedb::splitSet::stringifyRange ( const T &  Tstart,
const T &  Tend,
const T &  Tinterval,
const std::string &  Tspecializer,
std::string &  out 
)

Definition at line 23 of file splitSet.cpp.

Referenced by splitSet().

25  {
26  using namespace std;
27  ostringstream os;
28  os << Tstart << ":" << Tinterval << ":" << Tend << ":"
29  << Tspecializer;
30  out = os.str();
31  }
STL namespace.
Here is the caller graph for this function: