1/*
2 * Copyright (c) 2017, Matias Fontanini
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#ifndef CPPKAFKA_HEADER_LIST_ITERATOR_H
31#define CPPKAFKA_HEADER_LIST_ITERATOR_H
32
33#include <cstddef>
34#include <utility>
35#include <iterator>
36#include "header.h"
37
38#if (RD_KAFKA_VERSION >= RD_KAFKA_HEADERS_SUPPORT_VERSION)
39
40namespace cppkafka {
41
42template <typename HeaderType>
43class HeaderList;
44
45template <typename HeaderType>
46class HeaderIterator;
47
48template <typename HeaderType>
49bool operator==(const HeaderIterator<HeaderType>& lhs, const HeaderIterator<HeaderType>& rhs);
50
51/**
52 * \brief Iterator over a HeaderList object.
53 * \tparam HeaderType The type of header this iterator points to.
54 */
55template <typename HeaderType>
56class HeaderIterator {
57public:
58 friend HeaderList<HeaderType>;
59 using HeaderListType = HeaderList<HeaderType>;
60 using BufferType = typename HeaderType::ValueType;
61 //std::iterator_traits
62 using difference_type = std::ptrdiff_t;
63 using value_type = HeaderType;
64 using pointer = value_type*;
65 using reference = value_type&;
66 using iterator_category = std::bidirectional_iterator_tag;
67 friend bool operator==<HeaderType>(const HeaderIterator<HeaderType>& lhs,
68 const HeaderIterator<HeaderType>& rhs);
69
70 HeaderIterator(const HeaderIterator& other)
71 : header_list_(other.header_list_),
72 header_(make_header(other.header_)),
73 index_(other.index_) {
74
75 }
76 HeaderIterator& operator=(const HeaderIterator& other) {
77 if (this == &other) return *this;
78 header_list_ = other.header_list_;
79 header_ = make_header(other.header_);
80 index_ = other.index_;
81 return *this;
82 }
83 HeaderIterator(HeaderIterator&&) = default;
84 HeaderIterator& operator=(HeaderIterator&&) = default;
85
86 /**
87 * \brief Prefix increment of the iterator.
88 * \return Itself after being incremented.
89 */
90 HeaderIterator& operator++() {
91 assert(index_ < header_list_.size());
92 ++index_;
93 return *this;
94 }
95
96 /**
97 * \brief Postfix increment of the iterator.
98 * \return Itself before being incremented.
99 */
100 HeaderIterator operator++(int) {
101 HeaderIterator tmp(*this);
102 operator++();
103 return tmp;
104 }
105
106 /**
107 * \brief Prefix decrement of the iterator.
108 * \return Itself after being decremented.
109 */
110 HeaderIterator& operator--() {
111 assert(index_ > 0);
112 --index_;
113 return *this;
114 }
115
116 /**
117 * \brief Postfix decrement of the iterator.
118 * \return Itself before being decremented.
119 */
120 HeaderIterator operator--(int) {
121 HeaderIterator tmp(*this);
122 operator--();
123 return tmp;
124 }
125
126 /**
127 * \brief Dereferences this iterator.
128 * \return A reference to the header the iterator points to.
129 * \warning Throws if invalid or if *this == end().
130 */
131 const HeaderType& operator*() const {
132 header_ = header_list_.at(index_);
133 return header_;
134 }
135 HeaderType& operator*() {
136 header_ = header_list_.at(index_);
137 return header_;
138 }
139
140 /**
141 * \brief Dereferences this iterator.
142 * \return The address to the header the iterator points to.
143 * \warning Throws if invalid or if *this == end().
144 */
145 const HeaderType* operator->() const {
146 header_ = header_list_.at(index_);
147 return &header_;
148 }
149 HeaderType* operator->() {
150 header_ = header_list_.at(index_);
151 return &header_;
152 }
153
154private:
155 HeaderIterator(const HeaderListType& headers,
156 size_t index)
157 : header_list_(headers),
158 index_(index) {
159 }
160
161 template <typename T>
162 T make_header(const T& other) {
163 return other;
164 }
165
166 Header<Buffer> make_header(const Header<Buffer>& other) {
167 return Header<Buffer>(other.get_name(),
168 Buffer(other.get_value().get_data(),
169 other.get_value().get_size()));
170 }
171
172 const HeaderListType& header_list_;
173 HeaderType header_;
174 size_t index_;
175};
176
177// Equality comparison operators
178template <typename HeaderType>
179bool operator==(const HeaderIterator<HeaderType>& lhs, const HeaderIterator<HeaderType>& rhs) {
180 return (lhs.header_list_.get_handle() == rhs.header_list_.get_handle()) && (lhs.index_ == rhs.index_);
181}
182
183template <typename HeaderType>
184bool operator!=(const HeaderIterator<HeaderType>& lhs, const HeaderIterator<HeaderType>& rhs) {
185 return !(lhs == rhs);
186}
187
188} //namespace cppkafka
189
190#endif //RD_KAFKA_HEADERS_SUPPORT_VERSION
191
192#endif //CPPKAFKA_HEADER_LIST_ITERATOR_H
193
194