explicit glob_matcher(const boost::string_ref pat) noexcept : m_pat{pat} { // If we are in debug mode, ensure that the pattern is valid. assert(m_pat.length() > 0); #ifndef NDEBUG auto i = 0u; /* ** The following sequences are considered to be syntax ** violations when they occur within glob patterns: ** ** 1. Special characters within groups. ** 2. Empty groups. ** 3. Any backslash not followed by a special character; this ** includes trailing backslashes. */ do switch (m_pat[i]) { default: case '*': case '?': ++i; continue; case '[': assert(pat[++i] != ']'); goto group_mode; // Ensure that the character escaped using a backslash is a // special character. case '\\': assert(is_glob(pat[++i])); ++i; continue; regular_mode: continue; } while (i != pat.length()); return; // Check to ensure that the current group is valid. group_mode: for(;;) switch (m_pat[i]) { default: ++i; continue; case ']': ++i; goto regular_mode; case '\\': assert(is_glob(pat[++i])); ++i; continue; case '*': case '?': case '\0': assert(false && "Invalid group."); } #endif }
/* ** Determines whether the directory entry's name matches the glob ** pattern. */ bool operator()(const directory_entry& ent) const noexcept { #ifndef NDEBUG assert(m_pat.length() > 0); #endif // Offset into pattern that we are matching. auto i = 0u; // Offset into the file name. auto j = 0u; auto s = ent.name(); do switch(m_pat[i]) { default: if (m_pat[i++] != s[j++]) return false; continue; case '*': ++i; return match_wildcard(s, i, j); case '?': ++i; ++j; continue; case '[': ++i; if (!match_group(s, i, j)) return false; continue; case '\\': ++i; if (m_pat[i++] != s[j++]) return false; continue; } while (i != m_pat.length() && j != s.length()); return (i == m_pat.length() || m_pat[i] == '*') && j == s.length(); }
explicit directory_iterator(const boost::string_ref dir) : m_dir_len(dir.length()) { // Ensure that the string resulting from concatenating the path // to the directory, the platform directory separator, and the // file name can fit in the path buffer. The trailing "+ 1" term // accounts for the null terminating character. assert(m_dir_len + 1 + PLATFORM_MAX_FILENAME_LENGTH + 1 <= PLATFORM_MAX_PATHNAME_LENGTH); // We need to copy `dir` to `m_path_buf`, because `dir` might // not be null-terminated. boost::copy(dir, m_path_buf.begin()); m_path_buf[dir.length()] = '\0'; m_fd = ::open(m_path_buf.begin(), O_RDONLY); if (m_fd < 0) { throw std::system_error{errno, std::system_category(), "failed to open directory"}; } struct stat st; if (::fstat(m_fd, &st) == -1) { throw std::system_error{errno, std::system_category(), "failed to get directory status"}; } m_bufsz = detail::rumpot(st.st_size, st.st_blksize); m_buf = std::unique_ptr<char[]>{new char[m_bufsz]}; // We do not want to copy the null character, so we only copy // until dir + dir_len rather than dir + dir_len + 1. boost::copy(dir, m_path_buf.data()); m_path_buf[m_dir_len] = PLATFORM_DIRECTORY_SEPARATOR; read_chunk(); }
int list_modules( const boost::string_ref prog, const boost::string_ref desc ) { if (desc.length() > 0) { println("Suite ${quote}: $.", get_suite(prog), desc); } else { println("Suite ${quote}.", get_suite(prog)); } for (const auto& m : module_list{}) { if (m.description().length() > 0) { println("Module ${quote}: $.", m.name(), m.description()); } else { println("Module ${quote}.", m.name(), m.description()); } } return EXIT_SUCCESS; }
/* ** Updates the current file at the end of the directory path string. */ void update_path(const boost::string_ref filename) const noexcept { boost::copy(filename, m_path_buf.data() + m_dir_len + 1); m_path_len = m_dir_len + filename.length(); }
/* ** After this method is called, we must iteratively test each character ** of `s` beginning at `s[j]` to check whether it matches the characters ** after the wildcards beginning at `m_pat[i - 1]`. */ bool match_wildcard(const boost::string_ref s, unsigned i, unsigned j) const noexcept { /* ** We keep track of the index `pi` after each wildcard that we ** are trying to match, and the index `pj` into `s` at which we ** are looking for a match. If the characters after the wildcard ** fail to match the string beginning at `s[j]`, then we reset ** `i` to `pi` and `j` to `pj`. */ // First index of current subpattern for which we are looking // for a match. A subpattern is a pattern between a wildcard and // another wildcard or null character. auto pi = i; // Current index at which we are looking for a match. auto pj = j; while (s[j] != '\0') switch (m_pat[i]) { default: if (m_pat[i] != s[j]) { ++pj; i = pi; j = pj; continue; } else { ++i; ++j; continue; } case '*': ++i; pi = i; pj = j; continue; case '?': ++i; ++j; continue; case '[': ++i; if (!match_group(s, i, j)) { ++pj; i = pi; j = pj; } continue; case '\\': /* ** If we increment `i` by one, then we will ** interpret the following escaped character as ** a special character at the next iteration. To ** prevent this, we must anticipate what should ** happen in the next iteration. */ if (m_pat[i + 1] != s[j]) { ++pj; i = pi; j = pj; continue; } else { i += 2; ++j; continue; } } return i == m_pat.length(); }
format_intrusive_result format_value(boost::string_ref value) { return format_intrusive_result(value.data(), value.length()); }