summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-05-11 12:42:12 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-05-13 11:42:00 +0200
commit4ce9b5a1023be2e931d4205ed17f44f135c920d1 (patch)
treea8fdee5c427d6c0b4e907e4b902d751e69fe972f
parentae9780583c18c949bf975131a24eb8b8361ddbf6 (diff)
downloadmupdf-4ce9b5a1023be2e931d4205ed17f44f135c920d1.tar.xz
Add common page range parsing function for tools.
-rw-r--r--include/mupdf/fitz/string.h7
-rw-r--r--source/fitz/string.c47
-rw-r--r--source/pdf/pdf-clean-file.c27
-rw-r--r--source/tools/muconvert.c47
-rw-r--r--source/tools/mudraw.c44
-rw-r--r--source/tools/pdfinfo.c50
-rw-r--r--source/tools/pdfmerge.c59
-rw-r--r--source/tools/pdfpages.c47
8 files changed, 92 insertions, 236 deletions
diff --git a/include/mupdf/fitz/string.h b/include/mupdf/fitz/string.h
index 8daa28fc..2af6ba93 100644
--- a/include/mupdf/fitz/string.h
+++ b/include/mupdf/fitz/string.h
@@ -136,4 +136,11 @@ float fz_strtof_no_exp(const char *string, char **tailptr);
*/
int fz_grisu(float f, char *s, int *exp);
+/*
+ Check and parse string into page ranges:
+ ( ','? ([0-9]+|'N') ( '-' ([0-9]+|N) )? )+
+*/
+int fz_is_page_range(fz_context *ctx, const char *s);
+const char *fz_parse_page_range(fz_context *ctx, const char *s, int *a, int *b, int n);
+
#endif
diff --git a/source/fitz/string.c b/source/fitz/string.c
index 95b216fe..df171795 100644
--- a/source/fitz/string.c
+++ b/source/fitz/string.c
@@ -416,3 +416,50 @@ fz_off_t fz_atoo(const char *s)
return 0;
return fz_atoo_imp(s);
}
+
+int fz_is_page_range(fz_context *ctx, const char *s)
+{
+ /* TODO: check the actual syntax... */
+ while (*s)
+ {
+ if ((*s < '0' || *s > '9') && *s != 'N' && *s != '-' && *s != ',')
+ return 0;
+ s++;
+ }
+ return 1;
+}
+
+const char *fz_parse_page_range(fz_context *ctx, const char *s, int *a, int *b, int n)
+{
+ if (!s || !s[0])
+ return NULL;
+
+ if (s[0] == ',')
+ s += 1;
+
+ if (s[0] == 'N')
+ {
+ *a = n;
+ s += 1;
+ }
+ else
+ *a = strtol(s, (char**)&s, 10);
+
+ if (s[0] == '-')
+ {
+ if (s[1] == 'N')
+ {
+ *b = n;
+ s += 2;
+ }
+ else
+ *b = strtol(s+1, (char**)&s, 10);
+ }
+ else
+ *b = *a;
+
+ *a = fz_clampi(*a, 1, n);
+ *b = fz_clampi(*b, 1, n);
+
+ return s;
+}
diff --git a/source/pdf/pdf-clean-file.c b/source/pdf/pdf-clean-file.c
index 2a80f0cc..e886dc5f 100644
--- a/source/pdf/pdf-clean-file.c
+++ b/source/pdf/pdf-clean-file.c
@@ -206,39 +206,18 @@ static void retainpages(fz_context *ctx, globals *glo, int argc, char **argv)
while (argc - argidx)
{
int page, spage, epage;
- char *spec, *dash;
- char *pagelist = argv[argidx];
+ const char *pagelist = argv[argidx];
pagecount = pdf_count_pages(ctx, doc);
- spec = fz_strsep(&pagelist, ",");
- while (spec)
- {
- dash = strchr(spec, '-');
-
- if (dash == spec)
- spage = epage = pagecount;
- else
- spage = epage = atoi(spec);
-
- if (dash)
- {
- if (strlen(dash) > 1)
- epage = atoi(dash + 1);
- else
- epage = pagecount;
- }
-
- spage = fz_clampi(spage, 1, pagecount);
- epage = fz_clampi(epage, 1, pagecount);
+ while ((pagelist = fz_parse_page_range(ctx, pagelist, &spage, &epage, pagecount)))
+ {
if (spage < epage)
for (page = spage; page <= epage; ++page)
retainpage(ctx, doc, parent, kids, page);
else
for (page = spage; page >= epage; --page)
retainpage(ctx, doc, parent, kids, page);
-
- spec = fz_strsep(&pagelist, ",");
}
argidx++;
diff --git a/source/tools/muconvert.c b/source/tools/muconvert.c
index 7c2d1f4f..6f354b01 100644
--- a/source/tools/muconvert.c
+++ b/source/tools/muconvert.c
@@ -40,7 +40,7 @@ static void usage(void)
"\t\tcbz, pdf\n"
"\t-O -\tcomma separated list of options for output format\n"
"\n"
- "\tpages\tcomma separated list of page numbers and ranges\n"
+ "\tpages\tcomma separated list of page numbers and ranges, where N is the last page\n"
"\n"
);
fprintf(stderr, "%s\n", fz_cbz_write_options_usage);
@@ -48,17 +48,6 @@ static void usage(void)
exit(1);
}
-static int isrange(const char *s)
-{
- while (*s)
- {
- if ((*s < '0' || *s > '9') && *s != 'N' && *s != '-' && *s != ',')
- return 0;
- s++;
- }
- return 1;
-}
-
static void runpage(int number)
{
fz_matrix ctm;
@@ -74,44 +63,18 @@ static void runpage(int number)
fz_drop_page(ctx, page);
}
-static void runrange(char *s)
+static void runrange(const char *range)
{
int start, end, i;
- while (s[0])
- {
- if (s[0] == 'N')
- {
- start = count;
- s += 1;
- }
- else
- start = strtol(s, &s, 10);
-
- if (s[0] == '-')
- {
- if (s[1] == 'N')
- {
- end = count;
- s += 2;
- }
- else
- end = strtol(s+1, &s, 10);
- }
- else
- end = start;
-
- start = fz_clampi(start, 1, count);
- end = fz_clampi(end, 1, count);
+ while ((range = fz_parse_page_range(ctx, range, &start, &end, count)))
+ {
if (start < end)
for (i = start; i <= end; ++i)
runpage(i);
else
for (i = start; i >= end; --i)
runpage(i);
-
- if (s[0] != ',')
- break;
}
}
@@ -188,7 +151,7 @@ int muconvert_main(int argc, char **argv)
fz_layout_document(ctx, doc, layout_w, layout_h, layout_em);
count = fz_count_pages(ctx, doc);
- if (isrange(argv[i+1]))
+ if (i+1 < argc && fz_is_page_range(ctx, argv[i+1]))
runrange(argv[++i]);
else
runrange("1-N");
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 6523380b..a58912a9 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -455,17 +455,6 @@ static int gettime(void)
return (now.tv_sec - first.tv_sec) * 1000 + (now.tv_usec - first.tv_usec) / 1000;
}
-static int isrange(char *s)
-{
- while (*s)
- {
- if ((*s < '0' || *s > '9') && *s != '-' && *s != ',')
- return 0;
- s++;
- }
- return 1;
-}
-
static int has_percent_d(char *s)
{
/* find '%[0-9]*d' */
@@ -1187,41 +1176,20 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
}
}
-static void drawrange(fz_context *ctx, fz_document *doc, char *range)
+static void drawrange(fz_context *ctx, fz_document *doc, const char *range)
{
int page, spage, epage, pagecount;
- char *spec, *dash;
pagecount = fz_count_pages(ctx, doc);
- spec = fz_strsep(&range, ",");
- while (spec)
- {
- dash = strchr(spec, '-');
-
- if (dash == spec)
- spage = epage = pagecount;
- else
- spage = epage = atoi(spec);
-
- if (dash)
- {
- if (strlen(dash) > 1)
- epage = atoi(dash + 1);
- else
- epage = pagecount;
- }
-
- spage = fz_clampi(spage, 1, pagecount);
- epage = fz_clampi(epage, 1, pagecount);
+ while ((range = fz_parse_page_range(ctx, range, &spage, &epage, pagecount)))
+ {
if (spage < epage)
for (page = spage; page <= epage; page++)
drawpage(ctx, doc, page);
else
for (page = spage; page >= epage; page--)
drawpage(ctx, doc, page);
-
- spec = fz_strsep(&range, ",");
}
}
@@ -1648,9 +1616,9 @@ int mudraw_main(int argc, char **argv)
}
else
{
- if (fz_optind == argc || !isrange(argv[fz_optind]))
- drawrange(ctx, doc, "1-");
- if (fz_optind < argc && isrange(argv[fz_optind]))
+ if (fz_optind == argc || !fz_is_page_range(ctx, argv[fz_optind]))
+ drawrange(ctx, doc, "1-N");
+ if (fz_optind < argc && fz_is_page_range(ctx, argv[fz_optind]))
drawrange(ctx, doc, argv[fz_optind++]);
}
diff --git a/source/tools/pdfinfo.c b/source/tools/pdfinfo.c
index 0d30b22a..fd52d12f 100644
--- a/source/tools/pdfinfo.c
+++ b/source/tools/pdfinfo.c
@@ -912,10 +912,9 @@ printinfo(fz_context *ctx, globals *glo, char *filename, int show, int page)
}
static void
-showinfo(fz_context *ctx, globals *glo, char *filename, int show, char *pagelist)
+showinfo(fz_context *ctx, globals *glo, char *filename, int show, const char *pagelist)
{
int page, spage, epage;
- char *spec, *dash;
int allpages;
int pagecount;
fz_output *out = glo->out;
@@ -923,33 +922,12 @@ showinfo(fz_context *ctx, globals *glo, char *filename, int show, char *pagelist
if (!glo->doc)
infousage();
- allpages = !strcmp(pagelist, "1-");
+ allpages = !strcmp(pagelist, "1-N");
pagecount = pdf_count_pages(ctx, glo->doc);
- spec = fz_strsep(&pagelist, ",");
- while (spec && pagecount)
- {
- dash = strchr(spec, '-');
-
- if (dash == spec)
- spage = epage = pagecount;
- else
- spage = epage = atoi(spec);
-
- if (dash)
- {
- if (strlen(dash) > 1)
- epage = atoi(dash + 1);
- else
- epage = pagecount;
- }
-
- if (spage > epage)
- page = spage, spage = epage, epage = page;
-
- spage = fz_clampi(spage, 1, pagecount);
- epage = fz_clampi(epage, 1, pagecount);
+ while ((pagelist = fz_parse_page_range(ctx, pagelist, &spage, &epage, pagecount)))
+ {
if (allpages)
fz_printf(ctx, out, "Retrieving info from pages %d-%d...\n", spage, epage);
for (page = spage; page <= epage; page++)
@@ -963,26 +941,12 @@ showinfo(fz_context *ctx, globals *glo, char *filename, int show, char *pagelist
clearinfo(ctx, glo);
}
}
-
- spec = fz_strsep(&pagelist, ",");
}
if (allpages)
printinfo(ctx, glo, filename, show, -1);
}
-static int arg_is_page_range(const char *arg)
-{
- int c;
-
- while ((c = *arg++) != 0)
- {
- if ((c < '0' || c > '9') && (c != '-') && (c != ','))
- return 0;
- }
- return 1;
-}
-
static void
pdfinfo_info(fz_context *ctx, fz_output *out, char *filename, char *password, int show, char *argv[], int argc)
{
@@ -996,11 +960,11 @@ pdfinfo_info(fz_context *ctx, fz_output *out, char *filename, char *password, in
state = NO_FILE_OPENED;
while (argidx < argc)
{
- if (state == NO_FILE_OPENED || !arg_is_page_range(argv[argidx]))
+ if (state == NO_FILE_OPENED || !fz_is_page_range(ctx, argv[argidx]))
{
if (state == NO_INFO_GATHERED)
{
- showinfo(ctx, &glo, filename, show, "1-");
+ showinfo(ctx, &glo, filename, show, "1-N");
}
closexref(ctx, &glo);
@@ -1026,7 +990,7 @@ pdfinfo_info(fz_context *ctx, fz_output *out, char *filename, char *password, in
}
if (state == NO_INFO_GATHERED)
- showinfo(ctx, &glo, filename, show, "1-");
+ showinfo(ctx, &glo, filename, show, "1-N");
closexref(ctx, &glo);
}
diff --git a/source/tools/pdfmerge.c b/source/tools/pdfmerge.c
index 597bd4ce..fc097994 100644
--- a/source/tools/pdfmerge.c
+++ b/source/tools/pdfmerge.c
@@ -13,7 +13,7 @@ static void usage(void)
"\t-o\tname of PDF file to create\n"
"\t-O\tcomma separated list of output options\n"
"\tinput.pdf\tname of input file from which to copy pages\n"
- "\tpages\tcomma separated list of page ranges to copy (for example: 1-5,6,10-)\n\n"
+ "\tpages\tcomma separated list of page numbers and ranges\n"
);
fprintf(stderr, "%s\n", fz_pdf_write_options_usage);
exit(1);
@@ -23,19 +23,6 @@ static fz_context *ctx = NULL;
static pdf_document *doc_des = NULL;
static pdf_document *doc_src = NULL;
-/* This isrange is a duplicate with mudraw.c Not sure how we want to organize or if
- * we are fine with the small amount of code duplication */
-static int isrange(char *s)
-{
- while (*s)
- {
- if ((*s < '0' || *s > '9') && *s != '-' && *s != ',')
- return 0;
- s++;
- }
- return 1;
-}
-
static void page_merge(int page_from, int page_to, pdf_graft_map *graft_map)
{
pdf_obj *pageref = NULL;
@@ -91,46 +78,24 @@ static void page_merge(int page_from, int page_to, pdf_graft_map *graft_map)
}
}
-static void merge_range(char *range)
+static void merge_range(const char *range)
{
- int page, spage, epage, src_pagecount, des_pagecount;
- char *spec, *dash;
+ int start, end, i, count;
pdf_graft_map *graft_map;
- src_pagecount = fz_count_pages(ctx, (fz_document*) doc_src);
- des_pagecount = fz_count_pages(ctx, (fz_document*) doc_des);
- spec = fz_strsep(&range, ",");
+ count = pdf_count_pages(ctx, doc_src);
graft_map = pdf_new_graft_map(ctx, doc_src);
fz_try(ctx)
{
- while (spec)
+ while ((range = fz_parse_page_range(ctx, range, &start, &end, count)))
{
- dash = strchr(spec, '-');
-
- if (dash == spec)
- spage = epage = src_pagecount;
- else
- spage = epage = atoi(spec);
-
- if (dash)
- {
- if (strlen(dash) > 1)
- epage = atoi(dash + 1);
- else
- epage = src_pagecount;
- }
-
- spage = fz_clampi(spage, 1, src_pagecount);
- epage = fz_clampi(epage, 1, src_pagecount);
-
- if (spage < epage)
- for (page = spage; page <= epage; page++, des_pagecount++)
- page_merge(page, des_pagecount + 1, graft_map);
+ if (start < end)
+ for (i = start; i <= end; ++i)
+ page_merge(i, -1, graft_map);
else
- for (page = spage; page >= epage; page--, des_pagecount++)
- page_merge(page, des_pagecount + 1, graft_map);
- spec = fz_strsep(&range, ",");
+ for (i = start; i >= end; --i)
+ page_merge(i, -1, graft_map);
}
}
fz_always(ctx)
@@ -191,8 +156,8 @@ int pdfmerge_main(int argc, char **argv)
{
pdf_drop_document(ctx, doc_src);
doc_src = pdf_open_document(ctx, input);
- if (fz_optind == argc || !isrange(argv[fz_optind]))
- merge_range("1-");
+ if (fz_optind == argc || !fz_is_page_range(ctx, argv[fz_optind]))
+ merge_range("1-N");
else
merge_range(argv[fz_optind++]);
}
diff --git a/source/tools/pdfpages.c b/source/tools/pdfpages.c
index 7f3577da..62aa4eeb 100644
--- a/source/tools/pdfpages.c
+++ b/source/tools/pdfpages.c
@@ -102,10 +102,9 @@ showpage(fz_context *ctx, pdf_document *doc, fz_output *out, int page)
}
static int
-showpages(fz_context *ctx, pdf_document *doc, fz_output *out, char *pagelist)
+showpages(fz_context *ctx, pdf_document *doc, fz_output *out, const char *pagelist)
{
int page, spage, epage;
- char *spec, *dash;
int pagecount;
int ret = 0;
@@ -113,53 +112,17 @@ showpages(fz_context *ctx, pdf_document *doc, fz_output *out, char *pagelist)
infousage();
pagecount = pdf_count_pages(ctx, doc);
- spec = fz_strsep(&pagelist, ",");
- while (spec && pagecount)
+ while ((pagelist = fz_parse_page_range(ctx, pagelist, &spage, &epage, pagecount)))
{
- dash = strchr(spec, '-');
-
- if (dash == spec)
- spage = epage = pagecount;
- else
- spage = epage = atoi(spec);
-
- if (dash)
- {
- if (strlen(dash) > 1)
- epage = atoi(dash + 1);
- else
- epage = pagecount;
- }
-
if (spage > epage)
page = spage, spage = epage, epage = page;
-
- spage = fz_clampi(spage, 1, pagecount);
- epage = fz_clampi(epage, 1, pagecount);
-
for (page = spage; page <= epage; page++)
- {
ret |= showpage(ctx, doc, out, page);
- }
-
- spec = fz_strsep(&pagelist, ",");
}
return ret;
}
-static int arg_is_page_range(const char *arg)
-{
- int c;
-
- while ((c = *arg++) != 0)
- {
- if ((c < '0' || c > '9') && (c != '-') && (c != ','))
- return 0;
- }
- return 1;
-}
-
static int
pdfpages_pages(fz_context *ctx, fz_output *out, char *filename, char *password, char *argv[], int argc)
{
@@ -171,11 +134,11 @@ pdfpages_pages(fz_context *ctx, fz_output *out, char *filename, char *password,
state = NO_FILE_OPENED;
while (argidx < argc)
{
- if (state == NO_FILE_OPENED || !arg_is_page_range(argv[argidx]))
+ if (state == NO_FILE_OPENED || !fz_is_page_range(ctx, argv[argidx]))
{
if (state == NO_INFO_GATHERED)
{
- showpages(ctx, doc, out, "1-");
+ showpages(ctx, doc, out, "1-N");
}
pdf_drop_document(ctx, doc);
@@ -199,7 +162,7 @@ pdfpages_pages(fz_context *ctx, fz_output *out, char *filename, char *password,
}
if (state == NO_INFO_GATHERED)
- showpages(ctx, doc, out, "1-");
+ showpages(ctx, doc, out, "1-N");
pdf_drop_document(ctx, doc);