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