ewmscp  ..
Classes | Functions | Variables
options::internal Namespace Reference

template specialisation for options that are std::chrono::time_point<std::chrono::system_clock> More...

Classes

class  baseForContainer
 This class is an intermediate helper class for options that are container-based. More...
 
class  baseForMap
 This class is an intermediate helper class for options that are map-based. More...
 
class  conversionError
 
class  NoCfgFileRecursion
 standard option to suppress parsing of config files within config files More...
 
class  optionError
 
class  OptionHelp
 special derived class used to give help More...
 
class  OptionReadCfgFile
 special derived class used to read in config files More...
 
class  OptionWriteCfgFile
 special derived class used to write out config files More...
 
class  positional_base
 
class  rangeError
 
class  sourceFile
 class to remember the file (or cmd line) an option was set from More...
 
class  sourceItem
 class to remember from which line (or item) of a file/line an option was set from More...
 
class  supressed
 special class for options which never have a value setting in cfg files More...
 
class  typed_base
 
class  typedRangeError
 

Functions

template<typename T >
void conCatStr (std::ostringstream &msg, const T &begin)
 
template<typename T , typename ... Args>
void conCatStr (std::ostringstream &msg, const T &begin, const Args &... args)
 
template<typename ... Args>
std::string conCat (const Args &... args)
 
std::chrono::duration< double > parseNumberAndUnit (std::stringstream &aStream, int *aMonths=nullptr, int *aYears=nullptr)
 
std::chrono::system_clock::time_point fParseTimePointString (const std::string &aString)
 
template<class Rep , class Period >
void parseDurationString (std::chrono::duration< Rep, Period > &aDuration, const std::string &aString, int *aMonths=nullptr, int *aYears=nullptr)
 parse a string into a std::chrono::duration, if given set the years and months separately More...
 
bool fParseStreamToBrokenDownTime (std::istream &aStream, std::tm *aBrokenDownTime, double &aFractional, std::string &timezone)
 

Variables

static single< bool > gOptionDebugOptions ('\0', "debugOptions", "give debug output to option parsing")
 standard option for producing debug output about the options More...
 
static single< bool > gOptionNoCfgFiles ('\0', "noCfgFiles", "do not read the default config files, must be FIRST option")
 standard option to suppress parsing of config files More...
 
static NoCfgFileRecursion gNoCfgFileRecursion
 
static OptionHelp gHelp
 
static OptionWriteCfgFile gWriteCfgFile
 
static OptionReadCfgFile< false > gReadCfgFile ("readCfgFile", "read a config file")
 
static OptionReadCfgFile< true > gReadCfgFileIfThere ("readCfgFileIfThere", "read a config file if it's there")
 

Detailed Description

template specialisation for options that are std::chrono::time_point<std::chrono::system_clock>

special namespace for classes and functions that are meant for internal use only

Function Documentation

◆ conCat()

template<typename ... Args>
std::string options::internal::conCat ( const Args &...  args)
inline

Definition at line 338 of file Options.h.

338  {
339  std::ostringstream msg;
340  conCatStr(msg, args...);
341  return msg.str();
342  }

References conCatStr().

Referenced by options::base::base(), options::base::fHandleOption(), options::parser::fParse(), options::parser::fReadCfgFile(), and options::map< T >::fSetMe().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ conCatStr() [1/2]

template<typename T >
void options::internal::conCatStr ( std::ostringstream &  msg,
const T &  begin 
)

Definition at line 327 of file Options.h.

327  {
328  msg << begin;
329  }

Referenced by conCat(), and conCatStr().

Here is the caller graph for this function:

◆ conCatStr() [2/2]

template<typename T , typename ... Args>
void options::internal::conCatStr ( std::ostringstream &  msg,
const T &  begin,
const Args &...  args 
)
inline

Definition at line 330 of file Options.h.

332  {
333  msg << begin;
334  if (sizeof...(args)) {
335  conCatStr(msg, args...);
336  }
337  }

References conCatStr().

Here is the call graph for this function:

◆ fParseStreamToBrokenDownTime()

bool options::internal::fParseStreamToBrokenDownTime ( std::istream &  aStream,
std::tm *  aBrokenDownTime,
double &  aFractional,
std::string &  timezone 
)

Definition at line 146 of file OptionsChrono.cpp.

146  {
147  aStream >> aBrokenDownTime->tm_year;
148  if (aStream.fail() || aStream.get() != '/') {
149  return false;
150  }
151  aStream >> aBrokenDownTime->tm_mon;
152  if (aStream.fail() || aStream.get() != '/') {
153  return false;
154  }
155  aStream >> aBrokenDownTime->tm_mday;
156  if (aStream.fail()) {
157  return false;
158  }
159  aStream >> aBrokenDownTime->tm_hour;
160  if (!aStream.fail()) {
161  if (aStream.get() != ':') {
162  return false;
163  }
164  aStream >> aBrokenDownTime->tm_min;
165  if (aStream.fail()) {
166  return false;
167  }
168  if (aStream.peek() == ':') {
169  aStream.get();
170  aStream >> aFractional;
171  aBrokenDownTime->tm_sec = aFractional;
172  aFractional -= aBrokenDownTime->tm_sec;
173  if (aStream.fail()) {
174  return false;
175  }
176  }
177  }
178  aStream >> timezone;
179 
180  return true;
181  }

Referenced by fParseTimePointString().

Here is the caller graph for this function:

◆ fParseTimePointString()

std::chrono::system_clock::time_point options::internal::fParseTimePointString ( const std::string &  aString)

Definition at line 183 of file OptionsChrono.cpp.

183  {
184  std::string::size_type pointStringStart = 0;
185  std::string::size_type pointStringLength = std::string::npos;
186  std::string::size_type offsetStringStart = std::string::npos;
187  std::string::size_type offsetStringLength = std::string::npos;
188  bool offsetIsNegative = false;
189  {
190  auto after = aString.find("after");
191  if (after == 0) { // we have no time point
192  offsetStringStart = 6; // the offset starts after after
193  pointStringStart = std::string::npos;
194  } else if (after != std::string::npos) { // "after" after the offset before the point
195  offsetStringStart = 0;
196  offsetStringLength = after - 1;
197  pointStringStart = after + 6;
198  }
199  }
200  {
201  auto before = aString.find("before");
202  if (before == 0) { // we have no time point
203  offsetStringStart = 6; // the offset starts after before
204  pointStringStart = std::string::npos;
205  offsetIsNegative = true;
206  } else if (before != std::string::npos) { // "before" after the offset before the point
207  offsetStringStart = 0;
208  offsetStringLength = before - 1;
209  pointStringStart = before + 7;
210  offsetIsNegative = true;
211  }
212  }
213 
214  std::chrono::system_clock::time_point timePoint;
215  enum dateBitType {
216  kNow = 1 << 0,
217  kToday = 1 << 1,
218  kTomorrow = 1 << 2,
219  kYesterday = 1 << 3,
220  kWeekday = 1 << 4,
221  kDay = kToday | kTomorrow | kYesterday | kWeekday,
222  kLast = 1 << 5,
223  kThis = 1 << 6,
224  kNoon = 1 << 7
225 
226  };
227  if (pointStringStart < aString.size()) {
228  auto pointString = aString.substr(pointStringStart, pointStringLength);
229  std::transform(pointString.begin(), pointString.end(), pointString.begin(), ::tolower);
230 
231  typename std::underlying_type<dateBitType>::type dateBits = 0;
232  int weekDay = 0;
233  if (pointString.find("now") != std::string::npos) {
234  dateBits |= kNow;
235  } else if (pointString.find("today") != std::string::npos) {
236  dateBits |= kToday;
237  } else if (pointString.find("yesterday") != std::string::npos) {
238  dateBits |= kYesterday;
239  } else if (pointString.find("tomorrow") != std::string::npos) {
240  dateBits |= kTomorrow;
241  } else if (pointString.find("sun") != std::string::npos) {
242  dateBits |= kWeekday;
243  weekDay = 0;
244  } else if (pointString.find("mon") != std::string::npos) {
245  dateBits |= kWeekday;
246  weekDay = 1;
247  } else if (pointString.find("tue") != std::string::npos) {
248  dateBits |= kWeekday;
249  weekDay = 2;
250  } else if (pointString.find("wed") != std::string::npos) {
251  dateBits |= kWeekday;
252  weekDay = 3;
253  } else if (pointString.find("thu") != std::string::npos) {
254  dateBits |= kWeekday;
255  weekDay = 4;
256  } else if (pointString.find("fri") != std::string::npos) {
257  dateBits |= kWeekday;
258  weekDay = 5;
259  } else if (pointString.find("sat") != std::string::npos) {
260  dateBits |= kWeekday;
261  weekDay = 6;
262  }
263  if (pointString.find("noon") != std::string::npos) {
264  dateBits |= kNoon;
265  }
266  if (pointString.find("last") != std::string::npos) {
267  dateBits |= kLast;
268  }
269  if (pointString.find("this") != std::string::npos) {
270  dateBits |= kThis;
271  }
272 
273  if (dateBits != 0) {
274  timePoint = std::chrono::system_clock::now();
275  if (dateBits & kDay) {
276  auto coarse_time = std::chrono::system_clock::to_time_t(timePoint);
277  auto broken_down_time = std::localtime(&coarse_time);
278 
279  broken_down_time->tm_sec = 0;
280  broken_down_time->tm_min = 0;
281  broken_down_time->tm_hour = (dateBits & kNoon) ? 12 : 0;
282  if (dateBits & kYesterday) {
283  broken_down_time->tm_mday--;
284  } else if (dateBits & kTomorrow) {
285  broken_down_time->tm_mday++;
286  } else if (dateBits & kWeekday) {
287  auto dayOffset = weekDay - broken_down_time->tm_wday;
288  if (dateBits & kLast) {
289  if (dayOffset >= 0) {
290  dayOffset -= 7;
291  }
292  } else if (dateBits & kThis) {
293  // no change to the Offset
294  } else { // we imply the next day of that name
295  if (dayOffset <= 0) {
296  dayOffset += 7;
297  }
298  }
299  broken_down_time->tm_mday += dayOffset;
300  }
301 
302  timePoint = std::chrono::system_clock::from_time_t(std::mktime(broken_down_time));
303  }
304  } else { // no date bits found, we have a direct specification
305  if (pointString[0] == '@') { // as for date(1) this is seconds since 1970
306  auto seconds = std::stod(pointString.substr(1));
307  timePoint = std::chrono::system_clock::from_time_t(0) +
308  std::chrono::duration_cast<std::chrono::system_clock::duration>(std::chrono::duration<double>(seconds));
309  } else { // try direct spec like yyy/mm/dd [HH:MM:SS]
310  std::tm broken_down_time;
311  memset(&broken_down_time, 0, sizeof(broken_down_time));
312  double fractionalPart;
313  std::stringstream buf(aString.substr(pointStringStart, pointStringLength));
314  std::string timezone;
315  if (internal::fParseStreamToBrokenDownTime(buf, &broken_down_time, fractionalPart, timezone)) {
316  broken_down_time.tm_year -= 1900;
317  broken_down_time.tm_mon--;
318  broken_down_time.tm_isdst = -1;
319  #ifdef TZFILE_PATH
320  auto oldTZ = getenv("TZ");
321  std::string oldTZstring;
322  if (oldTZ) {
323  oldTZstring = oldTZ;
324  }
325  if (timezone.length() > 2) {
326  std::string tzfilename(TZFILE_PATH);
327  tzfilename += timezone;
328  struct stat s;
329  if (stat(tzfilename.c_str(), &s) < 0) {
330  parser::fGetInstance()->fGetErrorStream() << "can't find timezone file '" << tzfilename << "'\n";
331  parser::fGetInstance()->fComplainAndLeave();
332  }
333  timezone = ":" + timezone;
334  setenv("TZ", timezone.c_str(), true);
335  tzset();
336  }
337  #endif
338  timePoint = std::chrono::system_clock::from_time_t(std::mktime(&broken_down_time));
339  timePoint += std::chrono::duration_cast<std::chrono::system_clock::duration>(std::chrono::duration<double>(fractionalPart));
340  #ifdef TZFILE_PATH
341  if (timezone.length() > 2) {
342  if (oldTZ) {
343  setenv("TZ", oldTZstring.c_str(), true);
344  } else {
345  unsetenv("TZ");
346  }
347  }
348  #endif
349  } else {
350  parser::fGetInstance()->fGetErrorStream() << "Unrecognized time in '" << pointString << "'\n";
351  parser::fGetInstance()->fComplainAndLeave();
352  }
353  }
354  }
355  } else {
356  timePoint = std::chrono::system_clock::now();
357  }
358 
359  if (offsetStringStart < aString.size()) {
360  std::chrono::system_clock::duration offset;
361  auto offsetString = aString.substr(offsetStringStart, offsetStringLength);
362  std::transform(offsetString.begin(), offsetString.end(), offsetString.begin(), ::tolower);
363 
364  int months = 0;
365  int years = 0;
366  internal::parseDurationString(offset, offsetString, &months, &years);
367 
368  if (offsetIsNegative) {
369  timePoint -= offset;
370  } else {
371  timePoint += offset;
372  }
373  if (months != 0 || years != 0) {
374  auto coarse_time = std::chrono::system_clock::to_time_t(timePoint);
375  auto fractionalPart = timePoint - std::chrono::system_clock::from_time_t(coarse_time);
376  auto broken_down_time = std::localtime(&coarse_time);
377  if (offsetIsNegative) {
378  broken_down_time->tm_mon -= months;
379  broken_down_time->tm_year -= years;
380  } else {
381  broken_down_time->tm_mon += months;
382  broken_down_time->tm_year += years;
383  }
384  timePoint = std::chrono::system_clock::from_time_t(std::mktime(broken_down_time));
385  timePoint += fractionalPart;
386  }
387  }
388  return timePoint;
389  }

References options::parser::fComplainAndLeave(), options::parser::fGetErrorStream(), options::parser::fGetInstance(), fParseStreamToBrokenDownTime(), parseDurationString(), and statCollector::timePoint().

Referenced by options::single< std::chrono::system_clock::time_point >::fAddDefaultFromStream(), options::single< std::chrono::system_clock::time_point >::fSetMe(), options::escapedIO::operator>>(), parseDurationString(), and options::single< std::chrono::system_clock::time_point >::single().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseDurationString()

template<class Rep , class Period >
void options::internal::parseDurationString ( std::chrono::duration< Rep, Period > &  aDuration,
const std::string &  aString,
int *  aMonths = nullptr,
int *  aYears = nullptr 
)

parse a string into a std::chrono::duration, if given set the years and months separately

Definition at line 22 of file OptionsChrono.h.

22  {
23  auto between = aString.find("between");
24  if (between != std::string::npos) {
25  auto andpos = aString.find("and");
26  if (andpos != std::string::npos) {
27  auto t0 = fParseTimePointString(aString.substr(between + 8, andpos - 1 - (between + 8) ));
28  auto t1 = fParseTimePointString(aString.substr(andpos + 4));
29  aDuration = std::chrono::duration_cast<typename std::remove_reference<decltype(aDuration)>::type>(t1 - t0);
30  } else {
31  throw std::runtime_error("duration with 'between' without and");
32  }
33  } else {
34  std::stringstream sbuf(aString);
35  aDuration = aDuration.zero();
36  while (!sbuf.eof()) {
37  aDuration += std::chrono::duration_cast<typename std::remove_reference<decltype(aDuration)>::type>(parseNumberAndUnit(sbuf, aMonths, aYears));
38  }
39  }
40  };

References fParseTimePointString(), and parseNumberAndUnit().

Referenced by options::single< std::chrono::duration< Rep, Period > >::fAddDefaultFromStream(), fParseTimePointString(), options::single< std::chrono::duration< Rep, Period > >::fSetMe(), and options::escapedIO::operator>>().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseNumberAndUnit()

std::chrono::duration< double > options::internal::parseNumberAndUnit ( std::stringstream &  aStream,
int *  aMonths = nullptr,
int *  aYears = nullptr 
)

Definition at line 14 of file OptionsChrono.cpp.

14  {
15  class unitDescriptor {
16  public:
17  enum unitType {
18  kUnspecific = 0,
19  kWithEnlargingPrefix = 1 << 0,
20  kWithDiminishingPrefix = 1 << 1,
21  kWithPrefix = kWithEnlargingPrefix | kWithDiminishingPrefix,
22  kMonth = 1 << 2,
23  kYear = (1 << 3) | kWithEnlargingPrefix ,
24  kSecond = kWithDiminishingPrefix
25  };
26  const char *lUnitName;
27  double lFactor;
28  unitType lType;
29  unitDescriptor(decltype(lUnitName) aUnitName,
30  decltype(lFactor) aFactor,
31  decltype(lType) aType):
32  lUnitName(aUnitName), lFactor(aFactor), lType(aType) {
33  };
34  };
35 
36  static std::vector<unitDescriptor> unitDescriptors({
37  {"year", 31557500, unitDescriptor::kYear},
38  {"yr", 31557500, unitDescriptor::kYear},
39  {"a", 31557500, unitDescriptor::kYear},
40  {"month", 2629800, unitDescriptor::kMonth},
41  {"week", 3600 * 24 * 7, unitDescriptor::kUnspecific},
42  {"day", 3600 * 24, unitDescriptor::kUnspecific},
43  {"hour", 3600, unitDescriptor::kUnspecific},
44  {"minute", 60, unitDescriptor::kUnspecific},
45  {"min", 60, unitDescriptor::kUnspecific},
46  {"second", 1, unitDescriptor::kSecond},
47  {"sec", 1, unitDescriptor::kSecond},
48  {"s", 1, unitDescriptor::kSecond}
49  }
50  );
51 
52  class prefixDescriptor {
53  public:
54  const char *lName;
55  long long lFactor;
56  std::string::size_type lNameLength;
57  prefixDescriptor(decltype(lName) aName, decltype(lFactor) aFactor) :
58  lName(aName), lFactor(aFactor) {
59  lNameLength = strlen(aName);
60  }
61  };
62  static std::vector<prefixDescriptor> diminishingPrefixDescriptors ({
63  {"milli", 1000},
64  {"m", 1000},
65  {"micro", 1000000},
66  {"u", 1000000},
67  {"nano", 1000000000},
68  {"n", 1000000000}
69  }
70  );
71  static std::vector<prefixDescriptor> enlargingPrefixDescriptors ({
72  {"kilo", 1000},
73  {"k", 1000},
74  {"mega", 1000000},
75  {"m", 1000000},
76  {"giga", 1000000000},
77  {"g", 1000000000}
78  }
79  );
80 
81  double number;
82  aStream >> number;
83  if (aStream.eof()) {
84  return std::chrono::duration<double>::zero();
85  }
86  std::string unit;
87  aStream >> unit;
88  std::transform(unit.begin(), unit.end(), unit.begin(), ::tolower);
89  for (auto& unitDesc : unitDescriptors) {
90  auto location = unit.find(unitDesc.lUnitName);
91  if (location != std::string::npos) {
92  auto unitNameLength = strlen(unitDesc.lUnitName);
93  auto nExtraChars = unit.size() - location - unitNameLength;
94  if (nExtraChars > 0 && // next line is special condition to allow a plural-s
95  !(nExtraChars == 1 && unitNameLength > 2 && unit.back() == 's')) {
96  parser::fGetInstance()->fGetErrorStream() << "Garbage in '" << unit << "' after the unit '" << unitDesc.lUnitName << "'\n";
97  parser::fGetInstance()->fComplainAndLeave();
98  }
99  if (location != 0) {
100  if (!(unitDesc.lType & unitDescriptor::kWithPrefix)) {
101  parser::fGetInstance()->fGetErrorStream() << "Garbage in '" << unit << "' before the unit '" << unitDesc.lUnitName << "'\n";
102  parser::fGetInstance()->fComplainAndLeave();
103  }
104  bool prefixFound = false;
105  if (unitDesc.lType & unitDescriptor::kWithDiminishingPrefix) {
106  for (auto& prefix : diminishingPrefixDescriptors) {
107  if (unit.compare(0, location, prefix.lName) == 0) {
108  number /= prefix.lFactor;
109  prefixFound = true;
110  break;
111  }
112  }
113  }
114  if (unitDesc.lType & unitDescriptor::kWithEnlargingPrefix) {
115  for (auto& prefix : enlargingPrefixDescriptors) {
116  if (unit.compare(0, location, prefix.lName) == 0) {
117  number *= prefix.lFactor;
118  prefixFound = true;
119  break;
120  }
121  }
122  }
123  if (!prefixFound) {
124  parser::fGetInstance()->fGetErrorStream() << "No valid prefix found in '" << unit << "'\n";
125  parser::fGetInstance()->fComplainAndLeave();
126  }
127  }
128  if ((unitDesc.lType == unitDescriptor::kYear && aYears) ||
129  (unitDesc.lType == unitDescriptor::kMonth && aMonths)) {
130  if (unitDesc.lType == unitDescriptor::kYear) {
131  *aYears = number;
132  } else {
133  *aMonths = number;
134  }
135  return std::chrono::duration<double>::zero();
136  } else {
137  return std::chrono::duration<double>(unitDesc.lFactor * number);
138  }
139  }
140  }
141  parser::fGetInstance()->fGetErrorStream() << "Unrecognized time unit in '" << unit << "'\n";
142  parser::fGetInstance()->fComplainAndLeave();
143  return std::chrono::duration<double>::zero();
144  }

References options::parser::fComplainAndLeave(), options::parser::fGetErrorStream(), and options::parser::fGetInstance().

Referenced by parseDurationString().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ gHelp

OptionHelp options::internal::gHelp
static

Definition at line 949 of file Options.cpp.

◆ gNoCfgFileRecursion

NoCfgFileRecursion options::internal::gNoCfgFileRecursion
static

◆ gOptionDebugOptions

single<bool> options::internal::gOptionDebugOptions('\0', "debugOptions", "give debug output to option parsing")
static

standard option for producing debug output about the options

Referenced by options::parser::fParse().

◆ gOptionNoCfgFiles

single<bool> options::internal::gOptionNoCfgFiles('\0', "noCfgFiles", "do not read the default config files, must be FIRST option")
static

standard option to suppress parsing of config files

Referenced by options::parser::fParse().

◆ gReadCfgFile

OptionReadCfgFile<false> options::internal::gReadCfgFile("readCfgFile", "read a config file")
static

◆ gReadCfgFileIfThere

OptionReadCfgFile<true> options::internal::gReadCfgFileIfThere("readCfgFileIfThere", "read a config file if it's there")
static

◆ gWriteCfgFile

OptionWriteCfgFile options::internal::gWriteCfgFile
static

Definition at line 966 of file Options.cpp.

options::internal::parseNumberAndUnit
std::chrono::duration< double > parseNumberAndUnit(std::stringstream &aStream, int *aMonths=nullptr, int *aYears=nullptr)
Definition: OptionsChrono.cpp:14
copyRequest::backupModeType::before
@ before
copyRequest::backupModeType::after
@ after
options::internal::fParseTimePointString
std::chrono::system_clock::time_point fParseTimePointString(const std::string &aString)
Definition: OptionsChrono.cpp:183
options::internal::fParseStreamToBrokenDownTime
bool fParseStreamToBrokenDownTime(std::istream &aStream, std::tm *aBrokenDownTime, double &aFractional, std::string &timezone)
Definition: OptionsChrono.cpp:146
options::internal::conCatStr
void conCatStr(std::ostringstream &msg, const T &begin, const Args &... args)
Definition: Options.h:330
statCollector::timePoint
std::chrono::system_clock::time_point timePoint(const struct timespec &spec)
Definition: statCollector.h:115
options::internal::parseDurationString
void parseDurationString(std::chrono::duration< Rep, Period > &aDuration, const std::string &aString, int *aMonths=nullptr, int *aYears=nullptr)
parse a string into a std::chrono::duration, if given set the years and months separately
Definition: OptionsChrono.h:22