aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/util.hh
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2021-02-25 21:58:41 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2021-02-25 21:58:41 +0000
commit90d76fa399de4e207ea14ec4c0dd65434f60c152 (patch)
tree3c52e982cba5bcf7b91c99d1b63ba967b4ea8b92 /src/libutil/util.hh
parent4636cc9a1f6de70947abbfb17a0ad91981d1cad7 (diff)
parentca0994819d68aee26a2906c37a47ae609ac46c4c (diff)
Merge remote-tracking branch 'obsidian/path-info' into ca-drv-exotic
Diffstat (limited to 'src/libutil/util.hh')
-rw-r--r--src/libutil/util.hh54
1 files changed, 41 insertions, 13 deletions
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index cafe93702..ad49c65b3 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -106,7 +106,7 @@ string readFile(const Path & path);
void readFile(const Path & path, Sink & sink);
/* Write a string to a file. */
-void writeFile(const Path & path, const string & s, mode_t mode = 0666);
+void writeFile(const Path & path, std::string_view s, mode_t mode = 0666);
void writeFile(const Path & path, Source & source, mode_t mode = 0666);
@@ -155,9 +155,8 @@ void replaceSymlink(const Path & target, const Path & link,
/* Wrappers arount read()/write() that read/write exactly the
requested number of bytes. */
-void readFull(int fd, unsigned char * buf, size_t count);
-void writeFull(int fd, const unsigned char * buf, size_t count, bool allowInterrupts = true);
-void writeFull(int fd, const string & s, bool allowInterrupts = true);
+void readFull(int fd, char * buf, size_t count);
+void writeFull(int fd, std::string_view s, bool allowInterrupts = true);
MakeError(EndOfFile, Error);
@@ -374,8 +373,9 @@ template<class C> Strings quoteStrings(const C & c)
}
-/* Remove trailing whitespace from a string. */
-string chomp(const string & s);
+/* Remove trailing whitespace from a string. FIXME: return
+ std::string_view. */
+string chomp(std::string_view s);
/* Remove whitespace from the start and end of a string. */
@@ -383,7 +383,7 @@ string trim(const string & s, const string & whitespace = " \n\r\t");
/* Replace all occurrences of a string inside another string. */
-string replaceStrings(const std::string & s,
+string replaceStrings(std::string_view s,
const std::string & from, const std::string & to);
@@ -398,21 +398,49 @@ bool statusOk(int status);
/* Parse a string into an integer. */
-template<class N> bool string2Int(const string & s, N & n)
+template<class N>
+std::optional<N> string2Int(const std::string & s)
{
- if (string(s, 0, 1) == "-" && !std::numeric_limits<N>::is_signed)
- return false;
+ if (s.substr(0, 1) == "-" && !std::numeric_limits<N>::is_signed)
+ return std::nullopt;
std::istringstream str(s);
+ N n;
str >> n;
- return str && str.get() == EOF;
+ if (str && str.get() == EOF) return n;
+ return std::nullopt;
+}
+
+/* Like string2Int(), but support an optional suffix 'K', 'M', 'G' or
+ 'T' denoting a binary unit prefix. */
+template<class N>
+N string2IntWithUnitPrefix(std::string s)
+{
+ N multiplier = 1;
+ if (!s.empty()) {
+ char u = std::toupper(*s.rbegin());
+ if (std::isalpha(u)) {
+ if (u == 'K') multiplier = 1ULL << 10;
+ else if (u == 'M') multiplier = 1ULL << 20;
+ else if (u == 'G') multiplier = 1ULL << 30;
+ else if (u == 'T') multiplier = 1ULL << 40;
+ else throw UsageError("invalid unit specifier '%1%'", u);
+ s.resize(s.size() - 1);
+ }
+ }
+ if (auto n = string2Int<N>(s))
+ return *n * multiplier;
+ throw UsageError("'%s' is not an integer", s);
}
/* Parse a string into a float. */
-template<class N> bool string2Float(const string & s, N & n)
+template<class N>
+std::optional<N> string2Float(const string & s)
{
std::istringstream str(s);
+ N n;
str >> n;
- return str && str.get() == EOF;
+ if (str && str.get() == EOF) return n;
+ return std::nullopt;
}