File indexing completed on 2024-09-22 04:52:51
0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 0002 0003 This file is part of the Trojita Qt IMAP e-mail client, 0004 http://trojita.flaska.net/ 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License or (at your option) version 3 or any later version 0010 accepted by the membership of KDE e.V. (or its successor approved 0011 by the membership of KDE e.V.), which shall act as a proxy 0012 defined in Section 14 of version 3 of the license. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 #include "Sequence.h" 0024 #include <QStringList> 0025 #include <QTextStream> 0026 #include <algorithm> 0027 0028 namespace Imap 0029 { 0030 0031 Sequence::Sequence(const uint num): kind(DISTINCT) 0032 { 0033 numbers << num; 0034 } 0035 0036 Sequence Sequence::startingAt(const uint lo) 0037 { 0038 Sequence res(lo); 0039 res.lo = lo; 0040 res.kind = UNLIMITED; 0041 return res; 0042 } 0043 0044 QByteArray Sequence::toByteArray() const 0045 { 0046 switch (kind) { 0047 case DISTINCT: 0048 { 0049 Q_ASSERT(! numbers.isEmpty()); 0050 0051 QStringList res; 0052 int i = 0; 0053 while (i < numbers.size()) { 0054 int old = i; 0055 while (i < numbers.size() - 1 && 0056 numbers[i] == numbers[ i + 1 ] - 1) 0057 ++i; 0058 if (old != i) { 0059 // we've found a sequence 0060 res << QString::number(numbers[old]) + QLatin1Char(':') + QString::number(numbers[i]); 0061 } else { 0062 res << QString::number(numbers[i]); 0063 } 0064 ++i; 0065 } 0066 return res.join(QStringLiteral(",")).toLocal8Bit(); 0067 } 0068 case RANGE: 0069 Q_ASSERT(lo <= hi); 0070 if (lo == hi) 0071 return QByteArray::number(lo); 0072 else 0073 return QByteArray::number(lo) + ':' + QByteArray::number(hi); 0074 case UNLIMITED: 0075 return QByteArray::number(lo) + ":*"; 0076 } 0077 // fix gcc warning 0078 Q_ASSERT(false); 0079 return QByteArray(); 0080 } 0081 0082 Imap::Uids Sequence::toVector() const 0083 { 0084 switch (kind) { 0085 case DISTINCT: 0086 Q_ASSERT(!numbers.isEmpty()); 0087 return numbers; 0088 case RANGE: 0089 Q_ASSERT(lo <= hi); 0090 if (lo == hi) { 0091 return Imap::Uids() << lo; 0092 } else { 0093 Imap::Uids res; 0094 for (uint i = lo; i < hi; ++i) 0095 res << i; 0096 return res; 0097 } 0098 case UNLIMITED: 0099 Q_ASSERT(false); 0100 return Imap::Uids(); 0101 } 0102 Q_ASSERT(false); 0103 return Imap::Uids(); 0104 } 0105 0106 Sequence &Sequence::add(uint num) 0107 { 0108 Q_ASSERT(kind == DISTINCT); 0109 auto it = std::lower_bound(numbers.begin(), numbers.end(), num); 0110 if (it == numbers.end() || *it != num) 0111 numbers.insert(it, num); 0112 return *this; 0113 } 0114 0115 Sequence Sequence::fromVector(Imap::Uids numbers) 0116 { 0117 Q_ASSERT(!numbers.isEmpty()); 0118 std::sort(numbers.begin(), numbers.end()); 0119 Sequence seq(numbers.first()); 0120 for (int i = 1; i < numbers.size(); ++i) { 0121 seq.add(numbers[i]); 0122 } 0123 return seq; 0124 } 0125 0126 bool Sequence::isValid() const 0127 { 0128 if (kind == DISTINCT && numbers.isEmpty()) 0129 return false; 0130 else 0131 return true; 0132 } 0133 0134 QTextStream &operator<<(QTextStream &stream, const Sequence &s) 0135 { 0136 return stream << s.toByteArray(); 0137 } 0138 0139 bool operator==(const Sequence &a, const Sequence &b) 0140 { 0141 // This operator is used only in the test suite, so performance doesn't matter and this was *so* easy to hack together... 0142 return a.toVector() == b.toVector(); 0143 } 0144 0145 }