/** \file compare3.h */ // -*-c++-*- // Copyright (C) 2009-2010 Daniel Burrows // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. #ifndef COMPARE3_H #define COMPARE3_H #include #include #include #include #include #include #include // Forward-declare ref_ptrs. namespace cwidget { namespace util { template class ref_ptr; } } namespace aptitude { namespace util { // \todo If Boost is added as a dependency, this should use // call_traits instead. /** \brief Helper metafunction for building parameter types * automatically. */ template struct make_param { typedef const T &type; }; // Stuff to ensure that integers are passed as-is. template<> struct make_param { typedef unsigned int type; }; template<> struct make_param { typedef int type; }; template<> struct make_param { typedef unsigned long type; }; template<> struct make_param { typedef long type; }; template<> struct make_param { typedef unsigned short type; }; template<> struct make_param { typedef short type; }; template<> struct make_param { typedef unsigned short type; }; template<> struct make_param { typedef short type; }; // Pass pointers and references as-is. template struct make_param { typedef const T *type; }; template struct make_param { typedef const T *type; }; template struct make_param { typedef const T &type; }; template struct make_param { typedef const T &type; }; /** \brief An overloaded structure that provides a default 3-way * compare for various types. * * The default uses operator<, but some common types have more * efficient implementations. */ template class compare3_f { typedef typename make_param::type T_param; public: /** \brief Return a value less than zero if t1t2, and zero if t1=t2. */ int operator()(T_param t1, T_param t2) const { if(t1 < t2) return -1; else if(t2 < t1) return 1; else return 0; } }; template inline int compare3(const T &t1, const T &t2) { return compare3_f()(t1, t2); } /** \brief 3-way lexicographic comparison. */ template inline int lexicographical_compare3(const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2, Compare compare) { Iter it1(begin1), it2(begin2); while(it1 != end1 && it2 != end2) { const int cmp(compare(*it1, *it2)); if(cmp != 0) return cmp; ++it1; ++it2; } if(it2 != end2) return -1; else if(it1 != end1) return 1; else return 0; } /** \brief 3-way lexicographic comparison. */ template inline int lexicographical_compare3(const Iter &begin1, const Iter &end1, const Iter &begin2, const Iter &end2) { return lexicographical_compare3(begin1, end1, begin2, end2, compare3_f::value_type>()); } // Comparison for integers. template class compare3_f_int { public: int operator()(T n1, T n2) const { if(n1 < n2) return -1; else if(n2 < n1) return 1; else return 0; } }; template<> class compare3_f { int operator()(bool b1, bool b2) const { if(b1 == b2) return 0; else if(b1 < b2) return -1; else if(b1 > b2) return 1; } }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; template<> class compare3_f : public compare3_f_int { }; // Overloaded comparison on pointers. template class compare3_f { public: int operator()(T *t1, T *t2) const { return t1 - t2; } }; template class compare3_f { public: int operator()(const T *t1, const T *t2) const { return t1 - t2; } }; template class compare3_f > { public: int operator()(const cwidget::util::ref_ptr &t1, const cwidget::util::ref_ptr &t2) const { return t1.unsafe_get_ref() - t2.unsafe_get_ref(); } }; template class compare3_f > { public: int operator()(const std::basic_string &s1, const std::basic_string &s2) const { return s1.compare(s2); } }; template class compare3_f_container { public: int operator()(const T &c1, const T &c2) const { return lexicographical_compare3(c1.begin(), c1.end(), c2.begin(), c2.end()); } }; // Comparison operators for common STL types. template class compare3_f > { public: int operator()(const std::pair &p1, const std::pair &p2) const { const int cmp1 = compare3(p1.first, p2.first); if(cmp1 != 0) return cmp1; else return compare3(p1.second, p2.second); } }; template class compare3_f > : public compare3_f_container > { }; template class compare3_f > : public compare3_f_container > { }; template class compare3_f > : public compare3_f_container > { }; template class compare3_f > : public compare3_f_container > { }; template class compare3_f > : public compare3_f_container > { }; template class compare3_f > : public compare3_f_container > { }; template class compare3_f > : public compare3_f_container > { }; } } #endif // COMPARE3_H