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 |
41 | 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> |
45 | 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<> |
52 | 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> |
82 | 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(size: 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 |
109 | 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(size: 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(dest: DestStorage, src: SrcStorage, n: sizeof(set_value_type)*m_Size); |
132 | } |
133 | |
134 | // Destructor |
135 | ~is_any_ofF() |
136 | { |
137 | if(!use_fixed_storage(size: m_Size) && m_Storage.m_dynSet!=0) |
138 | { |
139 | delete [] m_Storage.m_dynSet; |
140 | } |
141 | } |
142 | |
143 | // Assignment |
144 | 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(size: 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(size: 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(size: 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(dest: DestStorage, src: SrcStorage, n: sizeof(set_value_type)*m_Size); |
212 | |
213 | return *this; |
214 | } |
215 | |
216 | // Operation |
217 | template<typename Char2T> |
218 | bool operator()( Char2T Ch ) const |
219 | { |
220 | const set_value_type* Storage= |
221 | (use_fixed_storage(size: 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 |
229 | 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 |
262 | is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {} |
263 | |
264 | // Operation |
265 | template<typename Char2T> |
266 | 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 |
287 | pred_andF( Pred1T Pred1, Pred2T Pred2 ) : |
288 | m_Pred1(Pred1), m_Pred2(Pred2) {} |
289 | |
290 | // Operation |
291 | template<typename CharT> |
292 | 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 |
312 | pred_orF( Pred1T Pred1, Pred2T Pred2 ) : |
313 | m_Pred1(Pred1), m_Pred2(Pred2) {} |
314 | |
315 | // Operation |
316 | template<typename CharT> |
317 | 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 |
337 | pred_notF( PredT Pred ) : m_Pred(Pred) {} |
338 | |
339 | // Operation |
340 | template<typename CharT> |
341 | 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 | |