1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_FRAMEWORK_INC_CLASSES_CHECKEDITERATOR_HXX
#define INCLUDED_FRAMEWORK_INC_CLASSES_CHECKEDITERATOR_HXX
#include <sal/types.h>
#include <iterator>
namespace framework{
/*-************************************************************************************************************
@short implement a iterator which support 2 end states!
@descr For our search methods we need a "walking" iterator object with special functionality!
We must check for 3 different states of an iterator - normal position, exact end, after end.
It's necessary to detect if we have not found a entry and must return our default or
default already returned and we must break loop!
see using in class FilterCache too for further information!
@Attention If your wish to debug this inline code ...
under windows and msdev you can use "set ENVCFLAGS=/Ob0" to do that!
@devstatus ready to use
@threadsafe no
*//*-*************************************************************************************************************/
template< class TContainer >
class CheckedIterator
{
// public methods
public:
// constructor / destructor
/*-****************************************************************************************************
@short standard constructor
@descr Set default values on members.
We set it internal to E_UNKNOWN to detect uninitialized instances of this class.
If we found one - we know: "We must call initialize first!"
*//*-*****************************************************************************************************/
inline CheckedIterator()
: m_eEndState ( E_UNKNOWN )
, m_pContainer( NULL )
{
}
// interface methods
/*-****************************************************************************************************
@short initialize instance with valid container
@descr Set new container at an instance of this class. The other member will set automatically!
m_pPosition = first element in container
m_eEndState = BEFOREEND
@param "rContainer", must be a valid reference to an existing container.
@onerror An assertion is thrown.
*//*-*****************************************************************************************************/
inline void initialize( const TContainer& rContainer )
{
// Check incoming parameter. We don't accept all!
SAL_WARN_IF( &rContainer==NULL, "fwk", "CheckedIterator::initialize(): Invalid parameter detected!" );
SAL_WARN_IF( m_eEndState!=E_UNKNOWN, "fwk", "CheckedIterator::initialize(): Instance already initialized! Don't do it again." );
if( m_eEndState == E_UNKNOWN )
{
// Set new container and update other member.
m_pContainer = &rContainer;
m_eEndState = E_BEFOREEND;
m_pPosition = m_pContainer->begin();
}
}
/*-****************************************************************************************************
@short set internal states to E_END
@descr Sometimes we need a "walking" check-iterator which is initialized with the END-state!
We need it to return one default value if no other ones exist ...
@seealso using in class FilterCache!
*//*-*****************************************************************************************************/
inline void setEnd()
{
m_pContainer = NULL;
m_eEndState = E_END;
}
/*-****************************************************************************************************
@short set internal states to E_AFTEREND
@descr Sometimes we need a "walking" check-iterator which is initialized with AFTEREND-state!
We need it if we don't have a container but must prevent us against further searching!
@seealso using in class FilterCache!
*//*-*****************************************************************************************************/
inline void setAfterEnd()
{
m_pContainer = NULL;
m_eEndState = E_AFTEREND;
}
/*-****************************************************************************************************
@short reset this iterator
@descr It must be called on an already initialized iterator.
Means the member m_pContainer must be valid. Otherwise the reaction
isn't defined.
*//*-*****************************************************************************************************/
inline void reset()
{
m_eEndState = E_UNKNOWN;
m_pContainer = NULL;
}
/*-****************************************************************************************************
@short step to next element in container.
@descr If end of container is reached we change our internal "m_eEndState".
If end reached for first time; we set it to E_END;
If you step to next element again; we set it to E_AFTEREND.
So you have a chance to differ between "exact end" and "after end"!
@seealso method isEnd()
@seealso method isAfterEnd()
@return A reference to our changed object himself.
*//*-*****************************************************************************************************/
inline CheckedIterator& operator++()
{
// Warn programmer if he forget to initailize object!
SAL_WARN_IF( m_pContainer==NULL, "fwk", "CheckedIterator::operator++(): Object not initialized!" );
// Step to next element if any exist or set our end states.
switch( m_eEndState )
{
case E_BEFOREEND: {
++m_pPosition;
// If iterator reaching end ... set right state!
if( m_pPosition == m_pContainer->end() )
{
m_eEndState = E_END;
}
}
break;
case E_END : {
// Set state only ... iterator already points to end of container!
m_eEndState = E_AFTEREND;
}
break;
}
return *this;
}
/*-****************************************************************************************************
@short return true if internal iterator was not initialized before
@descr These will be true, if use start a new search by using these iterator mechanism!
@seealso class FilterCache
@return True if internalk state E_UNKNOWN - false otherwise.
*//*-*****************************************************************************************************/
inline bool isUninitialized()
{
return( m_eEndState == E_UNKNOWN );
}
/*-****************************************************************************************************
@short return true if internal iterator reached end of container
@descr These will be true if you step to the end of internal container.
@seealso method isAfterEnd()
@return True if end reached; false otherwise.
*//*-*****************************************************************************************************/
inline bool isEnd()
{
// Is true if one end state is set!
return (
( m_eEndState == E_END ) ||
( m_eEndState == E_AFTEREND )
);
}
/*-****************************************************************************************************
@short return true if you call operator++ again and end already reached
@descr These indicate, that end already reached but you call operator++ again and again!
@seealso method isEnd()
@return True if end multiple reached; false otherwise.
*//*-*****************************************************************************************************/
inline bool isAfterEnd()
{
// Is true only, if special end state is set!
return( m_eEndState == E_AFTEREND );
}
/*-****************************************************************************************************
@short support readonly access to container entry
@descr Use it to get the value of current container item.
@return A reference to value of container entry.
*//*-*****************************************************************************************************/
inline typename TContainer::const_iterator getEntry()
{
// Warn programmer if he forget to initialize these object ...
SAL_WARN_IF( m_pContainer==NULL, "fwk", "CheckedIterator::getEntry(): Object not initialized!" );
// or try to read a non existing element!
SAL_WARN_IF( m_eEndState!=E_BEFOREEND, "fwk", "CheckedIterator::getEntry(): Wrong using of class detected!" );
return m_pPosition;
}
// private member
private:
// This enum defines our four states for an iterator position in current container.
enum EEndState
{
E_UNKNOWN ,
E_BEFOREEND ,
E_END ,
E_AFTEREND
};
const TContainer* m_pContainer; // pointer to current container
EEndState m_eEndState; // "position state" of iterator!
typename TContainer::const_iterator m_pPosition; // point to actual element in container
};
} // namespace framework
#endif // INCLUDED_FRAMEWORK_INC_CLASSES_CHECKEDITERATOR_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|