uvw  1.15.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 
290 struct UName {
291  UName(std::shared_ptr<uv_utsname_t> utsname): utsname{utsname} {}
292 
297  std::string sysname() const noexcept {
298  return utsname ? utsname->sysname : "";
299  }
300 
305  std::string release() const noexcept {
306  return utsname ? utsname->release : "";
307  }
308 
313  std::string version() const noexcept {
314  return utsname ? utsname->version : "";
315  }
316 
321  std::string machine() const noexcept {
322  return utsname ? utsname->machine : "";
323  }
324 
325 private:
326  std::shared_ptr<uv_utsname_t> utsname;
327 };
328 
329 
335 struct IPv4 {};
336 
337 
343 struct IPv6 {};
344 
345 
349 struct Addr {
350  std::string ip;
351  unsigned int port;
352 };
353 
354 
358 struct CPUInfo {
359  using CPUTime = decltype(uv_cpu_info_t::cpu_times);
360 
361  std::string model;
362  int speed;
370  CPUTime times;
371 };
372 
373 
378  std::string name;
379  char physical[6];
380  bool internal;
383 };
384 
385 
386 namespace details {
387 
388 
389 static constexpr std::size_t DEFAULT_SIZE = 128;
390 
391 
392 template<typename>
393 struct IpTraits;
394 
395 
396 template<>
397 struct IpTraits<IPv4> {
398  using Type = sockaddr_in;
399  using AddrFuncType = int(*)(const char *, int, Type *);
400  using NameFuncType = int(*)(const Type *, char *, std::size_t);
401  static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
402  static constexpr NameFuncType nameFunc = &uv_ip4_name;
403  static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
404 };
405 
406 
407 template<>
408 struct IpTraits<IPv6> {
409  using Type = sockaddr_in6;
410  using AddrFuncType = int(*)(const char *, int, Type *);
411  using NameFuncType = int(*)(const Type *, char *, std::size_t);
412  static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
413  static constexpr NameFuncType nameFunc = &uv_ip6_name;
414  static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
415 };
416 
417 
418 template<typename I>
419 Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
420  Addr addr;
421  char name[DEFAULT_SIZE];
422 
423  int err = details::IpTraits<I>::nameFunc(aptr, name, DEFAULT_SIZE);
424 
425  if(0 == err) {
426  addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
427  addr.ip = std::string{name};
428  }
429 
430  return addr;
431 }
432 
433 
434 template<typename I, typename F, typename H>
435 Addr address(F &&f, const H *handle) noexcept {
436  sockaddr_storage ssto;
437  int len = sizeof(ssto);
438  Addr addr{};
439 
440  int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
441 
442  if(0 == err) {
443  typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
444  addr = address<I>(aptr);
445  }
446 
447  return addr;
448 }
449 
450 
451 template<typename F, typename... Args>
452 std::string tryRead(F &&f, Args&&... args) noexcept {
453  std::size_t size = DEFAULT_SIZE;
454  char buf[DEFAULT_SIZE];
455  std::string str{};
456  auto err = std::forward<F>(f)(args..., buf, &size);
457 
458  if(UV_ENOBUFS == err) {
459  std::unique_ptr<char[]> data{new char[size]};
460  err = std::forward<F>(f)(args..., data.get(), &size);
461 
462  if(0 == err) {
463  str = data.get();
464  }
465  } else if(0 == err) {
466  str.assign(buf, size);
467  }
468 
469  return str;
470 }
471 
472 
473 }
474 
475 
481 struct Utilities {
482  using MallocFuncType = void*(*)(size_t);
483  using ReallocFuncType = void*(*)(void*, size_t);
484  using CallocFuncType = void*(*)(size_t, size_t);
485  using FreeFuncType = void(*)(void*);
486 
490  struct OS {
500  static PidType pid() noexcept {
501  return uv_os_getpid();
502  }
503 
513  static PidType parent() noexcept {
514  return uv_os_getppid();
515  }
516 
527  static std::string homedir() noexcept {
528  return details::tryRead(&uv_os_homedir);
529  }
530 
540  static std::string tmpdir() noexcept {
541  return details::tryRead(&uv_os_tmpdir);
542  }
543 
550  static std::string env(const std::string &name) noexcept {
551  return details::tryRead(&uv_os_getenv, name.c_str());
552  }
553 
561  static bool env(const std::string &name, const std::string &value) noexcept {
562  return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
563  }
564 
569  static std::string hostname() noexcept {
570  return details::tryRead(&uv_os_gethostname);
571  }
572 
582  static UName uname() noexcept {
583  auto ptr = std::make_shared<uv_utsname_t>();
584  uv_os_uname(ptr.get());
585  return ptr;
586  }
587 
600  static Passwd passwd() noexcept {
601  auto deleter = [](uv_passwd_t *passwd){
602  uv_os_free_passwd(passwd);
603  delete passwd;
604  };
605 
606  std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
607  uv_os_get_passwd(ptr.get());
608  return ptr;
609  }
610  };
611 
625  static int osPriority(PidType pid) {
626  int prio = 0;
627 
628  if(uv_os_getpriority(pid, &prio)) {
629  prio = UV_PRIORITY_LOW + 1;
630  }
631 
632  return prio;
633  }
634 
650  static bool osPriority(PidType pid, int prio) {
651  return 0 == uv_os_setpriority(pid, prio);
652  }
653 
659  static HandleType guessHandle(HandleCategory category) noexcept {
660  switch(category) {
661  case UV_ASYNC:
662  return HandleType::ASYNC;
663  case UV_CHECK:
664  return HandleType::CHECK;
665  case UV_FS_EVENT:
666  return HandleType::FS_EVENT;
667  case UV_FS_POLL:
668  return HandleType::FS_POLL;
669  case UV_HANDLE:
670  return HandleType::HANDLE;
671  case UV_IDLE:
672  return HandleType::IDLE;
673  case UV_NAMED_PIPE:
674  return HandleType::PIPE;
675  case UV_POLL:
676  return HandleType::POLL;
677  case UV_PREPARE:
678  return HandleType::PREPARE;
679  case UV_PROCESS:
680  return HandleType::PROCESS;
681  case UV_STREAM:
682  return HandleType::STREAM;
683  case UV_TCP:
684  return HandleType::TCP;
685  case UV_TIMER:
686  return HandleType::TIMER;
687  case UV_TTY:
688  return HandleType::TTY;
689  case UV_UDP:
690  return HandleType::UDP;
691  case UV_SIGNAL:
692  return HandleType::SIGNAL;
693  case UV_FILE:
694  return HandleType::FILE;
695  default:
696  return HandleType::UNKNOWN;
697  }
698  }
699 
718  static HandleType guessHandle(FileHandle file) noexcept {
719  HandleCategory category = uv_guess_handle(file);
720  return guessHandle(category);
721  }
722 
723 
731  static std::vector<CPUInfo> cpuInfo() noexcept {
732  std::vector<CPUInfo> cpuinfos;
733 
734  uv_cpu_info_t *infos;
735  int count;
736 
737  if(0 == uv_cpu_info(&infos, &count)) {
738  std::for_each(infos, infos+count, [&cpuinfos](const auto &info) {
739  cpuinfos.push_back({ info.model, info.speed, info.cpu_times });
740  });
741 
742  uv_free_cpu_info(infos, count);
743  }
744 
745  return cpuinfos;
746  }
747 
756  static std::vector<InterfaceAddress> interfaceAddresses() noexcept {
757  std::vector<InterfaceAddress> interfaces;
758 
759  uv_interface_address_t *ifaces{nullptr};
760  int count{0};
761 
762  if(0 == uv_interface_addresses(&ifaces, &count)) {
763  std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
764  InterfaceAddress interfaceAddress;
765 
766  interfaceAddress.name = iface.name;
767  std::copy(iface.phys_addr, (iface.phys_addr+6), interfaceAddress.physical);
768  interfaceAddress.internal = iface.is_internal == 0 ? false : true;
769 
770  if(iface.address.address4.sin_family == AF_INET) {
771  interfaceAddress.address = details::address<IPv4>(&iface.address.address4);
772  interfaceAddress.netmask = details::address<IPv4>(&iface.netmask.netmask4);
773  } else if(iface.address.address4.sin_family == AF_INET6) {
774  interfaceAddress.address = details::address<IPv6>(&iface.address.address6);
775  interfaceAddress.netmask = details::address<IPv6>(&iface.netmask.netmask6);
776  }
777 
778  interfaces.push_back(std::move(interfaceAddress));
779  });
780 
781  uv_free_interface_addresses(ifaces, count);
782  }
783 
784  return interfaces;
785  }
786 
800  static std::string indexToName(unsigned int index) noexcept {
801  return details::tryRead(&uv_if_indextoname, index);
802  }
803 
814  static std::string indexToIid(unsigned int index) noexcept {
815  return details::tryRead(&uv_if_indextoiid, index);
816  }
817 
841  static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
842  return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
843  }
844 
849  static std::array<double, 3> loadAverage() noexcept {
850  std::array<double, 3> avg;
851  uv_loadavg(avg.data());
852  return avg;
853  }
854 
862  static char ** setupArgs(int argc, char** argv) {
863  return uv_setup_args(argc, argv);
864  }
865 
870  static std::string processTitle() {
871  std::size_t size = details::DEFAULT_SIZE;
872  char buf[details::DEFAULT_SIZE];
873  std::string str{};
874 
875  if(0 == uv_get_process_title(buf, size)) {
876  str.assign(buf, size);
877  }
878 
879  return str;
880  }
881 
887  static bool processTitle(std::string title) {
888  return (0 == uv_set_process_title(title.c_str()));
889  }
890 
895  static uint64_t totalMemory() noexcept {
896  return uv_get_total_memory();
897  }
898 
903  static double uptime() noexcept {
904  double ret;
905 
906  if(0 != uv_uptime(&ret)) {
907  ret = 0;
908  }
909 
910  return ret;
911  }
912 
917  static RUsage rusage() noexcept {
918  RUsage ru;
919  auto err = uv_getrusage(&ru);
920  return err ? RUsage{} : ru;
921  }
922 
933  static uint64_t hrtime() noexcept {
934  return uv_hrtime();
935  }
936 
941  static std::string path() noexcept {
942  return details::tryRead(&uv_exepath);
943  }
944 
949  static std::string cwd() noexcept {
950  return details::tryRead(&uv_cwd);
951  }
952 
958  static bool chdir(const std::string &dir) noexcept {
959  return (0 == uv_chdir(dir.data()));
960  }
961 };
962 
963 
964 }
Address representation.
Definition: util.hpp:349
constexpr FileHandle StdERR
Definition: util.hpp:206
auto gid() const noexcept
Gets the gid.
Definition: util.hpp:248
unsigned int port
Definition: util.hpp:351
static Passwd passwd() noexcept
Gets a subset of the password file entry.
Definition: util.hpp:600
static HandleType guessHandle(FileHandle file) noexcept
Gets the type of the stream to be used with the given descriptor.
Definition: util.hpp:718
static std::string hostname() noexcept
Returns the hostname.
Definition: util.hpp:569
static std::string env(const std::string &name) noexcept
Retrieves an environment variable.
Definition: util.hpp:550
static std::vector< InterfaceAddress > interfaceAddresses() noexcept
Gets a set of descriptors of all the available interfaces.
Definition: util.hpp:756
std::string ip
Definition: util.hpp:350
uv_timespec_t TimeSpec
Definition: util.hpp:208
static double uptime() noexcept
Gets the current system uptime.
Definition: util.hpp:903
static UName uname() noexcept
Gets name and information about the current kernel.
Definition: util.hpp:582
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.hpp:199
static std::string tmpdir() noexcept
Gets the temp directory.
Definition: util.hpp:540
Utility class.
Definition: util.hpp:290
static std::string homedir() noexcept
Gets the current user&#39;s home directory.
Definition: util.hpp:527
uv_rusage_t RUsage
Definition: util.hpp:214
std::string sysname() const noexcept
Gets the operating system name (like "Linux").
Definition: util.hpp:297
static PidType pid() noexcept
Returns the current process id.
Definition: util.hpp:500
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:625
constexpr FileHandle StdIN
Definition: util.hpp:204
static char ** setupArgs(int argc, char **argv)
Store the program arguments.
Definition: util.hpp:862
CPU information.
Definition: util.hpp:358
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:490
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:650
static uint64_t hrtime() noexcept
Gets the current high-resolution real time.
Definition: util.hpp:933
std::string machine() const noexcept
Gets the hardware identifier.
Definition: util.hpp:321
The IPv6 tag.
Definition: util.hpp:343
static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept
Override the use of some standard library’s functions.
Definition: util.hpp:841
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:561
static RUsage rusage() noexcept
Gets the resource usage measures for the current process.
Definition: util.hpp:917
uv_uid_t Uid
Definition: util.hpp:210
Interface address.
Definition: util.hpp:377
static uint64_t totalMemory() noexcept
Gets memory information (in bytes).
Definition: util.hpp:895
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:800
CPUTime times
CPU times.
Definition: util.hpp:370
static std::string cwd() noexcept
Gets the current working directory.
Definition: util.hpp:949
std::string release() const noexcept
Gets the operating system release (like "2.6.28").
Definition: util.hpp:305
static std::string path() noexcept
Gets the executable path.
Definition: util.hpp:941
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.hpp:200
static PidType parent() noexcept
Returns the parent process id.
Definition: util.hpp:513
int width
Definition: util.hpp:191
constexpr Flags()
Constructs an uninitialized Flags object.
Definition: util.hpp:125
std::string name
Definition: util.hpp:378
static HandleType guessHandle(HandleCategory category) noexcept
Gets the type of the handle given a category.
Definition: util.hpp:659
int speed
Definition: util.hpp:362
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:361
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:731
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:958
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:849
std::string version() const noexcept
Gets the operating system version.
Definition: util.hpp:313
The IPv4 tag.
Definition: util.hpp:335
static bool processTitle(std::string title)
Sets the current process title.
Definition: util.hpp:887
Miscellaneous utilities.
Definition: util.hpp:481
static std::string processTitle()
Gets the title of the current process.
Definition: util.hpp:870
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:814
uvw default namespace.
Definition: async.hpp:11