aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/util.hh')
-rw-r--r--src/libutil/util.hh509
1 files changed, 360 insertions, 149 deletions
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 5a3976d02..040fed68f 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -1,4 +1,5 @@
#pragma once
+///@file
#include "types.hh"
#include "error.hh"
@@ -31,78 +32,114 @@ namespace nix {
struct Sink;
struct Source;
+void initLibUtil();
-/* The system for which Nix is compiled. */
+/**
+ * The system for which Nix is compiled.
+ */
extern const std::string nativeSystem;
-/* Return an environment variable. */
+/**
+ * @return an environment variable.
+ */
std::optional<std::string> getEnv(const std::string & key);
-/* Return a non empty environment variable. Returns nullopt if the env
-variable is set to "" */
+/**
+ * @return a non empty environment variable. Returns nullopt if the env
+ * variable is set to ""
+ */
std::optional<std::string> getEnvNonEmpty(const std::string & key);
-/* Get the entire environment. */
+/**
+ * Get the entire environment.
+ */
std::map<std::string, std::string> getEnv();
-/* Clear the environment. */
+/**
+ * Clear the environment.
+ */
void clearEnv();
-/* Return an absolutized path, resolving paths relative to the
- specified directory, or the current directory otherwise. The path
- is also canonicalised. */
+/**
+ * @return An absolutized path, resolving paths relative to the
+ * specified directory, or the current directory otherwise. The path
+ * is also canonicalised.
+ */
Path absPath(Path path,
std::optional<PathView> dir = {},
bool resolveSymlinks = false);
-/* Canonicalise a path by removing all `.' or `..' components and
- double or trailing slashes. Optionally resolves all symlink
- components such that each component of the resulting path is *not*
- a symbolic link. */
+/**
+ * Canonicalise a path by removing all `.` or `..` components and
+ * double or trailing slashes. Optionally resolves all symlink
+ * components such that each component of the resulting path is *not*
+ * a symbolic link.
+ */
Path canonPath(PathView path, bool resolveSymlinks = false);
-/* Return the directory part of the given canonical path, i.e.,
- everything before the final `/'. If the path is the root or an
- immediate child thereof (e.g., `/foo'), this means `/'
- is returned.*/
+/**
+ * @return The directory part of the given canonical path, i.e.,
+ * everything before the final `/`. If the path is the root or an
+ * immediate child thereof (e.g., `/foo`), this means `/`
+ * is returned.
+ */
Path dirOf(const PathView path);
-/* Return the base name of the given canonical path, i.e., everything
- following the final `/' (trailing slashes are removed). */
+/**
+ * @return the base name of the given canonical path, i.e., everything
+ * following the final `/` (trailing slashes are removed).
+ */
std::string_view baseNameOf(std::string_view path);
-/* Perform tilde expansion on a path. */
+/**
+ * Perform tilde expansion on a path.
+ */
std::string expandTilde(std::string_view path);
-/* Check whether 'path' is a descendant of 'dir'. Both paths must be
- canonicalized. */
+/**
+ * Check whether 'path' is a descendant of 'dir'. Both paths must be
+ * canonicalized.
+ */
bool isInDir(std::string_view path, std::string_view dir);
-/* Check whether 'path' is equal to 'dir' or a descendant of
- 'dir'. Both paths must be canonicalized. */
+/**
+ * Check whether 'path' is equal to 'dir' or a descendant of
+ * 'dir'. Both paths must be canonicalized.
+ */
bool isDirOrInDir(std::string_view path, std::string_view dir);
-/* Get status of `path'. */
+/**
+ * Get status of `path`.
+ */
struct stat stat(const Path & path);
struct stat lstat(const Path & path);
-/* Return true iff the given path exists. */
+/**
+ * @return true iff the given path exists.
+ */
bool pathExists(const Path & path);
-/* Read the contents (target) of a symbolic link. The result is not
- in any way canonicalised. */
+/**
+ * Read the contents (target) of a symbolic link. The result is not
+ * in any way canonicalised.
+ */
Path readLink(const Path & path);
bool isLink(const Path & path);
-/* Read the contents of a directory. The entries `.' and `..' are
- removed. */
+/**
+ * Read the contents of a directory. The entries `.` and `..` are
+ * removed.
+ */
struct DirEntry
{
std::string name;
ino_t ino;
- unsigned char type; // one of DT_*
+ /**
+ * one of DT_*
+ */
+ unsigned char type;
DirEntry(std::string name, ino_t ino, unsigned char type)
: name(std::move(name)), ino(ino), type(type) { }
};
@@ -113,74 +150,110 @@ DirEntries readDirectory(const Path & path);
unsigned char getFileType(const Path & path);
-/* Read the contents of a file into a string. */
+/**
+ * Read the contents of a file into a string.
+ */
std::string readFile(int fd);
std::string readFile(const Path & path);
void readFile(const Path & path, Sink & sink);
-/* Write a string to a file. */
+/**
+ * Write a string to a file.
+ */
void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false);
void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false);
-/* Flush a file's parent directory to disk */
+/**
+ * Flush a file's parent directory to disk
+ */
void syncParent(const Path & path);
-/* Read a line from a file descriptor. */
+/**
+ * Read a line from a file descriptor.
+ */
std::string readLine(int fd);
-/* Write a line to a file descriptor. */
+/**
+ * Write a line to a file descriptor.
+ */
void writeLine(int fd, std::string s);
-/* Delete a path; i.e., in the case of a directory, it is deleted
- recursively. It's not an error if the path does not exist. The
- second variant returns the number of bytes and blocks freed. */
+/**
+ * Delete a path; i.e., in the case of a directory, it is deleted
+ * recursively. It's not an error if the path does not exist. The
+ * second variant returns the number of bytes and blocks freed.
+ */
void deletePath(const Path & path);
void deletePath(const Path & path, uint64_t & bytesFreed);
std::string getUserName();
-/* Return the given user's home directory from /etc/passwd. */
+/**
+ * @return the given user's home directory from /etc/passwd.
+ */
Path getHomeOf(uid_t userId);
-/* Return $HOME or the user's home directory from /etc/passwd. */
+/**
+ * @return $HOME or the user's home directory from /etc/passwd.
+ */
Path getHome();
-/* Return $XDG_CACHE_HOME or $HOME/.cache. */
+/**
+ * @return $XDG_CACHE_HOME or $HOME/.cache.
+ */
Path getCacheDir();
-/* Return $XDG_CONFIG_HOME or $HOME/.config. */
+/**
+ * @return $XDG_CONFIG_HOME or $HOME/.config.
+ */
Path getConfigDir();
-/* Return the directories to search for user configuration files */
+/**
+ * @return the directories to search for user configuration files
+ */
std::vector<Path> getConfigDirs();
-/* Return $XDG_DATA_HOME or $HOME/.local/share. */
+/**
+ * @return $XDG_DATA_HOME or $HOME/.local/share.
+ */
Path getDataDir();
-/* Return the path of the current executable. */
+/**
+ * @return the path of the current executable.
+ */
std::optional<Path> getSelfExe();
-/* Return $XDG_STATE_HOME or $HOME/.local/state. */
+/**
+ * @return $XDG_STATE_HOME or $HOME/.local/state.
+ */
Path getStateDir();
-/* Create the Nix state directory and return the path to it. */
+/**
+ * Create the Nix state directory and return the path to it.
+ */
Path createNixStateDir();
-/* Create a directory and all its parents, if necessary. Returns the
- list of created directories, in order of creation. */
+/**
+ * Create a directory and all its parents, if necessary. Returns the
+ * list of created directories, in order of creation.
+ */
Paths createDirs(const Path & path);
inline Paths createDirs(PathView path)
{
return createDirs(Path(path));
}
-/* Create a symlink. */
+/**
+ * Create a symlink.
+ */
void createSymlink(const Path & target, const Path & link,
std::optional<time_t> mtime = {});
-/* Atomically create or replace a symlink. */
+/**
+ * Atomically create or replace a symlink.
+ */
void replaceSymlink(const Path & target, const Path & link,
std::optional<time_t> mtime = {});
@@ -196,24 +269,32 @@ void renameFile(const Path & src, const Path & dst);
void moveFile(const Path & src, const Path & dst);
-/* Wrappers arount read()/write() that read/write exactly the
- requested number of bytes. */
+/**
+ * Wrappers arount read()/write() that read/write exactly the
+ * requested number of bytes.
+ */
void readFull(int fd, char * buf, size_t count);
void writeFull(int fd, std::string_view s, bool allowInterrupts = true);
MakeError(EndOfFile, Error);
-/* Read a file descriptor until EOF occurs. */
+/**
+ * Read a file descriptor until EOF occurs.
+ */
std::string drainFD(int fd, bool block = true, const size_t reserveSize=0);
void drainFD(int fd, Sink & sink, bool block = true);
-/* If cgroups are active, attempt to calculate the number of CPUs available.
- If cgroups are unavailable or if cpu.max is set to "max", return 0. */
+/**
+ * If cgroups are active, attempt to calculate the number of CPUs available.
+ * If cgroups are unavailable or if cpu.max is set to "max", return 0.
+ */
unsigned int getMaxCPU();
-/* Automatic cleanup of resources. */
+/**
+ * Automatic cleanup of resources.
+ */
class AutoDelete
@@ -251,11 +332,15 @@ public:
};
-/* Create a temporary directory. */
+/**
+ * Create a temporary directory.
+ */
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
-/* Create a temporary file, returning a file handle and its path. */
+/**
+ * Create a temporary file, returning a file handle and its path.
+ */
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
@@ -298,27 +383,36 @@ public:
};
-/* Kill all processes running under the specified uid by sending them
- a SIGKILL. */
+/**
+ * Kill all processes running under the specified uid by sending them
+ * a SIGKILL.
+ */
void killUser(uid_t uid);
-/* Fork a process that runs the given function, and return the child
- pid to the caller. */
+/**
+ * Fork a process that runs the given function, and return the child
+ * pid to the caller.
+ */
struct ProcessOptions
{
std::string errorPrefix = "";
bool dieWithParent = true;
bool runExitHandlers = false;
bool allowVfork = false;
- int cloneFlags = 0; // use clone() with the specified flags (Linux only)
+ /**
+ * use clone() with the specified flags (Linux only)
+ */
+ int cloneFlags = 0;
};
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options = ProcessOptions());
-/* Run a program and return its stdout in a string (i.e., like the
- shell backtick operator). */
+/**
+ * Run a program and return its stdout in a string (i.e., like the
+ * shell backtick operator).
+ */
std::string runProgram(Path program, bool searchPath = false,
const Strings & args = Strings(),
const std::optional<std::string> & input = {});
@@ -343,25 +437,37 @@ std::pair<int, std::string> runProgram(RunOptions && options);
void runProgram2(const RunOptions & options);
-/* Change the stack size. */
+/**
+ * Change the stack size.
+ */
void setStackSize(size_t stackSize);
-/* Restore the original inherited Unix process context (such as signal
- masks, stack size). */
+/**
+ * Restore the original inherited Unix process context (such as signal
+ * masks, stack size).
+
+ * See startSignalHandlerThread(), saveSignalMask().
+ */
void restoreProcessContext(bool restoreMounts = true);
-/* Save the current mount namespace. Ignored if called more than
- once. */
+/**
+ * Save the current mount namespace. Ignored if called more than
+ * once.
+ */
void saveMountNamespace();
-/* Restore the mount namespace saved by saveMountNamespace(). Ignored
- if saveMountNamespace() was never called. */
+/**
+ * Restore the mount namespace saved by saveMountNamespace(). Ignored
+ * if saveMountNamespace() was never called.
+ */
void restoreMountNamespace();
-/* Cause this thread to not share any FS attributes with the main
- thread, because this causes setns() in restoreMountNamespace() to
- fail. */
+/**
+ * Cause this thread to not share any FS attributes with the main
+ * thread, because this causes setns() in restoreMountNamespace() to
+ * fail.
+ */
void unshareFilesystem();
@@ -376,16 +482,22 @@ public:
{ }
};
-/* Convert a list of strings to a null-terminated vector of char
- *'s. The result must not be accessed beyond the lifetime of the
- list of strings. */
+/**
+ * Convert a list of strings to a null-terminated vector of `char
+ * *`s. The result must not be accessed beyond the lifetime of the
+ * list of strings.
+ */
std::vector<char *> stringsToCharPtrs(const Strings & ss);
-/* Close all file descriptors except those listed in the given set.
- Good practice in child processes. */
+/**
+ * Close all file descriptors except those listed in the given set.
+ * Good practice in child processes.
+ */
void closeMostFDs(const std::set<int> & exceptions);
-/* Set the close-on-exec flag for the given file descriptor. */
+/**
+ * Set the close-on-exec flag for the given file descriptor.
+ */
void closeOnExec(int fd);
@@ -411,12 +523,16 @@ MakeError(Interrupted, BaseError);
MakeError(FormatError, Error);
-/* String tokenizer. */
+/**
+ * String tokenizer.
+ */
template<class C> C tokenizeString(std::string_view s, std::string_view separators = " \t\n\r");
-/* Concatenate the given strings with a separator between the
- elements. */
+/**
+ * Concatenate the given strings with a separator between the
+ * elements.
+ */
template<class C>
std::string concatStringsSep(const std::string_view sep, const C & ss)
{
@@ -441,7 +557,9 @@ auto concatStrings(Parts && ... parts)
}
-/* Add quotes around a collection of strings. */
+/**
+ * Add quotes around a collection of strings.
+ */
template<class C> Strings quoteStrings(const C & c)
{
Strings res;
@@ -450,16 +568,23 @@ template<class C> Strings quoteStrings(const C & c)
return res;
}
-/* Remove trailing whitespace from a string. FIXME: return
- std::string_view. */
+/**
+ * Remove trailing whitespace from a string.
+ *
+ * \todo return std::string_view.
+ */
std::string chomp(std::string_view s);
-/* Remove whitespace from the start and end of a string. */
+/**
+ * Remove whitespace from the start and end of a string.
+ */
std::string trim(std::string_view s, std::string_view whitespace = " \n\r\t");
-/* Replace all occurrences of a string inside another string. */
+/**
+ * Replace all occurrences of a string inside another string.
+ */
std::string replaceStrings(
std::string s,
std::string_view from,
@@ -469,14 +594,18 @@ std::string replaceStrings(
std::string rewriteStrings(std::string s, const StringMap & rewrites);
-/* Convert the exit status of a child as returned by wait() into an
- error string. */
+/**
+ * Convert the exit status of a child as returned by wait() into an
+ * error string.
+ */
std::string statusToString(int status);
bool statusOk(int status);
-/* Parse a string into an integer. */
+/**
+ * Parse a string into an integer.
+ */
template<class N>
std::optional<N> string2Int(const std::string_view s)
{
@@ -489,8 +618,10 @@ std::optional<N> string2Int(const std::string_view s)
}
}
-/* Like string2Int(), but support an optional suffix 'K', 'M', 'G' or
- 'T' denoting a binary unit prefix. */
+/**
+ * Like string2Int(), but support an optional suffix 'K', 'M', 'G' or
+ * 'T' denoting a binary unit prefix.
+ */
template<class N>
N string2IntWithUnitPrefix(std::string_view s)
{
@@ -511,7 +642,9 @@ N string2IntWithUnitPrefix(std::string_view s)
throw UsageError("'%s' is not an integer", s);
}
-/* Parse a string into a float. */
+/**
+ * Parse a string into a float.
+ */
template<class N>
std::optional<N> string2Float(const std::string_view s)
{
@@ -523,7 +656,9 @@ std::optional<N> string2Float(const std::string_view s)
}
-/* Convert a little-endian integer to host order. */
+/**
+ * Convert a little-endian integer to host order.
+ */
template<typename T>
T readLittleEndian(unsigned char * p)
{
@@ -535,66 +670,90 @@ T readLittleEndian(unsigned char * p)
}
-/* Return true iff `s' starts with `prefix'. */
+/**
+ * @return true iff `s` starts with `prefix`.
+ */
bool hasPrefix(std::string_view s, std::string_view prefix);
-/* Return true iff `s' ends in `suffix'. */
+/**
+ * @return true iff `s` ends in `suffix`.
+ */
bool hasSuffix(std::string_view s, std::string_view suffix);
-/* Convert a string to lower case. */
+/**
+ * Convert a string to lower case.
+ */
std::string toLower(const std::string & s);
-/* Escape a string as a shell word. */
+/**
+ * Escape a string as a shell word.
+ */
std::string shellEscape(const std::string_view s);
-/* Exception handling in destructors: print an error message, then
- ignore the exception. */
+/**
+ * Exception handling in destructors: print an error message, then
+ * ignore the exception.
+ */
void ignoreException(Verbosity lvl = lvlError);
-/* Tree formatting. */
+/**
+ * Tree formatting.
+ */
constexpr char treeConn[] = "├───";
constexpr char treeLast[] = "└───";
constexpr char treeLine[] = "│ ";
constexpr char treeNull[] = " ";
-/* Determine whether ANSI escape sequences are appropriate for the
- present output. */
+/**
+ * Determine whether ANSI escape sequences are appropriate for the
+ * present output.
+ */
bool shouldANSI();
-/* Truncate a string to 'width' printable characters. If 'filterAll'
- is true, all ANSI escape sequences are filtered out. Otherwise,
- some escape sequences (such as colour setting) are copied but not
- included in the character count. Also, tabs are expanded to
- spaces. */
+/**
+ * Truncate a string to 'width' printable characters. If 'filterAll'
+ * is true, all ANSI escape sequences are filtered out. Otherwise,
+ * some escape sequences (such as colour setting) are copied but not
+ * included in the character count. Also, tabs are expanded to
+ * spaces.
+ */
std::string filterANSIEscapes(std::string_view s,
bool filterAll = false,
unsigned int width = std::numeric_limits<unsigned int>::max());
-/* Base64 encoding/decoding. */
+/**
+ * Base64 encoding/decoding.
+ */
std::string base64Encode(std::string_view s);
std::string base64Decode(std::string_view s);
-/* Remove common leading whitespace from the lines in the string
- 's'. For example, if every line is indented by at least 3 spaces,
- then we remove 3 spaces from the start of every line. */
+/**
+ * Remove common leading whitespace from the lines in the string
+ * 's'. For example, if every line is indented by at least 3 spaces,
+ * then we remove 3 spaces from the start of every line.
+ */
std::string stripIndentation(std::string_view s);
-/* Get the prefix of 's' up to and excluding the next line break (LF
- optionally preceded by CR), and the remainder following the line
- break. */
+/**
+ * Get the prefix of 's' up to and excluding the next line break (LF
+ * optionally preceded by CR), and the remainder following the line
+ * break.
+ */
std::pair<std::string_view, std::string_view> getLine(std::string_view s);
-/* Get a value for the specified key from an associate container. */
+/**
+ * Get a value for the specified key from an associate container.
+ */
template <class T>
const typename T::mapped_type * get(const T & map, const typename T::key_type & key)
{
@@ -611,7 +770,9 @@ typename T::mapped_type * get(T & map, const typename T::key_type & key)
return &i->second;
}
-/* Get a value for the specified key from an associate container, or a default value if the key isn't present. */
+/**
+ * Get a value for the specified key from an associate container, or a default value if the key isn't present.
+ */
template <class T>
const typename T::mapped_type & getOr(T & map,
const typename T::key_type & key,
@@ -622,7 +783,9 @@ const typename T::mapped_type & getOr(T & map,
return i->second;
}
-/* Remove and return the first item from a container. */
+/**
+ * Remove and return the first item from a container.
+ */
template <class T>
std::optional<typename T::value_type> remove_begin(T & c)
{
@@ -634,7 +797,9 @@ std::optional<typename T::value_type> remove_begin(T & c)
}
-/* Remove and return the first item from a container. */
+/**
+ * Remove and return the first item from a container.
+ */
template <class T>
std::optional<typename T::value_type> pop(T & c)
{
@@ -649,25 +814,48 @@ template<typename T>
class Callback;
-/* Start a thread that handles various signals. Also block those signals
- on the current thread (and thus any threads created by it). */
+/**
+ * Start a thread that handles various signals. Also block those signals
+ * on the current thread (and thus any threads created by it).
+ * Saves the signal mask before changing the mask to block those signals.
+ * See saveSignalMask().
+ */
void startSignalHandlerThread();
+/**
+ * Saves the signal mask, which is the signal mask that nix will restore
+ * before creating child processes.
+ * See setChildSignalMask() to set an arbitrary signal mask instead of the
+ * current mask.
+ */
+void saveSignalMask();
+
+/**
+ * Sets the signal mask. Like saveSignalMask() but for a signal set that doesn't
+ * necessarily match the current thread's mask.
+ * See saveSignalMask() to set the saved mask to the current mask.
+ */
+void setChildSignalMask(sigset_t *sigs);
+
struct InterruptCallback
{
virtual ~InterruptCallback() { };
};
-/* Register a function that gets called on SIGINT (in a non-signal
- context). */
+/**
+ * Register a function that gets called on SIGINT (in a non-signal
+ * context).
+ */
std::unique_ptr<InterruptCallback> createInterruptCallback(
std::function<void()> callback);
void triggerInterrupt();
-/* A RAII class that causes the current thread to receive SIGUSR1 when
- the signal handler thread receives SIGINT. That is, this allows
- SIGINT to be multiplexed to multiple threads. */
+/**
+ * A RAII class that causes the current thread to receive SIGUSR1 when
+ * the signal handler thread receives SIGINT. That is, this allows
+ * SIGINT to be multiplexed to multiple threads.
+ */
struct ReceiveInterrupts
{
pthread_t target;
@@ -681,8 +869,10 @@ struct ReceiveInterrupts
-/* A RAII helper that increments a counter on construction and
- decrements it on destruction. */
+/**
+ * A RAII helper that increments a counter on construction and
+ * decrements it on destruction.
+ */
template<typename T>
struct MaintainCount
{
@@ -693,33 +883,50 @@ struct MaintainCount
};
-/* Return the number of rows and columns of the terminal. */
+/**
+ * @return the number of rows and columns of the terminal.
+ */
std::pair<unsigned short, unsigned short> getWindowSize();
-/* Used in various places. */
+/**
+ * Used in various places.
+ */
typedef std::function<bool(const Path & path)> PathFilter;
extern PathFilter defaultPathFilter;
-/* Common initialisation performed in child processes. */
+/**
+ * Common initialisation performed in child processes.
+ */
void commonChildInit();
-/* Create a Unix domain socket. */
+/**
+ * Create a Unix domain socket.
+ */
AutoCloseFD createUnixDomainSocket();
-/* Create a Unix domain socket in listen mode. */
+/**
+ * Create a Unix domain socket in listen mode.
+ */
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
-/* Bind a Unix domain socket to a path. */
+/**
+ * Bind a Unix domain socket to a path.
+ */
void bind(int fd, const std::string & path);
-/* Connect to a Unix domain socket. */
+/**
+ * Connect to a Unix domain socket.
+ */
void connect(int fd, const std::string & path);
-// A Rust/Python-like enumerate() iterator adapter.
-// Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
+/**
+ * A Rust/Python-like enumerate() iterator adapter.
+ *
+ * Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
+ */
template <typename T,
typename TIter = decltype(std::begin(std::declval<T>())),
typename = decltype(std::end(std::declval<T>()))>
@@ -729,23 +936,25 @@ constexpr auto enumerate(T && iterable)
{
size_t i;
TIter iter;
- bool operator != (const iterator & other) const { return iter != other.iter; }
- void operator ++ () { ++i; ++iter; }
- auto operator * () const { return std::tie(i, *iter); }
+ constexpr bool operator != (const iterator & other) const { return iter != other.iter; }
+ constexpr void operator ++ () { ++i; ++iter; }
+ constexpr auto operator * () const { return std::tie(i, *iter); }
};
struct iterable_wrapper
{
T iterable;
- auto begin() { return iterator{ 0, std::begin(iterable) }; }
- auto end() { return iterator{ 0, std::end(iterable) }; }
+ constexpr auto begin() { return iterator{ 0, std::begin(iterable) }; }
+ constexpr auto end() { return iterator{ 0, std::end(iterable) }; }
};
return iterable_wrapper{ std::forward<T>(iterable) };
}
-// C++17 std::visit boilerplate
+/**
+ * C++17 std::visit boilerplate
+ */
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
@@ -753,8 +962,10 @@ template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
std::string showBytes(uint64_t bytes);
-/* Provide an addition operator between strings and string_views
- inexplicably omitted from the standard library. */
+/**
+ * Provide an addition operator between strings and string_views
+ * inexplicably omitted from the standard library.
+ */
inline std::string operator + (const std::string & s1, std::string_view s2)
{
auto s = s1;