00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef AKONADI_ITEM_P_H
00021 #define AKONADI_ITEM_P_H
00022
00023 #include <QtCore/QDateTime>
00024 #include <QtCore/QMap>
00025 #include <QtCore/QVarLengthArray>
00026
00027 #include "entity_p.h"
00028 #include "itempayloadinternals_p.h"
00029
00030 #include <boost/bind.hpp>
00031
00032 #include <memory>
00033 #include <algorithm>
00034 #include <cassert>
00035 #include <vector>
00036
00037 namespace Akonadi {
00038
00039 namespace _detail {
00040
00041 template <typename T>
00042 class clone_ptr {
00043 T * t;
00044 public:
00045 clone_ptr() : t( 0 ) {}
00046 explicit clone_ptr( T * t ) : t( t ) {}
00047 clone_ptr( const clone_ptr & other ) : t ( other.t ? other.t->clone() : 0 ) {}
00048 ~clone_ptr() { delete t; }
00049 clone_ptr & operator=( const clone_ptr & other ) {
00050 if ( this != &other ) {
00051 clone_ptr copy( other );
00052 swap( copy );
00053 }
00054 return *this;
00055 }
00056 void swap( clone_ptr & other ) {
00057 using std::swap;
00058 swap( t, other.t );
00059 }
00060 T * operator->() const { return get(); }
00061 T & operator*() const { assert( get() != 0 ); return *get(); }
00062 T * get() const { return t; }
00063 T * release() { T * const r = t; t = 0; return r; }
00064 void reset( T * other=0 ) { delete t; t = other; }
00065
00066 private:
00067 struct _save_bool { void f() {}; };
00068 typedef void (_save_bool::*save_bool)();
00069 public:
00070 operator save_bool () const { return get() ? &_save_bool::f : 0 ; }
00071 };
00072
00073 template <typename T>
00074 inline void swap( clone_ptr<T> & lhs, clone_ptr<T> & rhs ) {
00075 lhs.swap( rhs );
00076 }
00077
00078 template <typename T, size_t N>
00079 class VarLengthArray {
00080 QVarLengthArray<T,N> impl;
00081 public:
00082 typedef T value_type;
00083 typedef T* iterator;
00084 typedef const T* const_iterator;
00085 typedef T* pointer;
00086 typedef const T* const_pointer;
00087 typedef T & reference;
00088 typedef const T & const_reference;
00089
00090 explicit VarLengthArray( int size=0 ) : impl( size ) {}
00091
00092
00093
00094 void push_back( const T & t ) { impl.append( t ); }
00095 int capacity() const { return impl.capacity(); }
00096 void clear() { impl.clear(); }
00097 size_t size() const { return impl.count(); }
00098 bool empty() const { return impl.isEmpty(); }
00099 void pop_back() { return impl.removeLast(); }
00100 void reserve( size_t n ) { impl.reserve( n ); }
00101 void resize( size_t n ) { impl.resize( n ); }
00102
00103 iterator begin() { return impl.data(); }
00104 iterator end() { return impl.data() + impl.size(); }
00105 const_iterator begin() const { return impl.data(); }
00106 const_iterator end() const { return impl.data() + impl.size(); }
00107 const_iterator cbegin() const { return begin(); }
00108 const_iterator cend() const { return end(); }
00109
00110 reference front() { return *impl.data(); }
00111 reference back() { return *(impl.data()+impl.size()); }
00112 const_reference front() const { return *impl.data(); }
00113 const_reference back() const { return *(impl.data()+impl.size()); }
00114
00115 reference operator[]( size_t n ) { return impl[n]; }
00116 const_reference operator[]( size_t n ) const { return impl[n]; }
00117 };
00118
00119 struct TypedPayload {
00120 clone_ptr<PayloadBase> payload;
00121 int sharedPointerId;
00122 int metaTypeId;
00123 };
00124
00125 struct BySharedPointerAndMetaTypeID : std::unary_function<TypedPayload,bool> {
00126 const int spid;
00127 const int mtid;
00128 BySharedPointerAndMetaTypeID( int spid, int mtid ) : spid( spid ), mtid( mtid ) {}
00129 bool operator()( const TypedPayload & tp ) const {
00130 return ( mtid == -1 || mtid == tp.metaTypeId )
00131 && ( spid == -1 || spid == tp.sharedPointerId ) ;
00132 }
00133 };
00134
00135 }
00136
00137 }
00138
00139 namespace std {
00140 template <>
00141 inline void swap<Akonadi::_detail::TypedPayload>( Akonadi::_detail::TypedPayload & lhs, Akonadi::_detail::TypedPayload & rhs ) {
00142 lhs.payload.swap( rhs.payload );
00143 swap( lhs.sharedPointerId, rhs.sharedPointerId );
00144 swap( lhs.metaTypeId, rhs.metaTypeId );
00145 }
00146 }
00147
00148 namespace Akonadi {
00149
00150 typedef std::vector<_detail::TypedPayload> PayloadContainer;
00151 }
00152
00153
00154 template <>
00155 class QForeachContainer<Akonadi::PayloadContainer> {};
00156
00157 namespace Akonadi {
00158
00159
00163 class ItemPrivate : public EntityPrivate
00164 {
00165 public:
00166 ItemPrivate( Item::Id id = -1 )
00167 : EntityPrivate( id ),
00168 mLegacyPayload(),
00169 mPayloads(),
00170 mConversionInProgress( false ),
00171 mRevision( -1 ),
00172 mCollectionId( -1 ),
00173 mSize( 0 ),
00174 mModificationTime(),
00175 mFlagsOverwritten( false ),
00176 mSizeChanged( false ),
00177 mClearPayload( false )
00178 {
00179 }
00180
00181 #if 0
00182 ItemPrivate( const ItemPrivate &other )
00183 : EntityPrivate( other )
00184 {
00185 mFlags = other.mFlags;
00186 mRevision = other.mRevision;
00187 mSize = other.mSize;
00188 mModificationTime = other.mModificationTime;
00189 mMimeType = other.mMimeType;
00190 mLegacyPayload = other.mLegacyPayload;
00191 mPayloads = other.mPayloads;
00192 mConversionInProgress = false;
00193 mAddedFlags = other.mAddedFlags;
00194 mDeletedFlags = other.mDeletedFlags;
00195 mFlagsOverwritten = other.mFlagsOverwritten;
00196 mSizeChanged = other.mSizeChanged;
00197 mCollectionId = other.mCollectionId;
00198 mClearPayload = other.mClearPayload;
00199 }
00200 #endif
00201
00202 ~ItemPrivate()
00203 {
00204 }
00205
00206 void resetChangeLog()
00207 {
00208 mFlagsOverwritten = false;
00209 mAddedFlags.clear();
00210 mDeletedFlags.clear();
00211 mSizeChanged = false;
00212 }
00213
00214 EntityPrivate *clone() const
00215 {
00216 return new ItemPrivate( *this );
00217 }
00218
00219 bool hasMetaTypeId( int mtid ) const {
00220 return std::find_if( mPayloads.begin(), mPayloads.end(),
00221 _detail::BySharedPointerAndMetaTypeID( -1, mtid ) )
00222 != mPayloads.end();
00223 }
00224
00225 PayloadBase * payloadBaseImpl( int spid, int mtid ) const {
00226 const PayloadContainer::const_iterator it
00227 = std::find_if( mPayloads.begin(), mPayloads.end(),
00228 _detail::BySharedPointerAndMetaTypeID( spid, mtid ) );
00229 return it == mPayloads.end() ? 0 : it->payload.get() ;
00230 }
00231
00232 bool movePayloadFrom( ItemPrivate * other, int mtid ) const {
00233 assert( other );
00234 const size_t oldSize = mPayloads.size();
00235 PayloadContainer & oPayloads = other->mPayloads;
00236 const _detail::BySharedPointerAndMetaTypeID matcher( -1, mtid );
00237 const size_t numMatching
00238 = std::count_if( oPayloads.begin(), oPayloads.end(), matcher );
00239 mPayloads.resize( oldSize + numMatching );
00240 using namespace std;
00241 for ( PayloadContainer::iterator
00242 dst = mPayloads.begin() + oldSize,
00243 src = oPayloads.begin(), end = oPayloads.end() ; src != end ; ++src )
00244 if ( matcher( *src ) ) {
00245 swap( *dst, *src );
00246 ++dst;
00247 }
00248 return numMatching > 0 ;
00249 }
00250
00251 #if 0
00252 std::auto_ptr<PayloadBase> takePayloadBaseImpl( int spid, int mtid ) {
00253 PayloadContainer::iterator it
00254 = std::find_if( mPayloads.begin(), mPayloads.end(),
00255 _detail::BySharedPointerAndMetaTypeID( spid, mtid ) );
00256 if ( it == mPayloads.end() )
00257 return std::auto_ptr<PayloadBase>();
00258 std::rotate( it, it + 1, mPayloads.end() );
00259 std::auto_ptr<PayloadBase> result( it->payload.release() );
00260 mPayloads.pop_back();
00261 return result;
00262 }
00263 #endif
00264
00265 void setPayloadBaseImpl( int spid, int mtid, std::auto_ptr<PayloadBase> p, bool add ) const {
00266
00267 if ( !add )
00268 mLegacyPayload.reset();
00269
00270 if ( !p.get() ) {
00271 if ( !add )
00272 mPayloads.clear();
00273 return;
00274 }
00275
00276
00277
00278 mPayloads.resize( add ? mPayloads.size() + 1 : 1 );
00279 _detail::TypedPayload & tp = mPayloads.back();
00280 tp.payload.reset( p.release() );
00281 tp.sharedPointerId = spid;
00282 tp.metaTypeId = mtid;
00283 }
00284
00285 void setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p );
00286 void tryEnsureLegacyPayload() const;
00287
00288 mutable _detail::clone_ptr<PayloadBase> mLegacyPayload;
00289 mutable PayloadContainer mPayloads;
00290 mutable bool mConversionInProgress;
00291 Item::Flags mFlags;
00292 int mRevision;
00293 Entity::Id mCollectionId;
00294 qint64 mSize;
00295 QDateTime mModificationTime;
00296 QString mMimeType;
00297 Item::Flags mAddedFlags;
00298 Item::Flags mDeletedFlags;
00299 bool mFlagsOverwritten : 1;
00300 bool mSizeChanged : 1;
00301 bool mClearPayload : 1;
00302 };
00303
00304 }
00305
00306 #endif
00307