uvw  1.11.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 <memory>
12 #include <array>
13 #include <uv.h>
14 
15 
16 #ifdef _WIN32
17 // MSVC doesn't have C++14 relaxed constexpr support yet. Hence the jugglery.
18 #define CONSTEXPR_SPECIFIER
19 #else
20 #define CONSTEXPR_SPECIFIER constexpr
21 #endif
22 
23 
24 namespace uvw {
25 
26 
27 namespace details {
28 
29 
30 enum class UVHandleType: std::underlying_type_t<uv_handle_type> {
31  UNKNOWN = UV_UNKNOWN_HANDLE,
32  ASYNC = UV_ASYNC,
33  CHECK = UV_CHECK,
34  FS_EVENT = UV_FS_EVENT,
35  FS_POLL = UV_FS_POLL,
36  HANDLE = UV_HANDLE,
37  IDLE = UV_IDLE,
38  PIPE = UV_NAMED_PIPE,
39  POLL = UV_POLL,
40  PREPARE = UV_PREPARE,
41  PROCESS = UV_PROCESS,
42  STREAM = UV_STREAM,
43  TCP = UV_TCP,
44  TIMER = UV_TIMER,
45  TTY = UV_TTY,
46  UDP = UV_UDP,
47  SIGNAL = UV_SIGNAL,
48  FILE = UV_FILE
49 };
50 
51 
52 template<typename T>
53 struct UVTypeWrapper {
54  using Type = T;
55 
56  constexpr UVTypeWrapper(): value{} {}
57  constexpr UVTypeWrapper(Type val): value{val} {}
58 
59  constexpr operator Type() const noexcept { return value; }
60 
61  bool operator==(UVTypeWrapper other) const noexcept {
62  return value == other.value;
63  }
64 
65 private:
66  const Type value;
67 };
68 
69 
70 template<typename T>
71 bool operator==(UVTypeWrapper<T> lhs, UVTypeWrapper<T> rhs) {
72  return !(lhs == rhs);
73 }
74 
75 
76 }
77 
78 
89 template<typename E>
90 class Flags final {
91  using InnerType = std::underlying_type_t<E>;
92 
93  constexpr InnerType toInnerType(E flag) const noexcept { return static_cast<InnerType>(flag); }
94 
95 public:
96  using Type = InnerType;
97 
102  template<E... V>
103  static CONSTEXPR_SPECIFIER Flags<E> from() {
104  auto flags = Flags<E>{};
105  int _[] = { 0, (flags = flags | V, 0)... };
106  return void(_), flags;
107  }
108 
113  constexpr Flags(E flag) noexcept: flags{toInnerType(flag)} {}
114 
120  constexpr Flags(Type f): flags{f} {}
121 
125  constexpr Flags(): flags{} {}
126 
127  constexpr Flags(const Flags &f) noexcept: flags{f.flags} { }
128  constexpr Flags(Flags &&f) noexcept: flags{std::move(f.flags)} { }
129 
130  ~Flags() noexcept { static_assert(std::is_enum<E>::value, "!"); }
131 
132  CONSTEXPR_SPECIFIER Flags & operator=(const Flags &f) noexcept {
133  flags = f.flags;
134  return *this;
135  }
136 
137  CONSTEXPR_SPECIFIER Flags & operator=(Flags &&f) noexcept {
138  flags = std::move(f.flags);
139  return *this;
140  }
141 
147  constexpr Flags operator|(const Flags &f) const noexcept { return Flags{flags | f.flags}; }
148 
154  constexpr Flags operator|(E flag) const noexcept { return Flags{flags | toInnerType(flag)}; }
155 
161  constexpr Flags operator&(const Flags &f) const noexcept { return Flags{flags & f.flags}; }
162 
168  constexpr Flags operator&(E flag) const noexcept { return Flags{flags & toInnerType(flag)}; }
169 
174  explicit constexpr operator bool() const noexcept { return !(flags == InnerType{}); }
175 
180  constexpr operator Type() const noexcept { return flags; }
181 
182 private:
183  InnerType flags;
184 };
185 
186 
190 struct WinSize {
191  int width;
192  int height;
193 };
194 
195 
196 using HandleType = details::UVHandleType;
198 using HandleCategory = details::UVTypeWrapper<uv_handle_type>;
199 using FileHandle = details::UVTypeWrapper<uv_file>;
200 using OSSocketHandle = details::UVTypeWrapper<uv_os_sock_t>;
201 using OSFileDescriptor = details::UVTypeWrapper<uv_os_fd_t>;
202 using PidType = details::UVTypeWrapper<uv_pid_t>;
204 constexpr FileHandle StdIN{0};
205 constexpr FileHandle StdOUT{1};
206 constexpr FileHandle StdERR{2};
208 using TimeSpec = uv_timespec_t;
209 using Stat = uv_stat_t;
210 using Uid = uv_uid_t;
211 using Gid = uv_gid_t;
213 using TimeVal = uv_timeval_t;
214 using RUsage = uv_rusage_t;
225 struct Passwd {
226  Passwd(std::shared_ptr<uv_passwd_t> pwd): passwd{pwd} {}
227 
232  std::string username() const noexcept {
233  return ((passwd && passwd->username) ? passwd->username : "");
234  }
235 
240  auto uid() const noexcept {
241  return (passwd ? passwd->uid : decltype(uv_passwd_t::uid){});
242  }
243 
248  auto gid() const noexcept {
249  return (passwd ? passwd->gid : decltype(uv_passwd_t::gid){});
250  }
251 
256  std::string shell() const noexcept {
257  return ((passwd && passwd->shell) ? passwd->shell : "");
258  }
259 
264  std::string homedir() const noexcept {
265  return ((passwd && passwd->homedir) ? passwd->homedir: "");
266  }
267 
272  operator bool() const noexcept {
273  return static_cast<bool>(passwd);
274  }
275 
276 private:
277  std::shared_ptr<uv_passwd_t> passwd;
278 };
279 
280 
286 struct IPv4 {};
287 
288 
294 struct IPv6 {};
295 
296 
300 struct Addr {
301  std::string ip;
302  unsigned int port;
303 };
304 
305 
309 struct CPUInfo {
310  using CPUTime = decltype(uv_cpu_info_t::cpu_times);
311 
312  std::string model;
313  int speed;
321  CPUTime times;
322 };
323 
324 
329  std::string name;
330  char physical[6];
331  bool internal;
334 };
335 
336 
337 namespace details {
338 
339 
340 static constexpr std::size_t DEFAULT_SIZE = 128;
341 
342 
343 template<typename>
344 struct IpTraits;
345 
346 
347 template<>
348 struct IpTraits<IPv4> {
349  using Type = sockaddr_in;
350  using AddrFuncType = int(*)(const char *, int, Type *);
351  using NameFuncType = int(*)(const Type *, char *, std::size_t);
352  static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
353  static constexpr NameFuncType nameFunc = &uv_ip4_name;
354  static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
355 };
356 
357 
358 template<>
359 struct IpTraits<IPv6> {
360  using Type = sockaddr_in6;
361  using AddrFuncType = int(*)(const char *, int, Type *);
362  using NameFuncType = int(*)(const Type *, char *, std::size_t);
363  static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
364  static constexpr NameFuncType nameFunc = &uv_ip6_name;
365  static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
366 };
367 
368 
369 template<typename I>
370 Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
371  Addr addr;
372  char name[DEFAULT_SIZE];
373 
374  int err = details::IpTraits<I>::nameFunc(aptr, name, DEFAULT_SIZE);
375 
376  if(0 == err) {
377  addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
378  addr.ip = std::string{name};
379  }
380 
381  return addr;
382 }
383 
384 
385 template<typename I, typename F, typename H>
386 Addr address(F &&f, const H *handle) noexcept {
387  sockaddr_storage ssto;
388  int len = sizeof(ssto);
389  Addr addr{};
390 
391  int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
392 
393  if(0 == err) {
394  typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
395  addr = address<I>(aptr);
396  }
397 
398  return addr;
399 }
400 
401 
402 template<typename F, typename... Args>
403 std::string tryRead(F &&f, Args&&... args) noexcept {
404  std::size_t size = DEFAULT_SIZE;
405  char buf[DEFAULT_SIZE];
406  std::string str{};
407  auto err = std::forward<F>(f)(args..., buf, &size);
408 
409  if(UV_ENOBUFS == err) {
410  std::unique_ptr<char[]> data{new char[size]};
411  err = std::forward<F>(f)(args..., data.get(), &size);
412 
413  if(0 == err) {
414  str = data.get();
415  }
416  } else if(0 == err) {
417  str.assign(buf, size);
418  }
419 
420  return str;
421 }
422 
423 
424 }
425 
426 
432 struct Utilities {
433  using MallocFuncType = void*(*)(size_t);
434  using ReallocFuncType = void*(*)(void*, size_t);
435  using CallocFuncType = void*(*)(size_t, size_t);
436  using FreeFuncType = void(*)(void*);
437 
441  struct OS {
451  static PidType pid() noexcept {
452  return uv_os_getpid();
453  }
454 
464  static PidType parent() noexcept {
465  return uv_os_getppid();
466  }
467 
478  static std::string homedir() noexcept {
479  return details::tryRead(&uv_os_homedir);
480  }
481 
491  static std::string tmpdir() noexcept {
492  return details::tryRead(&uv_os_tmpdir);
493  }
494 
501  static std::string env(const std::string &name) noexcept {
502  return details::tryRead(&uv_os_getenv, name.c_str());
503  }
504 
512  static bool env(const std::string &name, const std::string &value) noexcept {
513  return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
514  }
515 
520  static std::string hostname() noexcept {
521  return details::tryRead(&uv_os_gethostname);
522  }
523 
536  static Passwd passwd() noexcept {
537  auto deleter = [](uv_passwd_t *passwd){
538  uv_os_free_passwd(passwd);
539  delete passwd;
540  };
541 
542  std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
543  uv_os_get_passwd(ptr.get());
544  return ptr;
545  }
546  };
547 
561  static int osPriority(PidType pid) {
562  int prio = 0;
563 
564  if(uv_os_getpriority(pid, &prio)) {
565  prio = UV_PRIORITY_LOW + 1;
566  }
567 
568  return prio;
569  }
570 
586  static bool osPriority(PidType pid, int prio) {
587  return 0 == uv_os_setpriority(pid, prio);
588  }
589 
595  static HandleType guessHandle(HandleCategory category) noexcept {
596  switch(category) {
597  case UV_ASYNC:
598  return HandleType::ASYNC;
599  case UV_CHECK:
600  return HandleType::CHECK;
601  case UV_FS_EVENT:
602  return HandleType::FS_EVENT;
603  case UV_FS_POLL:
604  return HandleType::FS_POLL;
605  case UV_HANDLE:
606  return HandleType::HANDLE;
607  case UV_IDLE:
608  return HandleType::IDLE;
609  case UV_NAMED_PIPE:
610  return HandleType::PIPE;
611  case UV_POLL:
612  return HandleType::POLL;
613  case UV_PREPARE:
614  return HandleType::PREPARE;
615  case UV_PROCESS:
616  return HandleType::PROCESS;
617  case UV_STREAM:
618  return HandleType::STREAM;
619  case UV_TCP:
620  return HandleType::TCP;
621  case UV_TIMER:
622  return HandleType::TIMER;
623  case UV_TTY:
624  return HandleType::TTY;
625  case UV_UDP:
626  return HandleType::UDP;
627  case UV_SIGNAL:
628  return HandleType::SIGNAL;
629  case UV_FILE:
630  return HandleType::FILE;
631  default:
632  return HandleType::UNKNOWN;
633  }
634  }
635 
654  static HandleType guessHandle(FileHandle file) noexcept {
655  HandleCategory category = uv_guess_handle(file);
656  return guessHandle(category);
657  }
658 
659 
667  static std::vector<CPUInfo> cpuInfo() noexcept {
668  std::vector<CPUInfo> cpuinfos;
669 
670  uv_cpu_info_t *infos;
671  int count;
672 
673  if(0 == uv_cpu_info(&infos, &count)) {
674  std::for_each(infos, infos+count, [&cpuinfos](const auto &info) {
675  cpuinfos.push_back({ info.model, info.speed, info.cpu_times });
676  });
677 
678  uv_free_cpu_info(infos, count);
679  }
680 
681  return cpuinfos;
682  }
683 
692  static std::vector<InterfaceAddress> interfaceAddresses() noexcept {
693  std::vector<InterfaceAddress> interfaces;
694 
695  uv_interface_address_t *ifaces{nullptr};
696  int count{0};
697 
698  if(0 == uv_interface_addresses(&ifaces, &count)) {
699  std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
700  InterfaceAddress interfaceAddress;
701 
702  interfaceAddress.name = iface.name;
703  std::copy(iface.phys_addr, (iface.phys_addr+6), interfaceAddress.physical);
704  interfaceAddress.internal = iface.is_internal == 0 ? false : true;
705 
706  if(iface.address.address4.sin_family == AF_INET) {
707  interfaceAddress.address = details::address<IPv4>(&iface.address.address4);
708  interfaceAddress.netmask = details::address<IPv4>(&iface.netmask.netmask4);
709  } else if(iface.address.address4.sin_family == AF_INET6) {
710  interfaceAddress.address = details::address<IPv6>(&iface.address.address6);
711  interfaceAddress.netmask = details::address<IPv6>(&iface.netmask.netmask6);
712  }
713 
714  interfaces.push_back(std::move(interfaceAddress));
715  });
716 
717  uv_free_interface_addresses(ifaces, count);
718  }
719 
720  return interfaces;
721  }
722 
736  static std::string indexToName(unsigned int index) noexcept {
737  return details::tryRead(&uv_if_indextoname, index);
738  }
739 
750  static std::string indexToIid(unsigned int index) noexcept {
751  return details::tryRead(&uv_if_indextoiid, index);
752  }
753 
777  static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
778  return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
779  }
780 
785  static std::array<double, 3> loadAverage() noexcept {
786  std::array<double, 3> avg;
787  uv_loadavg(avg.data());
788  return avg;
789  }
790 
798  static char ** setupArgs(int argc, char** argv) {
799  return uv_setup_args(argc, argv);
800  }
801 
806  static std::string processTitle() {
807  std::size_t size = details::DEFAULT_SIZE;
808  char buf[details::DEFAULT_SIZE];
809  std::string str{};
810 
811  if(0 == uv_get_process_title(buf, size)) {
812  str.assign(buf, size);
813  }
814 
815  return str;
816  }
817 
823  static bool processTitle(std::string title) {
824  return (0 == uv_set_process_title(title.c_str()));
825  }
826 
831  static uint64_t totalMemory() noexcept {
832  return uv_get_total_memory();
833  }
834 
839  static double uptime() noexcept {
840  double ret;
841 
842  if(0 != uv_uptime(&ret)) {
843  ret = 0;
844  }
845 
846  return ret;
847  }
848 
853  static RUsage rusage() noexcept {
854  RUsage ru;
855  auto err = uv_getrusage(&ru);
856  return err ? RUsage{} : ru;
857  }
858 
869  static uint64_t hrtime() noexcept {
870  return uv_hrtime();
871  }
872 
877  static std::string path() noexcept {
878  return details::tryRead(&uv_exepath);
879  }
880 
885  static std::string cwd() noexcept {
886  return details::tryRead(&uv_cwd);
887  }
888 
894  static bool chdir(const std::string &dir) noexcept {
895  return (0 == uv_chdir(dir.data()));
896  }
897 };
898 
899 
900 }
Address representation.
Definition: util.hpp:300
constexpr FileHandle StdERR
Definition: util.hpp:206
auto gid() const noexcept
Gets the gid.
Definition: util.hpp:248
unsigned int port
Definition: util.hpp:302
static Passwd passwd() noexcept
Gets a subset of the password file entry.
Definition: util.hpp:536
static HandleType guessHandle(FileHandle file) noexcept
Gets the type of the stream to be used with the given descriptor.
Definition: util.hpp:654
static std::string hostname() noexcept
Returns the hostname.
Definition: util.hpp:520
static std::string env(const std::string &name) noexcept
Retrieves an environment variable.
Definition: util.hpp:501
static std::vector< InterfaceAddress > interfaceAddresses() noexcept
Gets a set of descriptors of all the available interfaces.
Definition: util.hpp:692
std::string ip
Definition: util.hpp:301
uv_timespec_t TimeSpec
Definition: util.hpp:208
static double uptime() noexcept
Gets the current system uptime.
Definition: util.hpp:839
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.hpp:199
static std::string tmpdir() noexcept
Gets the temp directory.
Definition: util.hpp:491
static std::string homedir() noexcept
Gets the current user&#39;s home directory.
Definition: util.hpp:478
uv_rusage_t RUsage
Definition: util.hpp:214
static PidType pid() noexcept
Returns the current process id.
Definition: util.hpp:451
Windows size representation.
Definition: util.hpp:190
details::UVTypeWrapper< uv_os_fd_t > OSFileDescriptor
Definition: util.hpp:201
static int osPriority(PidType pid)
Retrieves the scheduling priority of a process.
Definition: util.hpp:561
constexpr FileHandle StdIN
Definition: util.hpp:204
static char ** setupArgs(int argc, char **argv)
Store the program arguments.
Definition: util.hpp:798
CPU information.
Definition: util.hpp:309
uv_timeval_t TimeVal
Definition: util.hpp:213
std::string username() const noexcept
Gets the username.
Definition: util.hpp:232
constexpr FileHandle StdOUT
Definition: util.hpp:205
Utility class to handle flags.
Definition: util.hpp:90
details::UVTypeWrapper< uv_pid_t > PidType
Definition: util.hpp:202
constexpr Flags operator &(const Flags &f) const noexcept
And operator.
Definition: util.hpp:161
constexpr Flags(E flag) noexcept
Constructs a Flags object from a value of the enum E.
Definition: util.hpp:113
OS dedicated utilities.
Definition: util.hpp:441
constexpr Flags operator|(const Flags &f) const noexcept
Or operator.
Definition: util.hpp:147
static bool osPriority(PidType pid, int prio)
Sets the scheduling priority of a process.
Definition: util.hpp:586
static uint64_t hrtime() noexcept
Gets the current high-resolution real time.
Definition: util.hpp:869
The IPv6 tag.
Definition: util.hpp:294
static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept
Override the use of some standard library’s functions.
Definition: util.hpp:777
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:198
uv_gid_t Gid
Definition: util.hpp:211
static bool env(const std::string &name, const std::string &value) noexcept
Creates, updates or deletes an environment variable.
Definition: util.hpp:512
static RUsage rusage() noexcept
Gets the resource usage measures for the current process.
Definition: util.hpp:853
uv_uid_t Uid
Definition: util.hpp:210
Interface address.
Definition: util.hpp:328
static uint64_t totalMemory() noexcept
Gets memory information (in bytes).
Definition: util.hpp:831
int height
Definition: util.hpp:192
auto uid() const noexcept
Gets the uid.
Definition: util.hpp:240
std::string shell() const noexcept
Gets the shell.
Definition: util.hpp:256
static std::string indexToName(unsigned int index) noexcept
IPv6-capable implementation of if_indextoname.
Definition: util.hpp:736
CPUTime times
CPU times.
Definition: util.hpp:321
static std::string cwd() noexcept
Gets the current working directory.
Definition: util.hpp:885
static std::string path() noexcept
Gets the executable path.
Definition: util.hpp:877
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.hpp:200
static PidType parent() noexcept
Returns the parent process id.
Definition: util.hpp:464
int width
Definition: util.hpp:191
constexpr Flags()
Constructs an uninitialized Flags object.
Definition: util.hpp:125
std::string name
Definition: util.hpp:329
static HandleType guessHandle(HandleCategory category) noexcept
Gets the type of the handle given a category.
Definition: util.hpp:595
int speed
Definition: util.hpp:313
static CONSTEXPR_SPECIFIER Flags< E > from()
Utility factory method to pack a set of values all at once.
Definition: util.hpp:103
std::string model
Definition: util.hpp:312
constexpr Flags(Type f)
Constructs a Flags object from an instance of the underlying type of the enum E.
Definition: util.hpp:120
constexpr Flags operator|(E flag) const noexcept
Or operator.
Definition: util.hpp:154
static std::vector< CPUInfo > cpuInfo() noexcept
Gets information about the CPUs on the system.
Definition: util.hpp:667
Utility class.
Definition: util.hpp:225
uv_stat_t Stat
Definition: util.hpp:209
static bool chdir(const std::string &dir) noexcept
Changes the current working directory.
Definition: util.hpp:894
constexpr Flags operator &(E flag) const noexcept
And operator.
Definition: util.hpp:168
static std::array< double, 3 > loadAverage() noexcept
Gets the load average.
Definition: util.hpp:785
The IPv4 tag.
Definition: util.hpp:286
static bool processTitle(std::string title)
Sets the current process title.
Definition: util.hpp:823
Miscellaneous utilities.
Definition: util.hpp:432
static std::string processTitle()
Gets the title of the current process.
Definition: util.hpp:806
std::string homedir() const noexcept
Gets the homedir.
Definition: util.hpp:264
static std::string indexToIid(unsigned int index) noexcept
Retrieves a network interface identifier.
Definition: util.hpp:750
uvw default namespace.
Definition: async.hpp:11