diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/async/imap/MCIMAPAsyncConnection.cc | 41 | ||||
-rw-r--r-- | src/async/imap/MCIMAPAsyncConnection.h | 9 | ||||
-rw-r--r-- | src/async/imap/MCIMAPAsyncSession.cpp | 23 | ||||
-rw-r--r-- | src/async/imap/MCIMAPAsyncSession.h | 8 | ||||
-rw-r--r-- | src/async/imap/MCIMAPFetchMessagesOperation.cc | 37 | ||||
-rw-r--r-- | src/async/imap/MCIMAPFetchMessagesOperation.h | 7 | ||||
-rw-r--r-- | src/core/basetypes/MCAssert.cc | 2 | ||||
-rw-r--r-- | src/core/basetypes/MCIndexSet.cpp | 223 | ||||
-rw-r--r-- | src/core/basetypes/MCIndexSet.h | 15 | ||||
-rw-r--r-- | src/core/basetypes/MCRange.cc | 128 | ||||
-rw-r--r-- | src/core/basetypes/MCRange.h | 12 | ||||
-rw-r--r-- | src/core/basetypes/MCString.cc | 2 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.cc | 80 | ||||
-rw-r--r-- | src/core/imap/MCIMAPSession.h | 26 |
14 files changed, 538 insertions, 75 deletions
diff --git a/src/async/imap/MCIMAPAsyncConnection.cc b/src/async/imap/MCIMAPAsyncConnection.cc index 18922f37..1c82d07a 100644 --- a/src/async/imap/MCIMAPAsyncConnection.cc +++ b/src/async/imap/MCIMAPAsyncConnection.cc @@ -265,6 +265,7 @@ IMAPOperation * IMAPAsyncConnection::expungeOperation(String * folder) return op; } +#if 0 IMAPFetchMessagesOperation * IMAPAsyncConnection::fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID) { @@ -345,6 +346,46 @@ IMAPFetchMessagesOperation * IMAPAsyncConnection::syncMessagesByUIDForModSeqOper op->autorelease(); return op; } +#endif + +IMAPFetchMessagesOperation * IMAPAsyncConnection::fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes) +{ + IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); + op->setSession(this); + op->setFolder(folder); + op->setKind(requestKind); + op->setFetchByUidEnabled(true); + op->setIndexes(indexes); + op->autorelease(); + return op; +} + +IMAPFetchMessagesOperation * IMAPAsyncConnection::fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes) +{ + IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); + op->setSession(this); + op->setFolder(folder); + op->setKind(requestKind); + op->setIndexes(indexes); + op->autorelease(); + return op; +} + +IMAPFetchMessagesOperation * IMAPAsyncConnection::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes, uint64_t modSeq) +{ + IMAPFetchMessagesOperation * op = new IMAPFetchMessagesOperation(); + op->setSession(this); + op->setFolder(folder); + op->setKind(requestKind); + op->setFetchByUidEnabled(true); + op->setIndexes(indexes); + op->setModSequenceValue(modSeq); + op->autorelease(); + return op; +} IMAPFetchContentOperation * IMAPAsyncConnection::fetchMessageByUIDOperation(String * folder, uint32_t uid) { diff --git a/src/async/imap/MCIMAPAsyncConnection.h b/src/async/imap/MCIMAPAsyncConnection.h index 9772b5b3..b791617b 100644 --- a/src/async/imap/MCIMAPAsyncConnection.h +++ b/src/async/imap/MCIMAPAsyncConnection.h @@ -81,6 +81,7 @@ namespace mailcore { virtual IMAPOperation * expungeOperation(String * folder); +#if 0 virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID); virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, @@ -93,6 +94,14 @@ namespace mailcore { uint32_t firstUID, uint32_t lastUID, uint64_t modSeq); virtual IMAPFetchMessagesOperation * syncMessagesByUIDForModSeqOperation(String * folder, IMAPMessagesRequestKind requestKind, Array * uids, uint64_t modSeq); +#endif + virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes); + virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes); + virtual IMAPFetchMessagesOperation * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes, uint64_t modSeq); + virtual IMAPFetchContentOperation * fetchMessageByUIDOperation(String * folder, uint32_t uid); virtual IMAPFetchContentOperation * fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, Encoding encoding); diff --git a/src/async/imap/MCIMAPAsyncSession.cpp b/src/async/imap/MCIMAPAsyncSession.cpp index b2d31b0e..151e9dad 100644 --- a/src/async/imap/MCIMAPAsyncSession.cpp +++ b/src/async/imap/MCIMAPAsyncSession.cpp @@ -333,6 +333,7 @@ IMAPOperation * IMAPAsyncSession::expungeOperation(String * folder) return session->expungeOperation(folder); } +#if 0 IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID) { @@ -374,6 +375,28 @@ IMAPFetchMessagesOperation * IMAPAsyncSession::syncMessagesByUIDForModSeqOperati IMAPAsyncConnection * session = sessionForFolder(folder); return session->syncMessagesByUIDForModSeqOperation(folder, requestKind, uids, modSeq); } +#endif + +IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes) +{ + IMAPAsyncConnection * session = sessionForFolder(folder); + return session->fetchMessagesByUIDOperation(folder, requestKind, indexes); +} + +IMAPFetchMessagesOperation * IMAPAsyncSession::fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes) +{ + IMAPAsyncConnection * session = sessionForFolder(folder); + return session->fetchMessagesByNumberOperation(folder, requestKind, indexes); +} + +IMAPFetchMessagesOperation * IMAPAsyncSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes, uint64_t modSeq) +{ + IMAPAsyncConnection * session = sessionForFolder(folder); + return session->syncMessagesByUID(folder, requestKind, indexes, modSeq); +} IMAPFetchContentOperation * IMAPAsyncSession::fetchMessageByUIDOperation(String * folder, uint32_t uid, bool urgent) { diff --git a/src/async/imap/MCIMAPAsyncSession.h b/src/async/imap/MCIMAPAsyncSession.h index e8d45f6b..1722b2b1 100644 --- a/src/async/imap/MCIMAPAsyncSession.h +++ b/src/async/imap/MCIMAPAsyncSession.h @@ -94,6 +94,7 @@ namespace mailcore { virtual IMAPOperation * expungeOperation(String * folder); +#if 0 virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID); virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, @@ -106,6 +107,13 @@ namespace mailcore { uint32_t firstUID, uint32_t lastUID, uint64_t modSeq); virtual IMAPFetchMessagesOperation * syncMessagesByUIDForModSeqOperation(String * folder, IMAPMessagesRequestKind requestKind, Array * uids, uint64_t modSeq); +#endif + virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes); + virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes); + virtual IMAPFetchMessagesOperation * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes, uint64_t modSeq); virtual IMAPFetchContentOperation * fetchMessageByUIDOperation(String * folder, uint32_t uid, bool urgent = false); virtual IMAPFetchContentOperation * fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, diff --git a/src/async/imap/MCIMAPFetchMessagesOperation.cc b/src/async/imap/MCIMAPFetchMessagesOperation.cc index 21db5219..fcc67be5 100644 --- a/src/async/imap/MCIMAPFetchMessagesOperation.cc +++ b/src/async/imap/MCIMAPFetchMessagesOperation.cc @@ -17,10 +17,13 @@ using namespace mailcore; IMAPFetchMessagesOperation::IMAPFetchMessagesOperation() { mFetchByUidEnabled = false; +#if 0 mFirst = 0; mLast = 0; mUids = NULL; mNumbers = NULL; +#endif + mIndexes = NULL; mMessages = NULL; mVanishedMessages = NULL; mModSequenceValue = 0; @@ -28,8 +31,11 @@ IMAPFetchMessagesOperation::IMAPFetchMessagesOperation() IMAPFetchMessagesOperation::~IMAPFetchMessagesOperation() { +#if 0 MC_SAFE_RELEASE(mNumbers); MC_SAFE_RELEASE(mUids); +#endif + MC_SAFE_RELEASE(mIndexes); MC_SAFE_RELEASE(mMessages); MC_SAFE_RELEASE(mVanishedMessages); } @@ -44,6 +50,7 @@ bool IMAPFetchMessagesOperation::isFetchByUidEnabled() return mFetchByUidEnabled; } +#if 0 void IMAPFetchMessagesOperation::setFirst(uint32_t first) { mFirst = first; @@ -83,6 +90,17 @@ Array * IMAPFetchMessagesOperation::numbers() { return mNumbers; } +#endif + +void IMAPFetchMessagesOperation::setIndexes(IndexSet * indexes) +{ + MC_SAFE_REPLACE_RETAIN(IndexSet, mIndexes, indexes); +} + +IndexSet * IMAPFetchMessagesOperation::indexes() +{ + return mIndexes; +} void IMAPFetchMessagesOperation::setModSequenceValue(uint64_t modseq) { @@ -119,10 +137,11 @@ void IMAPFetchMessagesOperation::main() ErrorCode error; if (mFetchByUidEnabled) { if (mModSequenceValue != 0) { +#if 0 if (mUids != NULL) { IMAPSyncResult * syncResult; - syncResult = session()->session()->syncMessagesByUIDForModSeq(folder(), mKind, mUids, mModSequenceValue, this, &error); + syncResult = session()->session()->syncMessagesByUID(folder(), mKind, mUids, mModSequenceValue, this, &error); if (syncResult != NULL) { mMessages = syncResult->modifiedOrAddedMessages(); mVanishedMessages = syncResult->modifiedOrAddedMessages(); @@ -131,29 +150,43 @@ void IMAPFetchMessagesOperation::main() else { IMAPSyncResult * syncResult; - syncResult = session()->session()->syncMessagesByUIDForModSeq(folder(), mKind, mFirst, mLast, mModSequenceValue, this, &error); + syncResult = session()->session()->syncMessagesByUID(folder(), mKind, mFirst, mLast, mModSequenceValue, this, &error); if (syncResult != NULL) { mMessages = syncResult->modifiedOrAddedMessages(); mVanishedMessages = syncResult->modifiedOrAddedMessages(); } } +#endif + IMAPSyncResult * syncResult; + + syncResult = session()->session()->syncMessagesByUID(folder(), mKind, mIndexes, mModSequenceValue, this, &error); + if (syncResult != NULL) { + mMessages = syncResult->modifiedOrAddedMessages(); + mVanishedMessages = syncResult->modifiedOrAddedMessages(); + } } else { +#if 0 if (mUids != NULL) { mMessages = session()->session()->fetchMessagesByUID(folder(), mKind, mUids, this, &error); } else { mMessages = session()->session()->fetchMessagesByUID(folder(), mKind, mFirst, mLast, this, &error); } +#endif + mMessages = session()->session()->fetchMessagesByUID(folder(), mKind, mIndexes, this, &error); } } else { +#if 0 if (mNumbers != NULL) { mMessages = session()->session()->fetchMessagesByNumber(folder(), mKind, mNumbers, this, &error); } else { mMessages = session()->session()->fetchMessagesByNumber(folder(), mKind, mFirst, mLast, this, &error); } +#endif + mMessages = session()->session()->fetchMessagesByNumber(folder(), mKind, mIndexes, this, &error); } MC_SAFE_RETAIN(mMessages); MC_SAFE_RETAIN(mVanishedMessages); diff --git a/src/async/imap/MCIMAPFetchMessagesOperation.h b/src/async/imap/MCIMAPFetchMessagesOperation.h index 24cd5be8..9f13159c 100644 --- a/src/async/imap/MCIMAPFetchMessagesOperation.h +++ b/src/async/imap/MCIMAPFetchMessagesOperation.h @@ -23,6 +23,7 @@ namespace mailcore { virtual void setFetchByUidEnabled(bool enabled); virtual bool isFetchByUidEnabled(); +#if 0 virtual void setFirst(uint32_t first); virtual uint32_t first(); @@ -34,6 +35,9 @@ namespace mailcore { virtual void setNumbers(Array * numbers); virtual Array * numbers(); +#endif + virtual void setIndexes(IndexSet * indexes); + virtual IndexSet * indexes(); virtual void setModSequenceValue(uint64_t modseq); virtual uint64_t modSequenceValue(); @@ -50,10 +54,13 @@ namespace mailcore { private: bool mFetchByUidEnabled; +#if 0 uint32_t mFirst; uint32_t mLast; Array * mUids; Array * mNumbers; +#endif + IndexSet * mIndexes; IMAPMessagesRequestKind mKind; Array * mMessages; Array * mVanishedMessages; diff --git a/src/core/basetypes/MCAssert.cc b/src/core/basetypes/MCAssert.cc index afe9bfd5..82b5de26 100644 --- a/src/core/basetypes/MCAssert.cc +++ b/src/core/basetypes/MCAssert.cc @@ -1,6 +1,7 @@ #include "MCAssert.h" #include <stdio.h> +#include <stdlib.h> void mailcore::assertInteral(const char * filename, unsigned int line, int cond, const char * condString) { @@ -9,4 +10,5 @@ void mailcore::assertInteral(const char * filename, unsigned int line, int cond, } fprintf(stderr, "%s:%i: assert %s\n", filename, line, condString); + abort(); } diff --git a/src/core/basetypes/MCIndexSet.cpp b/src/core/basetypes/MCIndexSet.cpp index 7fd6cd6d..514e9d66 100644 --- a/src/core/basetypes/MCIndexSet.cpp +++ b/src/core/basetypes/MCIndexSet.cpp @@ -9,6 +9,9 @@ #include "MCIndexSet.h" #include "MCString.h" +#include "MCAssert.h" +#include "MCRange.h" +#include "MCLog.h" using namespace mailcore; @@ -47,6 +50,22 @@ IndexSet * IndexSet::indexSet() return result; } +IndexSet * IndexSet::indexSetWithRange(Range range) +{ + IndexSet * result = new IndexSet(); + result->autorelease(); + result->addRange(range); + return result; +} + +IndexSet * IndexSet::indexSetWithIndex(uint64_t idx) +{ + IndexSet * result = new IndexSet(); + result->autorelease(); + result->addIndex(idx); + return result; +} + unsigned int IndexSet::count() { unsigned int total = 0; @@ -63,13 +82,13 @@ int IndexSet::rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsi Range middleRange = mRanges[middle]; if (left == right) { - if ((idx >= middleRange.location) && (idx <= middleRange.location + middleRange.length)) { + if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) { return left; } return -1; } - if ((idx >= middleRange.location) && (idx <= middleRange.location + middleRange.length)) { + if ((idx >= RangeLeftBound(middleRange)) && (idx <= RangeRightBound(middleRange))) { return middle; } if (idx < middleRange.location) { @@ -119,6 +138,37 @@ int IndexSet::rightRangeIndexForIndex(uint64_t idx) return rightRangeIndexForIndexWithBounds(idx, 0, mCount - 1); } +int IndexSet::leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right) +{ + unsigned int middle = (left + right) / 2; + + Range middleRange = mRanges[middle]; + + if (left == right) { + if (idx <= middleRange.location) { + return left; + } + else { + return left + 1; + } + } + + if (idx <= middleRange.location) { + return leftRangeIndexForIndexWithBounds(idx, left, middle); + } + else { + return leftRangeIndexForIndexWithBounds(idx, middle + 1, right); + } +} + +int IndexSet::leftRangeIndexForIndex(uint64_t idx) +{ + if (mCount == 0) + return 0; + + return leftRangeIndexForIndexWithBounds(idx, 0, mCount - 1); +} + void IndexSet::addRangeIndex(unsigned int rangeIndex) { if (mAllocated < mCount + 1) { @@ -136,96 +186,138 @@ void IndexSet::addRangeIndex(unsigned int rangeIndex) for(unsigned int i = rangeIndex ; i < mCount ; i ++) { rangesReplacement[i + 1] = mRanges[i]; } + mCount ++; rangesReplacement[rangeIndex].location = 0; rangesReplacement[rangeIndex].length = 0; delete [] mRanges; mRanges = rangesReplacement; } else { - for(unsigned int i = mCount - 1 ; i >= rangeIndex ; i --) { - mRanges[i + 1] = mRanges[i]; + if (mCount > 0) { + for(int i = mCount - 1 ; i >= (int) rangeIndex ; i --) { + mRanges[i + 1] = mRanges[i]; + } } + mCount ++; mRanges[rangeIndex].location = 0; mRanges[rangeIndex].length = 0; } } -void IndexSet::addIndex(uint64_t idx) +void IndexSet::addRange(Range range) { - int leftRangeIndex; - int rightRangeIndex; + int rangeIndex = leftRangeIndexForIndex(range.location); + addRangeIndex(rangeIndex); + mRanges[rangeIndex] = range; - if (rangeIndexForIndex(idx) != -1) + mergeRanges(rangeIndex); + if (rangeIndex > 0) { + tryToMergeAdjacentRanges(rangeIndex - 1); + } + tryToMergeAdjacentRanges(rangeIndex); +} + +void IndexSet::tryToMergeAdjacentRanges(unsigned int rangeIndex) +{ + if (RangeRightBound(mRanges[rangeIndex]) == UINT64_MAX) return; - leftRangeIndex = rangeIndexForIndex(idx - 1); - rightRangeIndex = rangeIndexForIndex(idx + 1); - - if ((leftRangeIndex == -1) && (rightRangeIndex == -1)) { - rightRangeIndex = rightRangeIndexForIndex(idx); - addRangeIndex(rightRangeIndex); - mRanges[rightRangeIndex].location = idx; - mRanges[rightRangeIndex].length = 0; + if (RangeRightBound(mRanges[rangeIndex]) + 1 != mRanges[rangeIndex + 1].location) { + return; } - else if ((leftRangeIndex != -1) && (rightRangeIndex == -1)) { - if (mRanges[leftRangeIndex].location + mRanges[leftRangeIndex].length + 1 == idx) { - mRanges[leftRangeIndex].length ++; + + uint64_t right = RangeRightBound(mRanges[rangeIndex + 1]); + removeRangeIndex(rangeIndex + 1, 1); + mRanges[rangeIndex].length = right - mRanges[rangeIndex].location; +} + +void IndexSet::mergeRanges(unsigned int rangeIndex) +{ + int right = rangeIndex; + + for(int i = rangeIndex ; i < mCount ; i ++) { + if (RangeHasIntersection(mRanges[rangeIndex], mRanges[i])) { + right = i; } - } - else if ((leftRangeIndex == -1) && (rightRangeIndex != -1)) { - if (mRanges[rightRangeIndex].location - 1 == idx) { - mRanges[rightRangeIndex].location --; - mRanges[rightRangeIndex].length ++; + else { + break; } } + + if (right == rangeIndex) + return; + + IndexSet * indexSet = RangeUnion(mRanges[rangeIndex], mRanges[right]); + MCAssert(indexSet->rangesCount() > 0); + Range range = indexSet->allRanges()[0]; + removeRangeIndex(rangeIndex + 1, right - rangeIndex); + mRanges[rangeIndex] = range; } -void IndexSet::removeRangeIndex(unsigned int rangeIndex) +void IndexSet::addIndex(uint64_t idx) { - for(unsigned int i = rangeIndex + 1 ; i < mCount ; i --) { - mRanges[i - 1] = mRanges[i]; + addRange(RangeMake(idx, 0)); +} + +void IndexSet::removeRangeIndex(unsigned int rangeIndex, unsigned int count) +{ + for(unsigned int i = rangeIndex + count ; i < mCount ; i ++) { + mRanges[i - count] = mRanges[i]; } - mCount --; + mCount -= count; } -void IndexSet::removeIndex(uint64_t idx) +void IndexSet::removeRange(Range range) { - int rangeIndex = rangeIndexForIndex(idx); - if (rangeIndex == -1) - return; - if (idx == mRanges[rangeIndex].location) { - mRanges[rangeIndex].location ++; - mRanges[rangeIndex].length --; - if (mRanges[rangeIndex].length == 0) { - // remove range. - removeRangeIndex(rangeIndex); + int left = -1; + int right = -1; + int leftRangeIndex = leftRangeIndexForIndex(range.location); + for(int i = leftRangeIndex ; i < mCount ; i ++) { + if (RangeHasIntersection(mRanges[i], range)) { + IndexSet * indexSet = RangeRemoveRange(mRanges[i], range); + if (indexSet->rangesCount() == 0) { + if (left == -1) { + left = i; + } + right = i; + mRanges[i] = RangeEmpty; + } + else if (indexSet->rangesCount() == 1) { + mRanges[i] = indexSet->allRanges()[0]; + } + else { + MCAssert(indexSet->rangesCount() == 2); + addRangeIndex(i); + mRanges[i] = indexSet->allRanges()[0]; + mRanges[i + 1] = indexSet->allRanges()[1]; + } } - } - else if (idx == mRanges[rangeIndex].location + mRanges[rangeIndex].length) { - mRanges[rangeIndex].length --; - if (mRanges[rangeIndex].length == 0) { - // remove range. - removeRangeIndex(rangeIndex); + else { + break; } } - else { - // split range. - addRangeIndex(rangeIndex); - mRanges[rangeIndex] = mRanges[rangeIndex + 1]; - uint64_t right = mRanges[rangeIndex].location + mRanges[rangeIndex].length; - mRanges[rangeIndex].location = mRanges[rangeIndex + 1].location; - mRanges[rangeIndex].length = idx - mRanges[rangeIndex].location; - mRanges[rangeIndex + 1].location = idx + 1; - mRanges[rangeIndex + 1].length = right - mRanges[rangeIndex + 1].location; + + if (left != -1) { + removeRangeIndex(left, right - left + 1); } } +void IndexSet::removeIndex(uint64_t idx) +{ + removeRange(RangeMake(idx, 0)); +} + bool IndexSet::containsIndex(uint64_t idx) { int rangeIndex = rangeIndexForIndex(idx); return rangeIndex != -1; } +unsigned int IndexSet::rangesCount() +{ + return mCount; +} + Range * IndexSet::allRanges() { return mRanges; @@ -248,9 +340,15 @@ String * IndexSet::description() if (i != 0) { result->appendUTF8Format(","); } - result->appendUTF8Format("%llu-%llu", - (unsigned long long) mRanges[i].location, - (unsigned long long) (mRanges[i].location + mRanges[i].length)); + if (mRanges[i].length == 0) { + result->appendUTF8Format("%llu", + (unsigned long long) mRanges[i].location); + } + else { + result->appendUTF8Format("%llu-%llu", + (unsigned long long) mRanges[i].location, + (unsigned long long) (mRanges[i].location + mRanges[i].length)); + } } return result; } @@ -259,3 +357,16 @@ Object * IndexSet::copy() { return new IndexSet(this); } + +void IndexSet::intersectsRange(Range range) +{ + uint64_t right = RangeRightBound(range); + if (right == UINT64_MAX) { + removeRange(RangeMake(0, range.location - 1)); + } + else { + removeRange(RangeMake(0, range.location - 1)); + removeRange(RangeMake(right, UINT64_MAX)); + } +} + diff --git a/src/core/basetypes/MCIndexSet.h b/src/core/basetypes/MCIndexSet.h index 290b9aaa..3d9bdb6c 100644 --- a/src/core/basetypes/MCIndexSet.h +++ b/src/core/basetypes/MCIndexSet.h @@ -23,13 +23,20 @@ namespace mailcore { IndexSet(IndexSet * o); static IndexSet * indexSet(); + static IndexSet * indexSetWithRange(Range range); + static IndexSet * indexSetWithIndex(uint64_t idx); virtual unsigned int count(); virtual void addIndex(uint64_t idx); virtual void removeIndex(uint64_t idx); virtual bool containsIndex(uint64_t idx); - + + virtual void addRange(Range range); + virtual void removeRange(Range range); + virtual void intersectsRange(Range range); + virtual Range * allRanges(); + virtual unsigned int rangesCount(); virtual void removeAllIndexes(); public: // subclass behavior @@ -45,9 +52,13 @@ namespace mailcore { int rangeIndexForIndex(uint64_t idx); int rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); void addRangeIndex(unsigned int rangeIndex); - void removeRangeIndex(unsigned int rangeIndex); + void removeRangeIndex(unsigned int rangeIndex, unsigned int count); int rightRangeIndexForIndex(uint64_t idx); int rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + int leftRangeIndexForIndex(uint64_t idx); + int leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + void mergeRanges(unsigned int rangeIndex); + void tryToMergeAdjacentRanges(unsigned int rangeIndex); }; } diff --git a/src/core/basetypes/MCRange.cc b/src/core/basetypes/MCRange.cc index 48bb3d84..243c6a8f 100644 --- a/src/core/basetypes/MCRange.cc +++ b/src/core/basetypes/MCRange.cc @@ -1,7 +1,13 @@ #include "MCRange.h" +#include "MCIndexSet.h" + +#include <sys/param.h> + using namespace mailcore; +Range mailcore::RangeEmpty = {UINT64_MAX, 0}; + Range mailcore::RangeMake(uint64_t location, uint64_t length) { Range range; @@ -10,3 +16,125 @@ Range mailcore::RangeMake(uint64_t location, uint64_t length) return range; } +Range mailcore::RangeIntersection(Range range1, Range range2) +{ + if (RangeRightBound(range2) < range1.location) { + return RangeEmpty; + } + else if (RangeRightBound(range1) < range2.location) { + return RangeEmpty; + } + else { + uint64_t left1; + uint64_t right1; + uint64_t left2; + uint64_t right2; + uint64_t leftResult; + uint64_t rightResult; + + left1 = range1.location; + right1 = RangeRightBound(range1); + left2 = range2.location; + right2 = RangeRightBound(range2); + + leftResult = MAX(left1, left2); + rightResult = MIN(right1, right2); + if (rightResult == UINT64_MAX) { + return RangeMake(leftResult, UINT64_MAX); + } + else { + return RangeMake(leftResult, rightResult - leftResult); + } + } +} + +bool mailcore::RangeHasIntersection(Range range1, Range range2) +{ + return RangeIntersection(range1, range2).location != UINT64_MAX; +} + +IndexSet * mailcore::RangeRemoveRange(Range range1, Range range2) +{ + uint64_t left1; + uint64_t right1; + uint64_t left2; + uint64_t right2; + IndexSet * result; + + if (!RangeHasIntersection(range1, range2)) + return IndexSet::indexSetWithRange(range1); + + result = IndexSet::indexSet(); + + range2 = RangeIntersection(range1, range2); + + left1 = range1.location; + right1 = RangeRightBound(range1); + left2 = range2.location; + right2 = RangeRightBound(range2); + + if (left2 > left1) { + result->addRange(RangeMake(left1, left2 - left1 - 1)); + } + + if (right2 != UINT64_MAX) { + if (right1 == UINT64_MAX) { + result->addRange(RangeMake(right2 + 1, UINT64_MAX)); + } + else { + if (right2 < right1) { + result->addRange(RangeMake(right2 + 1, right1 - (right2 + 1))); + } + } + } + + return result; +} + +IndexSet * mailcore::RangeUnion(Range range1, Range range2) +{ + if (!RangeHasIntersection(range1, range2)) { + IndexSet * result = IndexSet::indexSet(); + + result->addRange(range1); + result->addRange(range2); + + return result; + } + else { + uint64_t left1; + uint64_t right1; + uint64_t left2; + uint64_t right2; + uint64_t resultLeft; + uint64_t resultRight; + + left1 = range1.location; + right1 = RangeRightBound(range1); + left2 = range2.location; + right2 = RangeRightBound(range2); + + resultLeft = MIN(left1, left2); + resultRight = MAX(right1, right2); + if (resultRight == UINT64_MAX) { + return IndexSet::indexSetWithRange(RangeMake(resultLeft, UINT64_MAX)); + } + else { + return IndexSet::indexSetWithRange(RangeMake(resultLeft, resultRight - resultLeft)); + } + } +} + +uint64_t mailcore::RangeLeftBound(Range range) +{ + return range.location; +} + +uint64_t mailcore::RangeRightBound(Range range) +{ + if (range.length == UINT64_MAX) + return UINT64_MAX; + return range.location + range.length; +} + + diff --git a/src/core/basetypes/MCRange.h b/src/core/basetypes/MCRange.h index 7b8b497d..2687bcab 100644 --- a/src/core/basetypes/MCRange.h +++ b/src/core/basetypes/MCRange.h @@ -8,12 +8,24 @@ namespace mailcore { + class IndexSet; + + // infinite length : UINT64_MAX + // empty range : location = UINT64_MAX struct Range { uint64_t location; uint64_t length; }; + extern Range RangeEmpty; + Range RangeMake(uint64_t location, uint64_t length); + IndexSet * RangeRemoveRange(Range range1, Range range2); + IndexSet * RangeUnion(Range range1, Range range2); + Range RangeIntersection(Range range1, Range range2); + bool RangeHasIntersection(Range range1, Range range2); + uint64_t RangeLeftBound(Range range); + uint64_t RangeRightBound(Range range); } #endif diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc index 75765c26..8335e5a4 100644 --- a/src/core/basetypes/MCString.cc +++ b/src/core/basetypes/MCString.cc @@ -1943,7 +1943,7 @@ String * String::substringWithRange(Range range) range.length = length() - range.location; } - return stringWithCharacters(unicodeCharacters() + range.location, range.length); + return stringWithCharacters(unicodeCharacters() + range.location, (unsigned int) range.length); } static chash * uniquedStringHash = NULL; diff --git a/src/core/imap/MCIMAPSession.cc b/src/core/imap/MCIMAPSession.cc index 0d0bf64e..2d76ff94 100644 --- a/src/core/imap/MCIMAPSession.cc +++ b/src/core/imap/MCIMAPSession.cc @@ -270,6 +270,23 @@ static clist * splitSet(struct mailimap_set * set, unsigned int splitCount) return result; } +static struct mailimap_set * setFromIndexSet(IndexSet * indexSet) +{ + struct mailimap_set * imap_set; + + imap_set = mailimap_set_new_empty(); + for(unsigned int i = 0 ; i < indexSet->rangesCount() ; i ++) { + uint64_t left = RangeLeftBound(indexSet->allRanges()[i]); + uint64_t right = RangeRightBound(indexSet->allRanges()[i]); + if (right == UINT64_MAX) { + right = 0; + } + mailimap_set_add_interval(imap_set, (uint32_t) left, (uint32_t) right); + } + + return imap_set; +} + void IMAPSession::init() { mHostname = NULL; @@ -1853,6 +1870,7 @@ IMAPSyncResult * IMAPSession::fetchMessages(String * folder, IMAPMessagesRequest return result; } +#if 0 Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID, IMAPProgressCallback * progressCallback, ErrorCode * pError) { @@ -1909,6 +1927,35 @@ Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestK mailimap_set_free(imapset); return result; } +#endif + +Array * IMAPSession::fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + struct mailimap_set * imapset = setFromIndexSet(uids); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, true, imapset, 0, NULL, 0, + progressCallback, pError); + if (syncResult == NULL) + return NULL; + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); + mailimap_set_free(imapset); + return result; +} + +Array * IMAPSession::fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + struct mailimap_set * imapset = setFromIndexSet(numbers); + IMAPSyncResult * syncResult = fetchMessages(folder, requestKind, false, imapset, 0, NULL, 0, + progressCallback, pError); + if (syncResult == NULL) + return NULL; + Array * result = syncResult->modifiedOrAddedMessages(); + result->retain()->autorelease(); + mailimap_set_free(imapset); + return result; +} static int fetch_rfc822(mailimap * session, uint32_t msgid, char ** result) @@ -2227,8 +2274,12 @@ void IMAPSession::idle(String * folder, uint32_t lastKnownUID, ErrorCode * pErro if (lastKnownUID != 0) { Array * msgs; +#if 0 msgs = fetchMessagesByUID(folder, IMAPMessagesRequestKindUid, lastKnownUID, 0, NULL, pError); +#endif + msgs = fetchMessagesByUID(folder, IMAPMessagesRequestKindUid, IndexSet::indexSetWithRange(RangeMake(lastKnownUID, UINT64_MAX)), + NULL, pError); if (* pError != ErrorNone) return; if (msgs->count() > 0) { @@ -2677,10 +2728,11 @@ unsigned int IMAPSession::lastFolderMessageCount() return mFolderMsgCount; } -IMAPSyncResult * IMAPSession::syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, - uint32_t firstUID, uint32_t lastUID, - uint64_t modseq, - IMAPProgressCallback * progressCallback, ErrorCode * pError) +#if 0 +IMAPSyncResult * IMAPSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + uint32_t firstUID, uint32_t lastUID, + uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_set * imapset = mailimap_set_new_interval(firstUID, lastUID); IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, firstUID, @@ -2689,9 +2741,9 @@ IMAPSyncResult * IMAPSession::syncMessagesByUIDForModSeq(String * folder, IMAPMe return result; } -IMAPSyncResult * IMAPSession::syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, - Array * uids, uint64_t modseq, - IMAPProgressCallback * progressCallback, ErrorCode * pError) +IMAPSyncResult * IMAPSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + Array * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError) { struct mailimap_set * imapset = setFromArray(uids); IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, @@ -2700,6 +2752,20 @@ IMAPSyncResult * IMAPSession::syncMessagesByUIDForModSeq(String * folder, IMAPMe mailimap_set_free(imapset); return result; } +#endif + +IMAPSyncResult * IMAPSession::syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError) +{ + MCAssert(uids->rangesCount() > 0); + struct mailimap_set * imapset = setFromIndexSet(uids); + IMAPSyncResult * result = fetchMessages(folder, requestKind, true, imapset, modseq, NULL, + (uint32_t) uids->allRanges()[0].location, + progressCallback, pError); + mailimap_set_free(imapset); + return result; +} IndexSet * IMAPSession::capability(ErrorCode * pError) { diff --git a/src/core/imap/MCIMAPSession.h b/src/core/imap/MCIMAPSession.h index 6239a2d7..2b4b8b91 100644 --- a/src/core/imap/MCIMAPSession.h +++ b/src/core/imap/MCIMAPSession.h @@ -80,6 +80,7 @@ namespace mailcore { virtual void expunge(String * folder, ErrorCode * pError); +#if 0 virtual Array * /* IMAPMessage */ fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, uint32_t firstUID, uint32_t lastUID, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, @@ -88,6 +89,12 @@ namespace mailcore { Array * /* Value */ uids, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, Array * /* Value */ numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError); +#endif + virtual Array * /* IMAPMessage */ fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers, IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual Data * fetchMessageByUID(String * folder, uint32_t uid, IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual Data * fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, @@ -96,13 +103,18 @@ namespace mailcore { ErrorCode * pError); /* When CONDSTORE or QRESYNC is available */ - virtual IMAPSyncResult * syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, - uint32_t firstUID, uint32_t lastUID, - uint64_t modseq, - IMAPProgressCallback * progressCallback, ErrorCode * pError); - virtual IMAPSyncResult * syncMessagesByUIDForModSeq(String * folder, IMAPMessagesRequestKind requestKind, - Array * uids, uint64_t modseq, - IMAPProgressCallback * progressCallback, ErrorCode * pError); +#if 0 + virtual IMAPSyncResult * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + uint32_t firstUID, uint32_t lastUID, + uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual IMAPSyncResult * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + Array * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError); +#endif + virtual IMAPSyncResult * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError); virtual void storeFlags(String * folder, Array * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError); virtual void storeLabels(String * folder, Array * uids, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError); |