uvw  1.3.0
util.hpp
1 #pragma once
2 
3 
4 #include <type_traits>
5 #include <algorithm>
6 #include <stdexcept>
7 #include <cstddef>
8 #include <utility>
9 #include <string>
10 #include <vector>
11 #include <array>
12 #include <uv.h>
13 
14 
15 #ifdef _WIN32
16 // MSVC doesn't have C++14 relaxed constexpr support yet. Hence the jugglery.
17 #define CONSTEXPR_SPECIFIER
18 #else
19 #define CONSTEXPR_SPECIFIER constexpr
20 #endif
21 
22 
23 namespace uvw {
24 
25 
26 namespace details {
27 
28 
29 enum class UVHandleType: std::underlying_type_t<uv_handle_type> {
30  UNKNOWN = UV_UNKNOWN_HANDLE,
31  ASYNC = UV_ASYNC,
32  CHECK = UV_CHECK,
33  FS_EVENT = UV_FS_EVENT,
34  FS_POLL = UV_FS_POLL,
35  HANDLE = UV_HANDLE,
36  IDLE = UV_IDLE,
37  PIPE = UV_NAMED_PIPE,
38  POLL = UV_POLL,
39  PREPARE = UV_PREPARE,
40  PROCESS = UV_PROCESS,
41  STREAM = UV_STREAM,
42  TCP = UV_TCP,
43  TIMER = UV_TIMER,
44  TTY = UV_TTY,
45  UDP = UV_UDP,
46  SIGNAL = UV_SIGNAL,
47  FILE = UV_FILE
48 };
49 
50 
51 template<typename T>
52 struct UVTypeWrapper {
53  using Type = T;
54 
55  constexpr UVTypeWrapper(Type val): value{val} {}
56  constexpr operator Type() const noexcept { return value; }
57 
58 private:
59  const Type value;
60 };
61 
62 
63 }
64 
65 
76 template<typename E>
77 class Flags final {
78  using InnerType = std::underlying_type_t<E>;
79 
80  constexpr InnerType toInnerType(E flag) const noexcept { return static_cast<InnerType>(flag); }
81 
82 public:
83  using Type = InnerType;
84 
89  template<E... V>
90  static CONSTEXPR_SPECIFIER Flags<E> from() {
91  auto flags = Flags<E>{};
92  int _[] = { 0, (flags = flags | V, 0)... };
93  return void(_), flags;
94  }
95 
100  constexpr Flags(E flag) noexcept: flags{toInnerType(flag)} {}
101 
107  constexpr Flags(Type f): flags{f} {}
108 
112  constexpr Flags(): flags{} {}
113 
114  constexpr Flags(const Flags &f) noexcept: flags{f.flags} { }
115  constexpr Flags(Flags &&f) noexcept: flags{std::move(f.flags)} { }
116 
117  ~Flags() noexcept { static_assert(std::is_enum<E>::value, "!"); }
118 
119  CONSTEXPR_SPECIFIER Flags & operator=(const Flags &f) noexcept {
120  flags = f.flags;
121  return *this;
122  }
123 
124  CONSTEXPR_SPECIFIER Flags & operator=(Flags &&f) noexcept {
125  flags = std::move(f.flags);
126  return *this;
127  }
128 
134  constexpr Flags operator|(const Flags &f) const noexcept { return Flags{flags | f.flags}; }
135 
141  constexpr Flags operator|(E flag) const noexcept { return Flags{flags | toInnerType(flag)}; }
142 
148  constexpr Flags operator&(const Flags &f) const noexcept { return Flags{flags & f.flags}; }
149 
155  constexpr Flags operator&(E flag) const noexcept { return Flags{flags & toInnerType(flag)}; }
156 
161  explicit constexpr operator bool() const noexcept { return !(flags == InnerType{}); }
162 
167  constexpr operator Type() const noexcept { return flags; }
168 
169 private:
170  InnerType flags;
171 };
172 
173 
177 struct WinSize {
178  int width;
179  int height;
180 };
181 
182 
183 using HandleType = details::UVHandleType;
185 using HandleCategory = details::UVTypeWrapper<uv_handle_type>;
186 using FileHandle = details::UVTypeWrapper<uv_file>;
187 using OSSocketHandle = details::UVTypeWrapper<uv_os_sock_t>;
188 using OSFileDescriptor = details::UVTypeWrapper<uv_os_fd_t>;
190 constexpr FileHandle StdIN{0};
191 constexpr FileHandle StdOUT{1};
192 constexpr FileHandle StdERR{2};
194 using TimeSpec = uv_timespec_t;
195 using Stat = uv_stat_t;
196 using Uid = uv_uid_t;
197 using Gid = uv_gid_t;
199 using TimeVal = uv_timeval_t;
200 using RUsage = uv_rusage_t;
211 struct Passwd {
212  Passwd(std::shared_ptr<uv_passwd_t> pwd): passwd{pwd} {}
213 
218  std::string username() const noexcept {
219  return ((passwd && passwd->username) ? passwd->username : "");
220  }
221 
226  auto uid() const noexcept {
227  return (passwd ? passwd->uid : decltype(uv_passwd_t::uid){});
228  }
229 
234  auto gid() const noexcept {
235  return (passwd ? passwd->gid : decltype(uv_passwd_t::gid){});
236  }
237 
242  std::string shell() const noexcept {
243  return ((passwd && passwd->shell) ? passwd->shell : "");
244  }
245 
250  std::string homedir() const noexcept {
251  return ((passwd && passwd->homedir) ? passwd->homedir: "");
252  }
253 
258  operator bool() const noexcept {
259  return static_cast<bool>(passwd);
260  }
261 
262 private:
263  std::shared_ptr<uv_passwd_t> passwd;
264 };
265 
266 
272 struct IPv4 {};
273 
274 
280 struct IPv6 {};
281 
282 
286 struct Addr {
287  std::string ip;
288  unsigned int port;
289 };
290 
291 
295 struct CPUInfo {
296  using CPUTime = decltype(uv_cpu_info_t::cpu_times);
297 
298  std::string model;
299  int speed;
307  CPUTime times;
308 };
309 
310 
315  std::string name;
316  char physical[6];
317  bool internal;
320 };
321 
322 
323 namespace details {
324 
325 
326 static constexpr std::size_t DEFAULT_SIZE = 128;
327 
328 
329 template<typename>
330 struct IpTraits;
331 
332 
333 template<>
334 struct IpTraits<IPv4> {
335  using Type = sockaddr_in;
336  using AddrFuncType = int(*)(const char *, int, Type *);
337  using NameFuncType = int(*)(const Type *, char *, std::size_t);
338  static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
339  static constexpr NameFuncType nameFunc = &uv_ip4_name;
340  static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
341 };
342 
343 
344 template<>
345 struct IpTraits<IPv6> {
346  using Type = sockaddr_in6;
347  using AddrFuncType = int(*)(const char *, int, Type *);
348  using NameFuncType = int(*)(const Type *, char *, std::size_t);
349  static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
350  static constexpr NameFuncType nameFunc = &uv_ip6_name;
351  static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
352 };
353 
354 
355 template<typename I>
356 Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
357  Addr addr;
358  char name[DEFAULT_SIZE];
359 
360  int err = details::IpTraits<I>::nameFunc(aptr, name, DEFAULT_SIZE);
361 
362  if(0 == err) {
363  addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
364  addr.ip = std::string{name};
365  }
366 
367  return addr;
368 }
369 
370 
371 template<typename I, typename F, typename H>
372 Addr address(F &&f, const H *handle) noexcept {
373  sockaddr_storage ssto;
374  int len = sizeof(ssto);
375  Addr addr{};
376 
377  int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
378 
379  if(0 == err) {
380  typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
381  addr = address<I>(aptr);
382  }
383 
384  return addr;
385 }
386 
387 
388 template<typename F, typename... Args>
389 std::string tryRead(F &&f, Args&&... args) noexcept {
390  std::size_t size = DEFAULT_SIZE;
391  char buf[DEFAULT_SIZE];
392  std::string str{};
393  auto err = std::forward<F>(f)(args..., buf, &size);
394 
395  if(UV_ENOBUFS == err) {
396  std::unique_ptr<char[]> data{new char[size]};
397  err = std::forward<F>(f)(args..., data.get(), &size);
398 
399  if(0 == err) {
400  str = data.get();
401  }
402  } else if(0 == err) {
403  str.assign(buf, size);
404  }
405 
406  return str;
407 }
408 
409 
410 }
411 
412 
418 struct Utilities {
419  using MallocFuncType = void*(*)(size_t);
420  using ReallocFuncType = void*(*)(void*, size_t);
421  using CallocFuncType = void*(*)(size_t, size_t);
422  using FreeFuncType = void(*)(void*);
423 
427  struct OS {
438  static std::string homedir() noexcept {
439  return details::tryRead(&uv_os_homedir);
440  }
441 
451  static std::string tmpdir() noexcept {
452  return details::tryRead(&uv_os_tmpdir);
453  }
454 
461  static std::string env(const std::string &name) noexcept {
462  return details::tryRead(&uv_os_getenv, name.c_str());
463  }
464 
472  static bool env(const std::string &name, const std::string &value) noexcept {
473  return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
474  }
475 
480  static std::string hostname() noexcept {
481  return details::tryRead(&uv_os_gethostname);
482  }
483 
496  static Passwd passwd() noexcept {
497  auto deleter = [](uv_passwd_t *passwd){
498  uv_os_free_passwd(passwd);
499  delete passwd;
500  };
501 
502  std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
503  uv_os_get_passwd(ptr.get());
504  return ptr;
505  }
506  };
507 
513  static HandleType guessHandle(HandleCategory category) noexcept {
514  switch(category) {
515  case UV_ASYNC:
516  return HandleType::ASYNC;
517  case UV_CHECK:
518  return HandleType::CHECK;
519  case UV_FS_EVENT:
520  return HandleType::FS_EVENT;
521  case UV_FS_POLL:
522  return HandleType::FS_POLL;
523  case UV_HANDLE:
524  return HandleType::HANDLE;
525  case UV_IDLE:
526  return HandleType::IDLE;
527  case UV_NAMED_PIPE:
528  return HandleType::PIPE;
529  case UV_POLL:
530  return HandleType::POLL;
531  case UV_PREPARE:
532  return HandleType::PREPARE;
533  case UV_PROCESS:
534  return HandleType::PROCESS;
535  case UV_STREAM:
536  return HandleType::STREAM;
537  case UV_TCP:
538  return HandleType::TCP;
539  case UV_TIMER:
540  return HandleType::TIMER;
541  case UV_TTY:
542  return HandleType::TTY;
543  case UV_UDP:
544  return HandleType::UDP;
545  case UV_SIGNAL:
546  return HandleType::SIGNAL;
547  case UV_FILE:
548  return HandleType::FILE;
549  default:
550  return HandleType::UNKNOWN;
551  }
552  }
553 
572  static HandleType guessHandle(FileHandle file) noexcept {
573  HandleCategory category = uv_guess_handle(file);
574  return guessHandle(category);
575  }
576 
577 
585  static std::vector<CPUInfo> cpuInfo() noexcept {
586  std::vector<CPUInfo> cpuinfos;
587 
588  uv_cpu_info_t *infos;
589  int count;
590 
591  if(0 == uv_cpu_info(&infos, &count)) {
592  std::for_each(infos, infos+count, [&cpuinfos](const auto &info) {
593  cpuinfos.push_back({ info.model, info.speed, info.cpu_times });
594  });
595 
596  uv_free_cpu_info(infos, count);
597  }
598 
599  return cpuinfos;
600  }
601 
602 
611  static std::vector<InterfaceAddress> interfaceAddresses() noexcept {
612  std::vector<InterfaceAddress> interfaces;
613 
614  uv_interface_address_t *ifaces{nullptr};
615  int count{0};
616 
617  if(0 == uv_interface_addresses(&ifaces, &count)) {
618  std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
619  InterfaceAddress interfaceAddress;
620 
621  interfaceAddress.name = iface.name;
622  std::copy(iface.phys_addr, (iface.phys_addr+6), interfaceAddress.physical);
623  interfaceAddress.internal = iface.is_internal == 0 ? false : true;
624 
625  if(iface.address.address4.sin_family == AF_INET) {
626  interfaceAddress.address = details::address<IPv4>(&iface.address.address4);
627  interfaceAddress.netmask = details::address<IPv4>(&iface.netmask.netmask4);
628  } else if(iface.address.address4.sin_family == AF_INET6) {
629  interfaceAddress.address = details::address<IPv6>(&iface.address.address6);
630  interfaceAddress.netmask = details::address<IPv6>(&iface.netmask.netmask6);
631  }
632 
633  interfaces.push_back(std::move(interfaceAddress));
634  });
635 
636  uv_free_interface_addresses(ifaces, count);
637  }
638 
639  return interfaces;
640  }
641 
642 
665  static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
666  return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
667  }
668 
673  static std::array<double, 3> loadAverage() noexcept {
674  std::array<double, 3> avg;
675  uv_loadavg(avg.data());
676  return avg;
677  }
678 
686  static char ** setupArgs(int argc, char** argv) {
687  return uv_setup_args(argc, argv);
688  }
689 
694  static std::string processTitle() {
695  std::size_t size = details::DEFAULT_SIZE;
696  char buf[details::DEFAULT_SIZE];
697  std::string str{};
698 
699  if(0 == uv_get_process_title(buf, size)) {
700  str.assign(buf, size);
701  }
702 
703  return str;
704  }
705 
711  static bool processTitle(std::string title) {
712  return (0 == uv_set_process_title(title.c_str()));
713  }
714 
719  static uint64_t totalMemory() noexcept {
720  return uv_get_total_memory();
721  }
722 
727  static double uptime() noexcept {
728  double ret;
729 
730  if(0 != uv_uptime(&ret)) {
731  ret = 0;
732  }
733 
734  return ret;
735  }
736 
741  static RUsage rusage() noexcept {
742  RUsage ru;
743  auto err = uv_getrusage(&ru);
744  return err ? RUsage{} : ru;
745  }
746 
757  static uint64_t hrtime() noexcept {
758  return uv_hrtime();
759  }
760 
765  static std::string path() noexcept {
766  return details::tryRead(&uv_exepath);
767  }
768 
773  static std::string cwd() noexcept {
774  return details::tryRead(&uv_cwd);
775  }
776 
782  static bool chdir(const std::string &dir) noexcept {
783  return (0 == uv_chdir(dir.data()));
784  }
785 };
786 
787 
788 }
Address representation.
Definition: util.hpp:286
constexpr FileHandle StdERR
Definition: util.hpp:192
auto gid() const noexcept
Gets the gid.
Definition: util.hpp:234
unsigned int port
Definition: util.hpp:288
static Passwd passwd() noexcept
Gets a subset of the password file entry.
Definition: util.hpp:496
static HandleType guessHandle(FileHandle file) noexcept
Gets the type of the stream to be used with the given descriptor.
Definition: util.hpp:572
static std::string hostname() noexcept
Returns the hostname.
Definition: util.hpp:480
static std::string env(const std::string &name) noexcept
Retrieves an environment variable.
Definition: util.hpp:461
static std::vector< InterfaceAddress > interfaceAddresses() noexcept
Gets a set of descriptors of all the available interfaces.
Definition: util.hpp:611
std::string ip
Definition: util.hpp:287
uv_timespec_t TimeSpec
Definition: util.hpp:194
static double uptime() noexcept
Gets the current system uptime.
Definition: util.hpp:727
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.hpp:186
static std::string tmpdir() noexcept
Gets the temp directory.
Definition: util.hpp:451
static std::string homedir() noexcept
Gets the current user&#39;s home directory.
Definition: util.hpp:438
uv_rusage_t RUsage
Definition: util.hpp:200
Windows size representation.
Definition: util.hpp:177
details::UVTypeWrapper< uv_os_fd_t > OSFileDescriptor
Definition: util.hpp:188
constexpr FileHandle StdIN
Definition: util.hpp:190
static char ** setupArgs(int argc, char **argv)
Store the program arguments.
Definition: util.hpp:686
CPU information.
Definition: util.hpp:295
uv_timeval_t TimeVal
Definition: util.hpp:199
std::string username() const noexcept
Gets the username.
Definition: util.hpp:218
constexpr FileHandle StdOUT
Definition: util.hpp:191
Utility class to handle flags.
Definition: util.hpp:77
constexpr Flags operator &(const Flags &f) const noexcept
And operator.
Definition: util.hpp:148
constexpr Flags(E flag) noexcept
Constructs a Flags object from a value of the enum E.
Definition: util.hpp:100
OS dedicated utilities.
Definition: util.hpp:427
constexpr Flags operator|(const Flags &f) const noexcept
Or operator.
Definition: util.hpp:134
static uint64_t hrtime() noexcept
Gets the current high-resolution real time.
Definition: util.hpp:757
The IPv6 tag.
Definition: util.hpp:280
static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept
Override the use of some standard library’s functions.
Definition: util.hpp:665
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:185
uv_gid_t Gid
Definition: util.hpp:197
static bool env(const std::string &name, const std::string &value) noexcept
Creates, updates or deletes an environment variable.
Definition: util.hpp:472
static RUsage rusage() noexcept
Gets the resource usage measures for the current process.
Definition: util.hpp:741
uv_uid_t Uid
Definition: util.hpp:196
Interface address.
Definition: util.hpp:314
static uint64_t totalMemory() noexcept
Gets memory information (in bytes).
Definition: util.hpp:719
int height
Definition: util.hpp:179
auto uid() const noexcept
Gets the uid.
Definition: util.hpp:226
std::string shell() const noexcept
Gets the shell.
Definition: util.hpp:242
CPUTime times
CPU times.
Definition: util.hpp:307
static std::string cwd() noexcept
Gets the current working directory.
Definition: util.hpp:773
static std::string path() noexcept
Gets the executable path.
Definition: util.hpp:765
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.hpp:187
int width
Definition: util.hpp:178
constexpr Flags()
Constructs an uninitialized Flags object.
Definition: util.hpp:112
std::string name
Definition: util.hpp:315
static HandleType guessHandle(HandleCategory category) noexcept
Gets the type of the handle given a category.
Definition: util.hpp:513
int speed
Definition: util.hpp:299
static CONSTEXPR_SPECIFIER Flags< E > from()
Utility factory method to pack a set of values all at once.
Definition: util.hpp:90
std::string model
Definition: util.hpp:298
constexpr Flags(Type f)
Constructs a Flags object from an instance of the underlying type of the enum E.
Definition: util.hpp:107
constexpr Flags operator|(E flag) const noexcept
Or operator.
Definition: util.hpp:141
static std::vector< CPUInfo > cpuInfo() noexcept
Gets information about the CPUs on the system.
Definition: util.hpp:585
Utility class.
Definition: util.hpp:211
uv_stat_t Stat
Definition: util.hpp:195
static bool chdir(const std::string &dir) noexcept
Changes the current working directory.
Definition: util.hpp:782
constexpr Flags operator &(E flag) const noexcept
And operator.
Definition: util.hpp:155
static std::array< double, 3 > loadAverage() noexcept
Gets the load average.
Definition: util.hpp:673
The IPv4 tag.
Definition: util.hpp:272
static bool processTitle(std::string title)
Sets the current process title.
Definition: util.hpp:711
Miscellaneous utilities.
Definition: util.hpp:418
static std::string processTitle()
Gets the title of the current process.
Definition: util.hpp:694
std::string homedir() const noexcept
Gets the homedir.
Definition: util.hpp:250
uvw default namespace.
Definition: async.hpp:11