00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00032 public:
00033
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
00065
00066 explicit List(FSizeType limit)
00067 : s_(), sumLength_( 0 ), upperLimit_( limit )
00068 { }
00069
00070
00071
00072
00073
00074
00075
00076
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
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
00093 void clear()
00094 {
00095 s_.clear();
00096 sumLength_ = 0;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 FSizeType insert(const FragmentType& insertFragment);
00109
00110
00111
00112
00113
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
00122
00123
00124
00125 FSizeType insert(Iterator where, const FragmentType& insertFragment);
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 FSizeType erase(const FragmentType& eraseFragment);
00138
00139
00140
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
00149
00150
00151
00152
00153 void erase(Iterator where)
00154 {
00155 sumLength_ -= where->length();
00156 s_.erase( where );
00157 }
00158
00159
00160 void swap(List& rhs)
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
00218
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
00240 private:
00241 ContainerType s_;
00242 FSizeType sumLength_;
00243 FSizeType upperLimit_;
00244 };
00245
00246
00247
00248
00249 template< class ListType >
00250 ListType inverse(const ListType& src);
00251
00252
00253
00254
00255
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
00262
00263
00264
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
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 }
00287
00289
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
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
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
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 }
00515
00516 #endif // #ifndef FILEFRAGMENTS_LIST_HPP_INCLUDED