1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #ifndef TROJITA_RINGBUFFER_H
23 #define TROJITA_RINGBUFFER_H
30 /** @short Circular buffer holding a number of items
32 This class holds a fixed number of items. Use the append() function to put stuff into it. When you want to retrieve them,
33 obtain an iterator by calling begin(). The returned iterator will cease to be valid immediately after modifying the ring
34 buffer. Iteration has to be performed by comparing the current value of an iterator for equivalence against the
35 container's end(), and incrementing the iterator. Any other form is not supported.
37 Invalidated iterators will likely not get caught.
43 /** @short Constat iterator fro visiting the items after each other, starting at the oldest one
45 The iterator itself is linear, ie. it won't wrap. It will however
49 const RingBuffer
<T
> *container_
;
52 /** @short Dereference the iterator */
53 const T
&operator*() const
55 // It has to point to a correct offset
56 Q_ASSERT(offset_
>= 0 && offset_
< container_
->buf_
.size());
57 int pos
= container_
->wrapped_
?
58 // It got wrapped, so we have to get wrapped past the end, too, and start at the oldest one
59 (container_
->appendPos_
+ offset_
) % container_
->buf_
.size() :
62 return container_
->buf_
[pos
];
65 const T
*operator->() const
70 /** @short Increment the iterator */
71 const_iterator
&operator++()
74 // Allow incrementing to the end, ie. one past the last item
75 Q_ASSERT(offset_
<= container_
->buf_
.size());
79 /** @short Compare two iterators from the same container for equality */
80 bool operator==(const const_iterator
&other
) const
82 Q_ASSERT(container_
== other
.container_
);
83 return offset_
== other
.offset_
;
86 /** @short Compare two iterators from the same container for inqeuality */
87 bool operator!=(const const_iterator
&other
) const
89 return !(*this == other
);
92 friend class RingBuffer
<T
>;
93 const_iterator(const RingBuffer
<T
> *container
, int offset
): container_(container
), offset_(offset
)
98 /** @short Instantiate a ring buffer holding size elements */
99 RingBuffer(const int size
): buf_(size
), appendPos_(0), wrapped_(false), skipped_(0)
104 /** @short Return an interator pointing to the oldest item in the container */
105 const_iterator
begin() const
107 return const_iterator(this, 0);
110 /** @short Return an interator pointing to one item past the recent addition */
111 const_iterator
end() const
113 return const_iterator(this, wrapped_
? buf_
.size() : appendPos_
);
116 /** @short Append an item to the container. Oldest item could get overwritten. */
117 void append(const T
&what
)
119 if (appendPos_
== buf_
.size()) {
125 buf_
[appendPos_
] = what
;
129 /** @short Remove all items from the container */
132 buf_
= QVector
<T
>(buf_
.size());
138 /** @short How many items were overwritten */
139 uint
skippedCount() const
153 #endif // TROJITA_RINGBUFFER_H