From 01b0486966ca2280b8a1a073b07cd51147c4cd19 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 8 Apr 2023 18:31:30 +0200 Subject: [PATCH 1/2] create sortpath --- internal/epub/sortpath/core.go | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 internal/epub/sortpath/core.go diff --git a/internal/epub/sortpath/core.go b/internal/epub/sortpath/core.go new file mode 100644 index 0000000..17b3eaa --- /dev/null +++ b/internal/epub/sortpath/core.go @@ -0,0 +1,83 @@ +package sortpath + +import ( + "path/filepath" + "regexp" + "strconv" + "strings" +) + +var split_path_regex = regexp.MustCompile(`^(.*?)(\d+)$`) + +type part struct { + name string + number int +} + +func (a part) Compare(b part) int { + if a.name == b.name { + return a.number - b.number + } else { + return strings.Compare(a.name, b.name) + } +} + +func parsePart(p string) part { + r := split_path_regex.FindStringSubmatch(p) + if len(r) == 0 { + return part{p, 0} + } + n, err := strconv.ParseInt(r[2], 10, 32) + if err != nil { + return part{p, 0} + } + return part{r[1], int(n)} +} + +func parse(filename string) []part { + pathname, name := filepath.Split(strings.ToLower(filename)) + pathname = strings.TrimSuffix(pathname, string(filepath.Separator)) + ext := filepath.Ext(name) + name = name[0 : len(name)-len(ext)] + + f := []part{} + for _, p := range strings.Split(pathname, string(filepath.Separator)) { + f = append(f, parsePart(p)) + } + f = append(f, parsePart(name)) + return f +} + +func comparePart(a, b []part) int { + m := len(a) + if m > len(b) { + m = len(b) + } + for i := 0; i < m; i++ { + c := a[i].Compare(b[i]) + if c != 0 { + return c + } + } + return len(a) - len(b) +} + +type by struct { + filenames []string + paths [][]part +} + +func (b by) Len() int { return len(b.filenames) } +func (b by) Less(i, j int) bool { return comparePart(b.paths[i], b.paths[j]) < 0 } +func (b by) Swap(i, j int) { + b.filenames[i], b.filenames[j] = b.filenames[j], b.filenames[i] + b.paths[i], b.paths[j] = b.paths[j], b.paths[i] +} + +func By(filenames []string) by { + p := [][]part{} + for _, filename := range filenames { + p = append(p, parse(filename)) + } + return by{filenames, p} +} From a46b02d38a9a8f25e395605dbd31d51971ea2051 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 8 Apr 2023 20:54:50 +0200 Subject: [PATCH 2/2] use sort path to support path with number --- internal/epub/core.go | 11 ++++++++++ internal/epub/image_processing.go | 35 +++++++++++++++---------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/internal/epub/core.go b/internal/epub/core.go index c23a008..f91e140 100644 --- a/internal/epub/core.go +++ b/internal/epub/core.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "regexp" + "sort" "strings" "text/template" "time" @@ -102,6 +103,16 @@ func (e *ePub) getParts() ([]*epubPart, error) { return nil, err } + sort.Slice(images, func(i, j int) bool { + if images[i].Id < images[j].Id { + return true + } else if images[i].Id == images[j].Id { + return images[i].Part < images[j].Part + } else { + return false + } + }) + parts := make([]*epubPart, 0) cover := images[0] if e.HasCover { diff --git a/internal/epub/image_processing.go b/internal/epub/image_processing.go index 3628235..8365530 100644 --- a/internal/epub/image_processing.go +++ b/internal/epub/image_processing.go @@ -16,13 +16,13 @@ import ( "strings" "sync" - _ "golang.org/x/image/webp" - + "github.com/celogeek/go-comic-converter/v2/internal/epub/sortpath" "github.com/disintegration/gift" "github.com/nwaples/rardecode" pdfimage "github.com/raff/pdfreader/image" "github.com/raff/pdfreader/pdfread" "golang.org/x/image/tiff" + _ "golang.org/x/image/webp" ) type Image struct { @@ -138,6 +138,7 @@ func LoadImages(path string, options *ImageOptions, dry bool) ([]*Image, error) img.Path, }) } + return images, nil } @@ -233,15 +234,6 @@ func LoadImages(path string, options *ImageOptions, dry bool) ([]*Image, error) return nil, fmt.Errorf("image not found") } - sort.Slice(images, func(i, j int) bool { - if images[i].Id < images[j].Id { - return true - } else if images[i].Id == images[j].Id && images[i].Part < images[j].Part { - return true - } - return false - }) - return images, nil } @@ -275,7 +267,7 @@ func loadDir(input string) (int, chan *imageTask, error) { return 0, nil, fmt.Errorf("image not found") } - sort.Strings(images) + sort.Sort(sortpath.By(images)) output := make(chan *imageTask) go func() { @@ -320,21 +312,28 @@ func loadCbz(input string) (int, chan *imageTask, error) { return 0, nil, fmt.Errorf("no images found") } - sort.SliceStable(images, func(i, j int) bool { - return strings.Compare(images[i].Name, images[j].Name) < 0 - }) + names := []string{} + for _, img := range images { + names = append(names, img.Name) + } + sort.Sort(sortpath.By(names)) + + indexedNames := make(map[string]int) + for i, name := range names { + indexedNames[name] = i + } output := make(chan *imageTask) go func() { defer close(output) - for i, img := range images { + for _, img := range images { f, err := img.Open() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } output <- &imageTask{ - Id: i, + Id: indexedNames[img.Name], Reader: f, Path: filepath.Dir(filepath.Clean(img.Name)), Filename: img.Name, @@ -373,7 +372,7 @@ func loadCbr(input string) (int, chan *imageTask, error) { return 0, nil, fmt.Errorf("no images found") } - sort.Strings(names) + sort.Sort(sortpath.By(names)) indexedNames := make(map[string]int) for i, name := range names {