Files
2026-06-09 00:22:22 -05:00

88 lines
2.2 KiB
C++

#include "sedpp/Regex.h"
#include <stdexcept>
namespace sedpp {
Regex::Regex(const std::string &pattern, const Options &options,
bool ignoreCase, bool multiline) {
int flags = 0;
// Keep regex flavor decisions here so compiler-normalized patterns can be
// reused by addresses and substitutions without duplicating regcomp flags.
if (options.extendedRegex) {
flags |= REG_EXTENDED;
}
if (ignoreCase) {
flags |= REG_ICASE;
}
if (multiline) {
flags |= REG_NEWLINE;
}
const int rc = ::regcomp(&regex_, pattern.c_str(), flags);
if (rc != 0) {
char message[256];
::regerror(rc, &regex_, message, sizeof(message));
throw std::runtime_error(message);
}
compiled_ = true;
}
Regex::Regex(Regex &&other) noexcept {
// regex_t is a C resource; moving transfers the compiled object and prevents
// the source wrapper from freeing it.
regex_ = other.regex_;
compiled_ = other.compiled_;
other.compiled_ = false;
}
Regex &Regex::operator=(Regex &&other) noexcept {
if (this != &other) {
if (compiled_) {
::regfree(&regex_);
}
regex_ = other.regex_;
compiled_ = other.compiled_;
other.compiled_ = false;
}
return *this;
}
Regex::~Regex() {
if (compiled_) {
::regfree(&regex_);
}
}
std::optional<Match> Regex::search(const std::string &text,
std::size_t start) const {
constexpr std::size_t kMaxGroups = 10;
Match match;
match.groups.resize(kMaxGroups);
const char *base = text.c_str();
// Searches after byte 0 should not let ^ match the original beginning again.
const int eflags = start == 0 ? 0 : REG_NOTBOL;
const int rc = ::regexec(&regex_, base + start, match.groups.size(),
match.groups.data(), eflags);
if (rc == REG_NOMATCH) {
return std::nullopt;
}
if (rc != 0) {
char message[256];
::regerror(rc, &regex_, message, sizeof(message));
throw std::runtime_error(message);
}
for (regmatch_t &group : match.groups) {
if (group.rm_so >= 0) {
// regexec saw base + start, so convert offsets back into the full string.
group.rm_so += static_cast<regoff_t>(start);
group.rm_eo += static_cast<regoff_t>(start);
}
}
return match;
}
} // namespace sedpp