Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

List.hpp

Go to the documentation of this file.
00001 //
00002 // FileFragments/List.hpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #ifndef FILEFRAGMENTS_LIST_HPP_INCLUDED
00023 #define FILEFRAGMENTS_LIST_HPP_INCLUDED
00024 
00025 namespace detail
00026 {
00027 
00028 template< class FragmentT, class ContainerT >
00029 class List
00030 {
00031 // Interface
00032 public:
00033     // Typedefs
00034     typedef FragmentT FragmentType;
00035     typedef ContainerT ContainerType;
00036     typedef typename FragmentType::SizeType FSizeType;
00037     typedef typename FragmentType::PayloadType PayloadType;
00038     typedef typename FragmentType::Traits Traits;
00039     typedef BadRange< FragmentType > BadRangeException;
00040     typedef typename ContainerType::value_type ValueType;
00041     typedef typename ContainerType::pointer Pointer;
00042     typedef typename ContainerType::const_pointer ConstPointer;
00043     typedef typename ContainerType::reference Reference;
00044     typedef typename ContainerType::const_reference ConstReference;
00045     typedef typename ContainerType::iterator Iterator;
00046     typedef typename ContainerType::const_iterator ConstIterator;
00047     typedef typename ContainerType::reverse_iterator ReverseIterator;
00048     typedef typename ContainerType::const_reverse_iterator ConstReverseIterator;
00049     typedef typename ContainerType::size_type SizeType;
00050     typedef typename ContainerType::difference_type DifferenceType;
00051     typedef ValueType value_type;
00052     typedef Pointer pointer;
00053     typedef ConstPointer const_pointer;
00054     typedef Reference reference;
00055     typedef ConstReference const_reference;
00056     typedef Iterator iterator;
00057     typedef ConstIterator const_iterator;
00058     typedef ReverseIterator reverse_iterator;
00059     typedef ConstReverseIterator const_reverse_iterator;
00060     typedef SizeType size_type;
00061     typedef DifferenceType difference_type;
00062     typedef ::std::pair< Iterator, Iterator > IteratorPair;
00063     typedef ::std::pair< ConstIterator, ConstIterator > ConstIteratorPair;
00064     // Constructor
00065     // Creates new list, that accepts fragments in the range 0..limit
00066     explicit List(FSizeType limit)
00067     : s_(), sumLength_( 0 ), upperLimit_( limit )
00068     { }
00069     // Copy constructor
00070         // Use implicit version
00071     // Destructor
00072         // Use implicit version        // We don't inherit from this class
00073     // Assignment
00074         // Use implicit version
00075 
00076     // Iterators
00077     Iterator begin() { return s_.begin(); }
00078     ConstIterator begin() const { return s_.begin(); }
00079     Iterator end() { return s_.end(); }
00080     ConstIterator end() const { return s_.end(); }
00081     ReverseIterator rbegin() { return s_.rbegin(); }
00082     ConstReverseIterator rbegin() const { return s_.rbegin(); }
00083     ReverseIterator rend() { return s_.rend(); }
00084     ConstReverseIterator rend() const { return s_.rend(); }
00085 
00086     // Accessors
00087     SizeType size() const { return s_.size(); }
00088     FSizeType limit() const { return upperLimit_; }
00089     FSizeType sumLength() const { return sumLength_; }
00090     FSizeType missing() const { return limit() - sumLength(); }
00091     bool empty() const { return s_.size() == 0; }
00092     // Operations
00093     void clear()
00094     {
00095         s_.clear();
00096         sumLength_ = 0;
00097     }
00098     // @insert  Inserts a fragment into the container. Because of the automatic
00099     //          sorting and merging guarantied by the container, this might
00100     //          not insert the full range indicated by the fragment in cases
00101     //          when parts of the range of the fragment are already present.
00102     //          Attempting to insert an empty fragment ( Length() == 0 ) is
00103     //          possible ( if the fragment is constructible in the first place )
00104     //          but does nothing.
00105     // @return  Returns the length of the range that has been inserted.
00106     //          Effectively it reflects the change of sumLength().
00107     // @complexity   ~O( log( n ) )
00108     FSizeType insert(const FragmentType& insertFragment);
00109     // @insert  Inserts a sequence of fragments. An optimized version should be
00110     //          written if 2 large containers have to be merged often.
00111     //          It is an error to insert a sequence which is part of the
00112     //          list. Doing so results in undefined behaviour.
00113     // @complexity   ~O( n_insert * log( n ) )
00114         template< typename InputIterator >            
00115     FSizeType insert(InputIterator first, InputIterator last)
00116     {
00117         FSizeType oldSum = sumLength();
00118         for( ; first != last; ) insert( *first++ );
00119         return sumLength() - oldSum;
00120     }
00121     // @insert  Inserts a fragment using an iterator as hint. Insertion is done
00122     //          in constant time, if no merging occurs and the element can be
00123     //          inserted before the hint. Otherwise normal insertion occurs.
00124     // @complexity   ~O( 1 ) or ~O( log( n ) )
00125     FSizeType insert(Iterator where, const FragmentType& insertFragment);
00126     // @erase   Deletes a fragment from the container. Because of the automatic
00127     //          sorting and merging guarantied by the container, this might
00128     //          not delete the full range indicated by the fragment, in cases
00129     //          when parts of the range of the fragment are not present.
00130     //          Attempting to delete an empty fragment ( Length() == 0 ) is
00131     //          possible but does nothing.
00132     // @return  Returns the length of the range that has been deleted.
00133     //          Effectively it reflects the change of sumLength().
00134     //          Note that this differs from the standard containers interface
00135     //          which usually returns a size_type for this kind of funtion,
00136     //          which indictaes the number of elements being erased.
00137     FSizeType erase(const FragmentType& eraseFragment);
00138     // @erase   Deletes a sequence of fragments from the container. That
00139     //          sequence need not be part of the list. If it is, use a loop
00140     //          over the next function instead, if speed is important.
00141     template< typename InputIterator >
00142     FSizeType erase(InputIterator first, InputIterator last)
00143     {
00144         FSizeType oldSum = sumLength();
00145         for( ; first != last; ) erase( *first++ );
00146         return oldSum - sumLength();
00147     }
00148     // @erase   This deletes the fragment the argument points to.
00149     //          Iterators that point to other fragments remain valid.
00150     // @return  Returns iterator that points to the next fragment after the one
00151     //          pointed to by the argument.
00152     // @complexity   ~O( log( n ) )
00153     void erase(Iterator where)
00154     {
00155         sumLength_ -= where->length();
00156         s_.erase( where );
00157     }
00158     // @swap    Swaps two lists.
00159     // @complexity   ~O( 1 )
00160     void swap(List& rhs)                    // throw ()
00161     {
00162         s_.swap( rhs.s_ );
00163         ::std::swap( sumLength_, rhs.sumLength_ );
00164         ::std::swap( upperLimit_, rhs.upperLimit_ );
00165     }
00166 
00167     Iterator lowerBound(const FragmentType& match)
00168     {
00169         return s_.lower_bound( match );
00170     }
00171     ConstIterator lowerBound(const FragmentType& match) const
00172     {
00173         return s_.lower_bound( match );
00174     }
00175     Iterator upperBound(const FragmentType& match)
00176     {
00177         return s_.upper_bound( match );
00178     }
00179     ConstIterator upperBound(const FragmentType& match) const
00180     {
00181         return s_.upper_bound( match );
00182     }
00183     IteratorPair equalRange(const FragmentType& match)
00184     {
00185         return s_.equal_range( match );
00186     }
00187     ConstIteratorPair equalRange(const FragmentType& match) const
00188     {
00189         return s_.equal_range( match );
00190     }
00191 
00192     Iterator lower_bound(const FragmentType& match)
00193     {
00194         return lowerBound( match );
00195     }
00196     ConstIterator lower_bound(const FragmentType& match) const
00197     {
00198         return lowerBound( match );
00199     }
00200     Iterator upper_bound(const FragmentType& match)
00201     {
00202         return upperBound( match );
00203     }
00204     ConstIterator upper_bound(const FragmentType& match) const
00205     {
00206         return upperBound( match );
00207     }
00208     IteratorPair equal_range(const FragmentType& match)
00209     {
00210         return equalRange( match );
00211     }
00212     ConstIteratorPair equal_range(const FragmentType& match) const
00213     {
00214         return equalRange( match );
00215     }
00216 
00217     // same as equalRange, except that fragments that are adjacent
00218     // to the argument are not part of the result
00219     IteratorPair overlappingRange(const FragmentType& match)
00220     {
00221         IteratorPair result( equalRange( match ) );
00222         if( result.first != result.second )
00223         {
00224             if( result.first->end() == match.begin() ) ++result.first;
00225             if( ( --result.second )->begin() != match.end() ) ++result.second;
00226         }
00227         return result;
00228     }
00229     ConstIteratorPair overlappingRange(const FragmentType& match) const
00230     {
00231         ConstIteratorPair result( equalRange( match ) );
00232         if( result.first != result.second )
00233         {
00234             if( result.first->end() == match.begin() ) ++result.first;
00235             if( ( --result.second )->begin() != match.end() ) ++result.second;
00236         }
00237         return result;
00238     }
00239 // Implementation
00240 private:
00241     ContainerType s_;
00242     FSizeType sumLength_;
00243     FSizeType upperLimit_;
00244 };
00245 
00246 // @inverse returns a list containing each range out of the base range 0..limit
00247 //          that is not part of the sourcelist
00248 // @complexity   ~O( n * log( n ) )
00249 template< class ListType >
00250 ListType inverse(const ListType& src);
00251 
00252 // @largestFragment
00253 //          Returns iterator to the first largest fragment in a list, or
00254 //          end() iterator if list is empty.
00255 // @complexity   ~O( n )
00256 template< class ListType >
00257 typename ListType::Iterator largestFragment(ListType& src);
00258 template< class ListType >
00259 typename ListType::ConstIterator largestFragment(const ListType& src);
00260 
00261 // @randomFragment
00262 //          Returns iterator to the random fragment in a list, or
00263 //          end() iterator if list is empty.
00264 // @complexity   ~O( n )
00265 template< class ListType >
00266 typename ListType::Iterator randomFragment(ListType& src);
00267 template< class ListType >
00268 typename ListType::ConstIterator randomFragment(const ListType& src);
00269 
00270 template< class ListType >
00271 bool hasPosition(const ListType& src, typename ListType::FSizeType pos);
00272 
00273 // returns if argument overlaps with any fragment in the list
00274 template< class ListType >
00275 bool overlaps(const ListType& src,
00276     const typename ListType::FragmentType& match);
00277 
00278 template< class ListType >
00279 bool overlaps(const ListType& src, const ListType& match);
00280 
00281 template< class ListType >
00282 typename ListType::FSizeType
00283 overlappingSum(const ListType& src,
00284     const typename ListType::FragmentType& match);
00285 
00286 } // namespace detail
00287 
00289 // Implementation
00291 
00292 namespace detail
00293 {
00294 
00295 template< class FragmentT, class ContainerT >
00296 inline typename List< FragmentT, ContainerT >::FSizeType
00297 List< FragmentT, ContainerT >::insert(
00298     const typename List< FragmentT, ContainerT >::FragmentType& insertFragment)
00299 {
00300     if( insertFragment.end() > limit() )
00301     {
00302 //        throw BadRangeException( insertFragment, limit() );
00303         CString errorMsg;
00304         errorMsg.Format(
00305             _T( "FF::SimpleFragmentList - invalid arg for insert - " )
00306             _T( "List - size: %u - limit: %I64u - sum: %I64u - " )
00307             _T( "Fragment - begin: %I64u - end: %I64u" ), size(), limit(), sumLength(),
00308             insertFragment.begin(), insertFragment.end() );
00309         theApp.Message( MSG_ERROR, errorMsg );
00310         return 0;
00311     }
00312     if( insertFragment.length() == 0 ) return 0;
00313     ::std::pair< Iterator, Iterator > insertRange =
00314         equalRange( insertFragment );
00315     if( insertRange.first != insertRange.second )
00316     {
00317         FSizeType chgSum =
00318             Traits::mergeAndReplace( s_, insertRange, insertFragment );
00319         sumLength_ += chgSum;
00320         return chgSum;
00321     }
00322     else
00323     {
00324         s_.insert( insertRange.second, insertFragment );
00325         sumLength_ += insertFragment.length();
00326         return insertFragment.length();
00327     }
00328 }
00329 
00330 template< class FragmentT, class ContainerT >
00331 inline typename List< FragmentT, ContainerT >::FSizeType
00332 List< FragmentT, ContainerT >::insert(
00333     typename List< FragmentT, ContainerT >::Iterator where,
00334     const typename List< FragmentT, ContainerT >::FragmentType& insertFragment)
00335 {
00336     Iterator tmp = where;
00337     CompareFragments< FragmentType > cmp;
00338     if( ( where == begin() || cmp( *--tmp, insertFragment ) )
00339         && ( where == end() || cmp( insertFragment, *where ) ) )
00340     {
00341         s_.insert( where, insertFragment );
00342         sumLength_ += insertFragment.length();
00343         return insertFragment.length();
00344     }
00345     else
00346     {
00347         return insert( insertFragment );
00348     }
00349 }
00350 
00351 template< class FragmentT, class ContainerT >
00352 inline typename List< FragmentT, ContainerT >::FSizeType
00353 List< FragmentT, ContainerT >::erase(
00354     const typename List< FragmentT, ContainerT >::FragmentType& eraseFragment)
00355 {
00356     if( eraseFragment.end() > limit() )
00357     {
00358 //        throw BadRangeException( eraseFragment, limit() );
00359         CString errorMsg;
00360         errorMsg.Format(
00361             _T( "FF::SimpleFragmentList - invalid arg for erase - " )
00362             _T( "List - size: %u - limit: %I64u - sum: %I64u - " )
00363             _T( "Fragment - begin: %I64i - end: %I64u" ), size(), limit(), sumLength(),
00364             eraseFragment.begin(), eraseFragment.end() );
00365         theApp.Message( MSG_ERROR, errorMsg );
00366         return 0;
00367     }
00368     if( eraseFragment.length() == 0 ) return 0;
00369     ::std::pair< Iterator, Iterator > eraseRange =
00370         overlappingRange( eraseFragment );
00371     if( eraseRange.first == eraseRange.second ) return 0;
00372     const FragmentType& frontFragment
00373         = eraseRange.first->begin() < eraseFragment.begin()
00374             ? FragmentType( *eraseRange.first,
00375                  eraseRange.first->begin(), eraseFragment.begin() )
00376             : FragmentType( *eraseRange.first, 0,
00377                 ::std::numeric_limits< FSizeType >::max() );
00378     --eraseRange.second;
00379     const FragmentType& backFragment
00380         = eraseRange.second->end() > eraseFragment.end()
00381         ? FragmentType( *eraseRange.second,
00382                 eraseFragment.end(), eraseRange.second->end() )
00383         : FragmentType( *eraseRange.second, 0,
00384                 ::std::numeric_limits< FSizeType >::max() );
00385     const FSizeType oldSum = sumLength();
00386     ++eraseRange.second;
00387     for( ; eraseRange.first != eraseRange.second; )
00388     {
00389         sumLength_ -= eraseRange.first->length();
00390         s_.erase( eraseRange.first++ );
00391     }
00392     if( frontFragment.end() < ::std::numeric_limits< FSizeType >::max() )
00393     {
00394         s_.insert( eraseRange.second, frontFragment );
00395         sumLength_ += frontFragment.length();
00396     }
00397     if( backFragment.end() < ::std::numeric_limits< FSizeType >::max() )
00398     {
00399         s_.insert( eraseRange.second, backFragment );
00400         sumLength_ += backFragment.length();
00401     }
00402     return oldSum - sumLength();
00403 }
00404 
00405 template< class ListType >
00406 inline ListType inverse(const ListType& src)
00407 {
00408     typedef typename ListType::FragmentType FragmentType;
00409     typedef typename ListType::PayloadType PayloadType;
00410     ListType result( src.limit() );
00411     typename ListType::FSizeType last = 0;
00412     for( typename ListType::ConstIterator i = src.begin(); i != src.end();
00413         ++i )
00414     {
00415         if( last < i->begin() )
00416         {
00417             result.insert( FragmentType( last, i->begin(),
00418                 PayloadType() ) );
00419         }
00420         last = i->end();
00421     }
00422     if( last < src.limit() )
00423     {
00424         result.insert( FragmentType( last, src.limit(), PayloadType() ) );
00425     }
00426     return result;
00427 }
00428 
00429 template< class ListType >
00430 inline typename ListType::Iterator largestFragment(ListType& src)
00431 {
00432     typedef typename ListType::Iterator Iterator;
00433     Iterator result = src.begin();
00434     for( Iterator i = result; i != src.end(); ++i )
00435         if( result->length() < i->length() ) result = i;
00436     return result;
00437 }
00438 template< class ListType >
00439 inline typename ListType::ConstIterator largestFragment(const ListType& src)
00440 {
00441     typedef typename ListType::ConstIterator ConstIterator;
00442     ConstIterator result = src.begin();
00443     for( ConstIterator i = result; i != src.end(); ++i )
00444         if( result->length() < i->length() ) result = i;
00445     return result;
00446 }
00447 
00448 template< class ListType >
00449 inline typename ListType::Iterator randomFragment(ListType& src)
00450 {
00451     if( src.empty() ) return src.end();
00452     typename ListType::Iterator result = src.begin();
00453     ::std::advance( result, ::std::rand() % src.size() );
00454     return result;
00455 }
00456 template< class ListType >
00457 inline typename ListType::Iterator randomFragment(const ListType& src)
00458 {
00459     if( src.empty() ) return src.end();
00460     typename ListType::ConstIterator result = src.begin();
00461     ::std::advance( result, ::std::rand() % src.size() );
00462     return result;
00463 }
00464 
00465 template< class ListType >
00466 bool hasPosition(const ListType& src, typename ListType::FSizeType pos)
00467 {
00468     typename ListType::ConstIteratorPair match = src.overlappingRange(
00469         typename ListType::FragmentType( pos, pos + 1,
00470         typename ListType::PayloadType() ) );
00471     return match.first != match.second;
00472 }
00473 
00474 template< class ListType >
00475 bool overlaps(const ListType& src,
00476     const typename ListType::FragmentType& match)
00477 {
00478     typename ListType::ConstIteratorPair matchPair
00479         = src.overlappingRange( match );
00480     return matchPair.first != matchPair.second;
00481 }    
00482 
00483 // ToDo: tweak for src.size() < match.size() and src.size ~== match.size()
00484 template< class ListType >
00485 bool overlaps(const ListType& src, const ListType& match)
00486 {
00487     for( typename ListType::ConstIterator matchIterator = match.begin();
00488         matchIterator != match.end(); ++matchIterator )
00489     {
00490         typename ListType::ConstIteratorPair matchPair
00491             = src.overlappingRange( *matchIterator );
00492         if( matchPair.first != matchPair.second ) return true;
00493     }
00494     return false;
00495 }
00496 
00497 template< class ListType >
00498 typename ListType::FSizeType
00499 overlappingSum(const ListType& src,
00500     const typename ListType::FragmentType& match)
00501 {
00502     typename ListType::ConstIteratorPair matchIterators
00503         = src.overlappingRange( match );
00504     typename ListType::FSizeType result = 0;
00505     for( ; matchIterators.first != matchIterators.second;
00506         ++matchIterators.first )
00507     {
00508         result += ::std::min( matchIterators.first->end(), match.end() )
00509             -  ::std::max( matchIterators.first->begin(), match.begin() );
00510     }
00511     return result;
00512 }    
00513 
00514 } // namespace detail
00515 
00516 #endif // #ifndef FILEFRAGMENTS_LIST_HPP_INCLUDED

Generated on Thu Dec 15 10:39:42 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2