| #ifndef UIMA_STLTOOLS_HPP |
| #define UIMA_STLTOOLS_HPP |
| /** \file stltools.hpp . |
| ------------------------------------------------------------------------------- |
| |
| |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| |
| ------------------------------------------------------------------------------- |
| |
| \brief Contains STL utility functions |
| |
| ------------------------------------------------------------------------------- |
| */ |
| |
| #include "uima/pragmas.hpp" |
| #include "uima/configure.h" |
| #include "uima/types.h" |
| |
| |
| //lint -e1905 : implicit default constructor generated (too often used in STL) |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Include dependencies */ |
| /* ----------------------------------------------------------------------- */ |
| |
| |
| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <map> |
| #include <string> |
| #include <utility> |
| #if defined( UIMA_NO_HASH_CONTAINERS_SUPPORTED ) || defined( UIMA_DONT_USE_HASH_CONTAINERS ) |
| // we include the appropriate headers |
| # include <set> |
| # include <map> |
| #else |
| # if defined(__GNUC__) |
| #define GCC_VERSION (__GNUC__ * 10000 \ |
| + __GNUC_MINOR__ * 100 \ |
| + __GNUC_PATCHLEVEL__) |
| # if (__GNUC__ >= 3) |
| # include <ext/hash_set> |
| # include <ext/hash_map> |
| # if (__GNUC_MINOR__ > 0) |
| using namespace __gnu_cxx; |
| # endif |
| # else // gcc 2.9 |
| # include <hash_set> |
| # include <hash_map> |
| # endif |
| # elif defined(__INTEL_COMPILER) |
| # define _HAS_TRADITIONAL_STL 1 |
| # include <hash_set> |
| # include <hash_map> |
| # else |
| # include <hashset> |
| # include <hashmap> |
| # endif |
| #endif |
| |
| namespace uima { |
| |
| /* ----------------------------------------------------------------------- */ |
| /* ----------------------------------------------------------------------- */ |
| |
| /**@name Hash container defines |
| Defines for hash container which may not be supported by some |
| compilers as they are not ANSI. |
| |
| Depending on the define <TT>UIMA_NO_HASH_CONTAINERS_SUPPORTED</TT>, |
| <TT>taf_stltools.hpp</TT> includes the appropriate headers |
| and establishes defines which can be used for hash and non-hash containers |
| (hash_set <=> set and hash_map <=> map). |
| The define ignores the arguments neccesary for hash |
| containers, but unnecessary for non-hash containers (hash-function). |
| Note: the arguments to the macros must be single tokens, so you cannot write the following: |
| |
| \code |
| typedef UIMA_TY_HASH_SET( ULString, |
| StringHashing1< ULString, icu::UChar >) |
| TyTokenStringSet; |
| \endcode |
| |
| but instead write: |
| |
| \code |
| typedef StringHashing1< ULString, icu::UChar > TyULStringHashFunc; |
| typedef UIMA_TY_HASH_SET( ULString, |
| TyULStringHashFunc) |
| TyTokenStringSet; |
| \endcode |
| |
| See the include file <TT>taf_strhashfuncts.hpp</TT> for some useful string hash |
| functions. |
| */ |
| //@{ |
| |
| // Depending on this define... |
| #if defined( UIMA_NO_HASH_CONTAINERS_SUPPORTED ) || defined( UIMA_DONT_USE_HASH_CONTAINERS ) |
| /// Define for a hash_set/set depending on <TT>UIMA_NO_HASH_CONTAINERS_SUPPORTED</TT> |
| # define UIMA_TY_HASH_SET( ClKeyType, ClElementType, ClHashFunction) \ |
| set< ClElementType, less< ClElementType > > |
| /// Define for a hash_multiset/multiset depending on <TT>UIMA_NO_HASH_CONTAINERS_SUPPORTED</TT> |
| # define UIMA_TY_HASH_MULTISET( ClKeyType, ClElementType, ClHashFunction) \ |
| multiset< ClElementType, less< ClElementType > > |
| /// Define for a hash_map/map depending on <TT>UIMA_NO_HASH_CONTAINERS_SUPPORTED</TT> |
| # define UIMA_TY_HASH_MAP( ClKeyType, ClElementType, ClHashFunction) \ |
| map< ClKeyType, ClElementType, less< ClKeyType > > |
| /// Define for a hash_multimap/multimap depending on <TT>UIMA_NO_HASH_CONTAINERS_SUPPORTED</TT> |
| # define UIMA_TY_HASH_MULTIMAP( ClKeyType, ClElementType, ClHashFunction) \ |
| multimap< ClKeyType, ClElementType, less< ClKeyType > > |
| #else |
| # define UIMA_TY_HASH_SET( ClElementType, ClHashFunction) \ |
| hash_set< ClElementType, ClHashFunction, equal_to< ClElementType > > |
| # define UIMA_TY_HASH_MULTISET( ClElementType, ClHashFunction) \ |
| hash_multiset< ClElementType, ClHashFunction, equal_to< ClElementType > > |
| # define UIMA_TY_HASH_MAP( ClKeyType, ClElementType, ClHashFunction) \ |
| hash_map< ClKeyType, ClElementType, ClHashFunction, equal_to< ClKeyType > > |
| # define UIMA_TY_HASH_MULTIMAP( ClKeyType, ClElementType, ClHashFunction) \ |
| hash_multimap< ClKeyType, ClElementType, ClHashFunction, equal_to< ClKeyType > > |
| #endif |
| //@} |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Types / Classes */ |
| /* ----------------------------------------------------------------------- */ |
| |
| /** |
| Define to iterate all elements of an STL container. |
| */ |
| #define STL_FOR_EACH( it, container ) \ |
| for ( it = container.begin(); it != container.end(); ++it ) |
| |
| |
| /** |
| Define to iterate in parallel all elements of two STL containers. |
| */ |
| #define STL_FOR_EACH2( it1, it2, container1, container2 ) \ |
| for ( it1 = container1.begin(), it2 = container2.begin(); it1 != container1.end() && it2 != container2.end(); ++it1 , ++it2 ) |
| |
| /** |
| Defines a shorthand for "named" pairs, where in addition to accessing the |
| parts of the pair as first and second accessor functions, more |
| descriptive names are defined. |
| For example: |
| STL_NAMED_PAIR(KcRulePair, KcTestCategory, category, KcTestConditions, conditions); |
| This defines a class KcRulePair as a pair of KcTestCategory and KcTestConditions with accessor |
| function category() and conditions() |
| */ |
| #define STL_NAMED_PAIR(name, TypeFirst, nameFirst, TypeSecond, nameSecond) \ |
| class UIMA_LINK_IMPORTSPEC name : public pair<TypeFirst, TypeSecond> { \ |
| public: \ |
| name(const TypeFirst& thefirst = TypeFirst(), const TypeSecond& thesecond = TypeSecond()) : \ |
| pair<TypeFirst, TypeSecond>(thefirst, thesecond) {} \ |
| TypeFirst& nameFirst() {return first;} \ |
| TypeSecond& nameSecond() {return second;} \ |
| const TypeFirst& nameFirst() const {return first;} \ |
| const TypeSecond& nameSecond() const {return second;} \ |
| } |
| |
| /** |
| Define to return the address of an object avaiable via an STL iterator. |
| */ |
| #define STL_ITER2PTR(iterator) \ |
| (&(*iterator)) |
| |
| |
| /** |
| Define to search through a complete STL container. |
| */ |
| #define STL_FIND(container, element) \ |
| find(container.begin(), container.end(), element) |
| |
| /** |
| Define to search through a complete STL container with predicate. |
| */ |
| #define STL_FIND_IF(container, predicate) \ |
| find_if(container.begin(), container.end(), predicate) |
| |
| /** |
| Function for a binary search through a range in a < sorted STL container. |
| In this case, use the lower_bound to do the actual binary_search. |
| */ |
| template < class FwdIt, class Value > |
| FwdIt |
| taf_stl_find_sorted( FwdIt itFirst, FwdIt itLast, const Value & crclValue) { |
| FwdIt it = lower_bound( itFirst, itLast, crclValue ); |
| // Since lower_bound always return a value, we must check if we hit a matching one |
| if (it != itLast && !( crclValue < *it )) { // don't use == only < |
| return it; |
| } |
| return itLast; |
| } |
| |
| /** |
| Function for a binary search through a range in a Compare sorted STL container. |
| In this case, use the lower_bound to do the actual binary_search. |
| */ |
| template < class FwdIt, class Value, class Compare > |
| FwdIt |
| taf_stl_find_sorted( FwdIt itFirst, FwdIt itLast, const Value & crclValue, Compare clCompare) { |
| FwdIt it = lower_bound( itFirst, itLast, crclValue, clCompare ); |
| // Since lower_bound always return a value, we must check if we hit a matching one |
| if (it != itLast && !clCompare( crclValue , *it )) { // don't use == only clCompare |
| return it; |
| } |
| return itLast; |
| } //lint !e1746: parameter 'clCompare' could be made const reference |
| |
| /** |
| Define to binary search through a complete sorted STL container. |
| */ |
| #define STL_FIND_SORTED(it, container, element) \ |
| taf_stl_find_sorted(container.begin(), container.end(), element) |
| |
| /** |
| Define to search through a STL container, |
| which is completely sorted by a given compare function. |
| */ |
| #define STL_FIND_SORTED_COMPARE(container, element, compare) \ |
| taf_stl_find_sorted(container.begin(), container.end(), element, compare) |
| |
| |
| |
| /** |
| STL tool function |
| */ |
| template <class T1, class T2> |
| struct first_equal_to : public std::binary_function<T1, T2, bool> { |
| bool operator()(const T1& x, const T2& y) const { |
| return x.first == y; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T1, class T2> |
| struct second_equal_to : public std::binary_function<T1, T2, bool> { |
| bool operator()(const T1& x, const T2& y) const { |
| return x.second == y; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T1, class T2> |
| struct it_first_equal_to : public std::binary_function<T1, T2, bool> { |
| bool operator()(const T1& x, const T2& y) const { |
| return (*x).first == y; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T1, class T2> |
| struct it_second_equal_to : public std::binary_function<T1, T2, bool> { |
| bool operator()(const T1& x, const T2& y) const { |
| return (*x).second == y; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct first_less : public std::binary_function<T, T, bool> { |
| bool operator()(const T& x, const T& y) const { |
| return x.first < y.first; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct second_less : public std::binary_function<T, T, bool> { |
| bool operator()(const T& x, const T& y) const { |
| return x.second < y.second; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct it_first_less : public std::binary_function<T, T, bool> { |
| bool operator()(const T x, const T y) const { |
| return (*x).first < (*y).first; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct it_second_less : public std::binary_function<T, T, bool> { |
| bool operator()(const T x, const T y) const { |
| return (*x).second < (*y).second; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct first_greater : public std::binary_function<T, T, bool> { |
| bool operator()(const T& x, const T& y) const { |
| return x.first > y.first; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct second_greater : public std::binary_function<T, T, bool> { |
| bool operator()(const T& x, const T& y) const { |
| return x.second > y.second; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct it_first_greater : public std::binary_function<T, T, bool> { |
| bool operator()(const T x, const T y) const { |
| return (*x).first > (*y).first; |
| } |
| }; |
| |
| /** |
| STL tool function |
| */ |
| template <class T> |
| struct it_second_greater : public std::binary_function<T, T, bool> { |
| bool operator()(const T x, const T y) const { |
| return (*x).second > (*y).second; |
| } |
| }; |
| |
| |
| /** |
| STL tool class |
| */ |
| template <class Element> |
| struct CountContainer : public std::map<Element, size_t, std::less< Element > > { |
| public: |
| // typedef vector<value_type*> SortedByCountContainer; |
| typedef std::map<Element, size_t, std::less< Element > > ParentType; |
| |
| #if defined(__xlC__) |
| // this is redundant information, but xlC5 needs it |
| typedef typename ParentType::iterator iterator; |
| #endif |
| |
| typedef std::vector<typename ParentType::const_iterator> SortedByCountContainer; |
| private: |
| SortedByCountContainer m_sortByCountMap; |
| bool m_sortMapDirty; |
| long m_sum; |
| bool m_sumDirty; |
| |
| public: |
| //add an element with count 0 to the count list if not already there |
| //(if element is already there, it's count is unchanged) |
| bool create(const Element& element) { |
| pair<typename CountContainer::iterator, bool> pairItBool; |
| pairItBool = insert(typename CountContainer::value_type(element, 0)); |
| if (pairItBool.second) { //if not yet there |
| m_sortByCountMap.push_back(pairItBool.first); |
| } |
| m_sortMapDirty = true; |
| m_sumDirty = true; |
| return pairItBool.second; |
| } |
| //increase the count of element by 1 |
| //(if element is not there already, it is created with a count of 1) |
| bool increase_count(const Element& element) { |
| pair<typename CountContainer::iterator, bool> pairItBool; |
| pairItBool = insert(typename CountContainer::value_type(element, 1)); |
| if (pairItBool.second) { //if not yet there |
| m_sortByCountMap.push_back(pairItBool.first); |
| } else { |
| ++(*pairItBool.first).second; |
| } |
| m_sortMapDirty = true; |
| m_sumDirty = true; |
| return pairItBool.second; |
| } |
| void eraseAll() { |
| (*this).clear(); |
| m_sortByCountMap.clear(); |
| } |
| size_t getCount(const Element& element) const { |
| typename CountContainer::const_iterator it(find(element)); |
| return (it == this->end() ? 0 : getCount(*it)); |
| } |
| size_t getCount(typename std::map<Element, size_t, std::less< Element > >::const_iterator it) const { |
| return (*it).second; |
| } |
| size_t getCount(const typename std::map<Element, size_t, std::less< Element > >::value_type& value) const { |
| return value.second; |
| } |
| float getPercentage(const Element& element) { |
| typename CountContainer::const_iterator it(find(element)); |
| return (it == this->end() ? 0.0 : getPercentage(*it)); |
| } |
| long getSum() { |
| if (m_sumDirty) { |
| m_sum = 0; |
| typename CountContainer::const_iterator it; |
| STL_FOR_EACH(it, (*this)) { |
| m_sum += getCount(it); |
| } |
| } |
| return m_sum; |
| } |
| float getPercentage(typename std::map<Element, size_t, std::less< Element > >::const_iterator it) { |
| return (getSum() == 0 ? (float)0 : (float)(*it).second / (float)getSum()) * 100.0; |
| } |
| float getPercentage(const typename std::map<Element, size_t, std::less< Element > >::value_type& value) { |
| return (getSum() == 0 ? (float)0 : (float)value.second / (float)getSum()) * 100.0; |
| } |
| const Element& getElement(typename std::map<Element, size_t, std::less< Element > >::const_iterator it) const { |
| return (*it).first; |
| } |
| const SortedByCountContainer& getSortedByCountContainer() { |
| if (m_sortMapDirty) { |
| sort(m_sortByCountMap.begin(), m_sortByCountMap.end(), it_second_greater<typename SortedByCountContainer::value_type>()); |
| } |
| return m_sortByCountMap; |
| } |
| } |
| ; //lint !e1509: base class destructor for class 'map' is not virtual |
| |
| /** |
| * STL Tool class with semantics of "less" |
| * applied to elements which are pointers and require dereferencing |
| */ |
| template< class T > |
| class UIMA_LINK_IMPORTSPEC less_derefptr : public std::binary_function< T, T, bool > { |
| public: |
| bool operator()( const T& x, const T& y ) const { |
| return (bool)((*x) < (*y)); |
| } |
| } |
| ; //lint !e1905: implicit default constructor generated for class 'less_derefptr' |
| |
| |
| /** |
| Prints all elements in a STL container to stream. |
| */ |
| template <class Container> |
| inline void |
| taf_STLStreamOut( |
| const Container & rclContainer, |
| std::ostream & rclOut, |
| const char* cpszDelimiter |
| ) { |
| //? ostream_iterator<typename Container::value_type> itOut(rclOut, cpszDelimiter); |
| ostream_iterator< |
| // typename must not be used for some GNU versions |
| #if ( ((GCC_VERSION < 30000) || (GCC_VERSION > 30203)) || defined(__xlC__) ) |
| typename |
| #endif |
| Container::value_type > itOut(rclOut, cpszDelimiter); |
| copy(rclContainer.begin(), rclContainer.end(), itOut); |
| } |
| |
| /** |
| Prints all elements in an associative STL container to a stream. |
| */ |
| template <class Container> |
| inline void |
| taf_STLStreamOutAssoc( |
| const Container & rclContainer, |
| std::ostream & rclOut, |
| const char* cpszDelimiter, |
| const char* cpszMapString |
| ) { |
| typename Container::const_iterator itOut; |
| STL_FOR_EACH(itOut, rclContainer) { //lint !e1703 !e1023: Call operator!=is ambiguous |
| rclOut << (*itOut).first << cpszMapString << (*itOut).second << cpszDelimiter; |
| } |
| } |
| |
| /** |
| Prints elements in a range in a STL container to stream. |
| Note: this does not work on HP CFRONT 10.36 |
| */ |
| template <class Container> |
| inline void |
| taf_STLStreamOut( |
| const Container & rclContainer, |
| typename Container::const_iterator itBeg, |
| typename Container::const_iterator itEnd, |
| std::ostream& rclOut, |
| const char* cpszDelimiter |
| ) { |
| ostream_iterator< |
| // typename must not be used for some GNU versions |
| #if ( ((GCC_VERSION < 30000) || (GCC_VERSION > 30203)) || defined(__xlC__) ) |
| typename |
| #endif |
| |
| Container::value_type> itOut(rclOut, cpszDelimiter); |
| copy(itBeg, itEnd, itOut); |
| } |
| |
| /** |
| Create a pair with none of the elements being constant. |
| */ |
| template <class T1, class T2> |
| inline std::pair<T1, T2> make_non_const_pair(T1& x, T2& y) { |
| return pair<T1, T2>(x, y); |
| } |
| |
| /** |
| Creates a pair with the first element being constant. |
| */ |
| template <class T1, class T2> |
| inline std::pair<const T1, T2> make_const_pair(const T1& x, T2& y) { |
| return pair<const T1, T2>(x, y); |
| } |
| |
| /** |
| Creates a pair with the both elements being constant. |
| */ |
| template <class T1, class T2> |
| inline std::pair<const T1, T2> make_double_const_pair(const T1& x, const T2& y) { |
| return pair<const T1, const T2>(x, y); |
| } |
| |
| |
| /** |
| A simple implementation of a triple. Usage analogous to pair. |
| */ |
| template<class A, class B, class C> |
| class UIMA_LINK_IMPORTSPEC triple { |
| public: |
| A first; //lint !e1925: Symbol 'first' is a public data member |
| B second; //lint !e1925: Symbol 'second' is a public data member |
| C third; //lint !e1925: Symbol 'third' is a public data member |
| |
| triple() { } |
| |
| ~triple() { } |
| |
| triple(const A& a, const B& b, const C& c) { |
| first = a; |
| second = b; |
| third = c; |
| } |
| |
| triple(const triple<A, B, C>& t) { |
| first = t.first; |
| second = t.second; |
| third = t.third; |
| } |
| |
| triple<A,B,C>& operator=(const triple<A,B,C>& t) { |
| first = t.first; |
| second = t.second; |
| third = t.third; |
| return *this; |
| } |
| |
| bool operator==(const triple<A, B, C>& t) const { |
| return ( (first == t.first) |
| && (second == t.second) |
| && (third == t.third) ); |
| } |
| |
| bool operator<(const triple<A,B,C>& t) const { |
| // lexicographical order |
| if (first != t.first) { |
| return first < t.first; |
| } else { // first == t.first |
| if (second != t.second) { |
| return second < t.second; |
| } else { // second == t.second |
| return third < t.third; |
| } |
| } |
| } |
| }; |
| |
| // SUN WSPro 6 does not recognize these operators defined in <utility> |
| // (because they are embedded in the namespace std::rel_op ??) |
| #ifdef UIMA_RELOPS_TEMPLATE_BUG |
| template <class T> |
| inline bool operator!=(const T& x, const T& y) { |
| return !(x == y); |
| } |
| |
| template <class T> |
| inline bool operator>(const T& x, const T& y) { |
| return y < x; |
| } |
| |
| template <class T> |
| inline bool operator<=(const T& x, const T& y) { |
| return !(y < x); |
| } |
| |
| template <class T> |
| inline bool operator>=(const T& x, const T& y) { |
| return !(x < y); |
| } |
| |
| #endif |
| |
| ///////////////////////////////////////////// |
| |
| |
| // find the index of the value in vec |
| // if it is nout foun, -1 is returned |
| template <class T> |
| int findIndex(vector<T> const & vec, T const & value) { |
| size_t i; |
| for (i=0; i<vec.size(); ++i) { |
| if (vec[i] == value) { |
| return (int)i; |
| } |
| } |
| return -1; |
| } |
| |
| // the equivalent to auto_ptr for single objects for arrays |
| template<class T> |
| class UIMA_LINK_IMPORTSPEC auto_array { |
| private: |
| T* iv_ar; |
| bool iv_ownsArray; |
| |
| // copy construtcor and assignment are hidden here!! |
| |
| auto_array(auto_array<T> & other) { |
| *this = other; |
| } |
| |
| auto_array<T> & operator=(auto_array<T> & other ) { |
| iv_ar = other.iv_ar; |
| if (other.iv_ownsArray) { |
| iv_ownsArray = true; |
| other.iv_ownsArray = false; |
| } else { |
| iv_ownsArray = false; |
| } |
| return *this; |
| } |
| |
| public: |
| auto_array(T* ar) |
| : iv_ar(ar), |
| iv_ownsArray(true) {} |
| |
| |
| ~auto_array() { |
| if (iv_ownsArray) { |
| delete[] iv_ar; |
| } |
| } |
| |
| T& operator[](size_t i) { |
| return iv_ar[i]; |
| } |
| |
| T const & operator[](size_t i) const { |
| return iv_ar[i]; |
| } |
| |
| T* release() { |
| iv_ownsArray = false; |
| return iv_ar; |
| } |
| |
| T* get() { |
| return iv_ar; |
| } |
| |
| T const * get() const { |
| return iv_ar; |
| } |
| |
| }; |
| |
| |
| } //namespace uima |
| |
| #endif /* UIMA_STLTOOLS_HPP */ |
| /* <EOF> */ |
| |