代码拉取完成,页面将自动刷新
/*
Copyright 2018 The pdfcpu Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package api
import (
"fmt"
"regexp"
"sort"
"strconv"
"strings"
"gitee.com/deeao/golang-pdfcpu/pkg/log"
"gitee.com/deeao/golang-pdfcpu/pkg/pdfcpu/types"
"github.com/pkg/errors"
)
var (
selectedPagesRegExp *regexp.Regexp
)
func setupRegExpForPageSelection() *regexp.Regexp {
e := "(\\d+)?-l(-\\d+)?|l(-(\\d+)-?)?"
e = "[!n]?((-\\d+)|(\\d+(-(\\d+)?)?)|" + e + ")"
e = "\\Qeven\\E|\\Qodd\\E|" + e
exp := "^" + e + "(," + e + ")*$"
re, _ := regexp.Compile(exp)
return re
}
func init() {
selectedPagesRegExp = setupRegExpForPageSelection()
}
// ParsePageSelection ensures a correct page selection expression.
func ParsePageSelection(s string) ([]string, error) {
if s == "" {
return nil, nil
}
// Ensure valid comma separated expression of:{ {even|odd}{!}{-}# | {even|odd}{!}#-{#} }*
//
// Negated expressions:
// '!' negates an expression
// since '!' needs to be part of a single quoted string in bash
// as an alternative also 'n' works instead of "!"
//
// Extract all but page 4 may be expressed as: "1-,!4" or "1-,n4"
//
// The pageSelection is evaluated strictly from left to right!
// e.g. "!3,1-5" extracts pages 1-5 whereas "1-5,!3" extracts pages 1,2,4,5
//
if !selectedPagesRegExp.MatchString(s) {
return nil, errors.Errorf("-pages \"%s\" => syntax error\n", s)
}
//log.CLI.Printf("pageSelection: %s\n", s)
return strings.Split(s, ","), nil
}
func handlePrefix(v string, negated bool, pageCount int, selectedPages types.IntSet) error {
// -l
if v == "l" {
for j := 1; j <= pageCount; j++ {
selectedPages[j] = !negated
}
return nil
}
// -l-#
if strings.HasPrefix(v, "l-") {
i, err := strconv.Atoi(v[2:])
if err != nil {
return err
}
if pageCount-i < 1 {
return nil
}
for j := 1; j <= pageCount-i; j++ {
selectedPages[j] = !negated
}
return nil
}
// -#
i, err := strconv.Atoi(v)
if err != nil {
return err
}
// Handle overflow gracefully
if i > pageCount {
i = pageCount
}
// identified
// -# ... select all pages up to and including #
// or !-# ... deselect all pages up to and including #
for j := 1; j <= i; j++ {
selectedPages[j] = !negated
}
return nil
}
func handleSuffix(v string, negated bool, pageCount int, selectedPages types.IntSet) error {
// must be #- ... select all pages from here until the end.
// or !#- ... deselect all pages from here until the end.
i, err := strconv.Atoi(v)
if err != nil {
return err
}
// Handle overflow gracefully
if i > pageCount {
return nil
}
for j := i; j <= pageCount; j++ {
selectedPages[j] = !negated
}
return nil
}
func handleSpecificPageOrLastXPages(s string, negated bool, pageCount int, selectedPages types.IntSet) error {
// l
if s == "l" {
selectedPages[pageCount] = !negated
return nil
}
// l-#
if strings.HasPrefix(s, "l-") {
pr := strings.Split(s[2:], "-")
i, err := strconv.Atoi(pr[0])
if err != nil {
return err
}
if pageCount-i < 1 {
return nil
}
j := pageCount - i
// l-#-
if strings.HasSuffix(s, "-") {
j = pageCount
}
for i := pageCount - i; i <= j; i++ {
selectedPages[i] = !negated
}
return nil
}
// must be # ... select a specific page
// or !# ... deselect a specific page
i, err := strconv.Atoi(s)
if err != nil {
return err
}
// Handle overflow gracefully
if i > pageCount {
return nil
}
selectedPages[i] = !negated
return nil
}
func negation(c byte) bool {
return c == '!' || c == 'n'
}
func selectEvenPages(selectedPages types.IntSet, pageCount int) {
for i := 2; i <= pageCount; i += 2 {
_, found := selectedPages[i]
if !found {
selectedPages[i] = true
}
}
}
func selectOddPages(selectedPages types.IntSet, pageCount int) {
for i := 1; i <= pageCount; i += 2 {
_, found := selectedPages[i]
if !found {
selectedPages[i] = true
}
}
}
func parsePageRange(pr []string, pageCount int, negated bool, selectedPages types.IntSet) error {
from, err := strconv.Atoi(pr[0])
if err != nil {
return err
}
// Handle overflow gracefully
if from > pageCount {
return nil
}
var thru int
if pr[1] == "l" {
// #-l
thru = pageCount
if len(pr) == 3 {
// #-l-#
i, err := strconv.Atoi(pr[2])
if err != nil {
return err
}
thru -= i
}
} else {
// #-#
var err error
thru, err = strconv.Atoi(pr[1])
if err != nil {
return err
}
}
// Handle overflow gracefully
if thru < from {
return nil
}
if thru > pageCount {
thru = pageCount
}
for i := from; i <= thru; i++ {
selectedPages[i] = !negated
}
return nil
}
func sortedPages(selectedPages types.IntSet) []int {
p := []int(nil)
for i, v := range selectedPages {
if v {
p = append(p, i)
}
}
sort.Ints(p)
return p
}
func logSelPages(selectedPages types.IntSet) {
if !log.CLIEnabled() || len(selectedPages) == 0 {
return
}
var b strings.Builder
for _, i := range sortedPages(selectedPages) {
fmt.Fprintf(&b, "%d,", i)
}
s := b.String()
if len(s) > 1 {
s = s[:len(s)-1]
}
// TODO Suppress for multifile cmds
if log.CLIEnabled() {
log.CLI.Printf("pages: %s\n", s)
}
}
func calcSelPages(pageCount int, pageSelection []string, selectedPages types.IntSet) error {
for _, v := range pageSelection {
//log.Stats.Printf("pageExp: <%s>\n", v)
if v == "even" {
selectEvenPages(selectedPages, pageCount)
continue
}
if v == "odd" {
selectOddPages(selectedPages, pageCount)
continue
}
var negated bool
if negation(v[0]) {
negated = true
//logInfoAPI.Printf("is a negated exp\n")
v = v[1:]
}
// -#
if v[0] == '-' {
v = v[1:]
if err := handlePrefix(v, negated, pageCount, selectedPages); err != nil {
return err
}
continue
}
// #-
if v[0] != 'l' && strings.HasSuffix(v, "-") {
if err := handleSuffix(v[:len(v)-1], negated, pageCount, selectedPages); err != nil {
return err
}
continue
}
// l l-# l-#-
if v[0] == 'l' {
if err := handleSpecificPageOrLastXPages(v, negated, pageCount, selectedPages); err != nil {
return err
}
continue
}
pr := strings.Split(v, "-")
if len(pr) >= 2 {
// v contains '-' somewhere in the middle
// #-# #-l #-l-#
if err := parsePageRange(pr, pageCount, negated, selectedPages); err != nil {
return err
}
continue
}
// #
if err := handleSpecificPageOrLastXPages(pr[0], negated, pageCount, selectedPages); err != nil {
return err
}
}
return nil
}
// selectedPages returns a set of used page numbers.
// key==page# => key 0 unused!
func selectedPages(pageCount int, pageSelection []string, log bool) (types.IntSet, error) {
selectedPages := types.IntSet{}
if err := calcSelPages(pageCount, pageSelection, selectedPages); err != nil {
return nil, err
}
if log {
logSelPages(selectedPages)
}
return selectedPages, nil
}
// PagesForPageSelection ensures a set of page numbers for an ascending page sequence
// where each page number may appear only once.
func PagesForPageSelection(pageCount int, pageSelection []string, ensureAllforNone bool, log bool) (types.IntSet, error) {
if len(pageSelection) > 0 {
return selectedPages(pageCount, pageSelection, log)
}
if !ensureAllforNone {
//log.CLI.Printf("pages: none\n")
return nil, nil
}
m := types.IntSet{}
for i := 1; i <= pageCount; i++ {
m[i] = true
}
//log.CLI.Printf("pages: all\n")
return m, nil
}
func RemainingPagesForPageRemoval(pageCount int, pageSelection []string, log bool) (types.IntSet, error) {
pagesToRemove, err := selectedPages(pageCount, pageSelection, log)
if err != nil {
return nil, err
}
m := types.IntSet{}
for i := 1; i <= pageCount; i++ {
m[i] = true
}
for k, v := range pagesToRemove {
if v {
m[k] = false
}
}
return m, nil
}
func deletePageFromCollection(cp *[]int, p int) {
a := []int{}
for _, i := range *cp {
if i != p {
a = append(a, i)
}
}
*cp = a
}
func processPageForCollection(cp *[]int, negated bool, i int) {
if !negated {
*cp = append(*cp, i)
} else {
deletePageFromCollection(cp, i)
}
}
func collectEvenPages(cp *[]int, pageCount int) {
for i := 2; i <= pageCount; i += 2 {
*cp = append(*cp, i)
}
}
func collectOddPages(cp *[]int, pageCount int) {
for i := 1; i <= pageCount; i += 2 {
*cp = append(*cp, i)
}
}
func handlePrefixForCollection(v string, negated bool, pageCount int, cp *[]int) error {
// -l
if v == "l" {
for j := 1; j <= pageCount; j++ {
processPageForCollection(cp, negated, j)
}
return nil
}
// -l-#
if strings.HasPrefix(v, "l-") {
i, err := strconv.Atoi(v[2:])
if err != nil {
return err
}
if pageCount-i < 1 {
return nil
}
for j := 1; j <= pageCount-i; j++ {
processPageForCollection(cp, negated, j)
}
return nil
}
// -#
i, err := strconv.Atoi(v)
if err != nil {
return err
}
// Handle overflow gracefully
if i > pageCount {
i = pageCount
}
// identified
// -# ... select all pages up to and including #
// or !-# ... deselect all pages up to and including #
for j := 1; j <= i; j++ {
processPageForCollection(cp, negated, j)
}
return nil
}
func handleSuffixForCollection(v string, negated bool, pageCount int, cp *[]int) error {
// must be #- ... select all pages from here until the end.
// or !#- ... deselect all pages from here until the end.
i, err := strconv.Atoi(v)
if err != nil {
return err
}
// Handle overflow gracefully
if i > pageCount {
return nil
}
for j := i; j <= pageCount; j++ {
processPageForCollection(cp, negated, j)
}
return nil
}
func handleSpecificPageOrLastXPagesForCollection(s string, negated bool, pageCount int, cp *[]int) error {
// l
if s == "l" {
processPageForCollection(cp, negated, pageCount)
return nil
}
// l-#
if strings.HasPrefix(s, "l-") {
pr := strings.Split(s[2:], "-")
i, err := strconv.Atoi(pr[0])
if err != nil {
return err
}
if pageCount-i < 1 {
return nil
}
j := pageCount - i
// l-#-
if strings.HasSuffix(s, "-") {
j = pageCount
}
for i := pageCount - i; i <= j; i++ {
processPageForCollection(cp, negated, i)
}
return nil
}
// must be # ... select a specific page
// or !# ... deselect a specific page
i, err := strconv.Atoi(s)
if err != nil {
return err
}
// Handle overflow gracefully
if i > pageCount {
return nil
}
processPageForCollection(cp, negated, i)
return nil
}
func parsePageRangeForCollection(pr []string, pageCount int, negated bool, cp *[]int) error {
from, err := strconv.Atoi(pr[0])
if err != nil {
return err
}
// Handle overflow gracefully
if from > pageCount {
return nil
}
var thru int
if pr[1] == "l" {
// #-l
thru = pageCount
if len(pr) == 3 {
// #-l-#
i, err := strconv.Atoi(pr[2])
if err != nil {
return err
}
thru -= i
}
} else {
// #-#
var err error
thru, err = strconv.Atoi(pr[1])
if err != nil {
return err
}
}
// Handle overflow gracefully
if thru < from {
return nil
}
if thru > pageCount {
thru = pageCount
}
for i := from; i <= thru; i++ {
processPageForCollection(cp, negated, i)
}
return nil
}
// PagesForPageCollection returns a slice of page numbers for a page collection.
// Any page number in any order any number of times allowed.
func PagesForPageCollection(pageCount int, pageSelection []string) ([]int, error) {
collectedPages := []int{}
for _, v := range pageSelection {
if v == "even" {
collectEvenPages(&collectedPages, pageCount)
continue
}
if v == "odd" {
collectOddPages(&collectedPages, pageCount)
continue
}
var negated bool
if negation(v[0]) {
negated = true
//logInfoAPI.Printf("is a negated exp\n")
v = v[1:]
}
// -#
if v[0] == '-' {
v = v[1:]
if err := handlePrefixForCollection(v, negated, pageCount, &collectedPages); err != nil {
return nil, err
}
continue
}
// #-
if v[0] != 'l' && strings.HasSuffix(v, "-") {
if err := handleSuffixForCollection(v[:len(v)-1], negated, pageCount, &collectedPages); err != nil {
return nil, err
}
continue
}
// l l-# l-#-
if v[0] == 'l' {
if err := handleSpecificPageOrLastXPagesForCollection(v, negated, pageCount, &collectedPages); err != nil {
return nil, err
}
continue
}
pr := strings.Split(v, "-")
if len(pr) >= 2 {
// v contains '-' somewhere in the middle
// #-# #-l #-l-#
if err := parsePageRangeForCollection(pr, pageCount, negated, &collectedPages); err != nil {
return nil, err
}
continue
}
// #
if err := handleSpecificPageOrLastXPagesForCollection(pr[0], negated, pageCount, &collectedPages); err != nil {
return nil, err
}
}
if len(collectedPages) == 0 {
return nil, errors.Errorf("pdfcpu: no page selected")
}
return collectedPages, nil
}
// PagesForPageRange returns a slice of page numbers for a page range.
func PagesForPageRange(from, thru int) []int {
s := make([]int, thru-from+1)
for i := 0; i < len(s); i++ {
s[i] = from + i
}
return s
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。