From 21fafaa04653068abc5ecb2a576e43b7c0cf3f40 Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 22 Oct 2006 23:08:13 +0000 Subject: [PATCH] add all_tracks_reverse_iterator --- stepmania/src/NoteData.cpp | 66 +++++++++++++++++++-------- stepmania/src/NoteData.h | 54 +++++++++++++++++----- stepmania/src/NoteDataWithScoring.cpp | 2 +- 3 files changed, 92 insertions(+), 30 deletions(-) diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index 951a70d2af..6702876eb6 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -897,10 +897,31 @@ void NoteData::LoadFromNode( const XNode* pNode ) ASSERT(0); } -template -void NoteData::_all_tracks_iterator::Find() +NoteData::reverse_iterator NoteData::rlower_bound( int iTrack, int iRow ) +{ + // TODO: optimize this + reverse_iterator i = m_TapNotes[iTrack].rbegin(); + for( ; i != m_TapNotes[iTrack].rend(); ++i ) + { + int first = i->first; + if( i->first <= iRow ) + return i; + } + + return i; +} + +NoteData::const_reverse_iterator NoteData::rlower_bound( int iTrack, int iRow ) const +{ + NoteData::reverse_iterator iter = ((NoteData*)this)->rlower_bound( iTrack, iRow ); + return iter; +} + +template +void NoteData::_all_tracks_iterator::Find() { int iMinRow = m_iEndRow+1; + int iMaxRow = m_iStartRow-1; // If no notes can be found in the range, m_iTrack will stay -1 and IsAtEnd() will return true. m_iTrack = -1; @@ -908,46 +929,55 @@ void NoteData::_all_tracks_iterator::Find() { iter &i = m_vIters[iTrack]; if( m_Cond ) - while( i != m_NoteData.end(iTrack) && i->first < iMinRow && !m_Cond(i->second) ) - ++i; - - if( i != m_NoteData.end(iTrack) && i->first < iMinRow ) { - iMinRow = i->first; + while( i != (m_NoteData.*myend)(iTrack) && (bReverse ? (i->first > iMaxRow) : (i->first < iMinRow)) && !m_Cond(i->second) ) + ++i; + } + + if( i != (m_NoteData.*myend)(iTrack) && (bReverse ? (i->first > iMaxRow) : (i->first < iMinRow)) ) + { + bReverse ? iMaxRow : iMinRow = i->first; m_iTrack = iTrack; } } } -template -NoteData::_all_tracks_iterator::_all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, NoteData::IteratorCond cond ) : - m_NoteData(nd), m_iTrack(0), m_iEndRow(iEndRow), m_Cond(cond) +template +NoteData::_all_tracks_iterator::_all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, NoteData::IteratorCond cond ) : + m_NoteData(nd), m_iTrack(0), m_iStartRow(iStartRow), m_iEndRow(iEndRow), m_Cond(cond) { ASSERT( m_NoteData.GetNumTracks() > 0 ); for( int iTrack = 0; iTrack < m_NoteData.GetNumTracks(); ++iTrack ) - m_vIters.push_back( m_NoteData.lower_bound(iTrack, iStartRow) ); + { + iter i = (m_NoteData.*mylower_bound)(iTrack, bReverse?iEndRow:iStartRow); + iter end = (m_NoteData.*myend)(iTrack); + m_vIters.push_back( i ); + } Find(); } -template -NoteData::_all_tracks_iterator &NoteData::_all_tracks_iterator::operator++() // preincrement +template +NoteData::_all_tracks_iterator &NoteData::_all_tracks_iterator::operator++() // preincrement { ++m_vIters[m_iTrack]; Find(); return *this; } -template -NoteData::_all_tracks_iterator NoteData::_all_tracks_iterator::operator++( int dummy ) // postincrement +template +NoteData::_all_tracks_iterator NoteData::_all_tracks_iterator::operator++( int dummy ) // postincrement { - _all_tracks_iterator ret(*this); + _all_tracks_iterator ret(*this); operator++(); return ret; } + // Explicit instantiation. -template class NoteData::_all_tracks_iterator; -template class NoteData::_all_tracks_iterator; +template class NoteData::_all_tracks_iterator; +template class NoteData::_all_tracks_iterator; +template class NoteData::_all_tracks_iterator; +template class NoteData::_all_tracks_iterator; /* * (c) 2001-2004 Chris Danford, Glenn Maynard diff --git a/stepmania/src/NoteData.h b/stepmania/src/NoteData.h index 358250f982..afd4ddaf41 100644 --- a/stepmania/src/NoteData.h +++ b/stepmania/src/NoteData.h @@ -24,19 +24,48 @@ public: typedef map TrackMap; typedef map::iterator iterator; typedef map::const_iterator const_iterator; + typedef map::reverse_iterator reverse_iterator; + typedef map::const_reverse_iterator const_reverse_iterator; + typedef iterator (NoteData::*iterator_method_int)(int); + typedef const_iterator (NoteData::*const_iterator_method_int)(int) const; + typedef reverse_iterator (NoteData::*reverse_iterator_method_int)(int); + typedef const_reverse_iterator (NoteData::*const_reverse_iterator_method_int)(int) const; + typedef iterator (NoteData::*iterator_method_int_int)(int,int); + typedef const_iterator (NoteData::*const_iterator_method_int_int)(int,int) const; + typedef reverse_iterator (NoteData::*reverse_iterator_method_int_int)(int,int); + typedef const_reverse_iterator (NoteData::*const_reverse_iterator_method_int_int)(int,int) const; + + iterator begin( int iTrack ) { return m_TapNotes[iTrack].begin(); } + const_iterator begin( int iTrack ) const { return m_TapNotes[iTrack].begin(); } + reverse_iterator rbegin( int iTrack ) { return m_TapNotes[iTrack].rbegin(); } + const_reverse_iterator rbegin( int iTrack ) const { return m_TapNotes[iTrack].rbegin(); } + iterator end( int iTrack ) { return m_TapNotes[iTrack].end(); } + const_iterator end( int iTrack ) const { return m_TapNotes[iTrack].end(); } + reverse_iterator rend( int iTrack ) { return m_TapNotes[iTrack].rend(); } + const_reverse_iterator rend( int iTrack ) const { return m_TapNotes[iTrack].rend(); } + iterator lower_bound( int iTrack, int iRow ) { return m_TapNotes[iTrack].lower_bound( iRow ); } + const_iterator lower_bound( int iTrack, int iRow ) const { return m_TapNotes[iTrack].lower_bound( iRow ); } + reverse_iterator rlower_bound( int iTrack, int iRow ); + const_reverse_iterator rlower_bound( int iTrack, int iRow ) const; + void swap( NoteData &nd ) { m_TapNotes.swap( nd.m_TapNotes ); } + + + + typedef bool (*IteratorCond)( const TapNote& ); // This is ugly to make it templated but I don't want to have to write the same class twice. - template + template class _all_tracks_iterator { ND &m_NoteData; vector m_vIters; int m_iTrack; + const int m_iStartRow; const int m_iEndRow; IteratorCond m_Cond; - void Find(); + void Find(); // point m_iTrack at the iterator with the smallest row that meets mCond and is within range public: _all_tracks_iterator( ND &nd, int iStartRow, int iEndRow, IteratorCond cond ); _all_tracks_iterator &operator++(); // preincrement @@ -49,8 +78,10 @@ public: inline const TN &operator*() const { DEBUG_ASSERT( !IsAtEnd() ); return m_vIters[m_iTrack]->second; } inline const TN *operator->() const { DEBUG_ASSERT( !IsAtEnd() ); return &m_vIters[m_iTrack]->second; } }; - typedef _all_tracks_iterator all_tracks_iterator; - typedef _all_tracks_iterator all_tracks_const_iterator; + typedef _all_tracks_iterator all_tracks_iterator; + typedef _all_tracks_iterator all_tracks_const_iterator; + typedef _all_tracks_iterator all_tracks_reverse_iterator; + typedef _all_tracks_iterator all_tracks_const_reverse_iterator; private: // There's no point in inserting empty notes into the map. @@ -78,13 +109,6 @@ public: return TAP_EMPTY; } - iterator begin( int iTrack ) { return m_TapNotes[iTrack].begin(); } - const_iterator begin( int iTrack ) const { return m_TapNotes[iTrack].begin(); } - iterator end( int iTrack ) { return m_TapNotes[iTrack].end(); } - const_iterator end( int iTrack ) const { return m_TapNotes[iTrack].end(); } - iterator lower_bound( int iTrack, int iRow ) { return m_TapNotes[iTrack].lower_bound( iRow ); } - const_iterator lower_bound( int iTrack, int iRow ) const { return m_TapNotes[iTrack].lower_bound( iRow ); } - void swap( NoteData &nd ) { m_TapNotes.swap( nd.m_TapNotes ); } inline iterator FindTapNote( unsigned iTrack, int iRow ) { return m_TapNotes[iTrack].find( iRow ); } inline const_iterator FindTapNote( unsigned iTrack, int iRow ) const { return m_TapNotes[iTrack].find( iRow ); } @@ -101,6 +125,14 @@ public: { return all_tracks_const_iterator( *this, iStartRow, iEndRow, cond ); } + all_tracks_reverse_iterator GetTapNoteRangeAllTracksReverse( int iStartRow, int iEndRow, IteratorCond cond = NULL ) + { + return all_tracks_reverse_iterator( *this, iStartRow, iEndRow, cond ); + } + all_tracks_const_reverse_iterator GetTapNoteRangeAllTracksReverse( int iStartRow, int iEndRow, IteratorCond cond = NULL) const + { + return all_tracks_const_reverse_iterator( *this, iStartRow, iEndRow, cond ); + } /* Return an iterator range include iStartRow to iEndRow. Extend the range to include diff --git a/stepmania/src/NoteDataWithScoring.cpp b/stepmania/src/NoteDataWithScoring.cpp index f731993985..be69627f83 100644 --- a/stepmania/src/NoteDataWithScoring.cpp +++ b/stepmania/src/NoteDataWithScoring.cpp @@ -68,7 +68,7 @@ int GetSuccessfulMines( const NoteData &in, int iStartIndex = 0, int iEndIndex = int iNumSuccessfulMinesNotes = 0; NoteData::all_tracks_const_iterator iter = in.GetTapNoteRangeAllTracks( iStartIndex, iEndIndex, AvoidedMines ); for( ; !iter.IsAtEnd(); ++iter ) - ++iNumSuccessfulMinesNotes; + iNumSuccessfulMinesNotes++; return iNumSuccessfulMinesNotes; }