1//
2// RowIterator.cpp
3//
4// Library: Data
5// Package: DataCore
6// Module: RowIterator
7//
8// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Data/RowIterator.h"
16#include "Poco/Data/RecordSet.h"
17#undef min
18#undef max
19#include <limits>
20
21
22namespace Poco {
23namespace Data {
24
25
26const std::size_t RowIterator::POSITION_END = std::numeric_limits<std::size_t>::max();
27
28
29RowIterator::RowIterator(RecordSet* pRecordSet, bool positionEnd):
30 _pRecordSet(pRecordSet),
31 _position(positionEnd ? POSITION_END : 0)
32{
33}
34
35
36RowIterator::RowIterator(const RowIterator& other):
37 _pRecordSet(other._pRecordSet),
38 _position(other._position)
39{
40}
41
42
43RowIterator::~RowIterator()
44{
45}
46
47
48RowIterator& RowIterator::operator = (const RowIterator& other)
49{
50 RowIterator tmp(other);
51 swap(tmp);
52 return *this;
53}
54
55
56void RowIterator::swap(RowIterator& other)
57{
58 using std::swap;
59
60 swap(_pRecordSet, other._pRecordSet);
61 swap(_position, other._position);
62}
63
64
65void RowIterator::increment() const
66{
67 if (POSITION_END == _position)
68 throw RangeException("End of iterator reached.");
69
70 if (_position < _pRecordSet->storageRowCount() - 1)
71 ++_position;
72 else
73 _position = POSITION_END;
74
75 if (_pRecordSet->getFilter() && POSITION_END != _position)
76 {
77 while (!_pRecordSet->isAllowed(_position))
78 {
79 increment();
80 if (POSITION_END == _position) break;
81 }
82 }
83}
84
85
86void RowIterator::decrement() const
87{
88 if (0 == _position)
89 throw RangeException("Beginning of iterator reached.");
90 else if (POSITION_END == _position)
91 _position = _pRecordSet->storageRowCount() - 1;
92 else
93 --_position;
94
95 if (_pRecordSet->getFilter() && 0 != _position)
96 {
97 while (!_pRecordSet->isAllowed(_position))
98 {
99 decrement();
100 if (0 == _position) break;
101 }
102 }
103}
104
105
106void RowIterator::setPosition(std::size_t pos) const
107{
108 if (_position == pos) return;
109
110 if (_pRecordSet->getFilter())
111 {
112 std::size_t start = _position;
113 if (_position > pos)
114 {
115 std::size_t end = _position - pos;
116 for (; start > end; --start)
117 {
118 if (pos) --pos;
119 else throw RangeException("Invalid position argument.");
120 }
121 }
122 else
123 {
124 std::size_t end = pos - _position;
125 for (; start < end; ++start)
126 {
127 if (_pRecordSet->storageRowCount() != pos) ++pos;
128 else throw RangeException("Invalid position argument.");
129 }
130 }
131 }
132
133 if (pos < _pRecordSet->storageRowCount())
134 _position = pos;
135 else if (pos == _pRecordSet->storageRowCount())
136 _position = POSITION_END;
137 else
138 throw RangeException("Invalid position argument.");
139}
140
141
142Row& RowIterator::operator * () const
143{
144 if (POSITION_END == _position)
145 throw InvalidAccessException("End of iterator reached.");
146
147 return _pRecordSet->row(_position);
148}
149
150
151Row* RowIterator::operator -> () const
152{
153 if (POSITION_END == _position)
154 throw InvalidAccessException("End of iterator reached.");
155
156 return &_pRecordSet->row(_position);
157}
158
159
160const RowIterator& RowIterator::operator ++ () const
161{
162 increment();
163 return *this;
164}
165
166
167RowIterator RowIterator::operator ++ (int) const
168{
169 RowIterator old(*this);
170 increment();
171 return old;
172}
173
174
175const RowIterator& RowIterator::operator -- () const
176{
177 decrement();
178 return *this;
179}
180
181
182RowIterator RowIterator::operator -- (int) const
183{
184 RowIterator old(*this);
185 decrement();
186 return old;
187}
188
189
190RowIterator RowIterator::operator + (std::size_t diff) const
191{
192 RowIterator ri(*this);
193 ri.setPosition(_position + diff);
194 return ri;
195}
196
197
198RowIterator RowIterator::operator - (std::size_t diff) const
199{
200 if (diff > _position) throw RangeException("Invalid position argument.");
201 RowIterator ri(*this);
202 ri.setPosition(_position - diff);
203 return ri;
204}
205
206
207} } // namespace Poco::Data
208