1 //  Boost string_algo library classification.hpp header file  ---------------------------//
2 
3 //  Copyright Pavol Droba 2002-2003.
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 //    (See accompanying file LICENSE_1_0.txt or copy at
7 //          http://www.boost.org/LICENSE_1_0.txt)
8 
9 //  See http://www.boost.org/ for updates, documentation, and revision history.
10 
11 #ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP
12 #define BOOST_STRING_CLASSIFICATION_DETAIL_HPP
13 
14 #include <boost/algorithm/string/config.hpp>
15 #include <algorithm>
16 #include <cstring>
17 #include <functional>
18 #include <locale>
19 
20 #include <boost/range/begin.hpp>
21 #include <boost/range/distance.hpp>
22 #include <boost/range/end.hpp>
23 
24 #include <boost/algorithm/string/predicate_facade.hpp>
25 #include <boost/type_traits/remove_const.hpp>
26 
27 namespace boost {
28     namespace algorithm {
29         namespace detail {
30 
31 //  classification functors -----------------------------------------------//
32 
33    // is_classified functor
34             struct is_classifiedF :
35                 public predicate_facade<is_classifiedF>
36             {
37                 // Boost.ResultOf support
38                 typedef bool result_type;
39 
40                 // Constructor from a locale
is_classifiedFboost::algorithm::detail::is_classifiedF41                 is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
42                     m_Type(Type), m_Locale(Loc) {}
43                 // Operation
44                 template<typename CharT>
operator ()boost::algorithm::detail::is_classifiedF45                 bool operator()( CharT Ch ) const
46                 {
47                     return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
48                 }
49 
50                 #if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x582) && !defined(_USE_OLD_RW_STL)
51                     template<>
operator ()boost::algorithm::detail::is_classifiedF52                     bool operator()( char const Ch ) const
53                     {
54                         return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
55                     }
56                 #endif
57 
58             private:
59                 std::ctype_base::mask m_Type;
60                 std::locale m_Locale;
61             };
62 
63 
64             // is_any_of functor
65             /*
66                 returns true if the value is from the specified set
67             */
68             template<typename CharT>
69             struct is_any_ofF :
70                 public predicate_facade<is_any_ofF<CharT> >
71             {
72             private:
73                 // set cannot operate on const value-type
74                 typedef typename ::boost::remove_const<CharT>::type set_value_type;
75 
76             public:
77                 // Boost.ResultOf support
78                 typedef bool result_type;
79 
80                 // Constructor
81                 template<typename RangeT>
is_any_ofFboost::algorithm::detail::is_any_ofF82                 is_any_ofF( const RangeT& Range ) : m_Size(0)
83                 {
84                     // Prepare storage
85                     m_Storage.m_dynSet=0;
86 
87                     std::size_t Size=::boost::distance(Range);
88                     m_Size=Size;
89                     set_value_type* Storage=0;
90 
91                     if(use_fixed_storage(m_Size))
92                     {
93                         // Use fixed storage
94                         Storage=&m_Storage.m_fixSet[0];
95                     }
96                     else
97                     {
98                         // Use dynamic storage
99                         m_Storage.m_dynSet=new set_value_type[m_Size];
100                         Storage=m_Storage.m_dynSet;
101                     }
102 
103                     // Use fixed storage
104                     ::std::copy(::boost::begin(Range), ::boost::end(Range), Storage);
105                     ::std::sort(Storage, Storage+m_Size);
106                 }
107 
108                 // Copy constructor
is_any_ofFboost::algorithm::detail::is_any_ofF109                 is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size)
110                 {
111                     // Prepare storage
112                     m_Storage.m_dynSet=0;
113                     const set_value_type* SrcStorage=0;
114                     set_value_type* DestStorage=0;
115 
116                     if(use_fixed_storage(m_Size))
117                     {
118                         // Use fixed storage
119                         DestStorage=&m_Storage.m_fixSet[0];
120                         SrcStorage=&Other.m_Storage.m_fixSet[0];
121                     }
122                     else
123                     {
124                         // Use dynamic storage
125                         m_Storage.m_dynSet=new set_value_type[m_Size];
126                         DestStorage=m_Storage.m_dynSet;
127                         SrcStorage=Other.m_Storage.m_dynSet;
128                     }
129 
130                     // Use fixed storage
131                     ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
132                 }
133 
134                 // Destructor
~is_any_ofFboost::algorithm::detail::is_any_ofF135                 ~is_any_ofF()
136                 {
137                     if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
138                     {
139                         delete [] m_Storage.m_dynSet;
140                     }
141                 }
142 
143                 // Assignment
operator =boost::algorithm::detail::is_any_ofF144                 is_any_ofF& operator=(const is_any_ofF& Other)
145                 {
146                     // Handle self assignment
147                     if(this==&Other) return *this;
148 
149                     // Prepare storage
150                     const set_value_type* SrcStorage;
151                     set_value_type* DestStorage;
152 
153                     if(use_fixed_storage(Other.m_Size))
154                     {
155                         // Use fixed storage
156                         DestStorage=&m_Storage.m_fixSet[0];
157                         SrcStorage=&Other.m_Storage.m_fixSet[0];
158 
159                         // Delete old storage if was present
160                         if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
161                         {
162                             delete [] m_Storage.m_dynSet;
163                         }
164 
165                         // Set new size
166                         m_Size=Other.m_Size;
167                     }
168                     else
169                     {
170                         // Other uses dynamic storage
171                         SrcStorage=Other.m_Storage.m_dynSet;
172 
173                         // Check what kind of storage are we using right now
174                         if(use_fixed_storage(m_Size))
175                         {
176                             // Using fixed storage, allocate new
177                             set_value_type* pTemp=new set_value_type[Other.m_Size];
178                             DestStorage=pTemp;
179                             m_Storage.m_dynSet=pTemp;
180                             m_Size=Other.m_Size;
181                         }
182                         else
183                         {
184                             // Using dynamic storage, check if can reuse
185                             if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2)
186                             {
187                                 // Reuse the current storage
188                                 DestStorage=m_Storage.m_dynSet;
189                                 m_Size=Other.m_Size;
190                             }
191                             else
192                             {
193                                 // Allocate the new one
194                                 set_value_type* pTemp=new set_value_type[Other.m_Size];
195                                 DestStorage=pTemp;
196 
197                                 // Delete old storage if necessary
198                                 if(m_Storage.m_dynSet!=0)
199                                 {
200                                     delete [] m_Storage.m_dynSet;
201                                 }
202                                 // Store the new storage
203                                 m_Storage.m_dynSet=pTemp;
204                                 // Set new size
205                                 m_Size=Other.m_Size;
206                             }
207                         }
208                     }
209 
210                     // Copy the data
211                     ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
212 
213                     return *this;
214                 }
215 
216                 // Operation
217                 template<typename Char2T>
operator ()boost::algorithm::detail::is_any_ofF218                 bool operator()( Char2T Ch ) const
219                 {
220                     const set_value_type* Storage=
221                         (use_fixed_storage(m_Size))
222                         ? &m_Storage.m_fixSet[0]
223                         : m_Storage.m_dynSet;
224 
225                     return ::std::binary_search(Storage, Storage+m_Size, Ch);
226                 }
227             private:
228                 // check if the size is eligible for fixed storage
use_fixed_storageboost::algorithm::detail::is_any_ofF229                 static bool use_fixed_storage(std::size_t size)
230                 {
231                     return size<=sizeof(set_value_type*)*2;
232                 }
233 
234 
235             private:
236                 // storage
237                 // The actual used storage is selected on the type
238                 union
239                 {
240                     set_value_type* m_dynSet;
241                     set_value_type m_fixSet[sizeof(set_value_type*)*2];
242                 }
243                 m_Storage;
244 
245                 // storage size
246                 ::std::size_t m_Size;
247             };
248 
249             // is_from_range functor
250             /*
251                 returns true if the value is from the specified range.
252                 (i.e. x>=From && x>=To)
253             */
254             template<typename CharT>
255             struct is_from_rangeF :
256                 public predicate_facade< is_from_rangeF<CharT> >
257             {
258                 // Boost.ResultOf support
259                 typedef bool result_type;
260 
261                 // Constructor
is_from_rangeFboost::algorithm::detail::is_from_rangeF262                 is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
263 
264                 // Operation
265                 template<typename Char2T>
operator ()boost::algorithm::detail::is_from_rangeF266                 bool operator()( Char2T Ch ) const
267                 {
268                     return ( m_From <= Ch ) && ( Ch <= m_To );
269                 }
270 
271             private:
272                 CharT m_From;
273                 CharT m_To;
274             };
275 
276             // class_and composition predicate
277             template<typename Pred1T, typename Pred2T>
278             struct pred_andF :
279                 public predicate_facade< pred_andF<Pred1T,Pred2T> >
280             {
281             public:
282 
283                 // Boost.ResultOf support
284                 typedef bool result_type;
285 
286                 // Constructor
pred_andFboost::algorithm::detail::pred_andF287                 pred_andF( Pred1T Pred1, Pred2T Pred2 ) :
288                     m_Pred1(Pred1), m_Pred2(Pred2) {}
289 
290                 // Operation
291                 template<typename CharT>
operator ()boost::algorithm::detail::pred_andF292                 bool operator()( CharT Ch ) const
293                 {
294                     return m_Pred1(Ch) && m_Pred2(Ch);
295                 }
296 
297             private:
298                 Pred1T m_Pred1;
299                 Pred2T m_Pred2;
300             };
301 
302             // class_or composition predicate
303             template<typename Pred1T, typename Pred2T>
304             struct pred_orF :
305                 public predicate_facade< pred_orF<Pred1T,Pred2T> >
306             {
307             public:
308                 // Boost.ResultOf support
309                 typedef bool result_type;
310 
311                 // Constructor
pred_orFboost::algorithm::detail::pred_orF312                 pred_orF( Pred1T Pred1, Pred2T Pred2 ) :
313                     m_Pred1(Pred1), m_Pred2(Pred2) {}
314 
315                 // Operation
316                 template<typename CharT>
operator ()boost::algorithm::detail::pred_orF317                 bool operator()( CharT Ch ) const
318                 {
319                     return m_Pred1(Ch) || m_Pred2(Ch);
320                 }
321 
322             private:
323                 Pred1T m_Pred1;
324                 Pred2T m_Pred2;
325             };
326 
327             // class_not composition predicate
328             template< typename PredT >
329             struct pred_notF :
330                 public predicate_facade< pred_notF<PredT> >
331             {
332             public:
333                 // Boost.ResultOf support
334                 typedef bool result_type;
335 
336                 // Constructor
pred_notFboost::algorithm::detail::pred_notF337                 pred_notF( PredT Pred ) : m_Pred(Pred) {}
338 
339                 // Operation
340                 template<typename CharT>
operator ()boost::algorithm::detail::pred_notF341                 bool operator()( CharT Ch ) const
342                 {
343                     return !m_Pred(Ch);
344                 }
345 
346             private:
347                 PredT m_Pred;
348             };
349 
350         } // namespace detail
351     } // namespace algorithm
352 } // namespace boost
353 
354 
355 #endif  // BOOST_STRING_CLASSIFICATION_DETAIL_HPP
356