summaryrefslogtreecommitdiff
path: root/competition/multilog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'competition/multilog.cpp')
-rw-r--r--competition/multilog.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/competition/multilog.cpp b/competition/multilog.cpp
new file mode 100644
index 0000000..bf10ec6
--- /dev/null
+++ b/competition/multilog.cpp
@@ -0,0 +1,57 @@
+#include <iostream>
+#include <string>
+#include <cassert>
+#include "multilog.h"
+
+
+static int uniqid() {
+ static int i = 0;
+ return i++;
+}
+
+
+MultiLog::Item::Item()
+ : id(uniqid()) {}
+
+int MultiLog::add(const string_view prefix) {
+ lock_guard guard(mut);
+
+ items.emplace_back();
+ items.back().line = prefix;
+ cout << prefix << endl;
+ return items.back().id;
+}
+
+void MultiLog::append(int id, const string_view text) {
+ lock_guard guard(mut);
+
+ assert(text.find('\n') == string::npos);
+
+ size_t idx = findId(id);
+ items[idx].line += text;
+ redrawLine(idx);
+}
+
+void MultiLog::complete(int id) {
+ lock_guard guard(mut);
+
+ size_t idx = findId(id);
+ items[idx].complete = true;
+ size_t nextIdx;
+ for (nextIdx = 0; nextIdx < items.size(); nextIdx++) {
+ if (!items[nextIdx].complete) break;
+ }
+ if (nextIdx > 0) items.erase(items.begin(), items.begin() + (nextIdx - 1));
+}
+
+size_t MultiLog::findId(int id) {
+ for (int i = 0; i < (int)items.size(); i++) {
+ if (items[i].id == id) return i;
+ }
+ assert(false);
+}
+
+void MultiLog::redrawLine(size_t idx) {
+ size_t offset = items.size() - idx;
+ cout << "\r\x1B[" << offset << "A\x1B[K" << items[idx].line << "\r\x1B[" << offset << "B" << flush;
+}