00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FILEFRAGMENTS_COMPATIBILITY_HPP_INCLUDED
00023 #define FILEFRAGMENTS_COMPATIBILITY_HPP_INCLUDED
00024
00025 namespace detail
00026 {
00027
00028
00029
00030
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
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
00066
00067 if ( !available || available[ blockEnd ] )
00068 {
00069 return FragmentType( blockEnd * blockSize,
00070 selectIterator->end() );
00071 }
00072 --blockEnd;
00073 }
00074
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
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
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
00182 if( in.sumLength() != nRemaining ) AfxThrowArchiveException( CArchiveException::generic );
00183 }
00184 catch( Exception& )
00185 {
00186 AfxThrowArchiveException( CArchiveException::generic );
00187 }
00188 }
00189
00190 }
00191
00192
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 }
00234
00235 #endif // #ifndef FILEFRAGMENTS_COMPATIBILITY_HPP_INCLUDED