From 4ce9b5a1023be2e931d4205ed17f44f135c920d1 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 11 May 2016 12:42:12 +0200 Subject: Add common page range parsing function for tools. --- include/mupdf/fitz/string.h | 7 ++++++ source/fitz/string.c | 47 ++++++++++++++++++++++++++++++++++++ source/pdf/pdf-clean-file.c | 27 +++------------------ source/tools/muconvert.c | 47 ++++-------------------------------- source/tools/mudraw.c | 44 +++++---------------------------- source/tools/pdfinfo.c | 50 ++++++-------------------------------- source/tools/pdfmerge.c | 59 +++++++++------------------------------------ source/tools/pdfpages.c | 47 ++++-------------------------------- 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); -- cgit v1.2.3