1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40//
41// W A R N I N G
42// -------------
43//
44// This file is not part of the Qt API. It exists purely as an
45// implementation detail. This header file may change from version to
46// version without notice, or even be removed.
47//
48// We mean it.
49
50#ifndef Patternist_SequenceMappingIterator_H
51#define Patternist_SequenceMappingIterator_H
52
53#include <private/qabstractxmlforwarditerator_p.h>
54#include <private/qdynamiccontext_p.h>
55
56QT_BEGIN_NAMESPACE
57
58namespace QPatternist
59{
60 /**
61 * @short Proxies another QAbstractXmlForwardIterator, and for each item, returns the
62 * Sequence returned from a mapping function.
63 *
64 * ItemMappingIterator is practical when the items in an QAbstractXmlForwardIterator needs to
65 * be translated to another sequence, while still doing it in a pipe-lined
66 * fashion. In contrast to ItemMappingIterator, SequenceMappingIterator maps
67 * each item into another QAbstractXmlForwardIterator, and where the SequenceMappingIterator's own
68 * result is the concatenation of all those Iterators. Hence, while ItemMappingIterator
69 * is better tailored for one-to-one or one-to-zero conversion, SequenceMappingIterator
70 * is more suitable for one-to-many conversion.
71 *
72 * This is achieved by that SequenceMappingIterator's constructor takes
73 * an instance of a class, that must have the following member:
74 *
75 * @code
76 * QAbstractXmlForwardIterator<TResult>::Ptr mapToSequence(const TSource::Ptr &item,
77 * const DynamicContext::Ptr &context) const;
78 * @endcode
79 *
80 * @author Frans Englich <frans.englich@nokia.com>
81 * @see ItemMappingIterator
82 * @ingroup Patternist_iterators
83 */
84 template<typename TResult, typename TSource, typename TMapper>
85 class SequenceMappingIterator : public QAbstractXmlForwardIterator<TResult>
86 {
87 public:
88 /**
89 * Constructs a SequenceMappingIterator.
90 *
91 * @param mapper the object that has the mapToItem() sequence.
92 * @param sourceIterator the QAbstractXmlForwardIterator whose items should be mapped.
93 * @param context the DynamicContext that will be passed to the map function.
94 * May be null.
95 */
96 SequenceMappingIterator(const TMapper &mapper,
97 const typename QAbstractXmlForwardIterator<TSource>::Ptr &sourceIterator,
98 const DynamicContext::Ptr &context);
99
100 virtual TResult next();
101 virtual xsInteger count();
102 virtual TResult current() const;
103 virtual xsInteger position() const;
104
105 /**
106 * The reason the implementation is placed in line here, is due to a bug
107 * in MSVC-2005 version 14.00.50727.762. Note that it works with version 14.00.50727.42.
108 */
109 virtual typename QAbstractXmlForwardIterator<TResult>::Ptr copy() const
110 {
111 return typename QAbstractXmlForwardIterator<TResult>::Ptr
112 (new SequenceMappingIterator<TResult, TSource, TMapper>(m_mapper,
113 m_mainIterator->copy(),
114 m_context));
115 }
116
117 private:
118 xsInteger m_position;
119 TResult m_current;
120 typename QAbstractXmlForwardIterator<TSource>::Ptr m_mainIterator;
121 typename QAbstractXmlForwardIterator<TResult>::Ptr m_currentIterator;
122 const typename DynamicContext::Ptr m_context;
123 const TMapper m_mapper;
124 };
125
126 template<typename TResult, typename TSource, typename TMapper>
127 SequenceMappingIterator<TResult, TSource, TMapper>::SequenceMappingIterator(
128 const TMapper &mapper,
129 const typename QAbstractXmlForwardIterator<TSource>::Ptr &iterator,
130 const DynamicContext::Ptr &context)
131 : m_position(0),
132 m_mainIterator(iterator),
133 m_context(context),
134 m_mapper(mapper)
135 {
136 Q_ASSERT(mapper);
137 Q_ASSERT(iterator);
138 }
139
140 template<typename TResult, typename TSource, typename TMapper>
141 TResult SequenceMappingIterator<TResult, TSource, TMapper>::next()
142 {
143 /* This was once implemented with a recursive function, but the stack
144 * got blown for some inputs by that approach. */
145 while(true)
146 {
147 while(!m_currentIterator)
148 {
149 const TSource mainItem(m_mainIterator->next());
150
151 if(qIsForwardIteratorEnd(mainItem)) /* We've reached the very end. */
152 {
153 m_position = -1;
154 m_current = TResult();
155 return TResult();
156 }
157 else
158 m_currentIterator = m_mapper->mapToSequence(mainItem, m_context);
159 }
160
161 m_current = m_currentIterator->next();
162
163 if(qIsForwardIteratorEnd(m_current))
164 {
165 m_currentIterator.reset();
166 continue;
167 }
168 else
169 {
170 ++m_position;
171 return m_current;
172 }
173 }
174 }
175
176 template<typename TResult, typename TSource, typename TMapper>
177 xsInteger SequenceMappingIterator<TResult, TSource, TMapper>::count()
178 {
179 TSource unit(m_mainIterator->next());
180 xsInteger c = 0;
181
182 while(!qIsForwardIteratorEnd(unit))
183 {
184 const typename QAbstractXmlForwardIterator<TResult>::Ptr sit(m_mapper->mapToSequence(unit, m_context));
185 c += sit->count();
186 unit = m_mainIterator->next();
187 }
188
189 return c;
190 }
191
192 template<typename TResult, typename TSource, typename TMapper>
193 TResult SequenceMappingIterator<TResult, TSource, TMapper>::current() const
194 {
195 return m_current;
196 }
197
198 template<typename TResult, typename TSource, typename TMapper>
199 xsInteger SequenceMappingIterator<TResult, TSource, TMapper>::position() const
200 {
201 return m_position;
202 }
203
204
205 /**
206 * @short An object generator for SequenceMappingIterator.
207 *
208 * makeSequenceMappingIterator() is a convenience function for avoiding specifying
209 * the full template instantiation for SequenceMappingIterator. Conceptually, it
210 * is identical to Qt's qMakePair().
211 *
212 * @returns a SequenceMappingIterator wrapped in a smart pointer, that has been
213 * passed the constructor arguments @p mapper, @p source, and @p context.
214 * @see makeMappingCallbackPtr()
215 * @relates QAbstractXmlForwardIterator
216 */
217 template<typename TResult, typename TSource, typename TMapper>
218 static inline
219 typename QAbstractXmlForwardIterator<TResult>::Ptr
220 makeSequenceMappingIterator(const TMapper &mapper,
221 const QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<TSource> > &source,
222 const DynamicContext::Ptr &context)
223 {
224 return typename QAbstractXmlForwardIterator<TResult>::Ptr
225 (new SequenceMappingIterator<TResult, TSource, TMapper>(mapper, source, context));
226 }
227}
228
229QT_END_NAMESPACE
230
231#endif
232

source code of qtxmlpatterns/src/xmlpatterns/iterators/qsequencemappingiterator_p.h