1 #include "serializer.h"
13 using namespace std::chrono;
15 extern steady_clock::time_point start;
19 if (--limit_left > 0) {
22 dprintf("Done in %.1f ms, found %" PRId64 " matches.\n",
23 1e3 * duration<float>(steady_clock::now() - start).count(), limit_matches);
25 printf("%" PRId64 "\n", limit_matches);
30 void print_possibly_escaped(const string &str)
33 printf("%s%c", str.c_str(), 0);
35 } else if (!stdout_is_tty) {
36 printf("%s\n", str.c_str());
40 // stdout is a terminal, so we should protect the user against
41 // escapes, stray newlines and the likes. First of all, check if
42 // all the characters are safe; we consider everything safe that
43 // isn't a control character, ', " or \. People could make
44 // filenames like "$(rm -rf)", but that's out-of-scope.
45 const char *ptr = str.data();
46 size_t len = str.size();
48 mbtowc(nullptr, 0, 0);
52 int ret = mbtowc(&pwc, ptr, len);
54 all_safe = false; // Malformed data.
55 } else if (ret == 0) {
57 } else if (pwc < 32 || pwc == '\'' || pwc == '"' || pwc == '\\') {
59 } else if (pwc == '`') {
60 // A rather odd case; ls quotes this but does not escape it.
66 } while (all_safe && *ptr != '\0');
69 printf("%s\n", str.c_str());
73 // Print escaped, but in such a way that the user can easily take the
74 // escaped output and paste into the shell. We print much like GNU ls does,
75 // ie., using the shell $'foo' construct whenever we need to print something
77 bool in_escaped_mode = false;
80 mbtowc(nullptr, 0, 0);
83 while (*ptr != '\0') {
84 int ret = mbtowc(nullptr, ptr, len);
91 } else if (ret == 0) {
94 if (*ptr < 32 || *ptr == '\'' || *ptr == '"' || *ptr == '\\') {
95 if (!in_escaped_mode) {
97 in_escaped_mode = true;
100 // The list of allowed escapes is from bash(1).
133 printf("\\%03o", *ptr);
137 if (in_escaped_mode) {
139 in_escaped_mode = false;
141 fwrite(ptr, ret, 1, stdout);
149 void Serializer::print(uint64_t seq, uint64_t skip, const string msg)
158 if (next_seq != seq) {
159 pending.push(Element{ seq, skip, move(msg) });
164 print_possibly_escaped(msg);
169 // See if any delayed prints can now be dealt with.
170 while (!pending.empty() && pending.top().seq == next_seq) {
171 if (!pending.top().msg.empty()) {
172 print_possibly_escaped(pending.top().msg);
175 next_seq += pending.top().skip;