BPNGClientLib
Library for accessing the Telemotive data logger devices
clientUtil.hh
Go to the documentation of this file.
1 //************************************************************
2 //
7 //************************************************************
8 
9 
10 #ifndef UTILITY_HH
11 #define UTILITY_HH
12 
13 #include <chrono>
14 #include <iosfwd>
15 #include <iostream>
16 #include <sstream>
17 #include <time.h>
18 #include <string.h>
19 #include <vector>
20 #include <sys/stat.h>
21 
23 extern const char *progname(const char *path)
24 {
25  const char *prog;
26 
27  if ((prog = strrchr(path, '/')))
28  return ++prog;
29  else
30  return path;
31 }
32 
33 
34 template <class Duration>
35 constexpr std::chrono::hours
36 toHours(const Duration &d)
37 {
38  return std::chrono::duration_cast<std::chrono::hours>(d);
39 }
40 
41 
42 template <class Duration>
43 constexpr std::chrono::minutes
44 toMinutes(const Duration &d)
45 {
46  return std::chrono::duration_cast<std::chrono::minutes>(d);
47 }
48 
49 
50 template <class Duration>
51 constexpr std::chrono::seconds
52 toSeconds(const Duration &d)
53 {
54  return std::chrono::duration_cast<std::chrono::seconds>(d);
55 }
56 
57 
58 template <class Duration>
59 constexpr std::chrono::milliseconds
60 toMilliseconds(const Duration &d)
61 {
62  return std::chrono::duration_cast<std::chrono::milliseconds>(d);
63 }
64 
65 
66 template <class Duration>
67 constexpr std::chrono::microseconds
68 toMicroseconds(const Duration &d)
69 {
70  return std::chrono::duration_cast<std::chrono::microseconds>(d);
71 }
72 
73 
74 template <class Duration>
75 constexpr std::chrono::nanoseconds
76 toNanoseconds(const Duration &d)
77 {
78  return std::chrono::duration_cast<std::chrono::nanoseconds>(d);
79 }
80 
81 
83 template <typename Rep, typename Period>
84 inline timespec
85 toTimespec(const std::chrono::duration<Rep, Period> &d)
86 {
87  return timespec {
88  static_cast<decltype(timespec::tv_sec)>(::toSeconds(d).count()),
89  static_cast<decltype(timespec::tv_nsec)>(::toNanoseconds(d - ::toSeconds(d)).count())};
90 }
91 
92 static void printTm(std::ostream &os, time_t sec, char origfill)
93 {
94  tm ptm;
95 
96  gmtime_r(&sec, &ptm);
97 
98  const std::ios::fmtflags oldflags = os.flags(std::ios::fixed | std::ios::dec);
99  const char oldfill = os.fill('0');
100 
101  if (origfill == '\0')
102  {
103  os << std::setw(2) << ptm.tm_hour
104  << std::setw(2) << ptm.tm_min
105  << std::setw(2) << ptm.tm_sec;
106  }
107  else
108  {
109  char fill = ':';
110  if (origfill == '-' || origfill == '.')
111  fill = origfill;
112 
113  os << std::setw(2) << ptm.tm_hour
114  << fill
115  << std::setw(2) << ptm.tm_min
116  << fill
117  << std::setw(2) << ptm.tm_sec;
118  }
119 
120  os.flags(oldflags);
121  os.fill(oldfill);
122 }
123 
124 extern std::ostream &operator<<(std::ostream &os, const tm &_t)
125 {
126  const std::ios::fmtflags oldflags = os.flags(std::ios::fixed | std::ios::dec);
127  const char oldfill = os.fill('0');
128 
129  // ISO format
130  os << std::setw(4) << _t.tm_year + 1900 << '-'
131  << std::setw(2) << _t.tm_mon + 1 << '-'
132  << std::setw(2) << _t.tm_mday << ' '
133  << std::setw(2) << _t.tm_hour << ':'
134  << std::setw(2) << _t.tm_min << ':'
135  << std::setw(2) << _t.tm_sec;
136 
137  os.flags(oldflags);
138  os.fill(oldfill);
139 
140  return os;
141 }
142 
144 
145 extern std::ostream &operator<<(std::ostream &os, const timespec &_t)
146 {
147  const std::ios::fmtflags oldflags = os.flags(std::ios::fixed | std::ios::right);
148  const char oldfill = os.fill(' ');
149 
150  if (os.flags() & std::ios::scientific)
151  os << _t.tv_sec;
152  else
153  printTm(os, _t.tv_sec, oldfill);
154 
155  os << '.' << std::setfill('0') << std::setw(9) << _t.tv_nsec;
156 
157  os.flags(oldflags);
158  os.fill(oldfill);
159 
160  return os;
161 }
162 
164 
169 template <typename Rep, typename Period>
170 inline std::ostream &
171 operator<<(std::ostream &os, const std::chrono::duration<Rep, Period> &d)
172 {
173  os << d.count();
174  return os;
175 }
176 
178 
184 template <typename Rep>
185 std::ostream &
186 operator<<(std::ostream &os, const std::chrono::duration<Rep, std::ratio<1>> &d)
187 {
188  os << d.count();
189  if (os.flags() & std::ios::showbase)
190  os << (os.flags() & std::ios::skipws ? "s" : " s");
191  return os;
192 }
193 
195 
201 template <typename Rep>
202 std::ostream &
203 operator<<(std::ostream &os, const std::chrono::duration<Rep, std::milli> &d)
204 {
205  os << d.count();
206  if (os.flags() & std::ios::showbase)
207  os << (os.flags() & std::ios::skipws ? "ms" : " ms");
208  return os;
209 }
210 
212 
218 template <typename Rep>
219 std::ostream &
220 operator<<(std::ostream &os, const std::chrono::duration<Rep, std::micro> &d)
221 {
222  os << d.count();
223  if (os.flags() & std::ios::showbase)
224  os << (os.flags() & std::ios::skipws ? "µs" : " µs");
225  return os;
226 }
227 
229 
235 template <typename Rep>
236 std::ostream &
237 operator<<(std::ostream &os, const std::chrono::duration<Rep, std::nano> &d)
238 {
239  os << d.count();
240  if (os.flags() & std::ios::showbase)
241  os << (os.flags() & std::ios::skipws ? "ns" : " ns");
242  return os;
243 }
244 
247 
256 template <typename Clock, typename Duration>
257 inline std::ostream &
258 operator<<(std::ostream &os, const std::chrono::time_point<Clock, Duration> &tp)
259 {
260  const auto d = tp.time_since_epoch();
261 
262  if (os.flags() & std::ios::scientific)
263  os << d;
264  else
265  os << toTimespec(d);
266 
267  return os;
268 }
269 
270 extern int mkdirPath(const std::string &_dirpath, int _mode = S_IRWXU | S_IRWXG | S_IRWXO)
271 {
272  if (_dirpath.empty())
273  {
274  errno = EINVAL;
275  return -1;
276  }
277 
278  struct stat sbuf;
279 
280  char *ps;
281  std::vector<char> p;
282 
283  // create a writeable copy of _dirpath, terminate it with null char
284  p.resize(_dirpath.size() + 1);
285  std::vector<char>::iterator pend = std::copy(_dirpath.begin(), _dirpath.end(), p.begin());
286  *pend = '\0';
287  ++pend;
288 
289  char * const pstart = &p[0];
290  ps = pstart;
291  while (ps != &*pend)
292  {
293  if (ps != pstart)
294  {
295  if (*ps == '/' || *ps == '\0')
296  {
297  // found path separator, temporarily replace it using a null char
298  *ps = '\0';
299 
300  // create that part if it doesn't yet exist
301  if (stat(pstart, &sbuf) == -1)
302  {
303  if (mkdir(pstart, _mode) == -1)
304  {
305  return -1;
306  }
307  }
308  else if (!S_ISDIR(sbuf.st_mode))
309  {
310  // it's not a directory, quit
311  errno = ENOTDIR;
312  return -1;
313  }
314 
315  *ps = '/'; // back to normal ...
316  }
317  }
318 
319  ++ps; // ... and advance
320  }
321 
322  errno = 0;
323  return 0;
324 }
325 
326 #endif /* UTILITY_HH */
const char * progname(const char *path)
Get the program name, similar to basename.
Definition: clientUtil.hh:23
std::ostream & operator<<(std::ostream &os, const timespec &_t)
Output operator for struct timespec as used e.g. by pselect or nanosleep.
Definition: clientUtil.hh:145
timespec toTimespec(const std::chrono::duration< Rep, Period > &d)
Convert a chrono duration into a POSIX timespec.
Definition: clientUtil.hh:85