diff options
author | Jay Berkenbilt <ejb@ql.org> | 2024-01-01 16:14:01 +0100 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2024-01-01 16:48:14 +0100 |
commit | 070ee710eb0aaf6ddc845735c6ea0c28d3b7e5a1 (patch) | |
tree | efe7e487fed4f341960792c6357bac6dd927afa1 /libqpdf/QUtil.cc | |
parent | 708ea4ef43c2f7d6a88f215f1b932c5118aceafb (diff) | |
download | qpdf-070ee710eb0aaf6ddc845735c6ea0c28d3b7e5a1.tar.zst |
Support excluding values from numeric ranges (fixes #564, #790)
Diffstat (limited to 'libqpdf/QUtil.cc')
-rw-r--r-- | libqpdf/QUtil.cc | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc index 5e88ff88..c0aca105 100644 --- a/libqpdf/QUtil.cc +++ b/libqpdf/QUtil.cc @@ -1303,6 +1303,10 @@ QUtil::str_compare_nocase(char const* s1, char const* s2) std::vector<int> QUtil::parse_numrange(char const* range, int max) { + // Performance note: this implementation aims to be straightforward, not efficient. Numeric + // range parsing is used only during argument processing. It is not used during processing of + // PDF files. + static std::regex group_re(R"((x)?(z|r?\d+)(?:-(z|r?\d+))?)"); auto parse_num = [&max](std::string const& s) -> int { if (s == "z") { @@ -1375,12 +1379,22 @@ QUtil::parse_numrange(char const* range, int max) first = false; auto first_num = parse_num(m[2].str()); auto is_span = m[3].matched; - int last_num; + int last_num{0}; if (is_span) { last_num = parse_num(m[3].str()); } if (is_exclude) { - // XXX + std::vector<int> work; + populate(work, first_num, is_span, last_num); + std::set<int> exclusions; + exclusions.insert(work.begin(), work.end()); + work = last_group; + last_group.clear(); + for (auto n: work) { + if (exclusions.count(n) == 0) { + last_group.emplace_back(n); + } + } } else { result.insert(result.end(), last_group.begin(), last_group.end()); populate(last_group, first_num, is_span, last_num); |