mirror of
https://github.com/qpdf/qpdf.git
synced 2024-05-31 09:20:52 +00:00
Support "r" in page ranges (fixes #155)
This commit is contained in:
parent
e577dfc87e
commit
666f794393
|
@ -1,3 +1,10 @@
|
||||||
|
2018-03-04 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* On the command line when specifying page ranges, support
|
||||||
|
preceding a page number by "r" to indicate that it should be
|
||||||
|
counted from the end. For example, the range r3-r1 would indicate
|
||||||
|
the last three pages of a document.
|
||||||
|
|
||||||
2018-03-03 Jay Berkenbilt <ejb@ql.org>
|
2018-03-03 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
* Ignore zlib data check errors while uncompressing streams. This
|
* Ignore zlib data check errors while uncompressing streams. This
|
||||||
|
|
|
@ -818,13 +818,15 @@ make
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The page range is a set of numbers separated by commas, ranges of
|
The page range is a set of numbers separated by commas, ranges of
|
||||||
numbers separated dashes, or combinations of those. The character
|
numbers separated dashes, or combinations of those. The character
|
||||||
“z” represents the last page. Pages can appear in any
|
“z” represents the last page. A number preceded by an
|
||||||
order. Ranges can appear with a high number followed by a low
|
“r” indicates to count from the end, so
|
||||||
number, which causes the pages to appear in reverse. Repeating a
|
“r3-r1” would be the last three pages of the document.
|
||||||
number will cause an error, but you can use the workaround
|
Pages can appear in any order. Ranges can appear with a high
|
||||||
discussed above should you really want to include the same page
|
number followed by a low number, which causes the pages to appear
|
||||||
twice.
|
in reverse. Repeating a number will cause an error, but you can
|
||||||
|
use the workaround discussed above should you really want to
|
||||||
|
include the same page twice.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Example page ranges:
|
Example page ranges:
|
||||||
|
@ -840,6 +842,17 @@ make
|
||||||
<literal>z-1</literal>: all pages in the document in reverse
|
<literal>z-1</literal>: all pages in the document in reverse
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>r3-r1</literal>: the last three pages of the document
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>r1-r3</literal>: the last three pages of the document
|
||||||
|
in reverse order
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
|
40
qpdf/qpdf.cc
40
qpdf/qpdf.cc
|
@ -358,11 +358,12 @@ input.\n\
|
||||||
\n\
|
\n\
|
||||||
The page range is a set of numbers separated by commas, ranges of\n\
|
The page range is a set of numbers separated by commas, ranges of\n\
|
||||||
numbers separated dashes, or combinations of those. The character\n\
|
numbers separated dashes, or combinations of those. The character\n\
|
||||||
\"z\" represents the last page. Pages can appear in any order. Ranges\n\
|
\"z\" represents the last page. A number preceded by an \"r\" indicates\n\
|
||||||
can appear with a high number followed by a low number, which causes the\n\
|
to count from the end, so \"r3-r1\" would be the last three pages of the\n\
|
||||||
pages to appear in reverse. Repeating a number will cause an error, but\n\
|
document. Pages can appear in any order. Ranges can appear with a\n\
|
||||||
the manual discusses a workaround should you really want to include the\n\
|
high number followed by a low number, which causes the pages to appear in\n\
|
||||||
same page twice.\n\
|
reverse. Repeating a number will cause an error, but the manual discusses\n\
|
||||||
|
a workaround should you really want to include the same page twice.\n\
|
||||||
\n\
|
\n\
|
||||||
If the page range is omitted, the range of 1-z is assumed. qpdf decides\n\
|
If the page range is omitted, the range of 1-z is assumed. qpdf decides\n\
|
||||||
that the page range is omitted if the range argument is either -- or a\n\
|
that the page range is omitted if the range argument is either -- or a\n\
|
||||||
|
@ -577,6 +578,22 @@ static void show_encryption(QPDF& pdf, Options& o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int maybe_from_end(int num, bool from_end, int max)
|
||||||
|
{
|
||||||
|
if (from_end)
|
||||||
|
{
|
||||||
|
if (num > max)
|
||||||
|
{
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num = max + 1 - num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<int> parse_numrange(char const* range, int max,
|
static std::vector<int> parse_numrange(char const* range, int max,
|
||||||
bool throw_error = false)
|
bool throw_error = false)
|
||||||
{
|
{
|
||||||
|
@ -593,6 +610,7 @@ static std::vector<int> parse_numrange(char const* range, int max,
|
||||||
st_after_number } state = st_top;
|
st_after_number } state = st_top;
|
||||||
bool last_separator_was_dash = false;
|
bool last_separator_was_dash = false;
|
||||||
int cur_number = 0;
|
int cur_number = 0;
|
||||||
|
bool from_end = false;
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
char ch = *p;
|
char ch = *p;
|
||||||
|
@ -616,14 +634,25 @@ static std::vector<int> parse_numrange(char const* range, int max,
|
||||||
state = st_after_number;
|
state = st_after_number;
|
||||||
cur_number = max;
|
cur_number = max;
|
||||||
}
|
}
|
||||||
|
else if (ch == 'r')
|
||||||
|
{
|
||||||
|
if (! (state == st_top))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("r not expected");
|
||||||
|
}
|
||||||
|
state = st_in_number;
|
||||||
|
from_end = true;
|
||||||
|
}
|
||||||
else if ((ch == ',') || (ch == '-'))
|
else if ((ch == ',') || (ch == '-'))
|
||||||
{
|
{
|
||||||
if (! ((state == st_in_number) || (state == st_after_number)))
|
if (! ((state == st_in_number) || (state == st_after_number)))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("unexpected separator");
|
throw std::runtime_error("unexpected separator");
|
||||||
}
|
}
|
||||||
|
cur_number = maybe_from_end(cur_number, from_end, max);
|
||||||
work.push_back(cur_number);
|
work.push_back(cur_number);
|
||||||
cur_number = 0;
|
cur_number = 0;
|
||||||
|
from_end = false;
|
||||||
if (ch == ',')
|
if (ch == ',')
|
||||||
{
|
{
|
||||||
state = st_top;
|
state = st_top;
|
||||||
|
@ -649,6 +678,7 @@ static std::vector<int> parse_numrange(char const* range, int max,
|
||||||
}
|
}
|
||||||
if ((state == st_in_number) || (state == st_after_number))
|
if ((state == st_in_number) || (state == st_after_number))
|
||||||
{
|
{
|
||||||
|
cur_number = maybe_from_end(cur_number, from_end, max);
|
||||||
work.push_back(cur_number);
|
work.push_back(cur_number);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1092,9 +1092,19 @@ my @nrange_tests = (
|
||||||
["1-10,1234,5",
|
["1-10,1234,5",
|
||||||
"qpdf: error in numeric range 1-10,1234,5: number 1234 out of range",
|
"qpdf: error in numeric range 1-10,1234,5: number 1234 out of range",
|
||||||
2],
|
2],
|
||||||
["1,3,5-10,z-13,13,9,z,2",
|
["1,r,3",
|
||||||
"numeric range 1,3,5-10,z-13,13,9,z,2" .
|
"qpdf: error in numeric range 1,r,3: number 16 out of range",
|
||||||
" -> 1 3 5 6 7 8 9 10 15 14 13 13 9 15 2",
|
2],
|
||||||
|
["1,r16,3",
|
||||||
|
"qpdf: error in numeric range 1,r16,3: number 0 out of range",
|
||||||
|
2],
|
||||||
|
["1,3,5-10,z-13,13,9,z,2,r2-r4",
|
||||||
|
"numeric range 1,3,5-10,z-13,13,9,z,2,r2-r4" .
|
||||||
|
" -> 1 3 5 6 7 8 9 10 15 14 13 13 9 15 2 14 13 12",
|
||||||
|
0],
|
||||||
|
["r1-r15", # r\d+ at end
|
||||||
|
"numeric range r1-r15" .
|
||||||
|
" -> 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1",
|
||||||
0],
|
0],
|
||||||
);
|
);
|
||||||
$n_tests += scalar(@nrange_tests);
|
$n_tests += scalar(@nrange_tests);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user