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
UVTypeWrapperuvw::details::UVTypeWrapper56 constexpr UVTypeWrapper(): value{} {}
UVTypeWrapperuvw::details::UVTypeWrapper57 constexpr UVTypeWrapper(Type val): value{val} {}
58
operator Typeuvw::details::UVTypeWrapper59 constexpr operator Type() const noexcept { return value; }
60
operator ==uvw::details::UVTypeWrapper61 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>
operator ==(UVTypeWrapper<T> lhs,UVTypeWrapper<T> rhs)71 bool operator==(UVTypeWrapper<T> lhs, UVTypeWrapper<T> rhs) {
72 return !(lhs == rhs);
73 }
74
75
76 }
77
78
79 /**
80 * @brief Utility class to handle flags.
81 *
82 * This class can be used to handle flags of a same enumeration type.<br/>
83 * It is meant to be used as an argument for functions and member methods and
84 * as part of events.<br/>
85 * `Flags<E>` objects can be easily _or-ed_ and _and-ed_ with other instances of
86 * the same type or with instances of the type `E` (that is, the actual flag
87 * type), thus converted to the underlying type when needed.
88 */
89 template<typename E>
90 class Flags final {
91 using InnerType = std::underlying_type_t<E>;
92
toInnerType(E flag) const93 constexpr InnerType toInnerType(E flag) const noexcept { return static_cast<InnerType>(flag); }
94
95 public:
96 using Type = InnerType;
97
98 /**
99 * @brief Utility factory method to pack a set of values all at once.
100 * @return A valid instance of Flags instantiated from values `V`.
101 */
102 template<E... V>
from()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
109 /**
110 * @brief Constructs a Flags object from a value of the enum `E`.
111 * @param flag A value of the enum `E`.
112 */
Flags(E flag)113 constexpr Flags(E flag) noexcept: flags{toInnerType(flag)} {}
114
115 /**
116 * @brief Constructs a Flags object from an instance of the underlying type
117 * of the enum `E`.
118 * @param f An instance of the underlying type of the enum `E`.
119 */
Flags(Type f)120 constexpr Flags(Type f): flags{f} {}
121
122 /**
123 * @brief Constructs an uninitialized Flags object.
124 */
Flags()125 constexpr Flags(): flags{} {}
126
Flags(const Flags & f)127 constexpr Flags(const Flags &f) noexcept: flags{f.flags} { }
Flags(Flags && f)128 constexpr Flags(Flags &&f) noexcept: flags{std::move(f.flags)} { }
129
~Flags()130 ~Flags() noexcept { static_assert(std::is_enum<E>::value, "!"); }
131
operator =(const Flags & f)132 CONSTEXPR_SPECIFIER Flags & operator=(const Flags &f) noexcept {
133 flags = f.flags;
134 return *this;
135 }
136
operator =(Flags && f)137 CONSTEXPR_SPECIFIER Flags & operator=(Flags &&f) noexcept {
138 flags = std::move(f.flags);
139 return *this;
140 }
141
142 /**
143 * @brief Or operator.
144 * @param f A valid instance of Flags.
145 * @return This instance _or-ed_ with `f`.
146 */
operator |(const Flags & f) const147 constexpr Flags operator|(const Flags &f) const noexcept { return Flags{flags | f.flags}; }
148
149 /**
150 * @brief Or operator.
151 * @param flag A value of the enum `E`.
152 * @return This instance _or-ed_ with `flag`.
153 */
operator |(E flag) const154 constexpr Flags operator|(E flag) const noexcept { return Flags{flags | toInnerType(flag)}; }
155
156 /**
157 * @brief And operator.
158 * @param f A valid instance of Flags.
159 * @return This instance _and-ed_ with `f`.
160 */
operator &(const Flags & f) const161 constexpr Flags operator&(const Flags &f) const noexcept { return Flags{flags & f.flags}; }
162
163 /**
164 * @brief And operator.
165 * @param flag A value of the enum `E`.
166 * @return This instance _and-ed_ with `flag`.
167 */
operator &(E flag) const168 constexpr Flags operator&(E flag) const noexcept { return Flags{flags & toInnerType(flag)}; }
169
170 /**
171 * @brief Checks if this instance is initialized.
172 * @return False if it's uninitialized, true otherwise.
173 */
operator bool() const174 explicit constexpr operator bool() const noexcept { return !(flags == InnerType{}); }
175
176 /**
177 * @brief Casts the instance to the underlying type of `E`.
178 * @return An integral representation of the contained flags.
179 */
operator Type() const180 constexpr operator Type() const noexcept { return flags; }
181
182 private:
183 InnerType flags;
184 };
185
186
187 /**
188 * @brief Windows size representation.
189 */
190 struct WinSize {
191 int width; /*!< The _width_ of the given window. */
192 int height; /*!< The _height_ of the given window. */
193 };
194
195
196 using HandleType = details::UVHandleType; /*!< The type of a handle. */
197
198 using HandleCategory = details::UVTypeWrapper<uv_handle_type>; /*!< Utility class that wraps an internal handle type. */
199 using FileHandle = details::UVTypeWrapper<uv_file>; /*!< Utility class that wraps an internal file handle. */
200 using OSSocketHandle = details::UVTypeWrapper<uv_os_sock_t>; /*!< Utility class that wraps an os socket handle. */
201 using OSFileDescriptor = details::UVTypeWrapper<uv_os_fd_t>; /*!< Utility class that wraps an os file descriptor. */
202 using PidType = details::UVTypeWrapper<uv_pid_t>; /*!< Utility class that wraps a cross platform representation of a pid. */
203
204 constexpr FileHandle StdIN{0}; /*!< Placeholder for stdin descriptor. */
205 constexpr FileHandle StdOUT{1}; /*!< Placeholder for stdout descriptor. */
206 constexpr FileHandle StdERR{2}; /*!< Placeholder for stderr descriptor. */
207
208 using TimeSpec = uv_timespec_t; /*!< Library equivalent for uv_timespec_t. */
209 using Stat = uv_stat_t; /*!< Library equivalent for uv_stat_t. */
210 using Uid = uv_uid_t; /*!< Library equivalent for uv_uid_t. */
211 using Gid = uv_gid_t; /*!< Library equivalent for uv_gid_t. */
212
213 using TimeVal = uv_timeval_t; /*!< Library equivalent for uv_timeval_t. */
214 using RUsage = uv_rusage_t; /*!< Library equivalent for uv_rusage_t. */
215
216
217 /**
218 * @brief Utility class.
219 *
220 * This class can be used to query the subset of the password file entry for the
221 * current effective uid (not the real uid).
222 *
223 * \sa Utilities::passwd
224 */
225 struct Passwd {
Passwduvw::Passwd226 Passwd(std::shared_ptr<uv_passwd_t> pwd): passwd{pwd} {}
227
228 /**
229 * @brief Gets the username.
230 * @return The username of the current effective uid (not the real uid).
231 */
usernameuvw::Passwd232 std::string username() const noexcept {
233 return ((passwd && passwd->username) ? passwd->username : "");
234 }
235
236 /**
237 * @brief Gets the uid.
238 * @return The current effective uid (not the real uid).
239 */
uiduvw::Passwd240 auto uid() const noexcept {
241 return (passwd ? passwd->uid : decltype(uv_passwd_t::uid){});
242 }
243
244 /**
245 * @brief Gets the gid.
246 * @return The gid of the current effective uid (not the real uid).
247 */
giduvw::Passwd248 auto gid() const noexcept {
249 return (passwd ? passwd->gid : decltype(uv_passwd_t::gid){});
250 }
251
252 /**
253 * @brief Gets the shell.
254 * @return The shell of the current effective uid (not the real uid).
255 */
shelluvw::Passwd256 std::string shell() const noexcept {
257 return ((passwd && passwd->shell) ? passwd->shell : "");
258 }
259
260 /**
261 * @brief Gets the homedir.
262 * @return The homedir of the current effective uid (not the real uid).
263 */
homediruvw::Passwd264 std::string homedir() const noexcept {
265 return ((passwd && passwd->homedir) ? passwd->homedir: "");
266 }
267
268 /**
269 * @brief Checks if the instance contains valid data.
270 * @return True if data are all valid, false otherwise.
271 */
operator booluvw::Passwd272 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
281 /**
282 * @brief The IPv4 tag.
283 *
284 * To be used as template parameter to switch between IPv4 and IPv6.
285 */
286 struct IPv4 {};
287
288
289 /**
290 * @brief The IPv6 tag.
291 *
292 * To be used as template parameter to switch between IPv4 and IPv6.
293 */
294 struct IPv6 {};
295
296
297 /**
298 * @brief Address representation.
299 */
300 struct Addr {
301 std::string ip; /*!< Either an IPv4 or an IPv6. */
302 unsigned int port; /*!< A valid service identifier. */
303 };
304
305
306 /**
307 * \brief CPU information.
308 */
309 struct CPUInfo {
310 using CPUTime = decltype(uv_cpu_info_t::cpu_times);
311
312 std::string model; /*!< The model of the CPU. */
313 int speed; /*!< The frequency of the CPU. */
314
315 /**
316 * @brief CPU times.
317 *
318 * It is built up of the following data members: `user`, `nice`, `sys`,
319 * `idle`, `irq`, all of them having type `uint64_t`.
320 */
321 CPUTime times;
322 };
323
324
325 /**
326 * \brief Interface address.
327 */
328 struct InterfaceAddress {
329 std::string name; /*!< The name of the interface (as an example _eth0_). */
330 char physical[6]; /*!< The physical address. */
331 bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
332 Addr address; /*!< The address of the given interface. */
333 Addr netmask; /*!< The netmask of the given interface. */
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;
sinPortuvw::details::IpTraits354 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;
sinPortuvw::details::IpTraits365 static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
366 };
367
368
369 template<typename I>
address(const typename details::IpTraits<I>::Type * aptr)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>
address(F && f,const H * handle)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>
tryRead(F && f,Args &&...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
427 /**
428 * @brief Miscellaneous utilities.
429 *
430 * Miscellaneous functions that don’t really belong to any other class.
431 */
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
438 /**
439 * @brief OS dedicated utilities.
440 */
441 struct OS {
442 /**
443 * @brief Returns the current process id.
444 *
445 * See the official
446 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_getpid)
447 * for further details.
448 *
449 * @return The current process id.
450 */
piduvw::Utilities::OS451 static PidType pid() noexcept {
452 return uv_os_getpid();
453 }
454
455 /**
456 * @brief Returns the parent process id.
457 *
458 * See the official
459 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_getppid)
460 * for further details.
461 *
462 * @return The parent process id.
463 */
parentuvw::Utilities::OS464 static PidType parent() noexcept {
465 return uv_os_getppid();
466 }
467
468 /**
469 * @brief Gets the current user's home directory.
470 *
471 * See the official
472 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir)
473 * for further details.
474 *
475 * @return The current user's home directory, an empty string in case of
476 * errors.
477 */
homediruvw::Utilities::OS478 static std::string homedir() noexcept {
479 return details::tryRead(&uv_os_homedir);
480 }
481
482 /**
483 * @brief Gets the temp directory.
484 *
485 * See the official
486 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_tmpdir)
487 * for further details.
488 *
489 * @return The temp directory, an empty string in case of errors.
490 */
tmpdiruvw::Utilities::OS491 static std::string tmpdir() noexcept {
492 return details::tryRead(&uv_os_tmpdir);
493 }
494
495 /**
496 * @brief Retrieves an environment variable.
497 * @param name The name of the variable to be retrieved.
498 * @return The value of the environment variable, an empty string in
499 * case of errors.
500 */
envuvw::Utilities::OS501 static std::string env(const std::string &name) noexcept {
502 return details::tryRead(&uv_os_getenv, name.c_str());
503 }
504
505 /**
506 * @brief Creates, updates or deletes an environment variable.
507 * @param name The name of the variable to be updated.
508 * @param value The value to be used for the variable (an empty string
509 * to unset it).
510 * @return True in case of success, false otherwise.
511 */
envuvw::Utilities::OS512 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
516 /**
517 * @brief Returns the hostname.
518 * @return The hostname, an empty string in case of errors.
519 */
hostnameuvw::Utilities::OS520 static std::string hostname() noexcept {
521 return details::tryRead(&uv_os_gethostname);
522 }
523
524 /**
525 * @brief Gets a subset of the password file entry.
526 *
527 * This function can be used to get the subset of the password file
528 * entry for the current effective uid (not the real uid).
529 *
530 * See the official
531 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_get_passwd)
532 * for further details.
533 *
534 * @return The accessible subset of the password file entry.
535 */
passwduvw::Utilities::OS536 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
548 /**
549 * @brief Retrieves the scheduling priority of a process.
550 *
551 * The returned value is between -20 (high priority) and 19 (low priority).
552 * A value that is out of range is returned in case of errors.
553 *
554 * @note
555 * On Windows, the result won't equal necessarily the exact value of the
556 * priority because of a mapping to a Windows priority class.
557 *
558 * @param pid A valid process id.
559 * @return The scheduling priority of the process.
560 */
osPriorityuvw::Utilities561 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
571 /**
572 * @brief Sets the scheduling priority of a process.
573 *
574 * The returned value range is between -20 (high priority) and 19 (low
575 * priority).
576 *
577 * @note
578 * On Windows, the priority is mapped to a Windows priority class. When
579 * retrieving the process priority, the result won't equal necessarily the
580 * exact value of the priority.
581 *
582 * @param pid A valid process id.
583 * @param prio The scheduling priority to set to the process.
584 * @return True in case of success, false otherwise.
585 */
osPriorityuvw::Utilities586 static bool osPriority(PidType pid, int prio) {
587 return 0 == uv_os_setpriority(pid, prio);
588 }
589
590 /**
591 * @brief Gets the type of the handle given a category.
592 * @param category A properly initialized handle category.
593 * @return The actual type of the handle as defined by HandleType
594 */
guessHandleuvw::Utilities595 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
636 /**
637 * @brief Gets the type of the stream to be used with the given descriptor.
638 *
639 * Returns the type of stream that should be used with a given file
640 * descriptor.<br/>
641 * Usually this will be used during initialization to guess the type of the
642 * stdio streams.
643 *
644 * @param file A valid descriptor.
645 * @return One of the following types:
646 *
647 * * `HandleType::UNKNOWN`
648 * * `HandleType::PIPE`
649 * * `HandleType::TCP`
650 * * `HandleType::TTY`
651 * * `HandleType::UDP`
652 * * `HandleType::FILE`
653 */
guessHandleuvw::Utilities654 static HandleType guessHandle(FileHandle file) noexcept {
655 HandleCategory category = uv_guess_handle(file);
656 return guessHandle(category);
657 }
658
659
660 /** @brief Gets information about the CPUs on the system.
661 *
662 * This function can be used to query the underlying system and get a set of
663 * descriptors of all the available CPUs.
664 *
665 * @return A set of descriptors of all the available CPUs.
666 */
cpuInfouvw::Utilities667 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
684 /**
685 * @brief Gets a set of descriptors of all the available interfaces.
686 *
687 * This function can be used to query the underlying system and get a set of
688 * descriptors of all the available interfaces, either internal or not.
689 *
690 * @return A set of descriptors of all the available interfaces.
691 */
interfaceAddressesuvw::Utilities692 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
723 /**
724 * @brief IPv6-capable implementation of
725 * [if_indextoname](https://linux.die.net/man/3/if_indextoname).
726 *
727 * Mapping between network interface names and indexes.
728 *
729 * See the official
730 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_if_indextoname)
731 * for further details.
732 *
733 * @param index Network interface index.
734 * @return Network interface name.
735 */
indexToNameuvw::Utilities736 static std::string indexToName(unsigned int index) noexcept {
737 return details::tryRead(&uv_if_indextoname, index);
738 }
739
740 /**
741 * @brief Retrieves a network interface identifier.
742 *
743 * See the official
744 * [documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_if_indextoiid)
745 * for further details.
746 *
747 * @param index Network interface index.
748 * @return Network interface identifier.
749 */
indexToIiduvw::Utilities750 static std::string indexToIid(unsigned int index) noexcept {
751 return details::tryRead(&uv_if_indextoiid, index);
752 }
753
754 /**
755 * @brief Override the use of some standard library’s functions.
756 *
757 * Override the use of the standard library’s memory allocation
758 * functions.<br/>
759 * This method must be invoked before any other `uvw` function is called or
760 * after all resources have been freed and thus the underlying library
761 * doesn’t reference any allocated memory chunk.
762 *
763 * If any of the function pointers is _null_, the invokation will fail.
764 *
765 * @note
766 * There is no protection against changing the allocator multiple times. If
767 * the user changes it they are responsible for making sure the allocator is
768 * changed while no memory was allocated with the previous allocator, or
769 * that they are compatible.
770 *
771 * @param mallocFunc Replacement function for _malloc_.
772 * @param reallocFunc Replacement function for _realloc_.
773 * @param callocFunc Replacement function for _calloc_.
774 * @param freeFunc Replacement function for _free_.
775 * @return True in case of success, false otherwise.
776 */
replaceAllocatoruvw::Utilities777 static bool replaceAllocator(MallocFuncType mallocFunc, ReallocFuncType reallocFunc, CallocFuncType callocFunc, FreeFuncType freeFunc) noexcept {
778 return (0 == uv_replace_allocator(mallocFunc, reallocFunc, callocFunc, freeFunc));
779 }
780
781 /**
782 * @brief Gets the load average.
783 * @return `[0,0,0]` on Windows (not available), the load average otherwise.
784 */
loadAverageuvw::Utilities785 static std::array<double, 3> loadAverage() noexcept {
786 std::array<double, 3> avg;
787 uv_loadavg(avg.data());
788 return avg;
789 }
790
791 /**
792 * @brief Store the program arguments.
793 *
794 * Required for getting / setting the process title.
795 *
796 * @return Arguments that haven't been consumed internally.
797 */
setupArgsuvw::Utilities798 static char ** setupArgs(int argc, char** argv) {
799 return uv_setup_args(argc, argv);
800 }
801
802 /**
803 * @brief Gets the title of the current process.
804 * @return The process title.
805 */
processTitleuvw::Utilities806 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
818 /**
819 * @brief Sets the current process title.
820 * @param title The process title to be set.
821 * @return True in case of success, false otherwise.
822 */
processTitleuvw::Utilities823 static bool processTitle(std::string title) {
824 return (0 == uv_set_process_title(title.c_str()));
825 }
826
827 /**
828 * @brief Gets memory information (in bytes).
829 * @return Memory information.
830 */
totalMemoryuvw::Utilities831 static uint64_t totalMemory() noexcept {
832 return uv_get_total_memory();
833 }
834
835 /**
836 * @brief Gets the current system uptime.
837 * @return The current system uptime or 0 in case of errors.
838 */
uptimeuvw::Utilities839 static double uptime() noexcept {
840 double ret;
841
842 if(0 != uv_uptime(&ret)) {
843 ret = 0;
844 }
845
846 return ret;
847 }
848
849 /**
850 * @brief Gets the resource usage measures for the current process.
851 * @return Resource usage measures, zeroes-filled object in case of errors.
852 */
rusageuvw::Utilities853 static RUsage rusage() noexcept {
854 RUsage ru;
855 auto err = uv_getrusage(&ru);
856 return err ? RUsage{} : ru;
857 }
858
859 /**
860 * @brief Gets the current high-resolution real time.
861 *
862 * The time is expressed in nanoseconds. It is relative to an arbitrary time
863 * in the past. It is not related to the time of the day and therefore not
864 * subject to clock drift. The primary use is for measuring performance
865 * between interval.
866 *
867 * @return The current high-resolution real time.
868 */
hrtimeuvw::Utilities869 static uint64_t hrtime() noexcept {
870 return uv_hrtime();
871 }
872
873 /**
874 * @brief Gets the executable path.
875 * @return The executable path, an empty string in case of errors.
876 */
pathuvw::Utilities877 static std::string path() noexcept {
878 return details::tryRead(&uv_exepath);
879 }
880
881 /**
882 * @brief Gets the current working directory.
883 * @return The current working directory, an empty string in case of errors.
884 */
cwduvw::Utilities885 static std::string cwd() noexcept {
886 return details::tryRead(&uv_cwd);
887 }
888
889 /**
890 * @brief Changes the current working directory.
891 * @param dir The working directory to be set.
892 * @return True in case of success, false otherwise.
893 */
chdiruvw::Utilities894 static bool chdir(const std::string &dir) noexcept {
895 return (0 == uv_chdir(dir.data()));
896 }
897 };
898
899
900 }
901