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

Compatibility.hpp

Go to the documentation of this file.
00001 //
00002 // FileFragments/Compatibility.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_COMPATIBILITY_HPP_INCLUDED
00023 #define FILEFRAGMENTS_COMPATIBILITY_HPP_INCLUDED
00024 
00025 namespace detail
00026 {
00027 
00028 // move to a common (private) base/mixin for block transfer (BT/ED2K)
00029 // selects an available block, either unaligned blocks or if none is available
00030 // a random aligned block
00031 template< class ListType, class AvailableType >
00032 typename ListType::FragmentType
00033 selectBlock(const ListType& src, typename ListType::FSizeType blockSize,
00034     const AvailableType* available )
00035 {
00036     typedef typename ListType::FragmentType FragmentType;
00037     typedef typename ListType::FSizeType FSizeType;
00038     typedef typename ListType::ConstIterator ConstIterator;
00039     
00040     if( src.empty() ) return FragmentType( 0,
00041         ::std::numeric_limits< FSizeType >::max() );
00042 
00043     ::std::deque< FSizeType > blocks;
00044 
00045     for( ConstIterator selectIterator = src.begin();
00046         selectIterator != src.end(); ++selectIterator )
00047     {
00048         FSizeType blockBegin = selectIterator->begin() / blockSize;
00049         FSizeType blockEnd = ( selectIterator->end() - 1 ) / blockSize;
00050                 if ( selectIterator->begin() % blockSize )
00051                 {
00052                         // the start of a block is complete, but part is missing
00053                         
00054                         if ( !available || available[ blockBegin ] )
00055                         {
00056                 return FragmentType( selectIterator->begin(),
00057                     ::std::min( selectIterator->end(),
00058                     blockSize * ( blockBegin + 1 ) ) );
00059                         }
00060             ++blockBegin;
00061                 }
00062                 if ( blockBegin <= blockEnd && selectIterator->end() % blockSize
00063             && selectIterator->end() < src.limit() )
00064                 {
00065                         // the end of a block is complete, but part is missing
00066                         
00067                         if ( !available || available[ blockEnd ] )
00068                         {
00069                 return FragmentType( blockEnd * blockSize,
00070                     selectIterator->end() );
00071                         }
00072             --blockEnd;
00073                 }
00074                 // this fragment contains one or more aligned empty blocks
00075         if( blockEnd != ~0ULL ) for( ; blockBegin <= blockEnd; ++blockBegin )
00076         {
00077             if( !available || available[ blockBegin ] )
00078             {
00079                 blocks.push_back( blockBegin );
00080             }
00081         }
00082         }
00083         
00084     if( blocks.empty() )  return FragmentType( 0,
00085         ::std::numeric_limits< FSizeType >::max() );
00086 
00087     FSizeType blockBegin = blocks[ ::std::rand() % blocks.size() ] * blockSize;
00088 
00089     return FragmentType( blockBegin, ::std::min( blockBegin + blockSize, src.limit() ) );
00090 }
00091 
00092 inline void SerializeOut(CArchive& ar, const SimpleFragment& out)
00093 {
00094     ar << out.begin();
00095     ar << out.length();
00096 }
00097 
00098 inline SimpleFragment SerializeIn(CArchive& ar, int version)
00099 {
00100     try
00101     {
00102         if ( version >= 29 )
00103         {
00104             u64 begin, length;
00105             ar >> begin >> length;
00106                         if ( begin + length < begin ) AfxThrowArchiveException( CArchiveException::generic );
00107             return SimpleFragment( begin, begin + length );
00108         }
00109         else
00110         {
00111             u32 begin, length;
00112             ar >> begin >> length;
00113                         if ( begin + length < begin ) AfxThrowArchiveException( CArchiveException::generic );
00114             return SimpleFragment( begin, begin + length );
00115         }
00116     }
00117     catch( Exception& )
00118     {
00119          AfxThrowArchiveException( CArchiveException::generic );
00120     }
00121 }
00122 
00123 // used in FragmentedFile.cpp
00124 inline void SerializeOut1(CArchive& ar, const SimpleFragmentList& out)
00125 {
00126     QWORD nTotal = out.limit();
00127     QWORD nRemaining = out.sumLength();
00128     DWORD nFragments = out.size();
00129     ar << nTotal << nRemaining << nFragments;
00130 
00131     for ( SimpleFragmentList::ConstIterator it = out.begin(); it != out.end();
00132         ++it )
00133     {
00134         SerializeOut( ar, *it );
00135     }
00136 }
00137 
00138 inline void SerializeIn1(CArchive& ar, SimpleFragmentList& in, int version)
00139 {
00140     if( version >= 29 )
00141     {
00142         try
00143         {
00144             QWORD nTotal, nRemaining;
00145             DWORD nFragments;
00146             ar >> nTotal >> nRemaining >> nFragments;
00147             in.swap( SimpleFragmentList( nTotal ) );
00148 
00149             for ( ; nFragments--; )
00150                         {
00151                                 const SimpleFragment& fragment = SerializeIn( ar, version );
00152                                 if ( fragment.end() > nTotal ) AfxThrowArchiveException( CArchiveException::generic );
00153                                 in.insert( in.end(), fragment );
00154                         }
00155 
00156             // Sanity check
00157             if( in.sumLength() != nRemaining ) AfxThrowArchiveException( CArchiveException::generic );
00158         }
00159         catch( Exception& )
00160         {
00161             AfxThrowArchiveException( CArchiveException::generic );
00162         }
00163 
00164     }
00165     else
00166     {
00167         try
00168         {
00169             DWORD nTotal, nRemaining;
00170             DWORD nFragments;
00171             ar >> nTotal >> nRemaining >> nFragments;
00172             in.swap( SimpleFragmentList( nTotal ) );
00173 
00174             for ( ; nFragments--; )
00175                         {
00176                                 const SimpleFragment& fragment = SerializeIn( ar, version );
00177                                 if ( fragment.end() > nTotal ) AfxThrowArchiveException( CArchiveException::generic );
00178                                 in.insert( in.end(), fragment );
00179                         }
00180 
00181             // Sanity check
00182             if( in.sumLength() != nRemaining ) AfxThrowArchiveException( CArchiveException::generic );
00183         }
00184         catch( Exception& ) // translate exception because Shareaza
00185         {                   // doesn't know about this one yet
00186             AfxThrowArchiveException( CArchiveException::generic );
00187         }
00188     }
00189 
00190 }
00191 
00192 // used in DownloadSource.cpp
00193 inline void SerializeOut2(CArchive& ar, const SimpleFragmentList& out)
00194 {
00195     ar.WriteCount( out.size() );
00196 
00197     for ( SimpleFragmentList::ConstIterator it = out.begin(); it != out.end();
00198         ++it )
00199     {
00200         SerializeOut( ar, *it );
00201     }
00202 }
00203 
00204 inline void SerializeIn2(CArchive& ar, SimpleFragmentList& in, int version)
00205 {
00206     try
00207     {
00208         if( version >= 20 )
00209         {
00210             for( int count = ar.ReadCount(); count--; )
00211                         {
00212                                 const SimpleFragment& fragment = SerializeIn( ar, version );
00213                                 if ( fragment.end() > in.limit() ) AfxThrowArchiveException( CArchiveException::generic );
00214                                 in.insert( in.end(), fragment );
00215                         }
00216         }
00217         else if( version >= 5 )
00218         {
00219             while( ar.ReadCount() )
00220                         {
00221                                 const SimpleFragment& fragment = SerializeIn( ar, version );
00222                                 if ( fragment.end() > in.limit() ) AfxThrowArchiveException( CArchiveException::generic );
00223                                 in.insert( in.end(), fragment );
00224                         }
00225         }
00226     }
00227     catch( Exception& )
00228     {
00229         AfxThrowArchiveException( CArchiveException::generic );
00230     }
00231 }
00232 
00233 } // namespace detail
00234 
00235 #endif // #ifndef FILEFRAGMENTS_COMPATIBILITY_HPP_INCLUDED

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