Chris@16: // Chris@16: // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: #ifndef BOOST_LOCALE_COLLATOR_HPP_INCLUDED Chris@16: #define BOOST_LOCALE_COLLATOR_HPP_INCLUDED Chris@16: Chris@16: #include Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable : 4275 4251 4231 4660) Chris@16: #endif Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: namespace locale { Chris@16: Chris@16: class info; Chris@16: Chris@16: /// Chris@16: /// \defgroup collation Collation Chris@16: /// Chris@16: /// This module introduces collation related classes Chris@16: /// Chris@16: /// @{ Chris@16: Chris@16: /// Chris@16: /// \brief a base class that includes collation level flags Chris@16: /// Chris@16: Chris@16: class collator_base { Chris@16: public: Chris@16: /// Chris@16: /// Unicode collation level types Chris@16: /// Chris@16: typedef enum { Chris@16: primary = 0, ///< 1st collation level: base letters Chris@16: secondary = 1, ///< 2nd collation level: letters and accents Chris@16: tertiary = 2, ///< 3rd collation level: letters, accents and case Chris@16: quaternary = 3, ///< 4th collation level: letters, accents, case and punctuation Chris@16: identical = 4 ///< identical collation level: include code-point comparison Chris@16: } level_type; Chris@16: }; Chris@16: Chris@16: /// Chris@16: /// \brief Collation facet. Chris@16: /// Chris@16: /// It reimplements standard C++ std::collate, Chris@16: /// allowing usage of std::locale for direct string comparison Chris@16: /// Chris@16: template Chris@16: class collator : Chris@16: public std::collate, Chris@16: public collator_base Chris@16: { Chris@16: public: Chris@16: /// Chris@16: /// Type of the underlying character Chris@16: /// Chris@16: typedef CharType char_type; Chris@16: /// Chris@16: /// Type of string used with this facet Chris@16: /// Chris@16: typedef std::basic_string string_type; Chris@16: Chris@16: Chris@16: /// Chris@16: /// Compare two strings in rage [b1,e1), [b2,e2) according using a collation level \a level. Calls do_compare Chris@16: /// Chris@16: /// Returns -1 if the first of the two strings sorts before the seconds, returns 1 if sorts after and 0 if Chris@16: /// they considered equal. Chris@16: /// Chris@16: int compare(level_type level, Chris@16: char_type const *b1,char_type const *e1, Chris@16: char_type const *b2,char_type const *e2) const Chris@16: { Chris@16: return do_compare(level,b1,e1,b2,e2); Chris@16: } Chris@16: /// Chris@16: /// Create a binary string that can be compared to other in order to get collation order. The string is created Chris@16: /// for text in range [b,e). It is useful for collation of multiple strings for text. Chris@16: /// Chris@16: /// The transformation follows these rules: Chris@16: /// \code Chris@16: /// compare(level,b1,e1,b2,e2) == sign( transform(level,b1,e1).compare(transform(level,b2,e2)) ); Chris@16: /// \endcode Chris@16: /// Chris@16: /// Calls do_transform Chris@16: /// Chris@16: string_type transform(level_type level,char_type const *b,char_type const *e) const Chris@16: { Chris@16: return do_transform(level,b,e); Chris@16: } Chris@16: Chris@16: /// Chris@16: /// Calculate a hash of a text in range [b,e). The value can be used for collation sensitive string comparison. Chris@16: /// Chris@16: /// If compare(level,b1,e1,b2,e2) == 0 then hash(level,b1,e1) == hash(level,b2,e2) Chris@16: /// Chris@16: /// Calls do_hash Chris@16: /// Chris@16: long hash(level_type level,char_type const *b,char_type const *e) const Chris@16: { Chris@16: return do_hash(level,b,e); Chris@16: } Chris@16: Chris@16: /// Chris@16: /// Compare two strings \a l and \a r using collation level \a level Chris@16: /// Chris@16: /// Returns -1 if the first of the two strings sorts before the seconds, returns 1 if sorts after and 0 if Chris@16: /// they considered equal. Chris@16: /// Chris@16: /// Chris@16: int compare(level_type level,string_type const &l,string_type const &r) const Chris@16: { Chris@16: return do_compare(level,l.data(),l.data()+l.size(),r.data(),r.data()+r.size()); Chris@16: } Chris@16: Chris@16: /// Chris@16: /// Calculate a hash that can be used for collation sensitive string comparison of a string \a s Chris@16: /// Chris@16: /// If compare(level,s1,s2) == 0 then hash(level,s1) == hash(level,s2) Chris@16: /// Chris@16: Chris@16: long hash(level_type level,string_type const &s) const Chris@16: { Chris@16: return do_hash(level,s.data(),s.data()+s.size()); Chris@16: } Chris@16: /// Chris@16: /// Create a binary string from string \a s, that can be compared to other, useful for collation of multiple Chris@16: /// strings. Chris@16: /// Chris@16: /// The transformation follows these rules: Chris@16: /// \code Chris@16: /// compare(level,s1,s2) == sign( transform(level,s1).compare(transform(level,s2)) ); Chris@16: /// \endcode Chris@16: /// Chris@16: string_type transform(level_type level,string_type const &s) const Chris@16: { Chris@16: return do_transform(level,s.data(),s.data()+s.size()); Chris@16: } Chris@16: Chris@16: protected: Chris@16: Chris@16: /// Chris@16: /// constructor of the collator object Chris@16: /// Chris@16: collator(size_t refs = 0) : std::collate(refs) Chris@16: { Chris@16: } Chris@16: Chris@16: virtual ~collator() Chris@16: { Chris@16: } Chris@16: Chris@16: /// Chris@16: /// This function is used to override default collation function that does not take in account collation level. Chris@16: /// Uses primary level Chris@16: /// Chris@16: virtual int do_compare( char_type const *b1,char_type const *e1, Chris@16: char_type const *b2,char_type const *e2) const Chris@16: { Chris@16: return do_compare(identical,b1,e1,b2,e2); Chris@16: } Chris@16: /// Chris@16: /// This function is used to override default collation function that does not take in account collation level. Chris@16: /// Uses primary level Chris@16: /// Chris@16: virtual string_type do_transform(char_type const *b,char_type const *e) const Chris@16: { Chris@16: return do_transform(identical,b,e); Chris@16: } Chris@16: /// Chris@16: /// This function is used to override default collation function that does not take in account collation level. Chris@16: /// Uses primary level Chris@16: /// Chris@16: virtual long do_hash(char_type const *b,char_type const *e) const Chris@16: { Chris@16: return do_hash(identical,b,e); Chris@16: } Chris@16: Chris@16: /// Chris@16: /// Actual function that performs comparison between the strings. For details see compare member function. Can be overridden. Chris@16: /// Chris@16: virtual int do_compare( level_type level, Chris@16: char_type const *b1,char_type const *e1, Chris@16: char_type const *b2,char_type const *e2) const = 0; Chris@16: /// Chris@16: /// Actual function that performs transformation. For details see transform member function. Can be overridden. Chris@16: /// Chris@16: virtual string_type do_transform(level_type level,char_type const *b,char_type const *e) const = 0; Chris@16: /// Chris@16: /// Actual function that calculates hash. For details see hash member function. Can be overridden. Chris@16: /// Chris@16: virtual long do_hash(level_type level,char_type const *b,char_type const *e) const = 0; Chris@16: Chris@16: Chris@16: }; Chris@16: Chris@16: /// Chris@16: /// \brief This class can be used in STL algorithms and containers for comparison of strings Chris@16: /// with a level other than primary Chris@16: /// Chris@16: /// For example: Chris@16: /// Chris@16: /// \code Chris@16: /// std::map > data; Chris@16: /// \endcode Chris@16: /// Chris@16: /// Would create a map the keys of which are sorted using secondary collation level Chris@16: /// Chris@16: template Chris@16: struct comparator Chris@16: { Chris@16: public: Chris@16: /// Chris@16: /// Create a comparator class for locale \a l and with collation leval \a level Chris@16: /// Chris@16: /// \note throws std::bad_cast if l does not have \ref collator facet installed Chris@16: /// Chris@16: comparator(std::locale const &l=std::locale(),collator_base::level_type level=default_level) : Chris@16: locale_(l), Chris@16: level_(level) Chris@16: { Chris@16: } Chris@16: Chris@16: /// Chris@16: /// Compare two strings -- equivalent to return left < right according to collation rules Chris@16: /// Chris@16: bool operator()(std::basic_string const &left,std::basic_string const &right) const Chris@16: { Chris@16: return std::use_facet >(locale_).compare(level_,left,right) < 0; Chris@16: } Chris@16: private: Chris@16: std::locale locale_; Chris@16: collator_base::level_type level_; Chris@16: }; Chris@16: Chris@16: Chris@16: /// Chris@16: ///@} Chris@16: /// Chris@16: Chris@16: } // locale Chris@16: } // boost Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: Chris@16: #endif Chris@16: /// Chris@16: /// \example collate.cpp Chris@16: /// Example of using collation functions Chris@16: /// Chris@16: // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4