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