summaryrefslogtreecommitdiff
path: root/framework/inc/classes/checkediterator.hxx
blob: ceb3d74b430dab15cdfb625611dae9932640045f (plain)
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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
/* -*- 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!

    @implements     -
    @base           -

    @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!"

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        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 automaticly!
                        m_pPosition = first element in container
                        m_eEndState = BEFOREEND

            @seealso    -

            @param      "rContainer", must be a valid reference to an existing container.
            @return     -

            @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!

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        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!

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        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.

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        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()

            @param      -
            @return     A reference to our changed object himself.

            @onerror    -
        *//*-*****************************************************************************************************/

        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

            @param      -
            @return     True if internalk state E_UNKNOWN - false otherwise.

            @onerror    -
        *//*-*****************************************************************************************************/

        inline sal_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()

            @param      -
            @return     True if end reached; false otherwise.

            @onerror    -
        *//*-*****************************************************************************************************/

        inline sal_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()

            @param      -
            @return     True if end multiple reached; false otherwise.

            @onerror    -
        *//*-*****************************************************************************************************/

        inline sal_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.

            @seealso    -

            @param      -
            @return     A reference to value of container entry.

            @onerror    -
        *//*-*****************************************************************************************************/

        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:

        // These enum defines our four states for an iterator position in curent 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: */