1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef __FRAMEWORK_CLASSES_CHECKEDITERATOR_HXX_
29 #define __FRAMEWORK_CLASSES_CHECKEDITERATOR_HXX_
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 
35 #include <macros/debug.hxx>
36 
37 //_________________________________________________________________________________________________________________
38 //	interface includes
39 //_________________________________________________________________________________________________________________
40 
41 //_________________________________________________________________________________________________________________
42 //	other includes
43 //_________________________________________________________________________________________________________________
44 #include <sal/types.h>
45 
46 #ifndef __SGI_STL_ITERATOR
47 #include <iterator>
48 #endif
49 
50 //_________________________________________________________________________________________________________________
51 //	namespace
52 //_________________________________________________________________________________________________________________
53 
54 namespace framework{
55 
56 //_________________________________________________________________________________________________________________
57 //	exported const
58 //_________________________________________________________________________________________________________________
59 
60 //_________________________________________________________________________________________________________________
61 //	exported definitions
62 //_________________________________________________________________________________________________________________
63 
64 /*-************************************************************************************************************//**
65 	@short          implement a iterator which support 2 end states!
66 	@descr			For our search methods we need a "walking" iterator object with special functionality!
67 					We must check for 3 different states of an iterator - normal position, exact end, after end.
68 					It's neccessary to detect if we have not found a entry and must return our default or
69 					default already returned and we must break loop!
70 					see using in class FilterCache too for further informations!
71 
72 	@Attention		If your wish to debug this inline code ...
73 					under windows and msdev you can use "set ENVCFLAGS=/Ob0" to do that!
74 
75 	@implements		-
76 	@base			-
77 
78 	@devstatus		ready to use
79 	@threadsafe		no
80 *//*-*************************************************************************************************************/
81 
82 template< class TContainer >
83 class CheckedIterator
84 {
85 	//-------------------------------------------------------------------------------------------------------------
86 	//	public methods
87 	//-------------------------------------------------------------------------------------------------------------
88 
89 	public:
90 
91 		//---------------------------------------------------------------------------------------------------------
92 		// constructor / destructor
93 		//---------------------------------------------------------------------------------------------------------
94 
95 		/*-****************************************************************************************************//**
96 			@short		standard constructor
97 			@descr		Set default values on members.
98 						We set it internal to E_UNKNOWN to detect uninitialized instances of this class.
99 						If we found one - we know: "We must call initialize first!"
100 
101 			@seealso	-
102 
103 			@param		-
104 			@return		-
105 
106 			@onerror	-
107 		*//*-*****************************************************************************************************/
108 
109 		inline CheckedIterator()
110                 :   m_eEndState ( E_UNKNOWN )
111                 ,   m_pContainer( NULL      )
112 		{
113 		}
114 
115 		//---------------------------------------------------------------------------------------------------------
116 		// interface methods
117 		//---------------------------------------------------------------------------------------------------------
118 
119 		/*-****************************************************************************************************//**
120 			@short		initialize instance with valid container
121 			@descr		Set new container at an instance of this class. The other member will set automaticly!
122 						m_pPosition = first element in container
123 						m_eEndState = BEFOREEND
124 
125 			@seealso	-
126 
127             @param      "rContainer", must be a valid reference to an existing container.
128 			@return		-
129 
130 			@onerror	An assertion is thrown.
131 		*//*-*****************************************************************************************************/
132 
133         inline void initialize( const TContainer& rContainer )
134 		{
135 			// Check incoming parameter. We don't accept all!
136             LOG_ASSERT2( &rContainer==NULL      , "CheckedIterator::initialize()", "Invalid parameter detected!"                        )
137 			LOG_ASSERT2( m_eEndState!=E_UNKNOWN	, "CheckedIterator::initialize()", "Instance already initialized! Don't do it again."	)
138 
139 			if( m_eEndState == E_UNKNOWN )
140 			{
141 				// Set new container and update other member.
142                 m_pContainer = &rContainer          ;
143                 m_eEndState  = E_BEFOREEND          ;
144                 m_pPosition  = m_pContainer->begin();
145 			}
146 		}
147 
148 		/*-****************************************************************************************************//**
149 			@short		set internal states to E_END
150 			@descr		Sometimes we need a "walking" check-iterator which is initialized with the END-state!
151 						We need it to return one default value if no other ones exist ...
152 
153 			@seealso	using in class FilterCache!
154 
155 			@param		-
156 			@return		-
157 
158 			@onerror	-
159 		*//*-*****************************************************************************************************/
160 
161 		inline void setEnd()
162 		{
163             m_pContainer = NULL  ;
164             m_eEndState  = E_END ;
165 		}
166 
167 		/*-****************************************************************************************************//**
168 			@short		set internal states to E_AFTEREND
169 			@descr		Sometimes we need a "walking" check-iterator which is initialized with AFTEREND-state!
170 						We need it if we don't have a container but must prevent us against further searching!
171 
172 			@seealso	using in class FilterCache!
173 
174 			@param		-
175 			@return		-
176 
177 			@onerror	-
178 		*//*-*****************************************************************************************************/
179 
180 		inline void setAfterEnd()
181 		{
182             m_pContainer = NULL       ;
183             m_eEndState  = E_AFTEREND ;
184 		}
185 
186         /*-****************************************************************************************************//**
187             @short      reset this iterator
188             @descr      It must be called on an already initialized iterator.
189                         Means the member m_pContainer must be valid. Otherwhise the reaction
190                         isn't defined.
191 
192             @param      -
193             @return     -
194 
195             @onerror    -
196         *//*-*****************************************************************************************************/
197 
198         inline void reset()
199         {
200             m_eEndState  = E_UNKNOWN;
201             m_pContainer = NULL;
202         }
203 
204 		/*-****************************************************************************************************//**
205 			@short		step to next element in container.
206 			@descr		If end of container is reached we change our internal "m_eEndState".
207 						If end reached for first time; we set it to E_END;
208 						If you step to next element again; we set it to E_AFTEREND.
209 						So you have a chance to differ between "exact end" and "after end"!
210 
211 			@seealso	method isEnd()
212 			@seealso	method isAfterEnd()
213 
214 			@param		-
215 			@return		A reference to our changed object himself.
216 
217 			@onerror	-
218 		*//*-*****************************************************************************************************/
219 
220 		inline CheckedIterator& operator++()
221 		{
222 			// Warn programmer if he forget to initailize object!
223             LOG_ASSERT2( m_pContainer==NULL, "CheckedIterator::operator++()", "Object not initialized!" )
224 			// Step to next element if any exist or set our end states.
225 			switch( m_eEndState )
226 			{
227 				case E_BEFOREEND:	{
228                                         ++m_pPosition;
229                                         // If iterator reaching end ... set right state!
230                                         if( m_pPosition == m_pContainer->end() )
231 										{
232 											m_eEndState = E_END;
233 										}
234 									}
235 									break;
236 				case E_END		:	{
237                                         // Set state only ... iterator already points to end of container!
238 										m_eEndState = E_AFTEREND;
239 									}
240 									break;
241 			}
242 			return *this;
243 		}
244 
245 		/*-****************************************************************************************************//**
246 			@short		return true if internal iterator was not initialized before
247 			@descr		These will be true, if use start a new search by using these iterator mechanism!
248 
249 			@seealso	class FilterCache
250 
251 			@param		-
252 			@return		True if internalk state E_UNKNOWN - false otherwise.
253 
254 			@onerror	-
255 		*//*-*****************************************************************************************************/
256 
257 		inline sal_Bool isUninitialized()
258 		{
259 			return( m_eEndState == E_UNKNOWN );
260 		}
261 
262 		/*-****************************************************************************************************//**
263 			@short		return true if internal iterator reached end of container
264 			@descr		These will be true if you step to the end of internal container.
265 
266 			@seealso	method isAfterEnd()
267 
268 			@param		-
269 			@return		True if end reached; false otherwise.
270 
271 			@onerror	-
272 		*//*-*****************************************************************************************************/
273 
274 		inline sal_Bool isEnd()
275 		{
276 			// Is true if one end state is set!
277 			return	(
278 						( m_eEndState == E_END		)	||
279 						( m_eEndState == E_AFTEREND	)
280 					);
281 		}
282 
283 		/*-****************************************************************************************************//**
284 			@short		return true if you call operator++ again and end already reached
285 			@descr		These indicate, that end already reached but you call operator++ again and again!
286 
287 			@seealso	method isEnd()
288 
289 			@param		-
290 			@return		True if end multiple reached; false otherwise.
291 
292 			@onerror	-
293 		*//*-*****************************************************************************************************/
294 
295 		inline sal_Bool isAfterEnd()
296 		{
297 			// Is true only, if special end state is set!
298 			return( m_eEndState == E_AFTEREND );
299 		}
300 
301 		/*-****************************************************************************************************//**
302 			@short		support readonly access to container entry
303 			@descr		Use it to get the value of current container item.
304 
305 			@seealso	-
306 
307 			@param		-
308 			@return		A reference to value of container entry.
309 
310 			@onerror	-
311 		*//*-*****************************************************************************************************/
312 
313 		inline typename TContainer::const_iterator getEntry()
314 		{
315 			// Warn programmer if he forget to initialize these object ...
316             LOG_ASSERT2( m_pContainer==NULL, "CheckedIterator::getEntry()", "Object not initialized!" )
317 			// or try to read a non existing element!
318             LOG_ASSERT2( m_eEndState!=E_BEFOREEND, "CheckedIterator::getEntry()", "Wrong using of class detected!" )
319 
320             return m_pPosition;
321 		}
322 
323 	//-------------------------------------------------------------------------------------------------------------
324 	//	private member
325 	//-------------------------------------------------------------------------------------------------------------
326 
327 	private:
328 
329 		// These enum defines our four states for an iterator position in curent container.
330 		enum EEndState
331 		{
332 			E_UNKNOWN	,
333 			E_BEFOREEND	,
334 			E_END		,
335 			E_AFTEREND
336 		};
337 
338         const TContainer*           m_pContainer    ;   // pointer to current container
339         EEndState                   m_eEndState     ;   // "position state" of iterator!
340         typename TContainer::const_iterator  m_pPosition     ;   // point to actual element in container
341 };
342 
343 }		//	namespace framework
344 
345 #endif	//	#ifndef __FRAMEWORK_CLASSES_CHECKEDITERATOR_HXX_
346