]> git.lizzy.rs Git - go-anidb.git/commitdiff
misc: Add an iterator to EpisodeRange
authorDiogo Franco (Kovensky) <diogomfranco@gmail.com>
Wed, 17 Jul 2013 20:54:10 +0000 (17:54 -0300)
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>
Wed, 17 Jul 2013 20:54:10 +0000 (17:54 -0300)
misc/episoderange.go
misc/episoderange_test.go

index 7e750cc7328e984f438749ad8f124ab116c77fb0..8645fba24d4e94c5473aae0f125f217bf694a4e0 100644 (file)
@@ -51,6 +51,72 @@ func (er *EpisodeRange) scale() int {
        return s
 }
 
+func (er *EpisodeRange) Infinite() bool {
+       return er != nil && er.End == nil
+}
+
+// Returns a channel that can be used to iterate using for/range.
+//
+// If the EpisodeRange is infinite, then the channel is also infinite.
+// The caller is allowed to close the channel in such case.
+func (er *EpisodeRange) Episodes() chan Episode {
+       ch := make(chan Episode, 1)
+       if er == nil || er.Start == nil {
+               close(ch)
+               return ch
+       }
+
+       start := *er.Start
+       inf := er.Infinite()
+       end := Episode{}
+       if !inf {
+               end = *er.End
+       }
+
+       go func() {
+               abort := false
+
+               if inf {
+                       // we allow the caller to close the channel on infinite lists
+                       defer func() { recover(); abort = true }()
+               } else {
+                       defer close(ch)
+               }
+
+               ep := start
+
+               switch {
+               case inf:
+                       for ; !abort && ep.Parts > 0 && ep.Number == start.Number; ep.IncPart() {
+                               ch <- ep
+                       }
+                       for ; !abort; ep.IncNumber() {
+                               ch <- ep
+                       }
+               case start.Part == -1 && end.Part == -1:
+                       for ; ep.Number <= end.Number; ep.IncNumber() {
+                               ch <- ep
+                       }
+               case start.Parts > 0:
+                       for ; ep.Number == start.Number; ep.IncPart() {
+                               ch <- ep
+                       }
+                       fallthrough
+               default:
+                       for ; ep.Number < end.Number; ep.IncNumber() {
+                               ch <- ep
+                       }
+                       if end.Part >= 0 {
+                               ep.Part = 0
+                       }
+                       for ; ep.Part <= end.Part; ep.IncPart() {
+                               ch <- ep
+                       }
+               }
+       }()
+       return ch
+}
+
 // If ec is an *Episode, returns true if the Episode is of the same type as the range
 // and has a Number >= Start.Number; if End is defined, then the episode's Number must
 // also be <= End.Number.
index aec5636f547edcf386b75fc3a43d9d9e4a3abce0..587e7a70a19ab478a67e4df5500835bcfb161d49 100644 (file)
@@ -79,3 +79,17 @@ func ExampleEpisodeRange_Split() {
        // [1 03-10]
        // [1-3 05-10]
 }
+
+func ExampleEpisodeRange_Episodes() {
+       a := misc.ParseEpisodeRange("C1-C3.2")
+       for ep := range a.Episodes() {
+               fmt.Println(ep)
+       }
+
+       // Output:
+       // C1
+       // C2
+       // C3.0
+       // C3.1
+       // C3.2
+}