aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/error.hh2
-rw-r--r--src/libutil/json-impls.hh14
-rw-r--r--src/libutil/monitor-fd.hh53
-rw-r--r--src/libutil/regex-combinators.hh30
-rw-r--r--src/libutil/tests/tests.cc36
5 files changed, 114 insertions, 21 deletions
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index 7d236028c..0ebeaba61 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -74,6 +74,8 @@ struct AbstractPos
virtual void print(std::ostream & out) const = 0;
std::optional<LinesOfCode> getCodeLines() const;
+
+ virtual ~AbstractPos() = default;
};
std::ostream & operator << (std::ostream & str, const AbstractPos & pos);
diff --git a/src/libutil/json-impls.hh b/src/libutil/json-impls.hh
new file mode 100644
index 000000000..bd75748ad
--- /dev/null
+++ b/src/libutil/json-impls.hh
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "nlohmann/json_fwd.hpp"
+
+// Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
+#define JSON_IMPL(TYPE) \
+ namespace nlohmann { \
+ using namespace nix; \
+ template <> \
+ struct adl_serializer<TYPE> { \
+ static TYPE from_json(const json & json); \
+ static void to_json(json & json, TYPE t); \
+ }; \
+ }
diff --git a/src/libutil/monitor-fd.hh b/src/libutil/monitor-fd.hh
index 5ee0b88ef..9518cf8aa 100644
--- a/src/libutil/monitor-fd.hh
+++ b/src/libutil/monitor-fd.hh
@@ -22,27 +22,38 @@ public:
{
thread = std::thread([fd]() {
while (true) {
- /* Wait indefinitely until a POLLHUP occurs. */
- struct pollfd fds[1];
- fds[0].fd = fd;
- /* This shouldn't be necessary, but macOS doesn't seem to
- like a zeroed out events field.
- See rdar://37537852.
- */
- fds[0].events = POLLHUP;
- auto count = poll(fds, 1, -1);
- if (count == -1) abort(); // can't happen
- /* This shouldn't happen, but can on macOS due to a bug.
- See rdar://37550628.
-
- This may eventually need a delay or further
- coordination with the main thread if spinning proves
- too harmful.
- */
- if (count == 0) continue;
- assert(fds[0].revents & POLLHUP);
- triggerInterrupt();
- break;
+ /* Wait indefinitely until a POLLHUP occurs. */
+ struct pollfd fds[1];
+ fds[0].fd = fd;
+ /* Polling for no specific events (i.e. just waiting
+ for an error/hangup) doesn't work on macOS
+ anymore. So wait for read events and ignore
+ them. */
+ fds[0].events =
+ #ifdef __APPLE__
+ POLLRDNORM
+ #else
+ 0
+ #endif
+ ;
+ auto count = poll(fds, 1, -1);
+ if (count == -1) abort(); // can't happen
+ /* This shouldn't happen, but can on macOS due to a bug.
+ See rdar://37550628.
+
+ This may eventually need a delay or further
+ coordination with the main thread if spinning proves
+ too harmful.
+ */
+ if (count == 0) continue;
+ if (fds[0].revents & POLLHUP) {
+ triggerInterrupt();
+ break;
+ }
+ /* This will only happen on macOS. We sleep a bit to
+ avoid waking up too often if the client is sending
+ input. */
+ sleep(1);
}
});
};
diff --git a/src/libutil/regex-combinators.hh b/src/libutil/regex-combinators.hh
new file mode 100644
index 000000000..0b997b25a
--- /dev/null
+++ b/src/libutil/regex-combinators.hh
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <string_view>
+
+namespace nix::regex {
+
+// TODO use constexpr string building like
+// https://github.com/akrzemi1/static_string/blob/master/include/ak_toolkit/static_string.hpp
+
+static inline std::string either(std::string_view a, std::string_view b)
+{
+ return std::string { a } + "|" + b;
+}
+
+static inline std::string group(std::string_view a)
+{
+ return std::string { "(" } + a + ")";
+}
+
+static inline std::string many(std::string_view a)
+{
+ return std::string { "(?:" } + a + ")*";
+}
+
+static inline std::string list(std::string_view a)
+{
+ return std::string { a } + many(group("," + a));
+}
+
+}
diff --git a/src/libutil/tests/tests.cc b/src/libutil/tests/tests.cc
index 6e325db98..250e83a38 100644
--- a/src/libutil/tests/tests.cc
+++ b/src/libutil/tests/tests.cc
@@ -312,6 +312,42 @@ namespace nix {
}
/* ----------------------------------------------------------------------------
+ * getLine
+ * --------------------------------------------------------------------------*/
+
+ TEST(getLine, all) {
+ {
+ auto [line, rest] = getLine("foo\nbar\nxyzzy");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "bar\nxyzzy");
+ }
+
+ {
+ auto [line, rest] = getLine("foo\r\nbar\r\nxyzzy");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "bar\r\nxyzzy");
+ }
+
+ {
+ auto [line, rest] = getLine("foo\n");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "");
+ }
+
+ {
+ auto [line, rest] = getLine("foo");
+ ASSERT_EQ(line, "foo");
+ ASSERT_EQ(rest, "");
+ }
+
+ {
+ auto [line, rest] = getLine("");
+ ASSERT_EQ(line, "");
+ ASSERT_EQ(rest, "");
+ }
+ }
+
+ /* ----------------------------------------------------------------------------
* toLower
* --------------------------------------------------------------------------*/