uvw  1.4.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(): value{} {}
56  constexpr UVTypeWrapper(Type val): value{val} {}
57 
58  constexpr operator Type() const noexcept { return value; }
59 
60  bool operator==(UVTypeWrapper other) const noexcept {
61  return value == other.value;
62  }
63 
64 private:
65  const Type value;
66 };
67 
68 
69 template<typename T>
70 bool operator==(UVTypeWrapper<T> lhs, UVTypeWrapper<T> rhs) {
71  return !(lhs == rhs);
72 }
73 
74 
75 }
76 
77 
88 template<typename E>
89 class Flags final {
90  using InnerType = std::underlying_type_t<E>;
91 
92  constexpr InnerType toInnerType(E flag) const noexcept { return static_cast<InnerType>(flag); }
93 
94 public:
95  using Type = InnerType;
96 
101  template<E... V>
102  static CONSTEXPR_SPECIFIER Flags<E> from() {
103  auto flags = Flags<E>{};
104  int _[] = { 0, (flags = flags | V, 0)... };
105  return void(_), flags;
106  }
107 
112  constexpr Flags(E flag) noexcept: flags{toInnerType(flag)} {}
113 
119  constexpr Flags(Type f): flags{f} {}
120 
124  constexpr Flags(): flags{} {}
125 
126  constexpr Flags(const Flags &f) noexcept: flags{f.flags} { }
127  constexpr Flags(Flags &&f) noexcept: flags{std::move(f.flags)} { }
128 
129  ~Flags() noexcept { static_assert(std::is_enum<E>::value, "!"); }
130 
131  CONSTEXPR_SPECIFIER Flags & operator=(const Flags &f) noexcept {
132  flags = f.flags;
133  return *this;
134  }
135 
136  CONSTEXPR_SPECIFIER Flags & operator=(Flags &&f) noexcept {
137  flags = std::move(f.flags);
138  return *this;
139  }
140 
146  constexpr Flags operator|(const Flags &f) const noexcept { return Flags{flags | f.flags}; }
147 
153  constexpr Flags operator|(E flag) const noexcept { return Flags{flags | toInnerType(flag)}; }
154 
160  constexpr Flags operator&(const Flags &f) const noexcept { return Flags{flags & f.flags}; }
161 
167  constexpr Flags operator&(E flag) const noexcept { return Flags{flags & toInnerType(flag)}; }
168 
173  explicit constexpr operator bool() const noexcept { return !(flags == InnerType{}); }
174 
179  constexpr operator Type() const noexcept { return flags; }
180 
181 private:
182  InnerType flags;
183 };
184 
185 
189 struct WinSize {
190  int width;
191  int height;
192 };
193 
194 
195 using HandleType = details::UVHandleType;
197 using HandleCategory = details::UVTypeWrapper<uv_handle_type>;
198 using FileHandle = details::UVTypeWrapper<uv_file>;
199 using OSSocketHandle = details::UVTypeWrapper<uv_os_sock_t>;
200 using OSFileDescriptor = details::UVTypeWrapper<uv_os_fd_t>;
201 using PidType = details::UVTypeWrapper<uv_pid_t>;
203 constexpr FileHandle StdIN{0};
204 constexpr FileHandle StdOUT{1};
205 constexpr FileHandle StdERR{2};
207 using TimeSpec = uv_timespec_t;
208 using Stat = uv_stat_t;
209 using Uid = uv_uid_t;
210 using Gid = uv_gid_t;
212 using TimeVal = uv_timeval_t;
213 using RUsage = uv_rusage_t;
224 struct Passwd {
225  Passwd(std::shared_ptr<uv_passwd_t> pwd): passwd{pwd} {}
226 
231  std::string username() const noexcept {
232  return ((passwd && passwd->username) ? passwd->username : "");
233  }
234 
239  auto uid() const noexcept {
240  return (passwd ? passwd->uid : decltype(uv_passwd_t::uid){});
241  }
242 
247  auto gid() const noexcept {
248  return (passwd ? passwd->gid : decltype(uv_passwd_t::gid){});
249  }
250 
255  std::string shell() const noexcept {
256  return ((passwd && passwd->shell) ? passwd->shell : "");
257  }
258 
263  std::string homedir() const noexcept {
264  return ((passwd && passwd->homedir) ? passwd->homedir: "");
265  }
266 
271  operator bool() const noexcept {
272  return static_cast<bool>(passwd);
273  }
274 
275 private:
276  std::shared_ptr<uv_passwd_t> passwd;
277 };
278 
279 
285 struct IPv4 {};
286 
287 
293 struct IPv6 {};
294 
295 
299 struct Addr {
300  std::string ip;
301  unsigned int port;
302 };
303 
304 
308 struct CPUInfo {
309  using CPUTime = decltype(uv_cpu_info_t::cpu_times);
310 
311  std::string model;
312  int speed;
320  CPUTime times;
321 };
322 
323 
328  std::string name;
329  char physical[6];
330  bool internal;
333 };
334 
335 
336 namespace details {
337 
338 
339 static constexpr std::size_t DEFAULT_SIZE = 128;
340 
341 
342 template<typename>
343 struct IpTraits;
344 
345 
346 template<>
347 struct IpTraits<IPv4> {
348  using Type = sockaddr_in;
349  using AddrFuncType = int(*)(const char *, int, Type *);
350  using NameFuncType = int(*)(const Type *, char *, std::size_t);
351  static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
352  static constexpr NameFuncType nameFunc = &uv_ip4_name;
353  static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
354 };
355 
356 
357 template<>
358 struct IpTraits<IPv6> {
359  using Type = sockaddr_in6;
360  using AddrFuncType = int(*)(const char *, int, Type *);
361  using NameFuncType = int(*)(const Type *, char *, std::size_t);
362  static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
363  static constexpr NameFuncType nameFunc = &uv_ip6_name;
364  static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
365 };
366 
367 
368 template<typename I>
369 Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
370  Addr addr;
371  char name[DEFAULT_SIZE];
372 
373  int err = details::IpTraits<I>::nameFunc(aptr, name, DEFAULT_SIZE);
374 
375  if(0 == err) {
376  addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
377  addr.ip = std::string{name};
378  }
379 
380  return addr;
381 }
382 
383 
384 template<typename I, typename F, typename H>
385 Addr address(F &&f, const H *handle) noexcept {
386  sockaddr_storage ssto;
387  int len = sizeof(ssto);
388  Addr addr{};
389 
390  int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
391 
392  if(0 == err) {
393  typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
394  addr = address<I>(aptr);
395  }
396 
397  return addr;
398 }
399 
400 
401 template<typename F, typename... Args>
402 std::string tryRead(F &&f, Args&&... args) noexcept {
403  std::size_t size = DEFAULT_SIZE;
404  char buf[DEFAULT_SIZE];
405  std::string str{};
406  auto err = std::forward<F>(f)(args..., buf, &size);
407 
408  if(UV_ENOBUFS == err) {
409  std::unique_ptr<char[]> data{new char[size]};
410  err = std::forward<F>(f)(args..., data.get(), &size);
411 
412  if(0 == err) {
413  str = data.get();
414  }
415  } else if(0 == err) {
416  str.assign(buf, size);
417  }
418 
419  return str;
420 }
421 
422 
423 }
424 
425 
431 struct Utilities {
432  using MallocFuncType = void*(*)(size_t);
433  using ReallocFuncType = void*(*)(void*, size_t);
434  using CallocFuncType = void*(*)(size_t, size_t);
435  using FreeFuncType = void(*)(void*);
436 
440  struct OS {
450  static PidType pid() noexcept {
451  return uv_os_getppid();
452  }
453 
464  static std::string homedir() noexcept {
465  return details::tryRead(&uv_os_homedir);
466  }
467 
477  static std::string tmpdir() noexcept {
478  return details::tryRead(&uv_os_tmpdir);
479  }
480 
487  static std::string env(const std::string &name) noexcept {
488  return details::tryRead(&uv_os_getenv, name.c_str());
489  }
490 
498  static bool env(const std::string &name, const std::string &value) noexcept {
499  return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
500  }
501 
506  static std::string hostname() noexcept {
507  return details::tryRead(&uv_os_gethostname);
508  }
509 
522  static Passwd passwd() noexcept {
523  auto deleter = [](uv_passwd_t *passwd){
524  uv_os_free_passwd(passwd);
525  delete passwd;
526  };
527 
528  std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
529  uv_os_get_passwd(ptr.get());
530  return ptr;
531  }
532  };
533 
539  static HandleType guessHandle(HandleCategory category) noexcept {
540  switch(category) {
541  case UV_ASYNC:
542  return HandleType::ASYNC;
543  case UV_CHECK:
544  return HandleType::CHECK;
545  case UV_FS_EVENT:
546  return HandleType::FS_EVENT;
547  case UV_FS_POLL:
548  return HandleType::FS_POLL;
549  case UV_HANDLE:
550  return HandleType::HANDLE;
551  case UV_IDLE:
552  return HandleType::IDLE;
553  case UV_NAMED_PIPE:
554  return HandleType::PIPE;
555  case UV_POLL:
556  return HandleType::POLL;
557  case UV_PREPARE:
558  return HandleType::PREPARE;
559  case UV_PROCESS:
560  return HandleType::PROCESS;
561  case UV_STREAM:
562  return HandleType::STREAM;
563  case UV_TCP:
564  return HandleType::TCP;
565  case UV_TIMER:
566  return HandleType::TIMER;
567  case UV_TTY:
568  return HandleType::TTY;
569  case UV_UDP:
570  return HandleType::UDP;
571  case UV_SIGNAL:
572  return HandleType::SIGNAL;
573  case UV_FILE:
574  return HandleType::FILE;
575  default:
576  return HandleType::UNKNOWN;
577  }
578  }
579 
598  static HandleType guessHandle(FileHandle file) noexcept {
599  HandleCategory category = uv_guess_handle(file);
600  return guessHandle(category);
601  }
602 
603 
611  static std::vector<CPUInfo> cpuInfo() noexcept {
612  std::vector<CPUInfo> cpuinfos;
613 
614  uv_cpu_info_t *infos;
615  int count;
616 
617  if(0 == uv_cpu_info(&infos, &count)) {
618  std::for_each(infos, infos+count, [&cpuinfos](const auto &info) {
619  cpuinfos.push_back({ info.model, info.speed, info.cpu_times });
620  });
621 
622  uv_free_cpu_info(infos, count);
623  }
624 
625  return cpuinfos;
626  }
627 
636  static std::vector<InterfaceAddress> interfaceAddresses() noexcept {
637  std::vector<InterfaceAddress> interfaces;
638 
639  uv_interface_address_t *ifaces{nullptr};
640  int count{0};
641 
642  if(0 == uv_interface_addresses(&ifaces, &count)) {
643  std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
644  InterfaceAddress interfaceAddress;
645 
646  interfaceAddress.name = iface.name;
647  std::copy(iface.phys_addr, (iface.phys_addr+6), interfaceAddress.physical);
648  interfaceAddress.internal = iface.is_internal == 0 ? false : true;
649 
650  if(iface.address.address4.sin_family == AF_INET) {
651  interfaceAddress.address = details::address<IPv4>(&iface.address.address4);
652  interfaceAddress.netmask = details::address<IPv4>(&iface.netmask.netmask4);
653  } else if(iface.address.address4.sin_family == AF_INET6) {
654  interfaceAddress.address = details::address<IPv6>(&iface.address.address6);
655  interfaceAddress.netmask = details::address<IPv6>(&iface.netmask.netmask6);
656  }
657 
658  interfaces.push_back(std::move(interfaceAddress));
659  });
660 
661  uv_free_interface_addresses(ifaces, count);
662  }
663 
664  return interfaces;
665  }
666 
680  static std::string indexToName(unsigned int index) noexcept {
681  return details::tryRead(&uv_if_indextoname, index);
682  }
683 
694  static std::string indexToIid(unsigned int index) noexcept {
695  return details::tryRead(&uv_if_indextoiid, index);
696  }
697 
720  static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
721  return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
722  }
723 
728  static std::array<double, 3> loadAverage() noexcept {
729  std::array<double, 3> avg;
730  uv_loadavg(avg.data());
731  return avg;
732  }
733 
741  static char ** setupArgs(int argc, char** argv) {
742  return uv_setup_args(argc, argv);
743  }
744 
749  static std::string processTitle() {
750  std::size_t size = details::DEFAULT_SIZE;
751  char buf[details::DEFAULT_SIZE];
752  std::string str{};
753 
754  if(0 == uv_get_process_title(buf, size)) {
755  str.assign(buf, size);
756  }
757 
758  return str;
759  }
760 
766  static bool processTitle(std::string title) {
767  return (0 == uv_set_process_title(title.c_str()));
768  }
769 
774  static uint64_t totalMemory() noexcept {
775  return uv_get_total_memory();
776  }
777 
782  static double uptime() noexcept {
783  double ret;
784 
785  if(0 != uv_uptime(&ret)) {
786  ret = 0;
787  }
788 
789  return ret;
790  }
791 
796  static RUsage rusage() noexcept {
797  RUsage ru;
798  auto err = uv_getrusage(&ru);
799  return err ? RUsage{} : ru;
800  }
801 
812  static uint64_t hrtime() noexcept {
813  return uv_hrtime();
814  }
815 
820  static std::string path() noexcept {
821  return details::tryRead(&uv_exepath);
822  }
823 
828  static std::string cwd() noexcept {
829  return details::tryRead(&uv_cwd);
830  }
831 
837  static bool chdir(const std::string &dir) noexcept {
838  return (0 == uv_chdir(dir.data()));
839  }
840 };
841 
842 
843 }
Address representation.
Definition: util.hpp:299
constexpr FileHandle StdERR
Definition: util.hpp:205
auto gid() const noexcept
Gets the gid.
Definition: util.hpp:247
unsigned int port
Definition: util.hpp:301
static Passwd passwd() noexcept
Gets a subset of the password file entry.
Definition: util.hpp:522
static HandleType guessHandle(FileHandle file) noexcept
Gets the type of the stream to be used with the given descriptor.
Definition: util.hpp:598
static std::string hostname() noexcept
Returns the hostname.
Definition: util.hpp:506
static std::string env(const std::string &name) noexcept
Retrieves an environment variable.
Definition: util.hpp:487
static std::vector< InterfaceAddress > interfaceAddresses() noexcept
Gets a set of descriptors of all the available interfaces.
Definition: util.hpp:636
std::string ip
Definition: util.hpp:300
uv_timespec_t TimeSpec
Definition: util.hpp:207
static double uptime() noexcept
Gets the current system uptime.
Definition: util.hpp:782
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.hpp:198
static std::string tmpdir() noexcept
Gets the temp directory.
Definition: util.hpp:477
static std::string homedir() noexcept
Gets the current user&#39;s home directory.
Definition: util.hpp:464
uv_rusage_t RUsage
Definition: util.hpp:213
static PidType pid() noexcept
Returns the parent process id.
Definition: util.hpp:450
Windows size representation.
Definition: util.hpp:189
details::UVTypeWrapper< uv_os_fd_t > OSFileDescriptor
Definition: util.hpp:200
constexpr FileHandle StdIN
Definition: util.hpp:203
static char ** setupArgs(int argc, char **argv)
Store the program arguments.
Definition: util.hpp:741
CPU information.
Definition: util.hpp:308
uv_timeval_t TimeVal
Definition: util.hpp:212
std::string username() const noexcept
Gets the username.
Definition: util.hpp:231
constexpr FileHandle StdOUT
Definition: util.hpp:204
Utility class to handle flags.
Definition: util.hpp:89
details::UVTypeWrapper< uv_pid_t > PidType
Definition: util.hpp:201
constexpr Flags operator &(const Flags &f) const noexcept
And operator.
Definition: util.hpp:160
constexpr Flags(E flag) noexcept
Constructs a Flags object from a value of the enum E.
Definition: util.hpp:112
OS dedicated utilities.
Definition: util.hpp:440
constexpr Flags operator|(const Flags &f) const noexcept
Or operator.
Definition: util.hpp:146
static uint64_t hrtime() noexcept
Gets the current high-resolution real time.
Definition: util.hpp:812
The IPv6 tag.
Definition: util.hpp:293
static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept
Override the use of some standard library’s functions.
Definition: util.hpp:720
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:197
uv_gid_t Gid
Definition: util.hpp:210
static bool env(const std::string &name, const std::string &value) noexcept
Creates, updates or deletes an environment variable.
Definition: util.hpp:498
static RUsage rusage() noexcept
Gets the resource usage measures for the current process.
Definition: util.hpp:796
uv_uid_t Uid
Definition: util.hpp:209
Interface address.
Definition: util.hpp:327
static uint64_t totalMemory() noexcept
Gets memory information (in bytes).
Definition: util.hpp:774
int height
Definition: util.hpp:191
auto uid() const noexcept
Gets the uid.
Definition: util.hpp:239
std::string shell() const noexcept
Gets the shell.
Definition: util.hpp:255
static std::string indexToName(unsigned int index) noexcept
IPv6-capable implementation of if_indextoname.
Definition: util.hpp:680
CPUTime times
CPU times.
Definition: util.hpp:320
static std::string cwd() noexcept
Gets the current working directory.
Definition: util.hpp:828
static std::string path() noexcept
Gets the executable path.
Definition: util.hpp:820
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.hpp:199
int width
Definition: util.hpp:190
constexpr Flags()
Constructs an uninitialized Flags object.
Definition: util.hpp:124
std::string name
Definition: util.hpp:328
static HandleType guessHandle(HandleCategory category) noexcept
Gets the type of the handle given a category.
Definition: util.hpp:539
int speed
Definition: util.hpp:312
static CONSTEXPR_SPECIFIER Flags< E > from()
Utility factory method to pack a set of values all at once.
Definition: util.hpp:102
std::string model
Definition: util.hpp:311
constexpr Flags(Type f)
Constructs a Flags object from an instance of the underlying type of the enum E.
Definition: util.hpp:119
constexpr Flags operator|(E flag) const noexcept
Or operator.
Definition: util.hpp:153
static std::vector< CPUInfo > cpuInfo() noexcept
Gets information about the CPUs on the system.
Definition: util.hpp:611
Utility class.
Definition: util.hpp:224
uv_stat_t Stat
Definition: util.hpp:208
static bool chdir(const std::string &dir) noexcept
Changes the current working directory.
Definition: util.hpp:837
constexpr Flags operator &(E flag) const noexcept
And operator.
Definition: util.hpp:167
static std::array< double, 3 > loadAverage() noexcept
Gets the load average.
Definition: util.hpp:728
The IPv4 tag.
Definition: util.hpp:285
static bool processTitle(std::string title)
Sets the current process title.
Definition: util.hpp:766
Miscellaneous utilities.
Definition: util.hpp:431
static std::string processTitle()
Gets the title of the current process.
Definition: util.hpp:749
std::string homedir() const noexcept
Gets the homedir.
Definition: util.hpp:263
static std::string indexToIid(unsigned int index) noexcept
Retrieves a network interface identifier.
Definition: util.hpp:694
uvw default namespace.
Definition: async.hpp:11