uvw  2.0.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 namespace uvw {
17 
18 
19 namespace details {
20 
21 
22 enum class UVHandleType: std::underlying_type_t<uv_handle_type> {
23  UNKNOWN = UV_UNKNOWN_HANDLE,
24  ASYNC = UV_ASYNC,
25  CHECK = UV_CHECK,
26  FS_EVENT = UV_FS_EVENT,
27  FS_POLL = UV_FS_POLL,
28  HANDLE = UV_HANDLE,
29  IDLE = UV_IDLE,
30  PIPE = UV_NAMED_PIPE,
31  POLL = UV_POLL,
32  PREPARE = UV_PREPARE,
33  PROCESS = UV_PROCESS,
34  STREAM = UV_STREAM,
35  TCP = UV_TCP,
36  TIMER = UV_TIMER,
37  TTY = UV_TTY,
38  UDP = UV_UDP,
39  SIGNAL = UV_SIGNAL,
40  FILE = UV_FILE
41 };
42 
43 
44 template<typename T>
45 struct UVTypeWrapper {
46  using Type = T;
47 
48  constexpr UVTypeWrapper(): value{} {}
49  constexpr UVTypeWrapper(Type val): value{val} {}
50 
51  constexpr operator Type() const noexcept { return value; }
52 
53  bool operator==(UVTypeWrapper other) const noexcept {
54  return value == other.value;
55  }
56 
57 private:
58  const Type value;
59 };
60 
61 
62 template<typename T>
63 bool operator==(UVTypeWrapper<T> lhs, UVTypeWrapper<T> rhs) {
64  return !(lhs == rhs);
65 }
66 
67 
68 }
69 
70 
81 template<typename E>
82 class Flags final {
83  using InnerType = std::underlying_type_t<E>;
84 
85  constexpr InnerType toInnerType(E flag) const noexcept { return static_cast<InnerType>(flag); }
86 
87 public:
88  using Type = InnerType;
89 
94  template<E... V>
95  static constexpr Flags<E> from() {
96  return (Flags<E>{} | ... | V);
97  }
98 
103  constexpr Flags(E flag) noexcept: flags{toInnerType(flag)} {}
104 
110  constexpr Flags(Type f): flags{f} {}
111 
115  constexpr Flags(): flags{} {}
116 
117  constexpr Flags(const Flags &f) noexcept: flags{f.flags} { }
118  constexpr Flags(Flags &&f) noexcept: flags{std::move(f.flags)} { }
119 
120  ~Flags() noexcept { static_assert(std::is_enum_v<E>); }
121 
122  constexpr Flags & operator=(const Flags &f) noexcept {
123  flags = f.flags;
124  return *this;
125  }
126 
127  constexpr Flags & operator=(Flags &&f) noexcept {
128  flags = std::move(f.flags);
129  return *this;
130  }
131 
137  constexpr Flags operator|(const Flags &f) const noexcept { return Flags{flags | f.flags}; }
138 
144  constexpr Flags operator|(E flag) const noexcept { return Flags{flags | toInnerType(flag)}; }
145 
151  constexpr Flags operator&(const Flags &f) const noexcept { return Flags{flags & f.flags}; }
152 
158  constexpr Flags operator&(E flag) const noexcept { return Flags{flags & toInnerType(flag)}; }
159 
164  explicit constexpr operator bool() const noexcept { return !(flags == InnerType{}); }
165 
170  constexpr operator Type() const noexcept { return flags; }
171 
172 private:
173  InnerType flags;
174 };
175 
176 
180 struct WinSize {
181  int width;
182  int height;
183 };
184 
185 
186 using HandleType = details::UVHandleType;
188 using HandleCategory = details::UVTypeWrapper<uv_handle_type>;
189 using FileHandle = details::UVTypeWrapper<uv_file>;
190 using OSSocketHandle = details::UVTypeWrapper<uv_os_sock_t>;
191 using OSFileDescriptor = details::UVTypeWrapper<uv_os_fd_t>;
192 using PidType = details::UVTypeWrapper<uv_pid_t>;
194 constexpr FileHandle StdIN{0};
195 constexpr FileHandle StdOUT{1};
196 constexpr FileHandle StdERR{2};
198 using TimeSpec = uv_timespec_t;
199 using Stat = uv_stat_t;
200 using Statfs = uv_statfs_t;
201 using Uid = uv_uid_t;
202 using Gid = uv_gid_t;
204 using TimeVal = uv_timeval_t;
205 using TimeVal64 = uv_timeval64_t;
206 using RUsage = uv_rusage_t;
217 struct Passwd {
218  Passwd(std::shared_ptr<uv_passwd_t> pwd): passwd{pwd} {}
219 
224  std::string username() const noexcept {
225  return ((passwd && passwd->username) ? passwd->username : "");
226  }
227 
232  auto uid() const noexcept {
233  return (passwd ? passwd->uid : decltype(uv_passwd_t::uid){});
234  }
235 
240  auto gid() const noexcept {
241  return (passwd ? passwd->gid : decltype(uv_passwd_t::gid){});
242  }
243 
248  std::string shell() const noexcept {
249  return ((passwd && passwd->shell) ? passwd->shell : "");
250  }
251 
256  std::string homedir() const noexcept {
257  return ((passwd && passwd->homedir) ? passwd->homedir: "");
258  }
259 
264  operator bool() const noexcept {
265  return static_cast<bool>(passwd);
266  }
267 
268 private:
269  std::shared_ptr<uv_passwd_t> passwd;
270 };
271 
272 
282 struct UtsName {
283  UtsName(std::shared_ptr<uv_utsname_t> utsname): utsname{utsname} {}
284 
289  std::string sysname() const noexcept {
290  return utsname ? utsname->sysname : "";
291  }
292 
297  std::string release() const noexcept {
298  return utsname ? utsname->release : "";
299  }
300 
305  std::string version() const noexcept {
306  return utsname ? utsname->version : "";
307  }
308 
313  std::string machine() const noexcept {
314  return utsname ? utsname->machine : "";
315  }
316 
317 private:
318  std::shared_ptr<uv_utsname_t> utsname;
319 };
320 
321 
327 struct IPv4 {};
328 
329 
335 struct IPv6 {};
336 
337 
341 struct Addr {
342  std::string ip;
343  unsigned int port;
344 };
345 
346 
350 struct CPUInfo {
351  using CPUTime = decltype(uv_cpu_info_t::cpu_times);
352 
353  std::string model;
354  int speed;
362  CPUTime times;
363 };
364 
365 
370  std::string name;
371  char physical[6];
372  bool internal;
375 };
376 
377 
378 namespace details {
379 
380 
381 static constexpr std::size_t DEFAULT_SIZE = 128;
382 
383 
384 template<typename>
385 struct IpTraits;
386 
387 
388 template<>
389 struct IpTraits<IPv4> {
390  using Type = sockaddr_in;
391  using AddrFuncType = int(*)(const char *, int, Type *);
392  using NameFuncType = int(*)(const Type *, char *, std::size_t);
393  static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
394  static constexpr NameFuncType nameFunc = &uv_ip4_name;
395  static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
396 };
397 
398 
399 template<>
400 struct IpTraits<IPv6> {
401  using Type = sockaddr_in6;
402  using AddrFuncType = int(*)(const char *, int, Type *);
403  using NameFuncType = int(*)(const Type *, char *, std::size_t);
404  static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
405  static constexpr NameFuncType nameFunc = &uv_ip6_name;
406  static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
407 };
408 
409 
410 template<typename I>
411 Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
412  Addr addr;
413  char name[DEFAULT_SIZE];
414 
415  int err = details::IpTraits<I>::nameFunc(aptr, name, DEFAULT_SIZE);
416 
417  if(0 == err) {
418  addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
419  addr.ip = std::string{name};
420  }
421 
422  return addr;
423 }
424 
425 
426 template<typename I, typename F, typename H>
427 Addr address(F &&f, const H *handle) noexcept {
428  sockaddr_storage ssto;
429  int len = sizeof(ssto);
430  Addr addr{};
431 
432  int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
433 
434  if(0 == err) {
435  typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
436  addr = address<I>(aptr);
437  }
438 
439  return addr;
440 }
441 
442 
443 template<typename F, typename... Args>
444 std::string tryRead(F &&f, Args&&... args) noexcept {
445  std::size_t size = DEFAULT_SIZE;
446  char buf[DEFAULT_SIZE];
447  std::string str{};
448  auto err = std::forward<F>(f)(args..., buf, &size);
449 
450  if(UV_ENOBUFS == err) {
451  std::unique_ptr<char[]> data{new char[size]};
452  err = std::forward<F>(f)(args..., data.get(), &size);
453 
454  if(0 == err) {
455  str = data.get();
456  }
457  } else if(0 == err) {
458  str.assign(buf, size);
459  }
460 
461  return str;
462 }
463 
464 
465 }
466 
467 
473 struct Utilities {
474  using MallocFuncType = void*(*)(size_t);
475  using ReallocFuncType = void*(*)(void*, size_t);
476  using CallocFuncType = void*(*)(size_t, size_t);
477  using FreeFuncType = void(*)(void*);
478 
482  struct OS {
492  static PidType pid() noexcept {
493  return uv_os_getpid();
494  }
495 
505  static PidType parent() noexcept {
506  return uv_os_getppid();
507  }
508 
519  static std::string homedir() noexcept {
520  return details::tryRead(&uv_os_homedir);
521  }
522 
532  static std::string tmpdir() noexcept {
533  return details::tryRead(&uv_os_tmpdir);
534  }
535 
542  static std::string env(const std::string &name) noexcept {
543  return details::tryRead(&uv_os_getenv, name.c_str());
544  }
545 
553  static bool env(const std::string &name, const std::string &value) noexcept {
554  return (0 == (value.empty() ? uv_os_unsetenv(name.c_str()) : uv_os_setenv(name.c_str(), value.c_str())));
555  }
556 
561  static std::string hostname() noexcept {
562  return details::tryRead(&uv_os_gethostname);
563  }
564 
574  static UtsName uname() noexcept {
575  auto ptr = std::make_shared<uv_utsname_t>();
576  uv_os_uname(ptr.get());
577  return ptr;
578  }
579 
592  static Passwd passwd() noexcept {
593  auto deleter = [](uv_passwd_t *passwd){
594  uv_os_free_passwd(passwd);
595  delete passwd;
596  };
597 
598  std::shared_ptr<uv_passwd_t> ptr{new uv_passwd_t, std::move(deleter)};
599  uv_os_get_passwd(ptr.get());
600  return ptr;
601  }
602  };
603 
617  static int osPriority(PidType pid) {
618  int prio = 0;
619 
620  if(uv_os_getpriority(pid, &prio)) {
621  prio = UV_PRIORITY_LOW + 1;
622  }
623 
624  return prio;
625  }
626 
642  static bool osPriority(PidType pid, int prio) {
643  return 0 == uv_os_setpriority(pid, prio);
644  }
645 
651  static HandleType guessHandle(HandleCategory category) noexcept {
652  switch(category) {
653  case UV_ASYNC:
654  return HandleType::ASYNC;
655  case UV_CHECK:
656  return HandleType::CHECK;
657  case UV_FS_EVENT:
658  return HandleType::FS_EVENT;
659  case UV_FS_POLL:
660  return HandleType::FS_POLL;
661  case UV_HANDLE:
662  return HandleType::HANDLE;
663  case UV_IDLE:
664  return HandleType::IDLE;
665  case UV_NAMED_PIPE:
666  return HandleType::PIPE;
667  case UV_POLL:
668  return HandleType::POLL;
669  case UV_PREPARE:
670  return HandleType::PREPARE;
671  case UV_PROCESS:
672  return HandleType::PROCESS;
673  case UV_STREAM:
674  return HandleType::STREAM;
675  case UV_TCP:
676  return HandleType::TCP;
677  case UV_TIMER:
678  return HandleType::TIMER;
679  case UV_TTY:
680  return HandleType::TTY;
681  case UV_UDP:
682  return HandleType::UDP;
683  case UV_SIGNAL:
684  return HandleType::SIGNAL;
685  case UV_FILE:
686  return HandleType::FILE;
687  default:
688  return HandleType::UNKNOWN;
689  }
690  }
691 
710  static HandleType guessHandle(FileHandle file) noexcept {
711  HandleCategory category = uv_guess_handle(file);
712  return guessHandle(category);
713  }
714 
715 
723  static std::vector<CPUInfo> cpuInfo() noexcept {
724  std::vector<CPUInfo> cpuinfos;
725 
726  uv_cpu_info_t *infos;
727  int count;
728 
729  if(0 == uv_cpu_info(&infos, &count)) {
730  std::for_each(infos, infos+count, [&cpuinfos](const auto &info) {
731  cpuinfos.push_back({ info.model, info.speed, info.cpu_times });
732  });
733 
734  uv_free_cpu_info(infos, count);
735  }
736 
737  return cpuinfos;
738  }
739 
748  static std::vector<InterfaceAddress> interfaceAddresses() noexcept {
749  std::vector<InterfaceAddress> interfaces;
750 
751  uv_interface_address_t *ifaces{nullptr};
752  int count{0};
753 
754  if(0 == uv_interface_addresses(&ifaces, &count)) {
755  std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
756  InterfaceAddress interfaceAddress;
757 
758  interfaceAddress.name = iface.name;
759  std::copy(iface.phys_addr, (iface.phys_addr+6), interfaceAddress.physical);
760  interfaceAddress.internal = iface.is_internal == 0 ? false : true;
761 
762  if(iface.address.address4.sin_family == AF_INET) {
763  interfaceAddress.address = details::address<IPv4>(&iface.address.address4);
764  interfaceAddress.netmask = details::address<IPv4>(&iface.netmask.netmask4);
765  } else if(iface.address.address4.sin_family == AF_INET6) {
766  interfaceAddress.address = details::address<IPv6>(&iface.address.address6);
767  interfaceAddress.netmask = details::address<IPv6>(&iface.netmask.netmask6);
768  }
769 
770  interfaces.push_back(std::move(interfaceAddress));
771  });
772 
773  uv_free_interface_addresses(ifaces, count);
774  }
775 
776  return interfaces;
777  }
778 
792  static std::string indexToName(unsigned int index) noexcept {
793  return details::tryRead(&uv_if_indextoname, index);
794  }
795 
806  static std::string indexToIid(unsigned int index) noexcept {
807  return details::tryRead(&uv_if_indextoiid, index);
808  }
809 
833  static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
834  return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
835  }
836 
841  static std::array<double, 3> loadAverage() noexcept {
842  std::array<double, 3> avg;
843  uv_loadavg(avg.data());
844  return avg;
845  }
846 
854  static char ** setupArgs(int argc, char** argv) {
855  return uv_setup_args(argc, argv);
856  }
857 
862  static std::string processTitle() {
863  std::size_t size = details::DEFAULT_SIZE;
864  char buf[details::DEFAULT_SIZE];
865  std::string str{};
866 
867  if(0 == uv_get_process_title(buf, size)) {
868  str.assign(buf, size);
869  }
870 
871  return str;
872  }
873 
879  static bool processTitle(std::string title) {
880  return (0 == uv_set_process_title(title.c_str()));
881  }
882 
887  static uint64_t totalMemory() noexcept {
888  return uv_get_total_memory();
889  }
890 
902  static uint64_t constrainedMemory() noexcept {
903  return uv_get_constrained_memory();
904  }
905 
910  static double uptime() noexcept {
911  double ret;
912 
913  if(0 != uv_uptime(&ret)) {
914  ret = 0;
915  }
916 
917  return ret;
918  }
919 
924  static RUsage rusage() noexcept {
925  RUsage ru;
926  auto err = uv_getrusage(&ru);
927  return err ? RUsage{} : ru;
928  }
929 
940  static uint64_t hrtime() noexcept {
941  return uv_hrtime();
942  }
943 
948  static std::string path() noexcept {
949  return details::tryRead(&uv_exepath);
950  }
951 
956  static std::string cwd() noexcept {
957  return details::tryRead(&uv_cwd);
958  }
959 
965  static bool chdir(const std::string &dir) noexcept {
966  return (0 == uv_chdir(dir.data()));
967  }
968 
974  static TimeVal64 timeOfDay() {
975  uv_timeval64_t ret;
976  uv_gettimeofday(&ret);
977  return ret;
978  }
979 };
980 
981 
982 }
Address representation.
Definition: util.hpp:341
constexpr FileHandle StdERR
Definition: util.hpp:196
auto gid() const noexcept
Gets the gid.
Definition: util.hpp:240
std::string version() const noexcept
Gets the operating system version.
Definition: util.hpp:305
unsigned int port
Definition: util.hpp:343
static Passwd passwd() noexcept
Gets a subset of the password file entry.
Definition: util.hpp:592
static HandleType guessHandle(FileHandle file) noexcept
Gets the type of the stream to be used with the given descriptor.
Definition: util.hpp:710
static std::string hostname() noexcept
Returns the hostname.
Definition: util.hpp:561
static std::string env(const std::string &name) noexcept
Retrieves an environment variable.
Definition: util.hpp:542
static std::vector< InterfaceAddress > interfaceAddresses() noexcept
Gets a set of descriptors of all the available interfaces.
Definition: util.hpp:748
std::string ip
Definition: util.hpp:342
std::string release() const noexcept
Gets the operating system release (like "2.6.28").
Definition: util.hpp:297
uv_timespec_t TimeSpec
Definition: util.hpp:198
static double uptime() noexcept
Gets the current system uptime.
Definition: util.hpp:910
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.hpp:189
static std::string tmpdir() noexcept
Gets the temp directory.
Definition: util.hpp:532
static std::string homedir() noexcept
Gets the current user&#39;s home directory.
Definition: util.hpp:519
uv_rusage_t RUsage
Definition: util.hpp:206
static PidType pid() noexcept
Returns the current process id.
Definition: util.hpp:492
Windows size representation.
Definition: util.hpp:180
details::UVTypeWrapper< uv_os_fd_t > OSFileDescriptor
Definition: util.hpp:191
std::string machine() const noexcept
Gets the hardware identifier.
Definition: util.hpp:313
static int osPriority(PidType pid)
Retrieves the scheduling priority of a process.
Definition: util.hpp:617
constexpr FileHandle StdIN
Definition: util.hpp:194
static char ** setupArgs(int argc, char **argv)
Store the program arguments.
Definition: util.hpp:854
CPU information.
Definition: util.hpp:350
uv_timeval_t TimeVal
Definition: util.hpp:204
std::string username() const noexcept
Gets the username.
Definition: util.hpp:224
constexpr FileHandle StdOUT
Definition: util.hpp:195
Utility class to handle flags.
Definition: util.hpp:82
details::UVTypeWrapper< uv_pid_t > PidType
Definition: util.hpp:192
constexpr Flags operator &(const Flags &f) const noexcept
And operator.
Definition: util.hpp:151
constexpr Flags(E flag) noexcept
Constructs a Flags object from a value of the enum E.
Definition: util.hpp:103
OS dedicated utilities.
Definition: util.hpp:482
constexpr Flags operator|(const Flags &f) const noexcept
Or operator.
Definition: util.hpp:137
static bool osPriority(PidType pid, int prio)
Sets the scheduling priority of a process.
Definition: util.hpp:642
static uint64_t hrtime() noexcept
Gets the current high-resolution real time.
Definition: util.hpp:940
The IPv6 tag.
Definition: util.hpp:335
static TimeVal64 timeOfDay()
Cross-platform implementation of gettimeofday
Definition: util.hpp:974
static UtsName uname() noexcept
Gets name and information about the current kernel.
Definition: util.hpp:574
static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept
Override the use of some standard library’s functions.
Definition: util.hpp:833
details::UVTypeWrapper< uv_handle_type > HandleCategory
Definition: util.hpp:188
uv_gid_t Gid
Definition: util.hpp:202
static bool env(const std::string &name, const std::string &value) noexcept
Creates, updates or deletes an environment variable.
Definition: util.hpp:553
static RUsage rusage() noexcept
Gets the resource usage measures for the current process.
Definition: util.hpp:924
uv_uid_t Uid
Definition: util.hpp:201
Interface address.
Definition: util.hpp:369
static uint64_t totalMemory() noexcept
Gets memory information (in bytes).
Definition: util.hpp:887
uv_statfs_t Statfs
Definition: util.hpp:200
int height
Definition: util.hpp:182
auto uid() const noexcept
Gets the uid.
Definition: util.hpp:232
std::string shell() const noexcept
Gets the shell.
Definition: util.hpp:248
static std::string indexToName(unsigned int index) noexcept
IPv6-capable implementation of if_indextoname.
Definition: util.hpp:792
CPUTime times
CPU times.
Definition: util.hpp:362
static std::string cwd() noexcept
Gets the current working directory.
Definition: util.hpp:956
static std::string path() noexcept
Gets the executable path.
Definition: util.hpp:948
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.hpp:190
static PidType parent() noexcept
Returns the parent process id.
Definition: util.hpp:505
int width
Definition: util.hpp:181
constexpr Flags()
Constructs an uninitialized Flags object.
Definition: util.hpp:115
std::string name
Definition: util.hpp:370
static HandleType guessHandle(HandleCategory category) noexcept
Gets the type of the handle given a category.
Definition: util.hpp:651
int speed
Definition: util.hpp:354
std::string model
Definition: util.hpp:353
constexpr Flags(Type f)
Constructs a Flags object from an instance of the underlying type of the enum E.
Definition: util.hpp:110
constexpr Flags operator|(E flag) const noexcept
Or operator.
Definition: util.hpp:144
std::string sysname() const noexcept
Gets the operating system name (like "Linux").
Definition: util.hpp:289
static std::vector< CPUInfo > cpuInfo() noexcept
Gets information about the CPUs on the system.
Definition: util.hpp:723
Utility class.
Definition: util.hpp:217
uv_stat_t Stat
Definition: util.hpp:199
static bool chdir(const std::string &dir) noexcept
Changes the current working directory.
Definition: util.hpp:965
constexpr Flags operator &(E flag) const noexcept
And operator.
Definition: util.hpp:158
static std::array< double, 3 > loadAverage() noexcept
Gets the load average.
Definition: util.hpp:841
Utility class.
Definition: util.hpp:282
static constexpr Flags< E > from()
Utility factory method to pack a set of values all at once.
Definition: util.hpp:95
The IPv4 tag.
Definition: util.hpp:327
static bool processTitle(std::string title)
Sets the current process title.
Definition: util.hpp:879
Miscellaneous utilities.
Definition: util.hpp:473
static std::string processTitle()
Gets the title of the current process.
Definition: util.hpp:862
static uint64_t constrainedMemory() noexcept
Gets the amount of memory available to the process (in bytes).
Definition: util.hpp:902
uv_timeval64_t TimeVal64
Definition: util.hpp:205
std::string homedir() const noexcept
Gets the homedir.
Definition: util.hpp:256
static std::string indexToIid(unsigned int index) noexcept
Retrieves a network interface identifier.
Definition: util.hpp:806
uvw default namespace.
Definition: async.hpp:11