aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/async/imap/MCIMAPAsyncConnection.cc41
-rw-r--r--src/async/imap/MCIMAPAsyncConnection.h9
-rw-r--r--src/async/imap/MCIMAPAsyncSession.cpp23
-rw-r--r--src/async/imap/MCIMAPAsyncSession.h8
-rw-r--r--src/async/imap/MCIMAPFetchMessagesOperation.cc37
-rw-r--r--src/async/imap/MCIMAPFetchMessagesOperation.h7
-rw-r--r--src/core/basetypes/MCAssert.cc2
-rw-r--r--src/core/basetypes/MCIndexSet.cpp223
-rw-r--r--src/core/basetypes/MCIndexSet.h15
-rw-r--r--src/core/basetypes/MCRange.cc128
-rw-r--r--src/core/basetypes/MCRange.h12
-rw-r--r--src/core/basetypes/MCString.cc2
-rw-r--r--src/core/imap/MCIMAPSession.cc80
-rw-r--r--src/core/imap/MCIMAPSession.h26
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);