1 //  Boost string_algo library predicate.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_PREDICATE_HPP
12 #define BOOST_STRING_PREDICATE_HPP
13 
14 #include <boost/algorithm/string/config.hpp>
15 #include <boost/range/begin.hpp>
16 #include <boost/range/end.hpp>
17 #include <boost/range/iterator.hpp>
18 #include <boost/range/const_iterator.hpp>
19 #include <boost/range/as_literal.hpp>
20 #include <boost/range/iterator_range_core.hpp>
21 
22 #include <boost/algorithm/string/compare.hpp>
23 #include <boost/algorithm/string/find.hpp>
24 #include <boost/algorithm/string/detail/predicate.hpp>
25 
26 /*! \file boost/algorithm/string/predicate.hpp
27     Defines string-related predicates.
28     The predicates determine whether a substring is contained in the input string
29     under various conditions: a string starts with the substring, ends with the
30     substring, simply contains the substring or if both strings are equal.
31     Additionaly the algorithm \c all() checks all elements of a container to satisfy a
32     condition.
33 
34     All predicates provide the strong exception guarantee.
35 */
36 
37 namespace boost {
38     namespace algorithm {
39 
40 //  starts_with predicate  -----------------------------------------------//
41 
42         //! 'Starts with' predicate
43         /*!
44             This predicate holds when the test string is a prefix of the Input.
45             In other words, if the input starts with the test.
46             When the optional predicate is specified, it is used for character-wise
47             comparison.
48 
49             \param Input An input sequence
50             \param Test A test sequence
51             \param Comp An element comparison predicate
52             \return The result of the test
53 
54               \note This function provides the strong exception-safety guarantee
55         */
56         template<typename Range1T, typename Range2T, typename PredicateT>
starts_with(const Range1T & Input,const Range2T & Test,PredicateT Comp)57             inline bool starts_with(
58             const Range1T& Input,
59             const Range2T& Test,
60             PredicateT Comp)
61         {
62             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
63             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
64 
65             typedef BOOST_STRING_TYPENAME
66                 range_const_iterator<Range1T>::type Iterator1T;
67             typedef BOOST_STRING_TYPENAME
68                 range_const_iterator<Range2T>::type Iterator2T;
69 
70             Iterator1T InputEnd=::boost::end(lit_input);
71             Iterator2T TestEnd=::boost::end(lit_test);
72 
73             Iterator1T it=::boost::begin(lit_input);
74             Iterator2T pit=::boost::begin(lit_test);
75             for(;
76                 it!=InputEnd && pit!=TestEnd;
77                 ++it,++pit)
78             {
79                 if( !(Comp(*it,*pit)) )
80                     return false;
81             }
82 
83             return pit==TestEnd;
84         }
85 
86         //! 'Starts with' predicate
87         /*!
88             \overload
89         */
90         template<typename Range1T, typename Range2T>
starts_with(const Range1T & Input,const Range2T & Test)91         inline bool starts_with(
92             const Range1T& Input,
93             const Range2T& Test)
94         {
95             return ::boost::algorithm::starts_with(Input, Test, is_equal());
96         }
97 
98         //! 'Starts with' predicate ( case insensitive )
99         /*!
100             This predicate holds when the test string is a prefix of the Input.
101             In other words, if the input starts with the test.
102             Elements are compared case insensitively.
103 
104             \param Input An input sequence
105             \param Test A test sequence
106             \param Loc A locale used for case insensitive comparison
107             \return The result of the test
108 
109             \note This function provides the strong exception-safety guarantee
110         */
111         template<typename Range1T, typename Range2T>
istarts_with(const Range1T & Input,const Range2T & Test,const std::locale & Loc=std::locale ())112         inline bool istarts_with(
113             const Range1T& Input,
114             const Range2T& Test,
115             const std::locale& Loc=std::locale())
116         {
117             return ::boost::algorithm::starts_with(Input, Test, is_iequal(Loc));
118         }
119 
120 
121 //  ends_with predicate  -----------------------------------------------//
122 
123         //! 'Ends with' predicate
124         /*!
125             This predicate holds when the test string is a suffix of the Input.
126             In other words, if the input ends with the test.
127             When the optional predicate is specified, it is used for character-wise
128             comparison.
129 
130 
131             \param Input An input sequence
132             \param Test A test sequence
133             \param Comp An element comparison predicate
134             \return The result of the test
135 
136               \note This function provides the strong exception-safety guarantee
137         */
138         template<typename Range1T, typename Range2T, typename PredicateT>
ends_with(const Range1T & Input,const Range2T & Test,PredicateT Comp)139         inline bool ends_with(
140             const Range1T& Input,
141             const Range2T& Test,
142             PredicateT Comp)
143         {
144             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
145             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
146 
147             typedef BOOST_STRING_TYPENAME
148                 range_const_iterator<Range1T>::type Iterator1T;
149             typedef BOOST_STRING_TYPENAME boost::detail::
150                 iterator_traits<Iterator1T>::iterator_category category;
151 
152             return detail::
153                 ends_with_iter_select(
154                     ::boost::begin(lit_input),
155                     ::boost::end(lit_input),
156                     ::boost::begin(lit_test),
157                     ::boost::end(lit_test),
158                     Comp,
159                     category());
160         }
161 
162 
163         //! 'Ends with' predicate
164         /*!
165             \overload
166         */
167         template<typename Range1T, typename Range2T>
ends_with(const Range1T & Input,const Range2T & Test)168         inline bool ends_with(
169             const Range1T& Input,
170             const Range2T& Test)
171         {
172             return ::boost::algorithm::ends_with(Input, Test, is_equal());
173         }
174 
175         //! 'Ends with' predicate ( case insensitive )
176         /*!
177             This predicate holds when the test container is a suffix of the Input.
178             In other words, if the input ends with the test.
179             Elements are compared case insensitively.
180 
181             \param Input An input sequence
182             \param Test A test sequence
183             \param Loc A locale used for case insensitive comparison
184             \return The result of the test
185 
186             \note This function provides the strong exception-safety guarantee
187         */
188         template<typename Range1T, typename Range2T>
iends_with(const Range1T & Input,const Range2T & Test,const std::locale & Loc=std::locale ())189         inline bool iends_with(
190             const Range1T& Input,
191             const Range2T& Test,
192             const std::locale& Loc=std::locale())
193         {
194             return ::boost::algorithm::ends_with(Input, Test, is_iequal(Loc));
195         }
196 
197 //  contains predicate  -----------------------------------------------//
198 
199         //! 'Contains' predicate
200         /*!
201             This predicate holds when the test container is contained in the Input.
202             When the optional predicate is specified, it is used for character-wise
203             comparison.
204 
205             \param Input An input sequence
206             \param Test A test sequence
207             \param Comp An element comparison predicate
208             \return The result of the test
209 
210                \note This function provides the strong exception-safety guarantee
211         */
212         template<typename Range1T, typename Range2T, typename PredicateT>
contains(const Range1T & Input,const Range2T & Test,PredicateT Comp)213         inline bool contains(
214             const Range1T& Input,
215             const Range2T& Test,
216             PredicateT Comp)
217         {
218             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
219             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
220 
221             if (::boost::empty(lit_test))
222             {
223                 // Empty range is contained always
224                 return true;
225             }
226 
227             // Use the temporary variable to make VACPP happy
228             bool bResult=(::boost::algorithm::first_finder(lit_test,Comp)(::boost::begin(lit_input), ::boost::end(lit_input)));
229             return bResult;
230         }
231 
232         //! 'Contains' predicate
233         /*!
234             \overload
235         */
236         template<typename Range1T, typename Range2T>
contains(const Range1T & Input,const Range2T & Test)237         inline bool contains(
238             const Range1T& Input,
239             const Range2T& Test)
240         {
241             return ::boost::algorithm::contains(Input, Test, is_equal());
242         }
243 
244         //! 'Contains' predicate ( case insensitive )
245         /*!
246             This predicate holds when the test container is contained in the Input.
247             Elements are compared case insensitively.
248 
249             \param Input An input sequence
250             \param Test A test sequence
251             \param Loc A locale used for case insensitive comparison
252             \return The result of the test
253 
254             \note This function provides the strong exception-safety guarantee
255         */
256         template<typename Range1T, typename Range2T>
icontains(const Range1T & Input,const Range2T & Test,const std::locale & Loc=std::locale ())257         inline bool icontains(
258             const Range1T& Input,
259             const Range2T& Test,
260             const std::locale& Loc=std::locale())
261         {
262             return ::boost::algorithm::contains(Input, Test, is_iequal(Loc));
263         }
264 
265 //  equals predicate  -----------------------------------------------//
266 
267         //! 'Equals' predicate
268         /*!
269             This predicate holds when the test container is equal to the
270             input container i.e. all elements in both containers are same.
271             When the optional predicate is specified, it is used for character-wise
272             comparison.
273 
274             \param Input An input sequence
275             \param Test A test sequence
276             \param Comp An element comparison predicate
277             \return The result of the test
278 
279             \note This is a two-way version of \c std::equal algorithm
280 
281             \note This function provides the strong exception-safety guarantee
282         */
283         template<typename Range1T, typename Range2T, typename PredicateT>
equals(const Range1T & Input,const Range2T & Test,PredicateT Comp)284         inline bool equals(
285             const Range1T& Input,
286             const Range2T& Test,
287             PredicateT Comp)
288         {
289             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
290             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
291 
292             typedef BOOST_STRING_TYPENAME
293                 range_const_iterator<Range1T>::type Iterator1T;
294             typedef BOOST_STRING_TYPENAME
295                 range_const_iterator<Range2T>::type Iterator2T;
296 
297             Iterator1T InputEnd=::boost::end(lit_input);
298             Iterator2T TestEnd=::boost::end(lit_test);
299 
300             Iterator1T it=::boost::begin(lit_input);
301             Iterator2T pit=::boost::begin(lit_test);
302             for(;
303                 it!=InputEnd && pit!=TestEnd;
304                 ++it,++pit)
305             {
306                 if( !(Comp(*it,*pit)) )
307                     return false;
308             }
309 
310             return  (pit==TestEnd) && (it==InputEnd);
311         }
312 
313         //! 'Equals' predicate
314         /*!
315             \overload
316         */
317         template<typename Range1T, typename Range2T>
equals(const Range1T & Input,const Range2T & Test)318         inline bool equals(
319             const Range1T& Input,
320             const Range2T& Test)
321         {
322             return ::boost::algorithm::equals(Input, Test, is_equal());
323         }
324 
325         //! 'Equals' predicate ( case insensitive )
326         /*!
327             This predicate holds when the test container is equal to the
328             input container i.e. all elements in both containers are same.
329             Elements are compared case insensitively.
330 
331             \param Input An input sequence
332             \param Test A test sequence
333             \param Loc A locale used for case insensitive comparison
334             \return The result of the test
335 
336             \note This is a two-way version of \c std::equal algorithm
337 
338             \note This function provides the strong exception-safety guarantee
339         */
340         template<typename Range1T, typename Range2T>
iequals(const Range1T & Input,const Range2T & Test,const std::locale & Loc=std::locale ())341         inline bool iequals(
342             const Range1T& Input,
343             const Range2T& Test,
344             const std::locale& Loc=std::locale())
345         {
346             return ::boost::algorithm::equals(Input, Test, is_iequal(Loc));
347         }
348 
349 // lexicographical_compare predicate -----------------------------//
350 
351         //! Lexicographical compare predicate
352         /*!
353              This predicate is an overload of std::lexicographical_compare
354              for range arguments
355 
356              It check whether the first argument is lexicographically less
357              then the second one.
358 
359              If the optional predicate is specified, it is used for character-wise
360              comparison
361 
362              \param Arg1 First argument
363              \param Arg2 Second argument
364              \param Pred Comparison predicate
365              \return The result of the test
366 
367              \note This function provides the strong exception-safety guarantee
368          */
369         template<typename Range1T, typename Range2T, typename PredicateT>
lexicographical_compare(const Range1T & Arg1,const Range2T & Arg2,PredicateT Pred)370         inline bool lexicographical_compare(
371             const Range1T& Arg1,
372             const Range2T& Arg2,
373             PredicateT Pred)
374         {
375             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_arg1(::boost::as_literal(Arg1));
376             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_arg2(::boost::as_literal(Arg2));
377 
378             return std::lexicographical_compare(
379                 ::boost::begin(lit_arg1),
380                 ::boost::end(lit_arg1),
381                 ::boost::begin(lit_arg2),
382                 ::boost::end(lit_arg2),
383                 Pred);
384         }
385 
386         //! Lexicographical compare predicate
387         /*!
388             \overload
389          */
390         template<typename Range1T, typename Range2T>
lexicographical_compare(const Range1T & Arg1,const Range2T & Arg2)391             inline bool lexicographical_compare(
392             const Range1T& Arg1,
393             const Range2T& Arg2)
394         {
395             return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_less());
396         }
397 
398         //! Lexicographical compare predicate (case-insensitive)
399         /*!
400             This predicate is an overload of std::lexicographical_compare
401             for range arguments.
402             It check whether the first argument is lexicographically less
403             then the second one.
404             Elements are compared case insensitively
405 
406 
407              \param Arg1 First argument
408              \param Arg2 Second argument
409              \param Loc A locale used for case insensitive comparison
410              \return The result of the test
411 
412              \note This function provides the strong exception-safety guarantee
413          */
414         template<typename Range1T, typename Range2T>
ilexicographical_compare(const Range1T & Arg1,const Range2T & Arg2,const std::locale & Loc=std::locale ())415         inline bool ilexicographical_compare(
416             const Range1T& Arg1,
417             const Range2T& Arg2,
418             const std::locale& Loc=std::locale())
419         {
420             return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_iless(Loc));
421         }
422 
423 
424 //  all predicate  -----------------------------------------------//
425 
426         //! 'All' predicate
427         /*!
428             This predicate holds it all its elements satisfy a given
429             condition, represented by the predicate.
430 
431             \param Input An input sequence
432             \param Pred A predicate
433             \return The result of the test
434 
435             \note This function provides the strong exception-safety guarantee
436         */
437         template<typename RangeT, typename PredicateT>
all(const RangeT & Input,PredicateT Pred)438         inline bool all(
439             const RangeT& Input,
440             PredicateT Pred)
441         {
442             iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
443 
444             typedef BOOST_STRING_TYPENAME
445                 range_const_iterator<RangeT>::type Iterator1T;
446 
447             Iterator1T InputEnd=::boost::end(lit_input);
448             for( Iterator1T It=::boost::begin(lit_input); It!=InputEnd; ++It)
449             {
450                 if (!Pred(*It))
451                     return false;
452             }
453 
454             return true;
455         }
456 
457     } // namespace algorithm
458 
459     // pull names to the boost namespace
460     using algorithm::starts_with;
461     using algorithm::istarts_with;
462     using algorithm::ends_with;
463     using algorithm::iends_with;
464     using algorithm::contains;
465     using algorithm::icontains;
466     using algorithm::equals;
467     using algorithm::iequals;
468     using algorithm::all;
469     using algorithm::lexicographical_compare;
470     using algorithm::ilexicographical_compare;
471 
472 } // namespace boost
473 
474 
475 #endif  // BOOST_STRING_PREDICATE_HPP
476