X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=lily%2Fsequential-music-iterator.cc;h=7260e3eb83f1e49c0d946489607239c1abc64496;hb=acec5c037f53a163237c31486b84971aa33deaab;hp=8218251942fa75c016bad1a52b259a0805b03489;hpb=287611887cd612ac84dbf10c5fe4e1a44cc56596;p=lilypond.git diff --git a/lily/sequential-music-iterator.cc b/lily/sequential-music-iterator.cc index 8218251942..7260e3eb83 100644 --- a/lily/sequential-music-iterator.cc +++ b/lily/sequential-music-iterator.cc @@ -12,10 +12,28 @@ #include "music-list.hh" #include "request-chord-iterator.hh" +/* + Invariant for the data structure. + + + if (gh_pair_p (cursor_)) + iter_p_->music_l_ == unsmob_music (gh_car (cursor_)) + else + iter_p_ == 0; + + The length of musiclist from start to up to cursor_ (cursor_ not + including), is summed + + here_mom_ = sum (length (musiclist [start ... cursor> )) %) + + */ + + Sequential_music_iterator::Sequential_music_iterator () { - cursor_ = 0; - here_mom_ = 0; + cursor_ = SCM_EOL; + here_mom_ = Moment (0); + iter_p_ =0; } @@ -24,61 +42,61 @@ Sequential_music_iterator::Sequential_music_iterator (Sequential_music_iterator { cursor_ = src.cursor_; here_mom_ = src.here_mom_; - iter_p_ = src.iter_p_->clone (); + if (src.iter_p_) + iter_p_ = src.iter_p_->clone (); + else + iter_p_ = 0; } Sequential_music_iterator::~Sequential_music_iterator() { - if (iter_p_) - { - /* if (iter_p_->ok () ) - music_l_->origin ()->warning (_ ("Must stop before this music ends")); - */ - delete iter_p_; - iter_p_ = 0; - } + delete iter_p_; } - void Sequential_music_iterator::construct_children() { cursor_ = dynamic_cast (music_l_)->music_list (); - - while (gh_pair_p (cursor_ )) + + iter_p_ = gh_pair_p (cursor_) ? get_iterator_p (unsmob_music (gh_car (cursor_))) : 0; + while (iter_p_ && !iter_p_->ok ()) { - start_next_element(); - if (!iter_p_->ok()) - { - leave_element(); - } - else - { - set_sequential_music_translator(); - break; - } + next_element (); } -} -void -Sequential_music_iterator::leave_element() -{ - delete iter_p_; - iter_p_ =0; - Moment elt_time = unsmob_music (gh_car (cursor_))->length_mom (); - here_mom_ += elt_time; - cursor_ =gh_cdr (cursor_); + /* + iter_p_->ok () is tautology, but what the heck. + */ + if (iter_p_ && iter_p_->ok()) + descend_to_child (); + } + +/* + maintain invariants: change cursor, iter and here_mom_ in one fell + swoop. +*/ void -Sequential_music_iterator::start_next_element() +Sequential_music_iterator::next_element () { - assert (!iter_p_); - iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_))); + here_mom_ += iter_p_->music_length_mom (); + delete iter_p_; + cursor_ = gh_cdr (cursor_); + + if (gh_pair_p (cursor_)) + iter_p_ = get_iterator_p (unsmob_music (gh_car (cursor_))); + else + iter_p_ = 0; } +/* + move to context of child iterator if it is deeper down in the + hierarchy. + */ + void -Sequential_music_iterator::set_sequential_music_translator() +Sequential_music_iterator::descend_to_child () { Translator_group * child_report = child_report = iter_p_->report_to_l (); if (dynamic_cast (iter_p_)) @@ -89,70 +107,89 @@ Sequential_music_iterator::set_sequential_music_translator() } +/* + Retrieve all music (starting at HERE), until a music with length L > + 0 is found. From the precondition, we know that UNTIL is later than + the earliest event. Hence we know + + L >= (UNTIL - HERE) + + so something that comes after this thing with L > 0 happens after + + HERE + L >= HERE + (UNTIL - HERE) = UNTIL + + Hence all events after the one with L>0 are uninteresting, so we + ignore them. + +*/ + SCM Sequential_music_iterator::get_music (Moment until)const { -#if 0 - /* - FIXME: get_music () is const, so we must operate on a copy of child-iter. - */ - SCM s = SCM_EOL; - while (1) - { - Moment local_until = until - here_mom_; - while (iter_p_->ok ()) - { - Moment here = iter_p_->pending_moment (); - if (here != local_until) - return s; - - s = gh_append2 (iter_p_->get_music (local_until), s); - } - - if (!iter_p_->ok ()) - { - // leave_element (); - - if (gh_pair_p (cursor_)) - start_next_element (); - else - return s; - } - } + if (until < pending_moment ()) + return s; + + Sequential_music_iterator * me = + dynamic_cast (clone ()); + while (me->ok ()) + { + SCM nm = me->iter_p_->get_music (until - me->here_mom_); + s = gh_append2 (nm, s); + + Moment m = 0; + for (SCM i = nm; gh_pair_p(i); i = gh_cdr (i)) + m = m >? unsmob_music (gh_car (i))->length_mom (); + + if (m > Moment (0)) + break ; + else + me->next_element (); + } + delete me; + return s; -#endif - return SCM_EOL; +} +/* + Skip events till UNTIL. We don't do any other side effects (such as + moving descending to child iterator contexts, because they might + depend on \context specs and \translator changes being executed + + */ +void +Sequential_music_iterator::skip (Moment until) +{ + while (ok ()) + { + Moment l =iter_p_->music_length_mom (); + if (l >= until - here_mom_) + iter_p_->skip (until - here_mom_); + + if (iter_p_->ok ()) + return ; + + next_element (); + } } void Sequential_music_iterator::process (Moment until) { - if (ok ()) + while (iter_p_) { - while (1) - { - Moment local_until = until - here_mom_; - while (iter_p_->ok ()) - { - Moment here = iter_p_->pending_moment (); - if (here != local_until) - return ; - - iter_p_->process (local_until); - } + iter_p_->process (until - here_mom_); + + /* + if the iter is still OK, there must be events left that have + + TIME > LEFT - if (!iter_p_->ok ()) - { - set_sequential_music_translator (); - leave_element (); - - if (gh_pair_p (cursor_)) - start_next_element (); - else - return ; - } - } + */ + if (iter_p_->ok ()) + return ; + + descend_to_child (); + next_element (); } }