uvw  1.18.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 TimeVal64 = uv_timeval64_t;
215 using RUsage = uv_rusage_t;
226 struct Passwd {
227  Passwd(std::shared_ptr<uv_passwd_t> pwd): passwd{pwd} {}
228 
233  std::string username() const noexcept {
234  return ((passwd && passwd->username) ? passwd->username : "");
235  }
236 
241  auto uid() const noexcept {
242  return (passwd ? passwd->uid : decltype(uv_passwd_t::uid){});
243  }
244 
249  auto gid() const noexcept {
250  return (passwd ? passwd->gid : decltype(uv_passwd_t::gid){});
251  }
252 
257  std::string shell() const noexcept {
258  return ((passwd && passwd->shell) ? passwd->shell : "");
259  }
260 
265  std::string homedir() const noexcept {
266  return ((passwd && passwd->homedir) ? passwd->homedir: "");
267  }
268 
273  operator bool() const noexcept {
274  return static_cast<bool>(passwd);
275  }
276 
277 private:
278  std::shared_ptr<uv_passwd_t> passwd;
279 };
280 
281 
291 struct UtsName {
292  UtsName(std::shared_ptr<uv_utsname_t> utsname): utsname{utsname} {}
293 
298  std::string sysname() const noexcept {
299  return utsname ? utsname->sysname : "";
300  }
301 
306  std::string release() const noexcept {
307  return utsname ? utsname->release : "";
308  }
309 
314  std::string version() const noexcept {
315  return utsname ? utsname->version : "";
316  }
317 
322  std::string machine() const noexcept {
323  return utsname ? utsname->machine : "";
324  }
325 
326 private:
327  std::shared_ptr<uv_utsname_t> utsname;
328 };
329 
330 
336 struct IPv4 {};
337 
338 
344 struct IPv6 {};
345 
346 
350 struct Addr {
351  std::string ip;
352  unsigned int port;
353 };
354 
355 
359 struct CPUInfo {
360  using CPUTime = decltype(uv_cpu_info_t::cpu_times);
361 
362  std::string model;
363  int speed;
371  CPUTime times;
372 };
373 
374 
379  std::string name;
380  char physical[6];
381  bool internal;
384 };
385 
386 
387 namespace details {
388 
389 
390 static constexpr std::size_t DEFAULT_SIZE = 128;
391 
392 
393 template<typename>
394 struct IpTraits;
395 
396 
397 template<>
398 struct IpTraits<IPv4> {
399  using Type = sockaddr_in;
400  using AddrFuncType = int(*)(const char *, int, Type *);
401  using NameFuncType = int(*)(const Type *, char *, std::size_t);
402  static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
403  static constexpr NameFuncType nameFunc = &uv_ip4_name;
404  static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
405 };
406 
407 
408 template<>
409 struct IpTraits<IPv6> {
410  using Type = sockaddr_in6;
411  using AddrFuncType = int(*)(const char *, int, Type *);
412  using NameFuncType = int(*)(const Type *, char *, std::size_t);
413  static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
414  static constexpr NameFuncType nameFunc = &uv_ip6_name;
415  static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
416 };
417 
418 
419 template<typename I>
420 Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
421  Addr addr;
422  char name[DEFAULT_SIZE];
423 
424  int err = details::IpTraits<I>::nameFunc(aptr, name, DEFAULT_SIZE);
425 
426  if(0 == err) {
427  addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
428  addr.ip = std::string{name};
429  }
430 
431  return addr;
432 }
433 
434 
435 template<typename I, typename F, typename H>
436 Addr address(F &&f, const H *handle) noexcept {
437  sockaddr_storage ssto;
438  int len = sizeof(ssto);
439  Addr addr{};
440 
441  int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
442 
443  if(0 == err) {
444  typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
445  addr = address<I>(aptr);
446  }
447 
448  return addr;
449 }
450 
451 
452 template<typename F, typename... Args>
453 std::string tryRead(F &&f, Args&&... args) noexcept {
454  std::size_t size = DEFAULT_SIZE;
455  char buf[DEFAULT_SIZE];
456  std::string str{};
457  auto err = std::forward<F>(f)(args..., buf, &size);
458 
459  if(UV_ENOBUFS == err) {
460  std::unique_ptr<char[]> data{new char[size]};
461  err = std::forward<F>(f)(args..., data.get(), &size);
462 
463  if(0 == err) {
464  str = data.get();
465  }
466  } else if(0 == err) {
467  str.assign(buf, size);
468  }
469 
470  return str;
471 }
472 
473 
474 }
475 
476 
482 struct Utilities {
483  using MallocFuncType = void*(*)(size_t);
484  using ReallocFuncType = void*(*)(void*, size_t);
485  using CallocFuncType = void*(*)(size_t, size_t);
486  using FreeFuncType = void(*)(void*);
487 
491  struct OS {
501  static PidType pid() noexcept {
502  return uv_os_getpid();
503  }
504 
514  static PidType parent() noexcept {
515  return uv_os_getppid();
516  }
517 
528  static std::string homedir() noexcept {
529  return details::tryRead(&uv_os_homedir);
530  }
531 
541  static std::string tmpdir() noexcept {
542  return details::tryRead(&uv_os_tmpdir);
543  }
544 
551  static std::string env(const std::string &name) noexcept {
552  return details::tryRead(&uv_os_getenv, name.c_str());
553  }
554 
562  static bool env(const std::string &name, const std::string &value) noexcept {
563  return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
564  }
565 
570  static std::string hostname() noexcept {
571  return details::tryRead(&uv_os_gethostname);
572  }
573 
583  static UtsName uname() noexcept {
584  auto ptr = std::make_shared<uv_utsname_t>();
585  uv_os_uname(ptr.get());
586  return ptr;
587  }
588 
601  static Passwd passwd() noexcept {
602  auto deleter = [](uv_passwd_t *passwd){
603  uv_os_free_passwd(passwd);
604  delete passwd;
605  };
606 
607  std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
608  uv_os_get_passwd(ptr.get());
609  return ptr;
610  }
611  };
612 
626  static int osPriority(PidType pid) {
627  int prio = 0;
628 
629  if(uv_os_getpriority(pid, &prio)) {
630  prio = UV_PRIORITY_LOW + 1;
631  }
632 
633  return prio;
634  }
635 
651  static bool osPriority(PidType pid, int prio) {
652  return 0 == uv_os_setpriority(pid, prio);
653  }
654 
660  static HandleType guessHandle(HandleCategory category) noexcept {
661  switch(category) {
662  case UV_ASYNC:
663  return HandleType::ASYNC;
664  case UV_CHECK:
665  return HandleType::CHECK;
666  case UV_FS_EVENT:
667  return HandleType::FS_EVENT;
668  case UV_FS_POLL:
669  return HandleType::FS_POLL;
670  case UV_HANDLE:
671  return HandleType::HANDLE;
672  case UV_IDLE:
673  return HandleType::IDLE;
674  case UV_NAMED_PIPE:
675  return HandleType::PIPE;
676  case UV_POLL:
677  return HandleType::POLL;
678  case UV_PREPARE:
679  return HandleType::PREPARE;
680  case UV_PROCESS:
681  return HandleType::PROCESS;
682  case UV_STREAM:
683  return HandleType::STREAM;
684  case UV_TCP:
685  return HandleType::TCP;
686  case UV_TIMER:
687  return HandleType::TIMER;
688  case UV_TTY:
689  return HandleType::TTY;
690  case UV_UDP:
691  return HandleType::UDP;
692  case UV_SIGNAL:
693  return HandleType::SIGNAL;
694  case UV_FILE:
695  return HandleType::FILE;
696  default:
697  return HandleType::UNKNOWN;
698  }
699  }
700 
719  static HandleType guessHandle(FileHandle file) noexcept {
720  HandleCategory category = uv_guess_handle(file);
721  return guessHandle(category);
722  }
723 
724 
732  static std::vector<CPUInfo> cpuInfo() noexcept {
733  std::vector<CPUInfo> cpuinfos;
734 
735  uv_cpu_info_t *infos;
736  int count;
737 
738  if(0 == uv_cpu_info(&infos, &count)) {
739  std::for_each(infos, infos+count, [&cpuinfos](const auto &info) {
740  cpuinfos.push_back({ info.model, info.speed, info.cpu_times });
741  });
742 
743  uv_free_cpu_info(infos, count);
744  }
745 
746  return cpuinfos;
747  }
748 
757  static std::vector<InterfaceAddress> interfaceAddresses() noexcept {
758  std::vector<InterfaceAddress> interfaces;
759 
760  uv_interface_address_t *ifaces{nullptr};
761  int count{0};
762 
763  if(0 == uv_interface_addresses(&ifaces, &count)) {
764  std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
765  InterfaceAddress interfaceAddress;
766 
767  interfaceAddress.name = iface.name;
768  std::copy(iface.phys_addr, (iface.phys_addr+6), interfaceAddress.physical);
769  interfaceAddress.internal = iface.is_internal == 0 ? false : true;
770 
771  if(iface.address.address4.sin_family == AF_INET) {
772  interfaceAddress.address = details::address<IPv4>(&iface.address.address4);
773  interfaceAddress.netmask = details::address<IPv4>(&iface.netmask.netmask4);
774  } else if(iface.address.address4.sin_family == AF_INET6) {
775  interfaceAddress.address = details::address<IPv6>(&iface.address.address6);
776  interfaceAddress.netmask = details::address<IPv6>(&iface.netmask.netmask6);
777  }
778 
779  interfaces.push_back(std::move(interfaceAddress));
780  });
781 
782  uv_free_interface_addresses(ifaces, count);
783  }
784 
785  return interfaces;
786  }
787 
801  static std::string indexToName(unsigned int index) noexcept {
802  return details::tryRead(&uv_if_indextoname, index);
803  }
804 
815  static std::string indexToIid(unsigned int index) noexcept {
816  return details::tryRead(&uv_if_indextoiid, index);
817  }
818 
842  static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
843  return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
844  }
845 
850  static std::array<double, 3> loadAverage() noexcept {
851  std::array<double, 3> avg;
852  uv_loadavg(avg.data());
853  return avg;
854  }
855 
863  static char ** setupArgs(int argc, char** argv) {
864  return uv_setup_args(argc, argv);
865  }
866 
871  static std::string processTitle() {
872  std::size_t size = details::DEFAULT_SIZE;
873  char buf[details::DEFAULT_SIZE];
874  std::string str{};
875 
876  if(0 == uv_get_process_title(buf, size)) {
877  str.assign(buf, size);
878  }
879 
880  return str;
881  }
882 
888  static bool processTitle(std::string title) {
889  return (0 == uv_set_process_title(title.c_str()));
890  }
891 
896  static uint64_t totalMemory() noexcept {
897  return uv_get_total_memory();
898  }
899 
911  static uint64_t constrainedMemory() noexcept {
912  return uv_get_constrained_memory();
913  }
914 
919  static double uptime() noexcept {
920  double ret;
921 
922  if(0 != uv_uptime(&ret)) {
923  ret = 0;
924  }
925 
926  return ret;
927  }
928 
933  static RUsage rusage() noexcept {
934  RUsage ru;
935  auto err = uv_getrusage(&ru);
936  return err ? RUsage{} : ru;
937  }
938 
949  static uint64_t hrtime() noexcept {
950  return uv_hrtime();
951  }
952 
957  static std::string path() noexcept {
958  return details::tryRead(&uv_exepath);
959  }
960 
965  static std::string cwd() noexcept {
966  return details::tryRead(&uv_cwd);
967  }
968 
974  static bool chdir(const std::string &dir) noexcept {
975  return (0 == uv_chdir(dir.data()));
976  }
977 
983  static TimeVal64 timeOfDay() {
984  uv_timeval64_t ret;
985  uv_gettimeofday(&ret);
986  return ret;
987  }
988 };
989 
990 
991 }
Address representation.
Definition: util.hpp:350
constexpr FileHandle StdERR
Definition: util.hpp:206
auto gid() const noexcept
Gets the gid.
Definition: util.hpp:249
std::string version() const noexcept
Gets the operating system version.
Definition: util.hpp:314
unsigned int port
Definition: util.hpp:352
static Passwd passwd() noexcept
Gets a subset of the password file entry.
Definition: util.hpp:601
static HandleType guessHandle(FileHandle file) noexcept
Gets the type of the stream to be used with the given descriptor.
Definition: util.hpp:719
static std::string hostname() noexcept
Returns the hostname.
Definition: util.hpp:570
static std::string env(const std::string &name) noexcept
Retrieves an environment variable.
Definition: util.hpp:551
static std::vector< InterfaceAddress > interfaceAddresses() noexcept
Gets a set of descriptors of all the available interfaces.
Definition: util.hpp:757
std::string ip
Definition: util.hpp:351
std::string release() const noexcept
Gets the operating system release (like "2.6.28").
Definition: util.hpp:306
uv_timespec_t TimeSpec
Definition: util.hpp:208
static double uptime() noexcept
Gets the current system uptime.
Definition: util.hpp:919
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.hpp:199
static std::string tmpdir() noexcept
Gets the temp directory.
Definition: util.hpp:541
static std::string homedir() noexcept
Gets the current user&#39;s home directory.
Definition: util.hpp:528
uv_rusage_t RUsage
Definition: util.hpp:215
static PidType pid() noexcept
Returns the current process id.
Definition: util.hpp:501
Windows size representation.
Definition: util.hpp:190
details::UVTypeWrapper< uv_os_fd_t > OSFileDescriptor
Definition: util.hpp:201
std::string machine() const noexcept
Gets the hardware identifier.
Definition: util.hpp:322
static int osPriority(PidType pid)
Retrieves the scheduling priority of a process.
Definition: util.hpp:626
constexpr FileHandle StdIN
Definition: util.hpp:204
static char ** setupArgs(int argc, char **argv)
Store the program arguments.
Definition: util.hpp:863
CPU information.
Definition: util.hpp:359
uv_timeval_t TimeVal
Definition: util.hpp:213
std::string username() const noexcept
Gets the username.
Definition: util.hpp:233
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:491
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:651
static uint64_t hrtime() noexcept
Gets the current high-resolution real time.
Definition: util.hpp:949
The IPv6 tag.
Definition: util.hpp:344
static TimeVal64 timeOfDay()
Cross-platform implementation of gettimeofday
Definition: util.hpp:983
static UtsName uname() noexcept
Gets name and information about the current kernel.
Definition: util.hpp:583
static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept
Override the use of some standard library’s functions.
Definition: util.hpp:842
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:562
static RUsage rusage() noexcept
Gets the resource usage measures for the current process.
Definition: util.hpp:933
uv_uid_t Uid
Definition: util.hpp:210
Interface address.
Definition: util.hpp:378
static uint64_t totalMemory() noexcept
Gets memory information (in bytes).
Definition: util.hpp:896
int height
Definition: util.hpp:192
auto uid() const noexcept
Gets the uid.
Definition: util.hpp:241
std::string shell() const noexcept
Gets the shell.
Definition: util.hpp:257
static std::string indexToName(unsigned int index) noexcept
IPv6-capable implementation of if_indextoname.
Definition: util.hpp:801
CPUTime times
CPU times.
Definition: util.hpp:371
static std::string cwd() noexcept
Gets the current working directory.
Definition: util.hpp:965
static std::string path() noexcept
Gets the executable path.
Definition: util.hpp:957
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.hpp:200
static PidType parent() noexcept
Returns the parent process id.
Definition: util.hpp:514
int width
Definition: util.hpp:191
constexpr Flags()
Constructs an uninitialized Flags object.
Definition: util.hpp:125
std::string name
Definition: util.hpp:379
static HandleType guessHandle(HandleCategory category) noexcept
Gets the type of the handle given a category.
Definition: util.hpp:660
int speed
Definition: util.hpp:363
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:362
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
std::string sysname() const noexcept
Gets the operating system name (like "Linux").
Definition: util.hpp:298
static std::vector< CPUInfo > cpuInfo() noexcept
Gets information about the CPUs on the system.
Definition: util.hpp:732
Utility class.
Definition: util.hpp:226
uv_stat_t Stat
Definition: util.hpp:209
static bool chdir(const std::string &dir) noexcept
Changes the current working directory.
Definition: util.hpp:974
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:850
Utility class.
Definition: util.hpp:291
The IPv4 tag.
Definition: util.hpp:336
static bool processTitle(std::string title)
Sets the current process title.
Definition: util.hpp:888
Miscellaneous utilities.
Definition: util.hpp:482
static std::string processTitle()
Gets the title of the current process.
Definition: util.hpp:871
static uint64_t constrainedMemory() noexcept
Gets the amount of memory available to the process (in bytes).
Definition: util.hpp:911
uv_timeval64_t TimeVal64
Definition: util.hpp:214
std::string homedir() const noexcept
Gets the homedir.
Definition: util.hpp:265
static std::string indexToIid(unsigned int index) noexcept
Retrieves a network interface identifier.
Definition: util.hpp:815
uvw default namespace.
Definition: async.hpp:11