include/corelib/ncbiutil.hpp

Go to the documentation of this file.
00001 #ifndef CORELIB___NCBI_UTILITY__HPP
00002 #define CORELIB___NCBI_UTILITY__HPP
00003 
00004 /*  $Id: ncbiutil.hpp 150242 2009-01-22 17:56:37Z gouriano $
00005  * ===========================================================================
00006  *
00007  *                            PUBLIC DOMAIN NOTICE
00008  *               National Center for Biotechnology Information
00009  *
00010  *  This software/database is a "United States Government Work" under the
00011  *  terms of the United States Copyright Act.  It was written as part of
00012  *  the author's official duties as a United States Government employee and
00013  *  thus cannot be copyrighted.  This software/database is freely available
00014  *  to the public for use. The National Library of Medicine and the U.S.
00015  *  Government have not placed any restriction on its use or reproduction.
00016  *
00017  *  Although all reasonable efforts have been taken to ensure the accuracy
00018  *  and reliability of the software and data, the NLM and the U.S.
00019  *  Government do not and cannot warrant the performance or results that
00020  *  may be obtained by using this software or data. The NLM and the U.S.
00021  *  Government disclaim all warranties, express or implied, including
00022  *  warranties of performance, merchantability or fitness for any particular
00023  *  purpose.
00024  *
00025  *  Please cite the author in any work or product based on this material.
00026  *
00027  * ===========================================================================
00028  *
00029  * Author: 
00030  *   Eugene Vasilchenko
00031  *
00032  *
00033  */
00034 
00035 /// @file ncbiutil.hpp
00036 /// Useful/utility classes and methods.
00037 
00038 
00039 #include <corelib/ncbistd.hpp>
00040 #include <corelib/ncbi_limits.h>
00041 #include <algorithm>
00042 #include <memory>
00043 #include <map>
00044 
00045 
00046 
00047 BEGIN_NCBI_SCOPE
00048 
00049 /** @addtogroup Utility Template Utilities
00050  *
00051  * @{
00052  */
00053 
00054 //-------------------------------------------
00055 // Utilities
00056 
00057 /// Check for equality of objects pointed to by pointer.
00058 template <class T>
00059 struct p_equal_to : public binary_function
00060 <const T*, const T*, bool>
00061 {
00062 #if defined(NCBI_COMPILER_MIPSPRO) || defined(NCBI_COMPILER_VISUALAGE)
00063     // fails to define these
00064     typedef const T* first_argument_type;
00065     typedef const T* second_argument_type;
00066 #endif
00067     // Sigh.  WorkShop rejects this code without typename (but only in
00068     // 64-bit mode!), and GCC rejects typename without a scope.
00069     bool operator() (const typename p_equal_to::first_argument_type& x,
00070                      const typename p_equal_to::second_argument_type& y) const
00071     { return *x == *y; }
00072 };
00073 
00074 /// Compare objects pointed to by (smart) pointer.
00075 template <class T>
00076 struct PPtrLess : public binary_function<T, T, bool>
00077 {
00078 #if defined(NCBI_COMPILER_MIPSPRO) || defined(NCBI_COMPILER_VISUALAGE)
00079     // fails to define these
00080     typedef T first_argument_type;
00081     typedef T second_argument_type;
00082 #endif
00083     bool operator() (const T& x, const T& y) const
00084     { return *x < *y; }
00085 };
00086 
00087 /// Check whether a pair's second element matches a given value.
00088 template <class Pair>
00089 struct pair_equal_to : public binary_function
00090 <Pair, typename Pair::second_type, bool>
00091 {
00092     bool operator() (const Pair& x,
00093                      const typename Pair::second_type& y) const
00094     { return x.second == y; }
00095 };
00096 
00097 /// Check for not null value (after C malloc, strdup etc.).
00098 template<class X>
00099 inline X* NotNull(X* object)
00100 {
00101     if ( !object ) {
00102         NCBI_THROW(CCoreException,eNullPtr,kEmptyStr);
00103     }
00104     return object;
00105 }
00106 
00107 /// Get map element (pointer) or NULL if absent.
00108 template<class Key, class Element>
00109 inline Element GetMapElement(const map<Key, Element>& m, const Key& key,
00110                              const Element& def = 0)
00111 {
00112     typename map<Key, Element>::const_iterator ptr = m.find(key);
00113     if ( ptr !=m.end() )
00114         return ptr->second;
00115     return def;
00116 }
00117 
00118 /// Set map element -- if data is null, erase the existing key.
00119 template<class Key, class Element>
00120 inline void SetMapElement(map<Key, Element*>& m, const Key& key, Element* data)
00121 {
00122     if ( data )
00123         m[key] = data;
00124     else
00125         m.erase(key);
00126 }
00127 
00128 /// Insert map element.
00129 template<class Key, class Element>
00130 inline bool InsertMapElement(map<Key, Element*>& m,
00131                              const Key& key, Element* data)
00132 {
00133     return m.insert(map<Key, Element*>::value_type(key, data)).second;
00134 }
00135 
00136 /// Get string map element or "" if absent.
00137 template<class Key>
00138 inline string GetMapString(const map<Key, string>& m, const Key& key)
00139 {
00140     typename map<Key, string>::const_iterator ptr = m.find(key);
00141     if ( ptr != m.end() )
00142         return ptr->second;
00143     return string();
00144 }
00145 
00146 /// Set string map element -- if data is null erase the existing key.
00147 template<class Key>
00148 inline void SetMapString(map<Key, string>& m,
00149                          const Key& key, const string& data)
00150 {
00151     if ( !data.empty() )
00152         m[key] = data;
00153     else
00154         m.erase(key);
00155 }
00156 
00157 /// Delete all elements from a container of pointers (list, vector, set,
00158 /// multiset); clear the container afterwards.
00159 template<class Cnt>
00160 inline void DeleteElements( Cnt& cnt )
00161 {
00162     for ( typename Cnt::iterator i = cnt.begin(); i != cnt.end(); ++i ) {
00163         delete *i;
00164     }
00165     cnt.clear();
00166 }
00167 
00168 /// Delete all elements from map containing pointers; clear container
00169 /// afterwards.
00170 template<class Key, class Element>
00171 inline void DeleteElements(map<Key, Element*>& m)
00172 {
00173     for ( typename map<Key, Element*>::iterator i = m.begin();  i != m.end();
00174           ++i ) {
00175         delete i->second;
00176     }
00177     m.clear();
00178 }
00179 
00180 /// Delete all elements from multimap containing pointers; clear container
00181 /// afterwards.
00182 template<class Key, class Element>
00183 inline void DeleteElements(multimap<Key, Element*>& m)
00184 {
00185     for ( typename map<Key, Element*>::iterator i = m.begin();  i != m.end();
00186           ++i ) {
00187         delete i->second;
00188     }
00189     m.clear();
00190 }
00191 
00192 /// Retrieve the result from the result cache - if cache is empty,
00193 /// insert into cache from the supplied source.
00194 template<class Result, class Source, class ToKey>
00195 inline
00196 Result&
00197 AutoMap(auto_ptr<Result>& cache, const Source& source, const ToKey& toKey)
00198 {
00199     Result* ret = cache.get();
00200     if ( !ret ) {
00201         cache.reset(ret = new Result);
00202         for ( typename Source::const_iterator i = source.begin();
00203               i != source.end();
00204               ++i ) {
00205             ret->insert(Result::value_type(toKey.GetKey(*i), *i));
00206         }
00207     }
00208     return *ret;
00209 }
00210 
00211 /// Get name attribute for Value object.
00212 template<class Value>
00213 struct CNameGetter
00214 {
00215     const string& GetKey(const Value* value) const
00216     {
00217         return value->GetName();
00218     }
00219 };
00220 
00221 // These templates may yield 0 if no (suitable) elements exist.  Also,
00222 // in part for consistency with the C Toolkit, lower scores are
00223 // better, and earlier elements win ties.
00224 
00225 
00226 
00227 /// Tracks the best score (lowest value).
00228 ///
00229 /// Values are specified by template parameter T, and scoring function by
00230 /// template parameter F.
00231 template <typename T, typename F>
00232 class CBestChoiceTracker : public unary_function<T, void>
00233 {
00234 public:
00235     /// Constructor.
00236     CBestChoiceTracker(F func) : m_Func(func), m_Value(T()), m_Score(kMax_Int)
00237     { }
00238 
00239     /// Define application operator.
00240     void operator() (const T& x)
00241     {
00242         int score = m_Func(x);
00243         if (score < m_Score) {
00244             m_Value = x;
00245             m_Score = score;
00246         }
00247     }
00248 
00249     /// Get best choice with lowest score.
00250     const T& GetBestChoice() { return m_Value; }
00251 
00252 private:
00253     F   m_Func;         ///< Scoring function
00254     T   m_Value;        ///< Current best value 
00255     int m_Score;        ///< Current best score
00256 };
00257 
00258 /// Find the best choice (lowest score) for values in a container.
00259 ///
00260 /// Container and scoring functions are specified as template parameters.
00261 template <typename C, typename F>
00262 inline
00263 typename C::value_type
00264 FindBestChoice(const C& container, F score_func)
00265 {
00266     typedef typename C::value_type T;
00267     CBestChoiceTracker<T, F> tracker(score_func);
00268     ITERATE (typename C, it, container) {
00269         tracker(*it);
00270     }
00271     return tracker.GetBestChoice();
00272 }
00273 
00274 
00275 END_NCBI_SCOPE
00276 
00277 #if !defined(HAVE_IS_SORTED)
00278 
00279 ///
00280 /// is_sorted is provided by some implementations of the STL and may
00281 /// be included in future releases of all standard-conforming implementations
00282 /// This is provided here for future compatibility
00283 ///
00284 
00285 BEGIN_STD_SCOPE
00286 
00287 template <class Iterator>
00288 bool is_sorted(Iterator iter1, Iterator iter2)
00289 {
00290     Iterator prev = iter1;
00291     for (++iter1;  iter1 != iter2;  ++iter1, ++prev) {
00292         if (*iter1 < *prev) {
00293             return false;
00294         }
00295     }
00296     return true;
00297 }
00298 
00299 
00300 template <class Iterator, class Predicate>
00301 bool is_sorted(Iterator iter1, Iterator iter2, Predicate pred)
00302 {
00303     Iterator prev = iter1;
00304     for (++iter1;  iter1 != iter2;  ++iter1, ++prev) {
00305         if (pred(*iter1, *prev)) {
00306             return false;
00307         }
00308     }
00309     return true;
00310 }
00311 
00312 
00313 END_STD_SCOPE
00314 
00315 #endif // !defined(HAVE_IS_SORTED)
00316 
00317 
00318 
00319 /* @} */
00320 
00321 #endif /* NCBI_UTILITY__HPP */
00322 
00323 

Generated on Sun Dec 6 22:01:29 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:20:35 2009 by modify_doxy.py rev. 173732