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