From: Diogo Franco (Kovensky) Date: Wed, 17 Jul 2013 20:54:10 +0000 (-0300) Subject: misc: Add an iterator to EpisodeRange X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=c49419f1971c6187a764867fdfe431800493bbf4;p=go-anidb.git misc: Add an iterator to EpisodeRange --- diff --git a/misc/episoderange.go b/misc/episoderange.go index 7e750cc..8645fba 100644 --- a/misc/episoderange.go +++ b/misc/episoderange.go @@ -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. diff --git a/misc/episoderange_test.go b/misc/episoderange_test.go index aec5636..587e7a7 100644 --- a/misc/episoderange_test.go +++ b/misc/episoderange_test.go @@ -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 +}