aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QUtil.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2024-01-01 16:14:01 +0100
committerJay Berkenbilt <ejb@ql.org>2024-01-01 16:48:14 +0100
commit070ee710eb0aaf6ddc845735c6ea0c28d3b7e5a1 (patch)
treeefe7e487fed4f341960792c6357bac6dd927afa1 /libqpdf/QUtil.cc
parent708ea4ef43c2f7d6a88f215f1b932c5118aceafb (diff)
downloadqpdf-070ee710eb0aaf6ddc845735c6ea0c28d3b7e5a1.tar.zst
Support excluding values from numeric ranges (fixes #564, #790)
Diffstat (limited to 'libqpdf/QUtil.cc')
-rw-r--r--libqpdf/QUtil.cc18
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);