// Boost string_algo library classification.hpp header file ---------------------------// // Copyright Pavol Droba 2002-2003. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/ for updates, documentation, and revision history. #ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP #define BOOST_STRING_CLASSIFICATION_DETAIL_HPP #include <boost/algorithm/string/config.hpp> #include <algorithm> #include <functional> #include <locale> #include <boost/range/begin.hpp> #include <boost/range/end.hpp> #include <boost/algorithm/string/predicate_facade.hpp> #include <boost/type_traits/remove_const.hpp> namespace boost { namespace algorithm { namespace detail { // classification functors -----------------------------------------------// // is_classified functor struct is_classifiedF : public predicate_facade<is_classifiedF> { // Boost.ResultOf support typedef bool result_type; // Constructor from a locale is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) : m_Type(Type), m_Locale(Loc) {} // Operation template<typename CharT> bool operator()( CharT Ch ) const { return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch ); } #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL) template<> bool operator()( char const Ch ) const { return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch ); } #endif private: std::ctype_base::mask m_Type; std::locale m_Locale; }; // is_any_of functor /* returns true if the value is from the specified set */ template<typename CharT> struct is_any_ofF : public predicate_facade<is_any_ofF<CharT> > { private: // set cannot operate on const value-type typedef typename ::boost::remove_const<CharT>::type set_value_type; public: // Boost.ResultOf support typedef bool result_type; // Constructor template<typename RangeT> is_any_ofF( const RangeT& Range ) : m_Size(0) { // Prepare storage m_Storage.m_dynSet=0; std::size_t Size=::boost::distance(Range); m_Size=Size; set_value_type* Storage=0; if(use_fixed_storage(m_Size)) { // Use fixed storage Storage=&m_Storage.m_fixSet[0]; } else { // Use dynamic storage m_Storage.m_dynSet=new set_value_type[m_Size]; Storage=m_Storage.m_dynSet; } // Use fixed storage ::std::copy(::boost::begin(Range), ::boost::end(Range), Storage); ::std::sort(Storage, Storage+m_Size); } // Copy constructor is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size) { // Prepare storage m_Storage.m_dynSet=0; const set_value_type* SrcStorage=0; set_value_type* DestStorage=0; if(use_fixed_storage(m_Size)) { // Use fixed storage DestStorage=&m_Storage.m_fixSet[0]; SrcStorage=&Other.m_Storage.m_fixSet[0]; } else { // Use dynamic storage m_Storage.m_dynSet=new set_value_type[m_Size]; DestStorage=m_Storage.m_dynSet; SrcStorage=Other.m_Storage.m_dynSet; } // Use fixed storage ::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size); } // Destructor ~is_any_ofF() { if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0) { delete [] m_Storage.m_dynSet; } } // Assignment is_any_ofF& operator=(const is_any_ofF& Other) { // Handle self assignment if(this==&Other) return *this; // Prepare storage const set_value_type* SrcStorage; set_value_type* DestStorage; if(use_fixed_storage(Other.m_Size)) { // Use fixed storage DestStorage=&m_Storage.m_fixSet[0]; SrcStorage=&Other.m_Storage.m_fixSet[0]; // Delete old storage if was present if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0) { delete [] m_Storage.m_dynSet; } // Set new size m_Size=Other.m_Size; } else { // Other uses dynamic storage SrcStorage=Other.m_Storage.m_dynSet; // Check what kind of storage are we using right now if(use_fixed_storage(m_Size)) { // Using fixed storage, allocate new set_value_type* pTemp=new set_value_type[Other.m_Size]; DestStorage=pTemp; m_Storage.m_dynSet=pTemp; m_Size=Other.m_Size; } else { // Using dynamic storage, check if can reuse if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2) { // Reuse the current storage DestStorage=m_Storage.m_dynSet; m_Size=Other.m_Size; } else { // Allocate the new one set_value_type* pTemp=new set_value_type[Other.m_Size]; DestStorage=pTemp; // Delete old storage if necessary if(m_Storage.m_dynSet!=0) { delete [] m_Storage.m_dynSet; } // Store the new storage m_Storage.m_dynSet=pTemp; // Set new size m_Size=Other.m_Size; } } } // Copy the data ::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size); return *this; } // Operation template<typename Char2T> bool operator()( Char2T Ch ) const { const set_value_type* Storage= (use_fixed_storage(m_Size)) ? &m_Storage.m_fixSet[0] : m_Storage.m_dynSet; return ::std::binary_search(Storage, Storage+m_Size, Ch); } private: // check if the size is eligible for fixed storage static bool use_fixed_storage(std::size_t size) { return size<=sizeof(set_value_type*)*2; } private: // storage // The actual used storage is selected on the type union { set_value_type* m_dynSet; set_value_type m_fixSet[sizeof(set_value_type*)*2]; } m_Storage; // storage size ::std::size_t m_Size; }; // is_from_range functor /* returns true if the value is from the specified range. (i.e. x>=From && x>=To) */ template<typename CharT> struct is_from_rangeF : public predicate_facade< is_from_rangeF<CharT> > { // Boost.ResultOf support typedef bool result_type; // Constructor is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {} // Operation template<typename Char2T> bool operator()( Char2T Ch ) const { return ( m_From <= Ch ) && ( Ch <= m_To ); } private: CharT m_From; CharT m_To; }; // class_and composition predicate template<typename Pred1T, typename Pred2T> struct pred_andF : public predicate_facade< pred_andF<Pred1T,Pred2T> > { public: // Boost.ResultOf support typedef bool result_type; // Constructor pred_andF( Pred1T Pred1, Pred2T Pred2 ) : m_Pred1(Pred1), m_Pred2(Pred2) {} // Operation template<typename CharT> bool operator()( CharT Ch ) const { return m_Pred1(Ch) && m_Pred2(Ch); } private: Pred1T m_Pred1; Pred2T m_Pred2; }; // class_or composition predicate template<typename Pred1T, typename Pred2T> struct pred_orF : public predicate_facade< pred_orF<Pred1T,Pred2T> > { public: // Boost.ResultOf support typedef bool result_type; // Constructor pred_orF( Pred1T Pred1, Pred2T Pred2 ) : m_Pred1(Pred1), m_Pred2(Pred2) {} // Operation template<typename CharT> bool operator()( CharT Ch ) const { return m_Pred1(Ch) || m_Pred2(Ch); } private: Pred1T m_Pred1; Pred2T m_Pred2; }; // class_not composition predicate template< typename PredT > struct pred_notF : public predicate_facade< pred_notF<PredT> > { public: // Boost.ResultOf support typedef bool result_type; // Constructor pred_notF( PredT Pred ) : m_Pred(Pred) {} // Operation template<typename CharT> bool operator()( CharT Ch ) const { return !m_Pred(Ch); } private: PredT m_Pred; }; } // namespace detail } // namespace algorithm } // namespace boost #endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP