-class Serializer {
-public:
- bool ready_to_print(int seq) { return next_seq == seq; }
- void print_delayed(int seq, const vector<string> msg);
- void release_current();
-
-private:
- int next_seq = 0;
- struct Element {
- int seq;
- vector<string> msg;
-
- bool operator<(const Element &other) const
- {
- return seq > other.seq;
- }
- };
- priority_queue<Element> pending;
-};
-
-void Serializer::print_delayed(int seq, const vector<string> msg)
-{
- pending.push(Element{ seq, move(msg) });
-}
-
-void Serializer::release_current()
-{
- ++next_seq;
-
- // See if any delayed prints can now be dealt with.
- while (!pending.empty() && pending.top().seq == next_seq) {
- if (limit_matches-- <= 0)
- return;
- for (const string &msg : pending.top().msg) {
- if (print_nul) {
- printf("%s%c", msg.c_str(), 0);
- } else {
- printf("%s\n", msg.c_str());
- }
- }
- pending.pop();
- ++next_seq;
- }
-}
-
-struct Needle {
- enum { STRSTR,
- REGEX, // Not currently used.
- GLOB } type;
- string str; // Filled in no matter what.
- regex_t re; // For REGEX.
-};
-
-bool matches(const Needle &needle, const char *haystack)
-{
- if (needle.type == Needle::STRSTR) {
- return strstr(haystack, needle.str.c_str()) != nullptr;
- } else if (needle.type == Needle::GLOB) {
- int flags = ignore_case ? FNM_CASEFOLD : 0;
- return fnmatch(needle.str.c_str(), haystack, flags) == 0;
- } else {
- assert(needle.type == Needle::REGEX);
- return regexec(&needle.re, haystack, /*nmatch=*/0, /*pmatch=*/nullptr, /*flags=*/0) == 0;
- }
-}
-
-bool has_access(const char *filename,
- unordered_map<string, bool> *access_rx_cache)
-{
- const char *end = strchr(filename + 1, '/');
- while (end != nullptr) {
- string parent_path(filename, end);
- auto it = access_rx_cache->find(parent_path);
- bool ok;
- if (it == access_rx_cache->end()) {
- ok = access(parent_path.c_str(), R_OK | X_OK) == 0;
- access_rx_cache->emplace(move(parent_path), ok);
- } else {
- ok = it->second;
- }
- if (!ok) {
- return false;
- }
- end = strchr(end + 1, '/');
- }
-
- return true;
-}