blob: f262bc61aa5f13a21afb6604f1f8fe0a853298d3 [file] [log] [blame]
#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> */