1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #if !defined(STLHELPERS_HEADER_GUARD_1357924680)
19 #define STLHELPERS_HEADER_GUARD_1357924680
20 
21 
22 
23 // Base include file.  Must be first.
24 #include <xalanc/Include/PlatformDefinitions.hpp>
25 
26 
27 
28 #include <algorithm>
29 #include <functional>
30 
31 
32 
33 #include <xalanc/Include/XalanMap.hpp>
34 
35 
36 
37 namespace XALAN_CPP_NAMESPACE {
38 
39 
40 
41 template<class Type>
42 struct
43 XalanDestroyFunctor
44 {
45     void
operator ()XALAN_CPP_NAMESPACE::XalanDestroyFunctor46     operator()(Type&  theArg)
47     {
48         theArg.~Type();
49     }
50 
51     void
operator ()XALAN_CPP_NAMESPACE::XalanDestroyFunctor52     operator()(Type*  theArg)
53     {
54         theArg->~Type();
55     }
56 
57     void
operator ()XALAN_CPP_NAMESPACE::XalanDestroyFunctor58     operator()(const Type*    theArg)
59     {
60         (*this)(const_cast<Type*>(theArg));
61     }
62 
63     void
operator ()XALAN_CPP_NAMESPACE::XalanDestroyFunctor64     operator()(
65                 Type*               theArg,
66                 MemoryManager&  theMemoryManager)
67     {
68         if (theArg != 0)
69         {
70             (*this)(*theArg);
71 
72             theMemoryManager.deallocate(theArg);
73         }
74     }
75 
76     void
operator ()XALAN_CPP_NAMESPACE::XalanDestroyFunctor77     operator()(
78                 const Type*         theArg,
79                 MemoryManager&  theMemoryManager)
80     {
81         (*this)(const_cast<Type*>(theArg), theMemoryManager);
82     }
83 };
84 
85 
86 
87 template<class Type>
88 XalanDestroyFunctor<Type>
makeXalanDestroyFunctor(const Type *)89 makeXalanDestroyFunctor(const Type*     /* theType */)
90 {
91     return XalanDestroyFunctor<Type>();
92 }
93 
94 
95 
96 /**
97  * Functor to delete objects, used in STL iteration algorithms.
98  */
99 template <class Type>
100 struct DeleteFunctor
101 {
DeleteFunctorXALAN_CPP_NAMESPACE::DeleteFunctor102     DeleteFunctor(MemoryManager&    theManager) :
103         m_memoryManager(theManager)
104     {
105     }
106 
107     /**
108      * Delete the object pointed to by argument.
109      *
110      * @param thePointer pointer to object to be deleted
111      */
112     void
operator ()XALAN_CPP_NAMESPACE::DeleteFunctor113     operator()(const Type*    thePointer) const
114     {
115         return makeXalanDestroyFunctor(thePointer)(thePointer, m_memoryManager);
116     }
117 
118 private:
119 
120    MemoryManager&   m_memoryManager;
121 };
122 
123 
124 /**
125  * Functor to call a clear() member function on its argument.
126  */
127 template <class Type>
128 struct ClearFunctor
129 {
130     /**
131      * Retrieve the value of a key-value pair.
132      *
133      * @param thePair key-value pair
134      * @return value
135      */
136     void
operator ()XALAN_CPP_NAMESPACE::ClearFunctor137     operator()(Type&   theArg) const
138     {
139         return theArg.clear();
140     }
141 };
142 
143 
144 
145 /**
146  * Functor to delete value objects in maps, used in STL iteration algorithms.
147  */
148 template <class T>
149 struct MapValueDeleteFunctor
150 {
MapValueDeleteFunctorXALAN_CPP_NAMESPACE::MapValueDeleteFunctor151     MapValueDeleteFunctor(MemoryManager&    theManager) :
152         m_memoryManager(theManager)
153     {
154     }
155 
156     /**
157      * Delete the value object in a map value pair.  The value of the pair must
158      * be of pointer type.
159      *
160      * @param thePair key-value pair
161      */
162     void
operator ()XALAN_CPP_NAMESPACE::MapValueDeleteFunctor163     operator()(const typename T::value_type&    thePair) const
164     {
165         return makeXalanDestroyFunctor(thePair.second)(thePair.second, m_memoryManager);
166     }
167 
168 private:
169 
170     MemoryManager&  m_memoryManager;
171 };
172 
173 
174 
175 template<class MapType>
176 MapValueDeleteFunctor<MapType>
makeMapValueDeleteFunctor(MapType & theMap)177 makeMapValueDeleteFunctor(MapType&   theMap)
178 {
179     return MapValueDeleteFunctor<MapType>(theMap.getMemoryManager());
180 }
181 
182 
183 
184 /**
185  * This functor is designed to compare 0-terminated arrays.  It substitutes
186  * for the default less<type*> so that pointers to arrays can be compared,
187  * rather than copies of arrays.  For example, you might want to use C-style
188  * strings as keys in a map, rather than string objects.  The default
189  * algorithm less<const char*> would just compare the pointers, and not the
190  * vector of characters to which it points.  Using this algorithm instead of
191  * the default will allow the map to work as expected.
192  */
193 template<class T>
194 struct less_null_terminated_arrays
195 {
196     /**
197      * Compare the values of two objects.
198      *
199      *
200      * @param theLHS first object to compare
201      * @param theRHS second object to compare
202      * @return true if objects are the same
203      */
204     bool
operator ()XALAN_CPP_NAMESPACE::less_null_terminated_arrays205     operator()(
206             const T*    theLHS,
207             const T*    theRHS) const
208     {
209         while(*theLHS && *theRHS)
210         {
211             if (*theLHS != *theRHS)
212             {
213                 break;
214             }
215             else
216             {
217                 theLHS++;
218                 theRHS++;
219             }
220         }
221 
222         return *theLHS < *theRHS ? true : false;
223     }
224 };
225 
226 
227 
228 template<class T>
229 struct equal_null_terminated_arrays
230 {
231     /**
232      * Compare the values of two objects.
233      *
234      *
235      * @param theLHS first object to compare
236      * @param theRHS second object to compare
237      * @return true if objects are the same
238      */
239     bool
operator ()XALAN_CPP_NAMESPACE::equal_null_terminated_arrays240     operator()(
241             const T*    theLHS,
242             const T*    theRHS) const
243     {
244         while(*theLHS && *theRHS)
245         {
246             if (*theLHS != *theRHS)
247             {
248                 return false;
249             }
250             else
251             {
252                 ++theLHS;
253                 ++theRHS;
254             }
255         }
256 
257         if (*theLHS || *theRHS)
258         {
259             return false;
260         }
261         else
262         {
263             return true;
264         }
265     }
266 };
267 
268 
269 
270 template <class ScalarType>
271 inline size_t
XalanScalarHash(ScalarType theValue,size_t theResult)272 XalanScalarHash(
273             ScalarType  theValue,
274             size_t      theResult)
275 {
276     return (theResult * 37) + (theResult >> 24) + size_type(theValue);
277 }
278 
279 
280 
281 template <class T>
282 struct hash_non_terminated_array
283 {
284     size_t
operator ()XALAN_CPP_NAMESPACE::hash_non_terminated_array285     operator() (
286         const T*    theKey,
287         size_t      theLength,
288         size_t      theInitialValue = 0) const
289     {
290         size_t      theHashValue = theInitialValue;
291 
292         const T*    theEnd =
293                 theKey + theLength;
294 
295         while (theKey != theEnd)
296         {
297             theHashValue += XalanScalarHash(*theKey, theHashValue);
298 
299             ++theKey;
300         }
301 
302         return ++theHashValue;
303     }
304 };
305 
306 
307 
308 template <class T>
309 struct hash_null_terminated_array
310 {
311     size_t
operator ()XALAN_CPP_NAMESPACE::hash_null_terminated_array312     operator() (
313         const T*   theKey,
314         size_t     theInitialValue = 0) const
315     {
316         size_t     theHashValue = theInitialValue;
317 
318         while (*theKey)
319         {
320             theHashValue += XalanScalarHash(*theKey, theHashValue);
321 
322             ++theKey;
323         }
324 
325         return ++theHashValue;
326     }
327 };
328 
329 
330 
331 template<>
332 struct XalanMapKeyTraits<const XalanDOMChar*>
333 {
334     typedef hash_null_terminated_array<XalanDOMChar>   Hasher;
335     typedef equal_null_terminated_arrays<XalanDOMChar>  Comparator;
336 };
337 
338 
339 
340 template<class CollectionType>
341 class CollectionClearGuard
342 {
343 public:
344 
CollectionClearGuard(CollectionType & theCollection)345     CollectionClearGuard(CollectionType&    theCollection) :
346         m_collection(&theCollection)
347     {
348     }
349 
~CollectionClearGuard()350     ~CollectionClearGuard()
351     {
352         if (m_collection != 0)
353         {
354             m_collection->clear();
355         }
356     }
357 
358     void
release()359     release()
360     {
361         m_collection = 0;
362     }
363 
364 private:
365 
366     // Not implemented...
367     CollectionClearGuard(const CollectionClearGuard<CollectionType>&);
368 
369     CollectionClearGuard<CollectionType>&
370     operator=(const CollectionClearGuard<CollectionType>&);
371 
372     // Data members...
373     CollectionType*     m_collection;
374 };
375 
376 
377 
378 template<class CollectionType, class DeleteFunctorType>
379 class CollectionDeleteGuard
380 {
381 public:
382 
CollectionDeleteGuard(CollectionType & theCollection)383     CollectionDeleteGuard(CollectionType&   theCollection) :
384         m_collection(&theCollection)
385     {
386     }
387 
~CollectionDeleteGuard()388     ~CollectionDeleteGuard()
389     {
390         if (m_collection != 0)
391         {
392             using std::for_each;
393 
394             // Delete all of the objects in the temp vector.
395             for_each(m_collection->begin(),
396                      m_collection->end(),
397                      DeleteFunctorType(m_collection->getMemoryManager()));
398         }
399     }
400 
401     void
release()402     release()
403     {
404         m_collection = 0;
405     }
406 
407 private:
408 
409     // Not implemented...
410     CollectionDeleteGuard(const CollectionDeleteGuard<CollectionType, DeleteFunctorType>&);
411 
412     CollectionDeleteGuard<CollectionType, DeleteFunctorType>&
413     operator=(const CollectionDeleteGuard<CollectionType, DeleteFunctorType>&);
414 
415     // Data members...
416     CollectionType*     m_collection;
417 };
418 
419 
420 
421 template<class T>
422 struct pointer_equals
423 {
424     bool
operator ()XALAN_CPP_NAMESPACE::pointer_equals425     operator()(
426         const T*    theLHS,
427         const T*    theRHS) const
428     {
429         assert(theLHS != 0 && theRHS != 0);
430 
431         return *theLHS == *theRHS;
432     }
433 };
434 
435 
436 
437 template<class T>
438 struct pointer_equals_predicate
439 {
pointer_equals_predicateXALAN_CPP_NAMESPACE::pointer_equals_predicate440     pointer_equals_predicate(const T*    theArg) :
441         m_arg(theArg)
442     {
443     }
444 
445     bool
operator ()XALAN_CPP_NAMESPACE::pointer_equals_predicate446     operator()(
447         const T*   theOther) const
448     {
449         assert(theOther != 0);
450 
451         return *theOther == *m_arg;
452     }
453 
454 private:
455 
456     const T*    m_arg;
457 };
458 
459 
460 
461 template<class T>
462 struct pointer_less
463 {
464     bool
operator ()XALAN_CPP_NAMESPACE::pointer_less465     operator()(
466         const T*    theLHS,
467         const T*    theRHS) const
468     {
469         assert(theLHS != 0 && theRHS != 0);
470 
471         using std::less;
472 
473         return less<T>()(*theLHS, *theRHS);
474     }
475 };
476 
477 
478 
479 template<class T>
480 struct pointer_equal
481 {
482     bool
operator ()XALAN_CPP_NAMESPACE::pointer_equal483     operator()(
484         const T*    theLHS,
485         const T*    theRHS) const
486     {
487         assert(theLHS != 0 && theRHS != 0);
488         return std::equal_to<T>()(*theLHS, *theRHS);
489     }
490 };
491 
492 
493 
494 
495 }
496 
497 
498 
499 #endif  // STLHELPERS_HEADER_GUARD_1357924680
500