1 //
2 // VMime library (http://www.vmime.org)
3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 3 of
8 // the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // Linking this library statically or dynamically with other modules is making
20 // a combined work based on this library.  Thus, the terms and conditions of
21 // the GNU General Public License cover the whole combination.
22 //
23 
24 #ifndef VMIME_NET_MESSAGESET_HPP_INCLUDED
25 #define VMIME_NET_MESSAGESET_HPP_INCLUDED
26 
27 
28 #include "vmime/config.hpp"
29 
30 
31 #if VMIME_HAVE_MESSAGING_FEATURES
32 
33 
34 #include "vmime/net/message.hpp"
35 
36 
37 namespace vmime {
38 namespace net {
39 
40 
41 // Forward references
42 class numberMessageRange;
43 class UIDMessageRange;
44 
45 
46 /** Enumerator used to retrieve the message number/UID ranges contained
47   * in a messageSet object.
48   */
49 
50 class VMIME_EXPORT messageSetEnumerator
51 {
52 public:
53 
54 	virtual void enumerateNumberMessageRange(const numberMessageRange& range) = 0;
55 	virtual void enumerateUIDMessageRange(const UIDMessageRange& range) = 0;
56 };
57 
58 
59 /** A range of (continuous) messages, designated either by their
60   * sequence number, or by their UID.
61   */
62 
63 class VMIME_EXPORT messageRange : public object
64 {
65 public:
66 
67 	virtual ~messageRange();
68 
69 	/** Enumerates this range with the specified enumerator.
70 	  *
71 	  * @param en enumerator that will receive the method calls while
72 	  * enumerating this range
73 	  */
74 	virtual void enumerate(messageSetEnumerator& en) const = 0;
75 
76 	/** Clones this message range.
77 	  */
78 	virtual messageRange* clone() const = 0;
79 
80 protected:
81 
82 	messageRange();
83 	messageRange(const messageRange&);
84 };
85 
86 
87 /** A range of (continuous) messages designated by their sequence number.
88   */
89 
90 class VMIME_EXPORT numberMessageRange : public messageRange
91 {
92 public:
93 
94 	/** Constructs a message range containing a single message.
95 	  *
96 	  * @param number message number (numbering starts at 1, not 0)
97 	  */
98 	numberMessageRange(const size_t number);
99 
100 	/** Constructs a message range for multiple messages.
101 	  *
102 	  * @param first number of the first message in the range (numbering
103 	  * starts at 1, not 0)
104 	  * @param last number of the last message in the range, or use the
105 	  * special value -1 to designate the last message in the folder
106 	  */
107 	numberMessageRange(const size_t first, const size_t last);
108 
109 	/** Constructs a message range by copying from another range.
110 	  *
111 	  * @param other range to copy
112 	  */
113 	numberMessageRange(const numberMessageRange& other);
114 
115 	/** Returns the number of the first message in the range.
116 	  *
117 	  * @return number of the first message
118 	  */
119 	size_t getFirst() const;
120 
121 	/** Returns the number of the last message in the range, or -1
122 	  * to designate the last message in the folder
123 	  *
124 	  * @return number of the last message
125 	  */
126 	size_t getLast() const;
127 
128 	void enumerate(messageSetEnumerator& en) const;
129 
130 	messageRange* clone() const;
131 
132 private:
133 
134 	size_t m_first, m_last;
135 };
136 
137 
138 /** A range of (continuous) messages represented by their UID.
139   */
140 
141 class VMIME_EXPORT UIDMessageRange : public messageRange
142 {
143 public:
144 
145 	/** Constructs a message range containing a single message.
146 	  *
147 	  * @param uid message UID
148 	  */
149 	UIDMessageRange(const message::uid& uid);
150 
151 	/** Constructs a message range for multiple messages.
152 	  *
153 	  * @param first UID of the first message in the range
154 	  * @param last UID of the last message in the range, or use the
155 	  * special value '*' to designate the last message in the folder
156 	  */
157 	UIDMessageRange(const message::uid& first, const message::uid& last);
158 
159 	/** Constructs a message range by copying from another range.
160 	  *
161 	  * @param other range to copy
162 	  */
163 	UIDMessageRange(const UIDMessageRange& other);
164 
165 	/** Returns the UID of the first message in the range.
166 	  *
167 	  * @return UID of the first message
168 	  */
169 	const message::uid getFirst() const;
170 
171 	/** Returns the UID of the last message in the range, or '*'
172 	  * to designate the last message in the folder
173 	  *
174 	  * @return UID of the last message
175 	  */
176 	const message::uid getLast() const;
177 
178 	void enumerate(messageSetEnumerator& en) const;
179 
180 	messageRange* clone() const;
181 
182 private:
183 
184 	message::uid m_first, m_last;
185 };
186 
187 
188 /** Represents a set of messages, designated either by their sequence
189   * number, or by their UID (but not both).
190   *
191   * Following is example code to designate messages by their number:
192   * \code{.cpp}
193   *    // Designate a single message with sequence number 42
194   *    vmime::net::messageSet::byNumber(42)
195   *
196   *    // Designate messages from sequence number 5 to sequence number 8 (including)
197   *    vmime::net::messageSet::byNumber(5, 8)
198   *
199   *    // Designate all messages in the folder, starting from number 42
200   *    vmime::net::messageSet::byNumber(42, -1)
201   * \endcode
202   * Or, to designate messages by their UID, use:
203   * \code{.cpp}
204   *    // Designate a single message with UID 1042
205   *    vmime::net::messageSet::byUID(1042)
206   *
207   *    // Designate messages from UID 1000 to UID 1042 (including)
208   *    vmime::net::messageSet::byUID(1000, 1042)
209   *
210   *    // Designate all messages in the folder, starting from UID 1000
211   *    vmime::net::messageSet::byUID(1000, "*")
212   * \endcode
213   */
214 
215 class VMIME_EXPORT messageSet : public object
216 {
217 public:
218 
219 	~messageSet();
220 
221 	messageSet(const messageSet& other);
222 
223 	/** Constructs an empty set.
224 	  *
225 	  * @return new empty message set
226 	  */
227 	static messageSet empty();
228 
229 	/** Constructs a new message set and initializes it with a single
230 	  * message represented by its sequence number.
231 	  *
232 	  * @param number message number (numbering starts at 1, not 0)
233 	  * @return new message set
234 	  */
235 	static messageSet byNumber(const size_t number);
236 
237 	/** Constructs a new message set and initializes it with a range
238 	  * of messages represented by their sequence number.
239 	  *
240 	  * @param first number of the first message in the range (numbering
241 	  * starts at 1, not 0)
242 	  * @param last number of the last message in the range, or use the
243 	  * special value -1 to designate the last message in the folder
244 	  * @return new message set
245 	  */
246 	static messageSet byNumber(const size_t first, const size_t last);
247 
248 	/** Constructs a new message set and initializes it with a possibly
249 	  * unsorted list of messages represented by their sequence number.
250 	  * Please note that numbering starts at 1, not 0.
251 	  *
252 	  * The function tries to group consecutive message numbers into
253 	  * ranges to reduce the size of the resulting set.
254 	  *
255 	  * For example, given the list "1,2,3,4,5,7,8,13,15,16,17" it will
256 	  * result in the following ranges: "1:5,7:8,13,15:17".
257 	  *
258 	  * @param numbers a vector containing numbers of the messages
259 	  * @return new message set
260 	  */
261 	static messageSet byNumber(const std::vector <size_t>& numbers);
262 
263 	/** Constructs a new message set and initializes it with a single
264 	  * message represented by its UID.
265 	  *
266 	  * @param uid message UID
267 	  * @return new message set
268 	  */
269 	static messageSet byUID(const message::uid& uid);
270 
271 	/** Constructs a new message set and initializes it with a range
272 	  * of messages represented by their sequence number.
273 	  *
274 	  * @param first UID of the first message in the range
275 	  * @param last UID of the last message in the range, or use the
276 	  * special value '*' to designate the last message in the folder
277 	  * @return new message set
278 	  */
279 	static messageSet byUID(const message::uid& first, const message::uid& last);
280 
281 	/** Constructs a new message set and initializes it with a possibly
282 	  * unsorted list of messages represented by their UID.
283 	  *
284 	  * For UIDs that actually are numbers (this is the case for IMAP), the
285 	  * function tries to group consecutive UIDs into ranges to reduce the
286 	  * size of the resulting set.
287 	  *
288 	  * For example, given the list "1,2,3,4,5,7,8,13,15,16,17" it will
289 	  * result in the following ranges: "1:5,7:8,13,15:17".
290 	  *
291 	  * @param uids a vector containing UIDs of the messages
292 	  * @return new message set
293 	  */
294 	static messageSet byUID(const std::vector <message::uid>& uids);
295 
296 	/** Adds the specified range to this set. The type of message range
297 	  * (either number or UID) must match the type of the ranges already
298 	  * contained in this set (ie. it's not possible to have a message
299 	  * set which contains both number ranges and UID ranges).
300 	  *
301 	  * @param range range to add
302 	  * @throw std::invalid_argument exception if the range type does
303 	  * not match the type of the ranges in this set
304 	  */
305 	void addRange(const messageRange& range);
306 
307 	/** Enumerates this set with the specified enumerator.
308 	  *
309 	  * @param en enumerator that will receive the method calls while
310 	  * enumerating the ranges in this set
311 	  */
312 	void enumerate(messageSetEnumerator& en) const;
313 
314 	/** Returns whether this set is empty (contains no range).
315 	  *
316 	  * @return true if this set is empty, or false otherwise
317 	  */
318 	bool isEmpty() const;
319 
320 	/** Returns whether this set references messages by their sequence
321 	  * number.
322 	  *
323 	  * @return true if this set references messages by their sequence
324 	  * number, or false otherwise
325 	  */
326 	bool isNumberSet() const;
327 
328 	/** Returns whether this set references messages by their UID.
329 	  *
330 	  * @return true if this set references messages by their UID,
331 	  * or false otherwise
332 	  */
333 	bool isUIDSet() const;
334 
335 	/** Returns the number of ranges contained in this set.
336 	  *
337 	  * @return range count
338 	  */
339 	size_t getRangeCount() const;
340 
341 	/** Returns the message range at the specified index.
342 	  *
343 	  * @param i range index (from 0 to getRangeCount())
344 	  * @return a reference to the message range at the specified index
345 	  */
346 	const messageRange& getRangeAt(const size_t i) const;
347 
348 private:
349 
350 	messageSet();
351 
352 	std::vector <messageRange*> m_ranges;
353 };
354 
355 
356 } // net
357 } // vmime
358 
359 
360 #endif // VMIME_HAVE_MESSAGING_FEATURES
361 
362 
363 #endif // VMIME_NET_MESSAGESET_HPP_INCLUDED
364