Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file c_regex_traits.hpp Chris@16: /// Contains the definition of the c_regex_traits\<\> template, which is a Chris@16: /// wrapper for the C locale functions that can be used to customize the Chris@16: /// behavior of static and dynamic regexes. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_TRAITS_C_REGEX_TRAITS_HPP_EAN_10_04_2005 Chris@16: #define BOOST_XPRESSIVE_TRAITS_C_REGEX_TRAITS_HPP_EAN_10_04_2005 Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace xpressive Chris@16: { Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // empty_locale Chris@16: struct empty_locale Chris@16: { Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // c_regex_traits_base Chris@16: template Chris@16: struct c_regex_traits_base Chris@16: { Chris@16: protected: Chris@16: template Chris@16: void imbue(Traits const &tr) Chris@16: { Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct c_regex_traits_base Chris@16: { Chris@16: protected: Chris@16: template Chris@16: static void imbue(Traits const &) Chris@16: { Chris@16: } Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_NO_WREGEX Chris@16: template Chris@16: struct c_regex_traits_base Chris@16: { Chris@16: protected: Chris@16: template Chris@16: static void imbue(Traits const &) Chris@16: { Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: Chris@16: template Chris@16: Char c_tolower(Char); Chris@16: Chris@16: template Chris@16: Char c_toupper(Char); Chris@16: Chris@16: template<> Chris@16: inline char c_tolower(char ch) Chris@16: { Chris@16: using namespace std; Chris@16: return static_cast(tolower(static_cast(ch))); Chris@16: } Chris@16: Chris@16: template<> Chris@16: inline char c_toupper(char ch) Chris@16: { Chris@16: using namespace std; Chris@16: return static_cast(toupper(static_cast(ch))); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_NO_WREGEX Chris@16: template<> Chris@16: inline wchar_t c_tolower(wchar_t ch) Chris@16: { Chris@16: using namespace std; Chris@16: return towlower(ch); Chris@16: } Chris@16: Chris@16: template<> Chris@16: inline wchar_t c_toupper(wchar_t ch) Chris@16: { Chris@16: using namespace std; Chris@16: return towupper(ch); Chris@16: } Chris@16: #endif Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // regex_traits_version_1_tag Chris@16: // Chris@16: struct regex_traits_version_1_tag; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // c_regex_traits Chris@16: // Chris@16: /// \brief Encapsaulates the standard C locale functions for use by the Chris@16: /// \c basic_regex\<\> class template. Chris@16: template Chris@16: struct c_regex_traits Chris@16: : detail::c_regex_traits_base Chris@16: { Chris@16: typedef Char char_type; Chris@16: typedef std::basic_string string_type; Chris@16: typedef detail::empty_locale locale_type; Chris@16: typedef typename detail::char_class_impl::char_class_type char_class_type; Chris@16: typedef regex_traits_version_2_tag version_tag; Chris@16: typedef detail::c_regex_traits_base base_type; Chris@16: Chris@16: /// Initialize a c_regex_traits object to use the global C locale. Chris@16: /// Chris@16: c_regex_traits(locale_type const &loc = locale_type()) Chris@16: : base_type() Chris@16: { Chris@16: this->imbue(loc); Chris@16: } Chris@16: Chris@16: /// Checks two c_regex_traits objects for equality Chris@16: /// Chris@16: /// \return true. Chris@16: bool operator ==(c_regex_traits const &) const Chris@16: { Chris@16: return true; Chris@16: } Chris@16: Chris@16: /// Checks two c_regex_traits objects for inequality Chris@16: /// Chris@16: /// \return false. Chris@16: bool operator !=(c_regex_traits const &) const Chris@16: { Chris@16: return false; Chris@16: } Chris@16: Chris@16: /// Convert a char to a Char Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return ch if Char is char, std::btowc(ch) if Char is wchar_t. Chris@16: static char_type widen(char ch); Chris@16: Chris@16: /// Returns a hash value for a Char in the range [0, UCHAR_MAX] Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return a value between 0 and UCHAR_MAX, inclusive. Chris@16: static unsigned char hash(char_type ch) Chris@16: { Chris@16: return static_cast(std::char_traits::to_int_type(ch)); Chris@16: } Chris@16: Chris@16: /// No-op Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return ch Chris@16: static char_type translate(char_type ch) Chris@16: { Chris@16: return ch; Chris@16: } Chris@16: Chris@16: /// Converts a character to lower-case using the current global C locale. Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return std::tolower(ch) if Char is char, std::towlower(ch) if Char is wchar_t. Chris@16: static char_type translate_nocase(char_type ch) Chris@16: { Chris@16: return detail::c_tolower(ch); Chris@16: } Chris@16: Chris@16: /// Converts a character to lower-case using the current global C locale. Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return std::tolower(ch) if Char is char, std::towlower(ch) if Char is wchar_t. Chris@16: static char_type tolower(char_type ch) Chris@16: { Chris@16: return detail::c_tolower(ch); Chris@16: } Chris@16: Chris@16: /// Converts a character to upper-case using the current global C locale. Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return std::toupper(ch) if Char is char, std::towupper(ch) if Char is wchar_t. Chris@16: static char_type toupper(char_type ch) Chris@16: { Chris@16: return detail::c_toupper(ch); Chris@16: } Chris@16: Chris@16: /// Returns a \c string_type containing all the characters that compare equal Chris@16: /// disregrarding case to the one passed in. This function can only be called Chris@16: /// if has_fold_case\ \>::value is \c true. Chris@16: /// Chris@16: /// \param ch The source character. Chris@16: /// \return \c string_type containing all chars which are equal to \c ch when disregarding Chris@16: /// case Chris@16: //typedef array fold_case_type; Chris@16: string_type fold_case(char_type ch) const Chris@16: { Chris@16: BOOST_MPL_ASSERT((is_same)); Chris@16: char_type ntcs[] = { Chris@16: detail::c_tolower(ch) Chris@16: , detail::c_toupper(ch) Chris@16: , 0 Chris@16: }; Chris@16: if(ntcs[1] == ntcs[0]) Chris@16: ntcs[1] = 0; Chris@16: return string_type(ntcs); Chris@16: } Chris@16: Chris@16: /// Checks to see if a character is within a character range. Chris@16: /// Chris@16: /// \param first The bottom of the range, inclusive. Chris@16: /// \param last The top of the range, inclusive. Chris@16: /// \param ch The source character. Chris@16: /// \return first <= ch && ch <= last. Chris@16: static bool in_range(char_type first, char_type last, char_type ch) Chris@16: { Chris@16: return first <= ch && ch <= last; Chris@16: } Chris@16: Chris@16: /// Checks to see if a character is within a character range, irregardless of case. Chris@16: /// Chris@16: /// \param first The bottom of the range, inclusive. Chris@16: /// \param last The top of the range, inclusive. Chris@16: /// \param ch The source character. Chris@16: /// \return in_range(first, last, ch) || in_range(first, last, tolower(ch)) || in_range(first, Chris@16: /// last, toupper(ch)) Chris@16: /// \attention The default implementation doesn't do proper Unicode Chris@16: /// case folding, but this is the best we can do with the standard Chris@16: /// C locale functions. Chris@16: static bool in_range_nocase(char_type first, char_type last, char_type ch) Chris@16: { Chris@16: return c_regex_traits::in_range(first, last, ch) Chris@16: || c_regex_traits::in_range(first, last, detail::c_tolower(ch)) Chris@16: || c_regex_traits::in_range(first, last, detail::c_toupper(ch)); Chris@16: } Chris@16: Chris@16: /// Returns a sort key for the character sequence designated by the iterator range [F1, F2) Chris@16: /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2) Chris@16: /// then v.transform(G1, G2) < v.transform(H1, H2). Chris@16: /// Chris@16: /// \attention Not currently used Chris@16: template Chris@16: static string_type transform(FwdIter begin, FwdIter end) Chris@16: { Chris@16: BOOST_ASSERT(false); // BUGBUG implement me Chris@16: } Chris@16: Chris@16: /// Returns a sort key for the character sequence designated by the iterator range [F1, F2) Chris@16: /// such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2) Chris@16: /// when character case is not considered then Chris@16: /// v.transform_primary(G1, G2) < v.transform_primary(H1, H2). Chris@16: /// Chris@16: /// \attention Not currently used Chris@16: template Chris@16: static string_type transform_primary(FwdIter begin, FwdIter end) Chris@16: { Chris@16: BOOST_ASSERT(false); // BUGBUG implement me Chris@16: } Chris@16: Chris@16: /// Returns a sequence of characters that represents the collating element Chris@16: /// consisting of the character sequence designated by the iterator range [F1, F2). Chris@16: /// Returns an empty string if the character sequence is not a valid collating element. Chris@16: /// Chris@16: /// \attention Not currently used Chris@16: template Chris@16: static string_type lookup_collatename(FwdIter begin, FwdIter end) Chris@16: { Chris@16: BOOST_ASSERT(false); // BUGBUG implement me Chris@16: } Chris@16: Chris@16: /// For the character class name represented by the specified character sequence, Chris@16: /// return the corresponding bitmask representation. Chris@16: /// Chris@16: /// \param begin A forward iterator to the start of the character sequence representing Chris@16: /// the name of the character class. Chris@16: /// \param end The end of the character sequence. Chris@16: /// \param icase Specifies whether the returned bitmask should represent the case-insensitive Chris@16: /// version of the character class. Chris@16: /// \return A bitmask representing the character class. Chris@16: template Chris@16: static char_class_type lookup_classname(FwdIter begin, FwdIter end, bool icase) Chris@16: { Chris@16: return detail::char_class_impl::lookup_classname(begin, end, icase); Chris@16: } Chris@16: Chris@16: /// Tests a character against a character class bitmask. Chris@16: /// Chris@16: /// \param ch The character to test. Chris@16: /// \param mask The character class bitmask against which to test. Chris@16: /// \pre mask is a bitmask returned by lookup_classname, or is several such masks bit-or'ed Chris@16: /// together. Chris@16: /// \return true if the character is a member of any of the specified character classes, false Chris@16: /// otherwise. Chris@16: static bool isctype(char_type ch, char_class_type mask) Chris@16: { Chris@16: return detail::char_class_impl::isctype(ch, mask); Chris@16: } Chris@16: Chris@16: /// Convert a digit character into the integer it represents. Chris@16: /// Chris@16: /// \param ch The digit character. Chris@16: /// \param radix The radix to use for the conversion. Chris@16: /// \pre radix is one of 8, 10, or 16. Chris@16: /// \return -1 if ch is not a digit character, the integer value of the character otherwise. If Chris@16: /// char_type is char, std::strtol is used for the conversion. If char_type is wchar_t, Chris@16: /// std::wcstol is used. Chris@16: static int value(char_type ch, int radix); Chris@16: Chris@16: /// No-op Chris@16: /// Chris@16: locale_type imbue(locale_type loc) Chris@16: { Chris@16: this->base_type::imbue(*this); Chris@16: return loc; Chris@16: } Chris@16: Chris@16: /// No-op Chris@16: /// Chris@16: static locale_type getloc() Chris@16: { Chris@16: locale_type loc; Chris@16: return loc; Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // c_regex_traits<>::widen specializations Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: inline char c_regex_traits::widen(char ch) Chris@16: { Chris@16: return ch; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_NO_WREGEX Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: inline wchar_t c_regex_traits::widen(char ch) Chris@16: { Chris@16: using namespace std; Chris@16: return btowc(ch); Chris@16: } Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // c_regex_traits<>::hash specializations Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: inline unsigned char c_regex_traits::hash(char ch) Chris@16: { Chris@16: return static_cast(ch); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_NO_WREGEX Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: inline unsigned char c_regex_traits::hash(wchar_t ch) Chris@16: { Chris@16: return static_cast(ch); Chris@16: } Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // c_regex_traits<>::value specializations Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: inline int c_regex_traits::value(char ch, int radix) Chris@16: { Chris@16: using namespace std; Chris@16: BOOST_ASSERT(8 == radix || 10 == radix || 16 == radix); Chris@16: char begin[2] = { ch, '\0' }, *end = 0; Chris@16: int val = strtol(begin, &end, radix); Chris@16: return begin == end ? -1 : val; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_NO_WREGEX Chris@16: /// INTERNAL ONLY Chris@16: template<> Chris@16: inline int c_regex_traits::value(wchar_t ch, int radix) Chris@16: { Chris@16: using namespace std; Chris@16: BOOST_ASSERT(8 == radix || 10 == radix || 16 == radix); Chris@16: wchar_t begin[2] = { ch, L'\0' }, *end = 0; Chris@16: int val = wcstol(begin, &end, radix); Chris@16: return begin == end ? -1 : val; Chris@16: } Chris@16: #endif Chris@16: Chris@16: // Narrow C traits has fold_case() member function. Chris@16: template<> Chris@16: struct has_fold_case > Chris@16: : mpl::true_ Chris@16: { Chris@16: }; Chris@16: Chris@16: }} Chris@16: Chris@16: #endif