mirror of
https://github.com/boostorg/algorithm.git
synced 2025-06-25 20:11:50 +02:00
Compare commits
111 Commits
svn-branch
...
boost-1.33
Author | SHA1 | Date | |
---|---|---|---|
fe9e7eac19 | |||
b1627fcec1 | |||
a38c211e8a | |||
5af41051f0 | |||
6c5f2a8d33 | |||
924368a775 | |||
344225bce1 | |||
a4137bbae6 | |||
04a40de48d | |||
5ecf446070 | |||
e909726c60 | |||
9878f92a41 | |||
d72eec3093 | |||
bc09128c6e | |||
0f707ed9c9 | |||
77307c2823 | |||
e00fd7f159 | |||
5419d39b2e | |||
7ad6c08c68 | |||
b6c5c86d9c | |||
0f4aa23e9c | |||
b0a2a9d3e0 | |||
8fc117aa7e | |||
0f827f89cf | |||
2074344846 | |||
3b889db8d1 | |||
1489b70457 | |||
c475f8559d | |||
d3d4ffe0e6 | |||
2b5de80031 | |||
aea6f39c11 | |||
54092d7934 | |||
747597c7ef | |||
72b4390091 | |||
77ae41a18a | |||
5d1448f3ac | |||
0a0facd7c7 | |||
053cc53eea | |||
54ac5bebd3 | |||
3542f868a0 | |||
4d346d43ad | |||
56862b0bcc | |||
108365abe7 | |||
fa09dddc75 | |||
6fb58192d7 | |||
792b4eae88 | |||
a23ae6316f | |||
5063e96367 | |||
5221839b71 | |||
ba00033cbf | |||
047a42934d | |||
747b4e17cc | |||
4c0efd3d1a | |||
67f7273ab3 | |||
ce6a647dd0 | |||
246794db2a | |||
325fa64dc3 | |||
33122fefa7 | |||
4b3118ed2b | |||
85e0e920bf | |||
483bc9e231 | |||
643c793f3b | |||
825468bc42 | |||
69339b779c | |||
7a88ef8658 | |||
2b2086dd8f | |||
bfa0f28830 | |||
f16de45e46 | |||
f6752d3ae1 | |||
961e8b399e | |||
21440d1b17 | |||
cc72a93094 | |||
9fd4119efc | |||
00d09671f5 | |||
4e55a78e2d | |||
48e65026d9 | |||
fb182c2566 | |||
d97ff92ae4 | |||
ddd9baba60 | |||
3786aa8b04 | |||
cc683155c7 | |||
dd8d053685 | |||
54075a951b | |||
8cf6df3ad6 | |||
caad29f22a | |||
06474a276d | |||
4185e3fb31 | |||
905cbf4a38 | |||
ccce29ecf5 | |||
029851b0ce | |||
22b59d1848 | |||
8242b4ba5a | |||
a568d32ba9 | |||
9dcf3e6b76 | |||
113c676eef | |||
b108993f89 | |||
81044b4233 | |||
71d18481dd | |||
16f4b20083 | |||
e0d1f0692d | |||
cf85da14ed | |||
ec606bbf14 | |||
729bb65a2d | |||
6df2923b40 | |||
6d7d244051 | |||
1e7aec2dee | |||
752c65be35 | |||
77303abc55 | |||
d92e09176c | |||
bc420c5acf | |||
d88e251f39 |
47
include/boost/algorithm/minmax.hpp
Normal file
47
include/boost/algorithm/minmax.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
// (C) Copyright Herve Bronnimann 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
1 July 2004
|
||||
Split the code into two headers to lessen dependence on
|
||||
Boost.tuple. (Herve)
|
||||
26 June 2004
|
||||
Added the code for the boost minmax library. (Herve)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ALGORITHM_MINMAX_HPP
|
||||
#define BOOST_ALGORITHM_MINMAX_HPP
|
||||
|
||||
/* PROPOSED STANDARD EXTENSIONS:
|
||||
*
|
||||
* minmax(a, b)
|
||||
* Effect: (b<a) ? std::make_pair(b,a) : std::make_pair(a,b);
|
||||
*
|
||||
* minmax(a, b, comp)
|
||||
* Effect: comp(b,a) ? std::make_pair(b,a) : std::make_pair(a,b);
|
||||
*
|
||||
*/
|
||||
|
||||
#include <boost/tuple/tuple.hpp> // for using pairs with boost::cref
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
tuple< T const&, T const& >
|
||||
minmax(T const& a, T const& b) {
|
||||
return (b<a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b));
|
||||
}
|
||||
|
||||
template <typename T, class BinaryPredicate>
|
||||
tuple< T const&, T const& >
|
||||
minmax(T const& a, T const& b, BinaryPredicate comp) {
|
||||
return comp(b,a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b));
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ALGORITHM_MINMAX_HPP
|
551
include/boost/algorithm/minmax_element.hpp
Normal file
551
include/boost/algorithm/minmax_element.hpp
Normal file
@ -0,0 +1,551 @@
|
||||
// (C) Copyright Herve Bronnimann 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
1 July 2004
|
||||
Split the code into two headers to lessen dependence on
|
||||
Boost.tuple. (Herve)
|
||||
26 June 2004
|
||||
Added the code for the boost minmax library. (Herve)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
|
||||
#define BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
|
||||
|
||||
/* PROPOSED STANDARD EXTENSIONS:
|
||||
*
|
||||
* minmax_element(first, last)
|
||||
* Effect: std::make_pair( std::min_element(first, last),
|
||||
* std::max_element(first, last) );
|
||||
*
|
||||
* minmax_element(first, last, comp)
|
||||
* Effect: std::make_pair( std::min_element(first, last, comp),
|
||||
* std::max_element(first, last, comp) );
|
||||
*/
|
||||
|
||||
#include <utility> // for std::pair and std::make_pair
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail { // for obtaining a uniform version of minmax_element
|
||||
// that compiles with VC++ 6.0 -- avoid the iterator_traits by
|
||||
// having comparison object over iterator, not over dereferenced value
|
||||
|
||||
template <typename Iterator>
|
||||
struct less_over_iter {
|
||||
bool operator()(Iterator const& it1,
|
||||
Iterator const& it2) const { return *it1 < *it2; }
|
||||
};
|
||||
|
||||
template <typename Iterator, class BinaryPredicate>
|
||||
struct binary_pred_over_iter {
|
||||
explicit binary_pred_over_iter(BinaryPredicate const& p ) : m_p( p ) {}
|
||||
bool operator()(Iterator const& it1,
|
||||
Iterator const& it2) const { return m_p(*it1, *it2); }
|
||||
private:
|
||||
BinaryPredicate m_p;
|
||||
};
|
||||
|
||||
// common base for the two minmax_element overloads
|
||||
|
||||
template <typename ForwardIter, class Compare >
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
basic_minmax_element(ForwardIter first, ForwardIter last, Compare comp)
|
||||
{
|
||||
if (first == last)
|
||||
return std::make_pair(last,last);
|
||||
|
||||
ForwardIter min_result = first;
|
||||
ForwardIter max_result = first;
|
||||
|
||||
// if only one element
|
||||
ForwardIter second = first; ++second;
|
||||
if (second == last)
|
||||
return std::make_pair(min_result, max_result);
|
||||
|
||||
// treat first pair separately (only one comparison for first two elements)
|
||||
ForwardIter potential_min_result = last;
|
||||
if (comp(first, second))
|
||||
max_result = second;
|
||||
else {
|
||||
min_result = second;
|
||||
potential_min_result = first;
|
||||
}
|
||||
|
||||
// then each element by pairs, with at most 3 comparisons per pair
|
||||
first = ++second; if (first != last) ++second;
|
||||
while (second != last) {
|
||||
if (comp(first, second)) {
|
||||
if (comp(first, min_result)) {
|
||||
min_result = first;
|
||||
potential_min_result = last;
|
||||
}
|
||||
if (comp(max_result, second))
|
||||
max_result = second;
|
||||
} else {
|
||||
if (comp(second, min_result)) {
|
||||
min_result = second;
|
||||
potential_min_result = first;
|
||||
}
|
||||
if (comp(max_result, first))
|
||||
max_result = first;
|
||||
}
|
||||
first = ++second;
|
||||
if (first != last) ++second;
|
||||
}
|
||||
|
||||
// if odd number of elements, treat last element
|
||||
if (first != last) { // odd number of elements
|
||||
if (comp(first, min_result))
|
||||
min_result = first, potential_min_result = last;
|
||||
else if (comp(max_result, first))
|
||||
max_result = first;
|
||||
}
|
||||
|
||||
// resolve min_result being incorrect with one extra comparison
|
||||
// (in which case potential_min_result is necessarily the correct result)
|
||||
if (potential_min_result != last
|
||||
&& !comp(min_result, potential_min_result))
|
||||
min_result = potential_min_result;
|
||||
|
||||
return std::make_pair(min_result,max_result);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename ForwardIter>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
minmax_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_minmax_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
minmax_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_minmax_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* PROPOSED BOOST EXTENSIONS
|
||||
* In the description below, [rfirst,rlast) denotes the reversed range
|
||||
* of [first,last). Even though the iterator type of first and last may
|
||||
* be only a Forward Iterator, it is possible to explain the semantics
|
||||
* by assuming that it is a Bidirectional Iterator. In the sequel,
|
||||
* reverse(ForwardIterator&) returns the reverse_iterator adaptor.
|
||||
* This is not how the functions would be implemented!
|
||||
*
|
||||
* first_min_element(first, last)
|
||||
* Effect: std::min_element(first, last);
|
||||
*
|
||||
* first_min_element(first, last, comp)
|
||||
* Effect: std::min_element(first, last, comp);
|
||||
*
|
||||
* last_min_element(first, last)
|
||||
* Effect: reverse( std::min_element(reverse(last), reverse(first)) );
|
||||
*
|
||||
* last_min_element(first, last, comp)
|
||||
* Effect: reverse( std::min_element(reverse(last), reverse(first), comp) );
|
||||
*
|
||||
* first_max_element(first, last)
|
||||
* Effect: std::max_element(first, last);
|
||||
*
|
||||
* first_max_element(first, last, comp)
|
||||
* Effect: max_element(first, last);
|
||||
*
|
||||
* last_max_element(first, last)
|
||||
* Effect: reverse( std::max_element(reverse(last), reverse(first)) );
|
||||
*
|
||||
* last_max_element(first, last, comp)
|
||||
* Effect: reverse( std::max_element(reverse(last), reverse(first), comp) );
|
||||
*
|
||||
* first_min_first_max_element(first, last)
|
||||
* Effect: std::make_pair( first_min_element(first, last),
|
||||
* first_max_element(first, last) );
|
||||
*
|
||||
* first_min_first_max_element(first, last, comp)
|
||||
* Effect: std::make_pair( first_min_element(first, last, comp),
|
||||
* first_max_element(first, last, comp) );
|
||||
*
|
||||
* first_min_last_max_element(first, last)
|
||||
* Effect: std::make_pair( first_min_element(first, last),
|
||||
* last_max_element(first, last) );
|
||||
*
|
||||
* first_min_last_max_element(first, last, comp)
|
||||
* Effect: std::make_pair( first_min_element(first, last, comp),
|
||||
* last_max_element(first, last, comp) );
|
||||
*
|
||||
* last_min_first_max_element(first, last)
|
||||
* Effect: std::make_pair( last_min_element(first, last),
|
||||
* first_max_element(first, last) );
|
||||
*
|
||||
* last_min_first_max_element(first, last, comp)
|
||||
* Effect: std::make_pair( last_min_element(first, last, comp),
|
||||
* first_max_element(first, last, comp) );
|
||||
*
|
||||
* last_min_last_max_element(first, last)
|
||||
* Effect: std::make_pair( last_min_element(first, last),
|
||||
* last_max_element(first, last) );
|
||||
*
|
||||
* last_min_last_max_element(first, last, comp)
|
||||
* Effect: std::make_pair( last_min_element(first, last, comp),
|
||||
* last_max_element(first, last, comp) );
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Min_element and max_element variants
|
||||
|
||||
namespace detail { // common base for the overloads
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
basic_first_min_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last) return last;
|
||||
ForwardIter min_result = first;
|
||||
while (++first != last)
|
||||
if (comp(first, min_result))
|
||||
min_result = first;
|
||||
return min_result;
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
basic_last_min_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last) return last;
|
||||
ForwardIter min_result = first;
|
||||
while (++first != last)
|
||||
if (!comp(min_result, first))
|
||||
min_result = first;
|
||||
return min_result;
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
basic_first_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last) return last;
|
||||
ForwardIter max_result = first;
|
||||
while (++first != last)
|
||||
if (comp(max_result, first))
|
||||
max_result = first;
|
||||
return max_result;
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
basic_last_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last) return last;
|
||||
ForwardIter max_result = first;
|
||||
while (++first != last)
|
||||
if (!comp(first, max_result))
|
||||
max_result = first;
|
||||
return max_result;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename ForwardIter>
|
||||
ForwardIter
|
||||
first_min_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_first_min_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
first_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_first_min_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
ForwardIter
|
||||
last_min_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_last_min_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
last_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_last_min_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
ForwardIter
|
||||
first_max_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_first_max_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
first_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_first_max_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
ForwardIter
|
||||
last_max_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_last_max_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
ForwardIter
|
||||
last_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_last_max_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
|
||||
// Minmax_element variants -- comments removed
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
basic_first_min_last_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last)
|
||||
return std::make_pair(last,last);
|
||||
|
||||
ForwardIter min_result = first;
|
||||
ForwardIter max_result = first;
|
||||
|
||||
ForwardIter second = ++first;
|
||||
if (second == last)
|
||||
return std::make_pair(min_result, max_result);
|
||||
|
||||
if (comp(second, min_result))
|
||||
min_result = second;
|
||||
else
|
||||
max_result = second;
|
||||
|
||||
first = ++second; if (first != last) ++second;
|
||||
while (second != last) {
|
||||
if (!comp(second, first)) {
|
||||
if (comp(first, min_result))
|
||||
min_result = first;
|
||||
if (!comp(second, max_result))
|
||||
max_result = second;
|
||||
} else {
|
||||
if (comp(second, min_result))
|
||||
min_result = second;
|
||||
if (!comp(first, max_result))
|
||||
max_result = first;
|
||||
}
|
||||
first = ++second; if (first != last) ++second;
|
||||
}
|
||||
|
||||
if (first != last) {
|
||||
if (comp(first, min_result))
|
||||
min_result = first;
|
||||
else if (!comp(first, max_result))
|
||||
max_result = first;
|
||||
}
|
||||
|
||||
return std::make_pair(min_result, max_result);
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
basic_last_min_first_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last) return std::make_pair(last,last);
|
||||
|
||||
ForwardIter min_result = first;
|
||||
ForwardIter max_result = first;
|
||||
|
||||
ForwardIter second = ++first;
|
||||
if (second == last)
|
||||
return std::make_pair(min_result, max_result);
|
||||
|
||||
if (comp(max_result, second))
|
||||
max_result = second;
|
||||
else
|
||||
min_result = second;
|
||||
|
||||
first = ++second; if (first != last) ++second;
|
||||
while (second != last) {
|
||||
if (comp(first, second)) {
|
||||
if (!comp(min_result, first))
|
||||
min_result = first;
|
||||
if (comp(max_result, second))
|
||||
max_result = second;
|
||||
} else {
|
||||
if (!comp(min_result, second))
|
||||
min_result = second;
|
||||
if (comp(max_result, first))
|
||||
max_result = first;
|
||||
}
|
||||
first = ++second; if (first != last) ++second;
|
||||
}
|
||||
|
||||
if (first != last) {
|
||||
if (!comp(min_result, first))
|
||||
min_result = first;
|
||||
else if (comp(max_result, first))
|
||||
max_result = first;
|
||||
}
|
||||
|
||||
return std::make_pair(min_result, max_result);
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
basic_last_min_last_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
if (first == last) return std::make_pair(last,last);
|
||||
|
||||
ForwardIter min_result = first;
|
||||
ForwardIter max_result = first;
|
||||
|
||||
ForwardIter second = first; ++second;
|
||||
if (second == last)
|
||||
return std::make_pair(min_result,max_result);
|
||||
|
||||
ForwardIter potential_max_result = last;
|
||||
if (comp(first, second))
|
||||
max_result = second;
|
||||
else {
|
||||
min_result = second;
|
||||
potential_max_result = second;
|
||||
}
|
||||
|
||||
first = ++second; if (first != last) ++second;
|
||||
while (second != last) {
|
||||
if (comp(first, second)) {
|
||||
if (!comp(min_result, first))
|
||||
min_result = first;
|
||||
if (!comp(second, max_result)) {
|
||||
max_result = second;
|
||||
potential_max_result = last;
|
||||
}
|
||||
} else {
|
||||
if (!comp(min_result, second))
|
||||
min_result = second;
|
||||
if (!comp(first, max_result)) {
|
||||
max_result = first;
|
||||
potential_max_result = second;
|
||||
}
|
||||
}
|
||||
first = ++second;
|
||||
if (first != last) ++second;
|
||||
}
|
||||
|
||||
if (first != last) {
|
||||
if (!comp(min_result, first))
|
||||
min_result = first;
|
||||
if (!comp(first, max_result)) {
|
||||
max_result = first;
|
||||
potential_max_result = last;
|
||||
}
|
||||
}
|
||||
|
||||
if (potential_max_result != last
|
||||
&& !comp(potential_max_result, max_result))
|
||||
max_result = potential_max_result;
|
||||
|
||||
return std::make_pair(min_result,max_result);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename ForwardIter>
|
||||
inline std::pair<ForwardIter,ForwardIter>
|
||||
first_min_first_max_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return minmax_element(first, last);
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
inline std::pair<ForwardIter,ForwardIter>
|
||||
first_min_first_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
return minmax_element(first, last, comp);
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
first_min_last_max_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_first_min_last_max_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
inline std::pair<ForwardIter,ForwardIter>
|
||||
first_min_last_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_first_min_last_max_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
last_min_first_max_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_last_min_first_max_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
inline std::pair<ForwardIter,ForwardIter>
|
||||
last_min_first_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_last_min_first_max_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
template <typename ForwardIter>
|
||||
std::pair<ForwardIter,ForwardIter>
|
||||
last_min_last_max_element(ForwardIter first, ForwardIter last)
|
||||
{
|
||||
return detail::basic_last_min_last_max_element(first, last,
|
||||
detail::less_over_iter<ForwardIter>() );
|
||||
}
|
||||
|
||||
template <typename ForwardIter, class BinaryPredicate>
|
||||
inline std::pair<ForwardIter,ForwardIter>
|
||||
last_min_last_max_element(ForwardIter first, ForwardIter last,
|
||||
BinaryPredicate comp)
|
||||
{
|
||||
return detail::basic_last_min_last_max_element(first, last,
|
||||
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
|
@ -1,9 +1,9 @@
|
||||
// Boost string_algo library string_algo.hpp header file ---------------------------//
|
||||
|
||||
// (C) Copyright Pavol Droba 2002-2003. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
// Copyright Pavol Droba 2002-2004. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
#include <boost/algorithm/string/std_containers_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
@ -14,7 +14,11 @@
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/algorithm/string/detail/case_conv.hpp>
|
||||
|
||||
/*! \file
|
||||
@ -31,36 +35,37 @@ namespace boost {
|
||||
//! Convert to lower case
|
||||
/*!
|
||||
Each element of the input sequence is converted to lower
|
||||
case. The result is copied to the given output iterator.
|
||||
case. The result is a copy of the input converted to lower case.
|
||||
It is returned as a sequence or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input collection
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param Loc A locale used for conversion
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
|
||||
*/
|
||||
template<typename OutputIteratorT, typename CollectionT>
|
||||
template<typename OutputIteratorT, typename RangeT>
|
||||
inline OutputIteratorT
|
||||
to_lower_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return std::transform(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
Output,
|
||||
detail::to_lowerF<
|
||||
typename value_type_of<CollectionT>::type >(Loc));
|
||||
::boost::algorithm::detail::to_lowerF<
|
||||
typename range_value<RangeT>::type >(Loc));
|
||||
}
|
||||
|
||||
//! Convert to lower case
|
||||
/*!
|
||||
Each element of the input sequence is converted to lower
|
||||
case. The result is a copy of the input converted to lower case.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Loc a locale used for conversion
|
||||
\return A copy of the input converted to lower case
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT to_lower_copy(
|
||||
@ -70,12 +75,12 @@ namespace boost {
|
||||
return SequenceT(
|
||||
make_transform_iterator(
|
||||
begin(Input),
|
||||
detail::to_lowerF<
|
||||
typename value_type_of<SequenceT>::type >(Loc)),
|
||||
::boost::algorithm::detail::to_lowerF<
|
||||
typename range_value<SequenceT>::type >(Loc)),
|
||||
make_transform_iterator(
|
||||
end(Input),
|
||||
detail::to_lowerF<
|
||||
typename value_type_of<SequenceT>::type >(Loc)));
|
||||
::boost::algorithm::detail::to_lowerF<
|
||||
typename range_value<SequenceT>::type >(Loc)));
|
||||
}
|
||||
|
||||
//! Convert to lower case
|
||||
@ -83,20 +88,20 @@ namespace boost {
|
||||
Each element of the input sequence is converted to lower
|
||||
case. The input sequence is modified in-place.
|
||||
|
||||
\param Input A collection
|
||||
\param Input A range
|
||||
\param Loc a locale used for conversion
|
||||
*/
|
||||
template<typename MutableCollectionT>
|
||||
template<typename WritableRangeT>
|
||||
inline void to_lower(
|
||||
MutableCollectionT& Input,
|
||||
WritableRangeT& Input,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
std::transform(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
begin(Input),
|
||||
detail::to_lowerF<
|
||||
typename value_type_of<MutableCollectionT>::type >(Loc));
|
||||
::boost::algorithm::detail::to_lowerF<
|
||||
typename range_value<WritableRangeT>::type >(Loc));
|
||||
}
|
||||
|
||||
// to_upper -----------------------------------------------//
|
||||
@ -104,36 +109,36 @@ namespace boost {
|
||||
//! Convert to upper case
|
||||
/*!
|
||||
Each element of the input sequence is converted to upper
|
||||
case. The result is copied to the given output iterator.
|
||||
case. The result is a copy of the input converted to upper case.
|
||||
It is returned as a sequence or copied to the output iterator
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input collection
|
||||
\param Loc a locale used for conversion
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param Loc A locale used for conversion
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename OutputIteratorT, typename CollectionT>
|
||||
template<typename OutputIteratorT, typename RangeT>
|
||||
inline OutputIteratorT
|
||||
to_upper_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return std::transform(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
Output,
|
||||
detail::to_upperF<
|
||||
typename value_type_of<CollectionT>::type >(Loc));
|
||||
::boost::algorithm::detail::to_upperF<
|
||||
typename range_value<RangeT>::type >(Loc));
|
||||
}
|
||||
|
||||
//! Convert to upper case
|
||||
/*!
|
||||
Each element of the input sequence is converted to upper
|
||||
case. The result is a copy if the input converted to upper case.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Loc a locale used for conversion
|
||||
\return A copy of the input converted to upper case
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT to_upper_copy(
|
||||
@ -143,12 +148,12 @@ namespace boost {
|
||||
return SequenceT(
|
||||
make_transform_iterator(
|
||||
begin(Input),
|
||||
detail::to_upperF<
|
||||
typename value_type_of<SequenceT>::type >(Loc)),
|
||||
::boost::algorithm::detail::to_upperF<
|
||||
typename range_value<SequenceT>::type >(Loc)),
|
||||
make_transform_iterator(
|
||||
end(Input),
|
||||
detail::to_upperF<
|
||||
typename value_type_of<SequenceT>::type >(Loc)));
|
||||
::boost::algorithm::detail::to_upperF<
|
||||
typename range_value<SequenceT>::type >(Loc)));
|
||||
|
||||
}
|
||||
|
||||
@ -157,20 +162,20 @@ namespace boost {
|
||||
Each element of the input sequence is converted to upper
|
||||
case. The input sequence is modified in-place.
|
||||
|
||||
\param Input An input collection
|
||||
\param Input An input range
|
||||
\param Loc a locale used for conversion
|
||||
*/
|
||||
template<typename MutableCollectionT>
|
||||
template<typename WritableRangeT>
|
||||
inline void to_upper(
|
||||
MutableCollectionT& Input,
|
||||
WritableRangeT& Input,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
std::transform(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
begin(Input),
|
||||
detail::to_upperF<
|
||||
typename value_type_of<MutableCollectionT>::type >(Loc));
|
||||
::boost::algorithm::detail::to_upperF<
|
||||
typename range_value<WritableRangeT>::type >(Loc));
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
|
@ -12,7 +12,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <boost/algorithm/string/detail/classification.hpp>
|
||||
#include <boost/algorithm/string/predicate_facade.hpp>
|
||||
|
||||
/*! \file
|
||||
Classification predicates are included in the library to give
|
||||
@ -28,7 +30,7 @@ namespace boost {
|
||||
|
||||
//! is_classified predicate
|
||||
/*!
|
||||
Construct the \c is_classified predicate. This predicate holds, if an input is
|
||||
Construct the \c is_classified predicate. This predicate holds if the input is
|
||||
of specified \c std::ctype category.
|
||||
|
||||
\param Type A \c std::ctype category
|
||||
@ -43,7 +45,7 @@ namespace boost {
|
||||
|
||||
//! is_space predicate
|
||||
/*!
|
||||
Construct the \c is_classified predicate for \c ctype_base::space category.
|
||||
Construct the \c is_classified predicate for the \c ctype_base::space category.
|
||||
|
||||
\param Loc A locale used for classification
|
||||
\return An instance of the \c is_classified predicate
|
||||
@ -186,24 +188,24 @@ namespace boost {
|
||||
|
||||
//! is_any_of predicate
|
||||
/*!
|
||||
Construct the \c is_any_of predicate. The predicate holds, if an input
|
||||
Construct the \c is_any_of predicate. The predicate holds if the input
|
||||
is included in the specified set of characters.
|
||||
|
||||
\param Set A set of characters to be recognized
|
||||
\return An instance of the \c is_any_of predicate
|
||||
*/
|
||||
template<typename ContainerT>
|
||||
template<typename RangeT>
|
||||
inline detail::is_any_ofF<
|
||||
BOOST_STRING_TYPENAME value_type_of<ContainerT>::type>
|
||||
is_any_of( const ContainerT& Set )
|
||||
BOOST_STRING_TYPENAME range_value<RangeT>::type>
|
||||
is_any_of( const RangeT& Set )
|
||||
{
|
||||
return detail::is_any_ofF<
|
||||
BOOST_STRING_TYPENAME value_type_of<ContainerT>::type>(Set);
|
||||
BOOST_STRING_TYPENAME range_value<RangeT>::type>(Set);
|
||||
}
|
||||
|
||||
//! is_from_range predicate
|
||||
/*!
|
||||
Construct the \c is_from_range predicate. The predicate holds, if an input
|
||||
Construct the \c is_from_range predicate. The predicate holds if the input
|
||||
is included in the specified range. (i.e. From <= Ch <= To )
|
||||
|
||||
\param From The start of the range
|
||||
@ -215,6 +217,74 @@ namespace boost {
|
||||
{
|
||||
return detail::is_from_rangeF<CharT>(From,To);
|
||||
}
|
||||
|
||||
// predicate combinators ---------------------------------------------------//
|
||||
|
||||
//! predicate 'and' composition predicate
|
||||
/*!
|
||||
Construct the \c class_and predicate. This predicate can be used
|
||||
to logically combine two classification predicates. \c class_and holds,
|
||||
if both predicates return true.
|
||||
|
||||
\param Pred1 The first predicate
|
||||
\param Pred2 The second predicate
|
||||
\return An instance of the \c class_and predicate
|
||||
*/
|
||||
template<typename Pred1T, typename Pred2T>
|
||||
inline detail::pred_andF<Pred1T, Pred2T>
|
||||
operator&&(
|
||||
const predicate_facade<Pred1T>& Pred1,
|
||||
const predicate_facade<Pred2T>& Pred2 )
|
||||
{
|
||||
// Doing the static_cast with the pointer instead of the reference
|
||||
// is a workaround for some compilers which have problems with
|
||||
// static_cast's of template references, i.e. CW8. /grafik/
|
||||
return detail::pred_andF<Pred1T,Pred2T>(
|
||||
*static_cast<const Pred1T*>(&Pred1),
|
||||
*static_cast<const Pred2T*>(&Pred2) );
|
||||
}
|
||||
|
||||
//! predicate 'or' composition predicate
|
||||
/*!
|
||||
Construct the \c class_or predicate. This predicate can be used
|
||||
to logically combine two classification predicates. \c class_or holds,
|
||||
if one of the predicates return true.
|
||||
|
||||
\param Pred1 The first predicate
|
||||
\param Pred2 The second predicate
|
||||
\return An instance of the \c class_or predicate
|
||||
*/
|
||||
template<typename Pred1T, typename Pred2T>
|
||||
inline detail::pred_orF<Pred1T, Pred2T>
|
||||
operator||(
|
||||
const predicate_facade<Pred1T>& Pred1,
|
||||
const predicate_facade<Pred2T>& Pred2 )
|
||||
{
|
||||
// Doing the static_cast with the pointer instead of the reference
|
||||
// is a workaround for some compilers which have problems with
|
||||
// static_cast's of template references, i.e. CW8. /grafik/
|
||||
return detail::pred_orF<Pred1T,Pred2T>(
|
||||
*static_cast<const Pred1T*>(&Pred1),
|
||||
*static_cast<const Pred2T*>(&Pred2));
|
||||
}
|
||||
|
||||
//! predicate negation operator
|
||||
/*!
|
||||
Construct the \c class_not predicate. This predicate represents a negation.
|
||||
\c class_or holds if of the predicates return false.
|
||||
|
||||
\param Pred The predicate to be negated
|
||||
\return An instance of the \c class_not predicate
|
||||
*/
|
||||
template<typename PredT>
|
||||
inline detail::pred_notF<PredT>
|
||||
operator!( const predicate_facade<PredT>& Pred )
|
||||
{
|
||||
// Doing the static_cast with the pointer instead of the reference
|
||||
// is a workaround for some compilers which have problems with
|
||||
// static_cast's of template references, i.e. CW8. /grafik/
|
||||
return detail::pred_notF<PredT>(*static_cast<const PredT*>(&Pred));
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
|
||||
@ -236,69 +306,4 @@ namespace boost {
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
// predicate combinators ---------------------------------------------------//
|
||||
/*
|
||||
* These operators must be declared in the global namespace, otherwise
|
||||
* they are not resolved correctly. There will not a problem with a name-clash,
|
||||
* since they are define only for internal types
|
||||
*/
|
||||
|
||||
//! predicate 'and' composition predicate
|
||||
/*!
|
||||
Construct the \c class_and predicate. This predicate can be used
|
||||
to logically combine two classification predicates. \c class_and holds,
|
||||
if both predicates return true.
|
||||
|
||||
\param Pred1 The first predicate
|
||||
\param Pred2 The second predicate
|
||||
\return An instance of the \c class_and predicate
|
||||
*/
|
||||
template<typename Pred1T, typename Pred2T>
|
||||
inline boost::algorithm::detail::pred_andF<Pred1T, Pred2T>
|
||||
operator&&(
|
||||
const boost::algorithm::detail::predicate_facade<Pred1T>& Pred1,
|
||||
const boost::algorithm::detail::predicate_facade<Pred2T>& Pred2 )
|
||||
{
|
||||
return boost::algorithm::detail::pred_andF<Pred1T,Pred2T>(
|
||||
static_cast<const Pred1T&>(Pred1),
|
||||
static_cast<const Pred2T&>(Pred2) );
|
||||
}
|
||||
|
||||
//! predicate 'or' composition predicate
|
||||
/*!
|
||||
Construct the \c class_or predicate. This predicate can be used
|
||||
to logically combine two classification predicates. \c class_or holds,
|
||||
if one of the predicates return true.
|
||||
|
||||
\param Pred1 The first predicate
|
||||
\param Pred2 The second predicate
|
||||
\return An instance of the \c class_or predicate
|
||||
*/
|
||||
template<typename Pred1T, typename Pred2T>
|
||||
inline boost::algorithm::detail::pred_orF<Pred1T, Pred2T>
|
||||
operator||(
|
||||
const boost::algorithm::detail::predicate_facade<Pred1T>& Pred1,
|
||||
const boost::algorithm::detail::predicate_facade<Pred2T>& Pred2 )
|
||||
{
|
||||
return boost::algorithm::detail::pred_orF<Pred1T,Pred2T>(
|
||||
static_cast<const Pred1T&>(Pred1),
|
||||
static_cast<const Pred2T&>(Pred2));
|
||||
}
|
||||
|
||||
//! predicate negation operator
|
||||
/*!
|
||||
Construct the \c class_not predicate. This predicate represents a negation.
|
||||
\c class_or holds, if of the predicates return false.
|
||||
|
||||
\param Pred The predicate to be negated
|
||||
\return An instance of the \c class_not predicate
|
||||
*/
|
||||
template<typename PredT>
|
||||
inline boost::algorithm::detail::pred_notF<PredT>
|
||||
operator!( const boost::algorithm::detail::predicate_facade<PredT>& Pred )
|
||||
{
|
||||
return boost::algorithm::detail::pred_notF<PredT>(static_cast<const PredT&>(Pred));
|
||||
}
|
||||
|
||||
#endif // BOOST_STRING_PREDICATE_HPP
|
||||
|
@ -1,268 +0,0 @@
|
||||
// Boost string_algo library collection_traits.hpp header file -------------//
|
||||
|
||||
// Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// (C) Copyright Thorsten Ottosen 2002-2003. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// Orignal idea of container traits was proposed by Jeremy Siek and
|
||||
// Thorsten Ottosen. This implemenetation is lightweighted version
|
||||
// of container_traits adapter for usage with string_algo library
|
||||
|
||||
#ifndef BOOST_STRING_COLLECTION_TRAITS_HPP
|
||||
#define BOOST_STRING_COLLECTION_TRAITS_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
|
||||
// Implementation
|
||||
#include <boost/algorithm/string/detail/collection_traits.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines collection_traits class and related free-standing functions.
|
||||
This facility is used to unify the access to different types of collections.
|
||||
It allows the algorithms in the library to work with STL collections, c-style
|
||||
array, null-terminated c-strings (and more) using the same interface.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
// collection_traits template class -----------------------------------------//
|
||||
|
||||
//! collection_traits class
|
||||
/*!
|
||||
Collection traits provides uniform access to different types of
|
||||
collections. This functionality allows to write generic algorithms
|
||||
which work with several different kinds of collections.
|
||||
|
||||
Currently following collection types are supported:
|
||||
- containers with STL compatible container interface ( see ContainerConcept )
|
||||
( i.e. \c std::vector<>, \c std::list<>, \c std::string<> ... )
|
||||
- c-style array
|
||||
( \c char[10], \c int[15] ... )
|
||||
- null-terminated c-strings
|
||||
( \c char*, \c wchar_T* )
|
||||
- std::pair of iterators
|
||||
( i.e \c std::pair<vector<int>::iterator,vector<int>::iterator> )
|
||||
|
||||
Collection traits provide a external collection interface operations.
|
||||
All are accessible using free-standing functions.
|
||||
|
||||
Following operations are supported:
|
||||
- \c size()
|
||||
- \c empty()
|
||||
- \c begin()
|
||||
- \c end()
|
||||
|
||||
Container traits have somewhat limited functionality on compilers not
|
||||
supporting partial template specialization and partial template ordering.
|
||||
*/
|
||||
template< typename T >
|
||||
struct collection_traits
|
||||
{
|
||||
private:
|
||||
typedef BOOST_STRING_TYPENAME ::boost::mpl::apply_if<
|
||||
::boost::algorithm::detail::is_pair<T>,
|
||||
detail::pair_container_traits_selector<T>,
|
||||
BOOST_STRING_TYPENAME ::boost::mpl::apply_if<
|
||||
::boost::is_array<T>,
|
||||
detail::array_container_traits_selector<T>,
|
||||
BOOST_STRING_TYPENAME ::boost::mpl::apply_if<
|
||||
::boost::is_pointer<T>,
|
||||
detail::pointer_container_traits_selector<T>,
|
||||
detail::default_container_traits_selector<T>
|
||||
>
|
||||
>
|
||||
>::type container_helper_type;
|
||||
public:
|
||||
//! Function type
|
||||
typedef container_helper_type function_type;
|
||||
//! Value type
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
container_helper_type::value_type value_type;
|
||||
//! Size type
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
container_helper_type::size_type size_type;
|
||||
//! Iterator type
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
container_helper_type::iterator iterator;
|
||||
//! Const iterator type
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
container_helper_type::const_iterator const_iterator;
|
||||
//! Result iterator type ( iterator of const_iterator, depending on the constness of the conainer )
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
container_helper_type::result_iterator result_iterator;
|
||||
//! Difference type
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
container_helper_type::difference_type difference_type;
|
||||
|
||||
}; // 'collection_traits'
|
||||
|
||||
// collection_traits metafunctions -----------------------------------------//
|
||||
|
||||
//! Container value_type trait
|
||||
/*!
|
||||
Extract the type of elements conained in a container
|
||||
*/
|
||||
template< typename C >
|
||||
struct value_type_of
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME collection_traits<C>::value_type type;
|
||||
};
|
||||
|
||||
//! Container difference trait
|
||||
/*!
|
||||
Extract the container's difference type
|
||||
*/
|
||||
template< typename C >
|
||||
struct difference_type_of
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME collection_traits<C>::difference_type type;
|
||||
};
|
||||
|
||||
//! Container iterator trait
|
||||
/*!
|
||||
Extract the container's iterator type
|
||||
*/
|
||||
template< typename C >
|
||||
struct iterator_of
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME collection_traits<C>::iterator type;
|
||||
};
|
||||
|
||||
//! Container const_iterator trait
|
||||
/*!
|
||||
Extract the container's const_iterator type
|
||||
*/
|
||||
template< typename C >
|
||||
struct const_iterator_of
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME collection_traits<C>::const_iterator type;
|
||||
};
|
||||
|
||||
|
||||
//! Container result_iterator
|
||||
/*!
|
||||
Extract the container's result_iterator type. This type maps to \c C::iterator
|
||||
for mutable container and \c C::const_iterator for const containers.
|
||||
*/
|
||||
template< typename C >
|
||||
struct result_iterator_of
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME collection_traits<C>::result_iterator type;
|
||||
};
|
||||
|
||||
// collection_traits related functions -----------------------------------------//
|
||||
|
||||
//! Free-standing size() function
|
||||
/*!
|
||||
Get the size of the container. Uses collection_traits.
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::size_type
|
||||
size( const C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::size( c );
|
||||
}
|
||||
|
||||
//! Free-standing empty() function
|
||||
/*!
|
||||
Check whenever the container is empty. Uses container traits.
|
||||
*/
|
||||
template< typename C >
|
||||
inline bool empty( const C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::empty( c );
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
//! Free-standing begin() function
|
||||
/*!
|
||||
Get the begin iterator of the container. Uses collection_traits.
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::iterator
|
||||
begin( C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::begin( c );
|
||||
}
|
||||
|
||||
//! Free-standing begin() function
|
||||
/*!
|
||||
\overload
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::const_iterator
|
||||
begin( const C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::begin( c );
|
||||
}
|
||||
|
||||
//! Free-standing end() function
|
||||
/*!
|
||||
Get the begin iterator of the container. Uses collection_traits.
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::iterator
|
||||
end( C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::end( c );
|
||||
}
|
||||
|
||||
//! Free-standing end() function
|
||||
/*!
|
||||
\overload
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::const_iterator
|
||||
end( const C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::end( c );
|
||||
}
|
||||
|
||||
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
//! Free-standing begin() function
|
||||
/*!
|
||||
\overload
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::result_iterator
|
||||
begin( C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::begin( c );
|
||||
}
|
||||
|
||||
//! Free-standing end() function
|
||||
/*!
|
||||
\overload
|
||||
*/
|
||||
template< typename C >
|
||||
inline BOOST_STRING_TYPENAME collection_traits<C>::result_iterator
|
||||
end( C& c )
|
||||
{
|
||||
return collection_traits<C>::function_type::end( c );
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_STRING_COLLECTION_TRAITS_HPP
|
@ -14,7 +14,7 @@
|
||||
#include <locale>
|
||||
|
||||
/*! \file
|
||||
Defines element comparison predicates. Many algorithms in this library can
|
||||
Defines element comparison predicates. Many algorithms in this library can
|
||||
take an additional argument with a predicate used to compare elements.
|
||||
This makes it possible, for instance, to have case insensitive versions
|
||||
of the algorithms.
|
||||
@ -22,13 +22,13 @@
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
|
||||
// is_equal functor -----------------------------------------------//
|
||||
|
||||
//! is_equal functor
|
||||
/*!
|
||||
Standard STL equal_to does handle only comparison between arguments
|
||||
of the same type. This is less restrictive version which wraps == operator.
|
||||
Standard STL equal_to only handle comparison between arguments
|
||||
of the same type. This is a less restrictive version which wraps operator ==.
|
||||
*/
|
||||
struct is_equal
|
||||
{
|
||||
@ -54,24 +54,28 @@ namespace boost {
|
||||
/*!
|
||||
\param Loc locales used for comparison
|
||||
*/
|
||||
is_iequal( const std::locale& Loc=std::locale() ) :
|
||||
is_iequal( const std::locale& Loc=std::locale() ) :
|
||||
m_Loc( Loc ) {}
|
||||
|
||||
//! Function operator
|
||||
//! Function operator
|
||||
/*!
|
||||
Compare two operands. Case is ignored.
|
||||
*/
|
||||
template< typename T1, typename T2 >
|
||||
bool operator ()( const T1& Arg1, const T2& Arg2 ) const
|
||||
{
|
||||
return std::toupper(Arg1,m_Loc)==std::toupper(Arg2,m_Loc);
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::toupper(Arg1)==std::toupper(Arg2);
|
||||
#else
|
||||
return std::toupper(Arg1,m_Loc)==std::toupper(Arg2,m_Loc);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
std::locale m_Loc;
|
||||
};
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace algorithm
|
||||
|
||||
// pull names to the boost namespace
|
||||
using algorithm::is_equal;
|
||||
|
@ -11,8 +11,9 @@
|
||||
#define BOOST_STRING_CONCEPT_HPP
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines concepts used in string_algo library
|
||||
@ -23,8 +24,8 @@ namespace boost {
|
||||
|
||||
//! Finder concept
|
||||
/*!
|
||||
Defines finder concept. Finder is a functor which selects
|
||||
an arbitraty part of a container. Search is performed on
|
||||
Defines the Finder concept. Finder is a functor which selects
|
||||
an arbitrary part of a string. Search is performed on
|
||||
the range specified by starting and ending iterators.
|
||||
|
||||
Result of the find operation must be convertible to iterator_range.
|
||||
@ -49,7 +50,7 @@ namespace boost {
|
||||
|
||||
//! Formatter concept
|
||||
/*!
|
||||
Defines formatter concept. Formatter is a functor, which
|
||||
Defines the Formatter concept. Formatter is a functor, which
|
||||
takes a result from a finder operation and transforms it
|
||||
in a specific way.
|
||||
|
||||
|
@ -11,15 +11,17 @@
|
||||
#define BOOST_STRING_CONFIG_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#ifdef BOOST_STRING_DEDUCED_TYPENAME
|
||||
# error "macro already defined!"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#define BOOST_STRING_TYPENAME
|
||||
#else
|
||||
#define BOOST_STRING_TYPENAME BOOST_DEDUCED_TYPENAME
|
||||
|
||||
// Metrowerks workaround
|
||||
#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
|
||||
#pragma parse_func_templ off
|
||||
#endif
|
||||
|
||||
#endif // BOOST_STRING_CONFIG_HPP
|
||||
|
@ -20,7 +20,7 @@ namespace boost {
|
||||
|
||||
// case conversion functors -----------------------------------------------//
|
||||
|
||||
// a tolower functor
|
||||
// a tolower functor
|
||||
template<typename CharT>
|
||||
struct to_lowerF : public std::unary_function<CharT, CharT>
|
||||
{
|
||||
@ -30,13 +30,17 @@ namespace boost {
|
||||
// Operation
|
||||
CharT operator ()( CharT Ch ) const
|
||||
{
|
||||
return std::tolower( Ch, m_Loc );
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::tolower( Ch);
|
||||
#else
|
||||
return std::tolower( Ch, m_Loc );
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
const std::locale& m_Loc;
|
||||
};
|
||||
|
||||
// a toupper functor
|
||||
// a toupper functor
|
||||
template<typename CharT>
|
||||
struct to_upperF : public std::unary_function<CharT, CharT>
|
||||
{
|
||||
@ -46,7 +50,11 @@ namespace boost {
|
||||
// Operation
|
||||
CharT operator ()( CharT Ch ) const
|
||||
{
|
||||
return std::toupper( Ch, m_Loc );
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
return std::toupper( Ch);
|
||||
#else
|
||||
return std::toupper( Ch, m_Loc );
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
const std::locale& m_Loc;
|
||||
|
@ -15,26 +15,19 @@
|
||||
#include <functional>
|
||||
#include <locale>
|
||||
#include <set>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/algorithm/string/predicate_facade.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
namespace detail {
|
||||
|
||||
// predicate facade ------------------------------------------------------//
|
||||
|
||||
// Predicate facade
|
||||
/*
|
||||
This class allows to recognize classification
|
||||
predicates, so that they can be combined using
|
||||
composition operators.
|
||||
*/
|
||||
template<typename Derived>
|
||||
struct predicate_facade {};
|
||||
|
||||
// classification functors -----------------------------------------------//
|
||||
|
||||
|
||||
// is_classified functor
|
||||
struct is_classifiedF :
|
||||
public predicate_facade<is_classifiedF>
|
||||
@ -42,7 +35,7 @@ namespace boost {
|
||||
// Boost.Lambda support
|
||||
template <class Args> struct sig { typedef bool type; };
|
||||
|
||||
// Constructor from a locale
|
||||
// Constructor from a locale
|
||||
is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
|
||||
m_Type(Type), m_Locale(Loc) {}
|
||||
|
||||
@ -53,13 +46,21 @@ namespace boost {
|
||||
return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
|
||||
}
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
|
||||
template<>
|
||||
bool operator()( char const Ch ) const
|
||||
{
|
||||
return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
const std::ctype_base::mask m_Type;
|
||||
const std::locale m_Locale;
|
||||
};
|
||||
|
||||
// is_any_of functor
|
||||
/*
|
||||
// is_any_of functor
|
||||
/*
|
||||
returns true if the value is from the specified set
|
||||
*/
|
||||
template<typename CharT>
|
||||
@ -69,26 +70,26 @@ namespace boost {
|
||||
// Boost.Lambda support
|
||||
template <class Args> struct sig { typedef bool type; };
|
||||
|
||||
// Constructor
|
||||
template< typename SeqT >
|
||||
is_any_ofF( const SeqT& Seq ) :
|
||||
m_Set( begin(Seq), end(Seq) ) {}
|
||||
|
||||
// Constructor
|
||||
template<typename RangeT>
|
||||
is_any_ofF( const RangeT& Range ) :
|
||||
m_Set( begin(Range), end(Range) ) {}
|
||||
|
||||
// Operation
|
||||
template<typename Char2T>
|
||||
bool operator()( Char2T Ch ) const
|
||||
{
|
||||
return m_Set.find(Ch)!=m_Set.end();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// set cannot operate on const value-type
|
||||
typedef typename remove_const<CharT>::type set_value_type;
|
||||
std::set<set_value_type> m_Set;
|
||||
std::set<set_value_type> m_Set;
|
||||
};
|
||||
|
||||
// is_from_range functor
|
||||
/*
|
||||
// is_from_range functor
|
||||
/*
|
||||
returns true if the value is from the specified range.
|
||||
(i.e. x>=From && x>=To)
|
||||
*/
|
||||
@ -99,16 +100,16 @@ namespace boost {
|
||||
// Boost.Lambda support
|
||||
template <class Args> struct sig { typedef bool type; };
|
||||
|
||||
// Constructor
|
||||
// Constructor
|
||||
is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
|
||||
|
||||
|
||||
// Operation
|
||||
template<typename Char2T>
|
||||
bool operator()( Char2T Ch ) const
|
||||
{
|
||||
return ( m_From <= Ch ) && ( Ch <= m_To );
|
||||
return ( m_From <= Ch ) && ( Ch <= m_To );
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
CharT m_From;
|
||||
CharT m_To;
|
||||
@ -130,11 +131,11 @@ namespace boost {
|
||||
|
||||
// Operation
|
||||
template<typename CharT>
|
||||
bool operator()( CharT Ch ) const
|
||||
bool operator()( CharT Ch ) const
|
||||
{
|
||||
return m_Pred1(Ch) && m_Pred2(Ch);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Pred1T m_Pred1;
|
||||
Pred2T m_Pred2;
|
||||
@ -155,11 +156,11 @@ namespace boost {
|
||||
|
||||
// Operation
|
||||
template<typename CharT>
|
||||
bool operator()( CharT Ch ) const
|
||||
bool operator()( CharT Ch ) const
|
||||
{
|
||||
return m_Pred1(Ch) || m_Pred2(Ch);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Pred1T m_Pred1;
|
||||
Pred2T m_Pred2;
|
||||
@ -179,11 +180,11 @@ namespace boost {
|
||||
|
||||
// Operation
|
||||
template<typename CharT>
|
||||
bool operator()( CharT Ch ) const
|
||||
bool operator()( CharT Ch ) const
|
||||
{
|
||||
return !m_Pred(Ch);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
PredT m_Pred;
|
||||
};
|
||||
|
@ -1,621 +0,0 @@
|
||||
// Boost string_algo library collection_traits.hpp header file -----------------------//
|
||||
|
||||
// Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_STRING_DETAIL_COLLECTION_TRAITS_HPP
|
||||
#define BOOST_STRING_DETAIL_COLLECTION_TRAITS_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/algorithm/string/yes_no_type.hpp>
|
||||
|
||||
// Container traits implementation ---------------------------------------------------------
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
namespace detail {
|
||||
|
||||
// Default collection traits -----------------------------------------------------------------
|
||||
|
||||
// Default collection helper
|
||||
/*
|
||||
Wraps std::container compliant containers
|
||||
*/
|
||||
template< typename ContainerT >
|
||||
struct default_container_traits
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME ContainerT::value_type value_type;
|
||||
typedef BOOST_STRING_TYPENAME ContainerT::iterator iterator;
|
||||
typedef BOOST_STRING_TYPENAME ContainerT::const_iterator const_iterator;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::if_< ::boost::is_const<ContainerT>,
|
||||
const_iterator,
|
||||
iterator
|
||||
>::type result_iterator;
|
||||
typedef BOOST_STRING_TYPENAME ContainerT::difference_type difference_type;
|
||||
typedef BOOST_STRING_TYPENAME ContainerT::size_type size_type;
|
||||
|
||||
// static operations
|
||||
template< typename C >
|
||||
static size_type size( const C& c )
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
static bool empty( const C& c )
|
||||
{
|
||||
return c.empty();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
template< typename C >
|
||||
static iterator begin( C& c )
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
static const_iterator begin( const C& c )
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
static iterator end( C& c )
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
static const_iterator end( const C& c )
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
||||
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
template< typename C >
|
||||
static result_iterator begin( C& c )
|
||||
{
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
template< typename C >
|
||||
static result_iterator end( C& c )
|
||||
{
|
||||
return c.end();
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_container_traits_selector
|
||||
{
|
||||
typedef default_container_traits<T> type;
|
||||
};
|
||||
|
||||
// Pair container traits ---------------------------------------------------------------------
|
||||
|
||||
// pair selector
|
||||
template< typename T, typename U >
|
||||
yes_type is_pair_impl( const std::pair<T,U>* );
|
||||
no_type is_pair_impl( ... );
|
||||
|
||||
template<typename T> struct is_pair
|
||||
{
|
||||
private:
|
||||
static T* t;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT( bool, value=
|
||||
sizeof(is_pair_impl(t))==sizeof(yes_type) );
|
||||
};
|
||||
|
||||
// pair helper
|
||||
template< typename PairT >
|
||||
struct pair_container_traits
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME PairT::first_type element_type;
|
||||
|
||||
typedef BOOST_STRING_TYPENAME ::boost::detail::
|
||||
iterator_traits<element_type>::value_type value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef BOOST_STRING_TYPENAME ::boost::detail::
|
||||
iterator_traits<element_type>::difference_type difference_type;
|
||||
|
||||
typedef element_type iterator;
|
||||
typedef element_type const_iterator;
|
||||
typedef element_type result_iterator;
|
||||
|
||||
// static operations
|
||||
template< typename P >
|
||||
static size_type size( const P& p )
|
||||
{
|
||||
difference_type diff = std::distance( p.first, p.second );
|
||||
if ( diff < 0 )
|
||||
return 0;
|
||||
else
|
||||
return diff;
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static bool empty( const P& p )
|
||||
{
|
||||
return p.first==p.second;
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static const_iterator begin( const P& p )
|
||||
{
|
||||
return p.first;
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static const_iterator end( const P& p )
|
||||
{
|
||||
return p.second;
|
||||
}
|
||||
}; // 'pair_container_helper'
|
||||
|
||||
template<typename T>
|
||||
struct pair_container_traits_selector
|
||||
{
|
||||
typedef pair_container_traits<T> type;
|
||||
};
|
||||
|
||||
// Array container traits ---------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// array traits ( partial specialization )
|
||||
template< typename T >
|
||||
struct array_traits;
|
||||
|
||||
template< typename T, std::size_t sz >
|
||||
struct array_traits<T[sz]>
|
||||
{
|
||||
// typedef
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef T value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
// size of the array ( static );
|
||||
BOOST_STATIC_CONSTANT( size_type, array_size = sz );
|
||||
};
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
// array traits ( no partial specialization )
|
||||
/*
|
||||
without parial specialization we are able to
|
||||
provide support only for a limited number of
|
||||
types. Currently the primitive numeric types
|
||||
are supported
|
||||
*/
|
||||
template< typename T, typename BaseT >
|
||||
struct array_traits_impl
|
||||
{
|
||||
typedef BaseT value_type;
|
||||
typedef BaseT* iterator;
|
||||
typedef const BaseT* const_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
// size of the array
|
||||
BOOST_STATIC_CONSTANT( size_type, array_size = sizeof(T)/sizeof(BaseT) );
|
||||
};
|
||||
|
||||
template< typename T, typename BaseT >
|
||||
struct array_traits_impl_selector
|
||||
{
|
||||
typedef array_traits_impl<T,BaseT> type;
|
||||
};
|
||||
|
||||
struct array_traits_void
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template< typename T, typename BaseT >
|
||||
struct array_traits_cv_selector
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::apply_if<
|
||||
::boost::is_convertible<T,BaseT*>,
|
||||
array_traits_impl_selector<T,BaseT>,
|
||||
::boost::mpl::apply_if<
|
||||
::boost::is_convertible<T,const BaseT*>,
|
||||
array_traits_impl_selector<T, const BaseT>,
|
||||
::boost::mpl::apply_if<
|
||||
::boost::is_convertible<T, volatile BaseT*>,
|
||||
array_traits_impl_selector<T, volatile BaseT>,
|
||||
array_traits_impl_selector<T, const volatile BaseT>
|
||||
>
|
||||
>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct array_traits_select
|
||||
{
|
||||
template< typename T1, typename T2 >
|
||||
struct apply
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::apply_if<
|
||||
::boost::is_convertible<T,const volatile T2*>,
|
||||
array_traits_cv_selector<T,T2>,
|
||||
::boost::mpl::identity<T1> >::type type;
|
||||
};
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct array_traits_selector
|
||||
{
|
||||
private:
|
||||
// supported array base types
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::vector10<
|
||||
wchar_t,
|
||||
#else // BOOST_NO_INTRINSIC_WCHAR_T
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::vector9<
|
||||
#endif // BOOST_NO_INTRINSIC_WCHAR_T
|
||||
char,
|
||||
signed char,
|
||||
unsigned char,
|
||||
signed short,
|
||||
unsigned short,
|
||||
signed int,
|
||||
unsigned int,
|
||||
signed long,
|
||||
unsigned long
|
||||
>::type array_base_types;
|
||||
|
||||
public:
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::fold<
|
||||
array_base_types,
|
||||
::boost::algorithm::detail::array_traits_void,
|
||||
::boost::algorithm::detail::array_traits_select<T> >::type type;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct array_traits
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
array_traits_selector<T>::type traits_type;
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::value_type value_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::iterator iterator;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::const_iterator const_iterator;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::size_type size_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::difference_type difference_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size );
|
||||
};
|
||||
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
// array lenght resolving
|
||||
/*
|
||||
Lenght of string contained in a static array could
|
||||
be different from the size of the array.
|
||||
For string processing we need the lenght without
|
||||
terminating 0.
|
||||
|
||||
Therefore, the lenght is calulated for char and wchar_t
|
||||
using char_traits, rather then simply returning
|
||||
the array size.
|
||||
*/
|
||||
template< typename T >
|
||||
struct array_length_selector
|
||||
{
|
||||
template< typename TraitsT >
|
||||
struct array_length
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
TraitsT::size_type size_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
size_type,
|
||||
array_size=TraitsT::array_size );
|
||||
|
||||
template< typename A >
|
||||
static size_type length( const A& )
|
||||
{
|
||||
return array_size;
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static bool empty( const A& )
|
||||
{
|
||||
return array_size==0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// specialization for char
|
||||
template<>
|
||||
struct array_length_selector<char>
|
||||
{
|
||||
template< typename TraitsT >
|
||||
struct array_length
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
TraitsT::size_type size_type;
|
||||
|
||||
template< typename A >
|
||||
static size_type length( const A& a )
|
||||
{
|
||||
if ( a==0 )
|
||||
return 0;
|
||||
else
|
||||
return std::char_traits<char>::length(a);
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static bool empty( const A& a )
|
||||
{
|
||||
return a==0 || a[0]==0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// specialization for wchar_t
|
||||
template<>
|
||||
struct array_length_selector<wchar_t>
|
||||
{
|
||||
template< typename TraitsT >
|
||||
struct array_length
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
TraitsT::size_type size_type;
|
||||
|
||||
template< typename A >
|
||||
static size_type length( const A& a )
|
||||
{
|
||||
if ( a==0 )
|
||||
return 0;
|
||||
else
|
||||
return std::char_traits<wchar_t>::length(a);
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static bool empty( const A& a )
|
||||
{
|
||||
return a==0 || a[0]==0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct array_container_traits
|
||||
{
|
||||
private:
|
||||
// resolve array traits
|
||||
typedef array_traits<T> traits_type;
|
||||
|
||||
public:
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::value_type value_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::iterator iterator;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::const_iterator const_iterator;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::size_type size_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
traits_type::difference_type difference_type;
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::if_< ::boost::is_const<T>,
|
||||
const_iterator,
|
||||
iterator
|
||||
>::type result_iterator;
|
||||
|
||||
private:
|
||||
// resolve array size
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::remove_cv<value_type>::type char_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
array_length_selector<char_type>::
|
||||
BOOST_NESTED_TEMPLATE array_length<traits_type> array_length_type;
|
||||
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size );
|
||||
|
||||
// static operations
|
||||
template< typename A >
|
||||
static size_type size( const A& a )
|
||||
{
|
||||
return array_length_type::length(a);
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static bool empty( const A& a )
|
||||
{
|
||||
return array_length_type::empty(a);
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
template< typename A >
|
||||
static iterator begin( A& a )
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static const_iterator begin( const A& a )
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static iterator end( A& a )
|
||||
{
|
||||
return a+array_length_type::length(a);
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static const_iterator end( const A& a )
|
||||
{
|
||||
return a+array_length_type::length(a);
|
||||
}
|
||||
|
||||
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
template< typename A >
|
||||
static result_iterator begin( A& a )
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
template< typename A >
|
||||
static result_iterator end( A& a )
|
||||
{
|
||||
return a+array_length_type::length(a);
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct array_container_traits_selector
|
||||
{
|
||||
typedef array_container_traits<T> type;
|
||||
};
|
||||
|
||||
// Pointer container traits ---------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
struct pointer_container_traits
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::remove_pointer<T>::type value_type;
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::remove_cv<value_type>::type char_type;
|
||||
typedef ::std::char_traits<char_type> char_traits;
|
||||
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
::boost::mpl::if_< ::boost::is_const<T>,
|
||||
const_iterator,
|
||||
iterator
|
||||
>::type result_iterator;
|
||||
|
||||
// static operations
|
||||
template< typename P >
|
||||
static size_type size( const P& p )
|
||||
{
|
||||
if ( p==0 )
|
||||
return 0;
|
||||
else
|
||||
return char_traits::length(p);
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static bool empty( const P& p )
|
||||
{
|
||||
return p==0 || p[0]==0;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
template< typename P >
|
||||
static iterator begin( P& p )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static const_iterator begin( const P& p )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static iterator end( P& p )
|
||||
{
|
||||
if ( p==0 )
|
||||
return p;
|
||||
else
|
||||
return p+char_traits::length(p);
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static const_iterator end( const P& p )
|
||||
{
|
||||
if ( p==0 )
|
||||
return p;
|
||||
else
|
||||
return p+char_traits::length(p);
|
||||
}
|
||||
|
||||
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
template< typename P >
|
||||
static result_iterator begin( P& p )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template< typename P >
|
||||
static result_iterator end( P& p )
|
||||
{
|
||||
if ( p==0 )
|
||||
return p;
|
||||
else
|
||||
return p+char_traits::length(p);
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct pointer_container_traits_selector
|
||||
{
|
||||
typedef pointer_container_traits<T> type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace algorithm
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_STRING_DETAIL_COLLECTION_HPP
|
@ -11,7 +11,9 @@
|
||||
#define BOOST_STRING_FIND_FORMAT_DETAIL_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/algorithm/string/detail/find_format_store.hpp>
|
||||
#include <boost/algorithm/string/detail/replace_storage.hpp>
|
||||
|
||||
@ -60,7 +62,7 @@ namespace boost {
|
||||
{
|
||||
typedef find_format_store<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<InputT>::type,
|
||||
range_const_iterator<InputT>::type,
|
||||
FormatterT,
|
||||
FormatResultT > store_type;
|
||||
|
||||
@ -121,7 +123,7 @@ namespace boost {
|
||||
{
|
||||
typedef find_format_store<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<InputT>::type,
|
||||
range_const_iterator<InputT>::type,
|
||||
FormatterT,
|
||||
FormatResultT > store_type;
|
||||
|
||||
@ -174,14 +176,14 @@ namespace boost {
|
||||
typename FormatResultT >
|
||||
inline void find_format_impl2(
|
||||
InputT& Input,
|
||||
FinderT Finder,
|
||||
FinderT,
|
||||
FormatterT Formatter,
|
||||
const FindResultT& FindResult,
|
||||
const FormatResultT& FormatResult)
|
||||
{
|
||||
typedef find_format_store<
|
||||
BOOST_STRING_TYPENAME
|
||||
iterator_of<InputT>::type,
|
||||
range_iterator<InputT>::type,
|
||||
FormatterT,
|
||||
FormatResultT > store_type;
|
||||
|
||||
|
@ -11,7 +11,9 @@
|
||||
#define BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <boost/algorithm/string/detail/find_format_store.hpp>
|
||||
#include <boost/algorithm/string/detail/replace_storage.hpp>
|
||||
|
||||
@ -59,7 +61,7 @@ namespace boost {
|
||||
const FormatResultT& FormatResult )
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<InputT>::type input_iterator_type;
|
||||
range_const_iterator<InputT>::type input_iterator_type;
|
||||
|
||||
typedef find_format_store<
|
||||
input_iterator_type,
|
||||
@ -72,7 +74,7 @@ namespace boost {
|
||||
// Initialize last match
|
||||
input_iterator_type LastMatch=begin(Input);
|
||||
|
||||
// Iterate throug all matches
|
||||
// Iterate through all matches
|
||||
while( M )
|
||||
{
|
||||
// Copy the beginning of the sequence
|
||||
@ -126,7 +128,7 @@ namespace boost {
|
||||
const FormatResultT& FormatResult)
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<InputT>::type input_iterator_type;
|
||||
range_const_iterator<InputT>::type input_iterator_type;
|
||||
|
||||
typedef find_format_store<
|
||||
input_iterator_type,
|
||||
@ -142,7 +144,7 @@ namespace boost {
|
||||
// Output temporary
|
||||
InputT Output;
|
||||
|
||||
// Iterate throug all matches
|
||||
// Iterate through all matches
|
||||
while( M )
|
||||
{
|
||||
// Copy the beginning of the sequence
|
||||
@ -196,7 +198,7 @@ namespace boost {
|
||||
FormatResultT FormatResult)
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
iterator_of<InputT>::type input_iterator_type;
|
||||
range_iterator<InputT>::type input_iterator_type;
|
||||
typedef find_format_store<
|
||||
input_iterator_type,
|
||||
FormatterT,
|
||||
@ -207,7 +209,7 @@ namespace boost {
|
||||
|
||||
// Instantiate replacement storage
|
||||
std::deque<
|
||||
BOOST_STRING_TYPENAME value_type_of<InputT>::type> Storage;
|
||||
BOOST_STRING_TYPENAME range_value<InputT>::type> Storage;
|
||||
|
||||
// Initialize replacement iterators
|
||||
input_iterator_type InsertIt=begin(Input);
|
||||
|
@ -11,8 +11,7 @@
|
||||
#define BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
@ -36,7 +35,7 @@ namespace boost {
|
||||
public:
|
||||
// Construction
|
||||
find_format_store(
|
||||
const base_type FindResult,
|
||||
const base_type& FindResult,
|
||||
const format_result_type& FormatResult,
|
||||
const formatter_type& Formatter ) :
|
||||
base_type(FindResult),
|
||||
|
@ -10,70 +10,16 @@
|
||||
#ifndef BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
|
||||
#define BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
|
||||
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
namespace detail {
|
||||
|
||||
// finder virtualizer -----------------------------------------------//
|
||||
|
||||
template<typename IteratorT>
|
||||
struct virtual_finder
|
||||
{
|
||||
// typedefs
|
||||
typedef IteratorT input_iterator_type;
|
||||
typedef iterator_range<IteratorT> match_type;
|
||||
|
||||
// virtual destructor
|
||||
virtual ~virtual_finder() {}
|
||||
|
||||
// clone
|
||||
virtual virtual_finder* clone() const=0;
|
||||
|
||||
// operation
|
||||
virtual match_type do_find(
|
||||
input_iterator_type Begin,
|
||||
input_iterator_type End ) const=0;
|
||||
};
|
||||
|
||||
template<typename IteratorT, typename FinderT>
|
||||
struct virtual_finder_typed : public virtual_finder<IteratorT>
|
||||
{
|
||||
// typedefs
|
||||
typedef virtual_finder<IteratorT> base_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
base_type::input_iterator_type input_iterator_type;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
base_type::match_type match_type;
|
||||
|
||||
// constuction
|
||||
virtual_finder_typed( FinderT Finder ) : m_Finder(Finder) {}
|
||||
|
||||
// clone
|
||||
virtual_finder_typed* clone() const
|
||||
{
|
||||
return new virtual_finder_typed(m_Finder);
|
||||
}
|
||||
|
||||
// operation
|
||||
virtual match_type do_find(
|
||||
input_iterator_type Begin,
|
||||
input_iterator_type End ) const
|
||||
{
|
||||
return m_Finder(Begin,End);
|
||||
}
|
||||
|
||||
private:
|
||||
// Finder
|
||||
FinderT m_Finder;
|
||||
};
|
||||
|
||||
|
||||
// find_iterator base -----------------------------------------------//
|
||||
|
||||
// Find iterator base
|
||||
@ -84,40 +30,36 @@ namespace boost {
|
||||
// typedefs
|
||||
typedef IteratorT input_iterator_type;
|
||||
typedef iterator_range<IteratorT> match_type;
|
||||
|
||||
typedef function2<
|
||||
match_type,
|
||||
input_iterator_type,
|
||||
input_iterator_type> finder_type;
|
||||
|
||||
protected:
|
||||
// Protected construction/destruction
|
||||
|
||||
// Default constructor
|
||||
find_iterator_base() : m_pFinder(0) {};
|
||||
find_iterator_base() {};
|
||||
// Copy construction
|
||||
find_iterator_base( const find_iterator_base& Other ) :
|
||||
m_pFinder(0)
|
||||
{
|
||||
if ( Other.m_pFinder )
|
||||
{
|
||||
m_pFinder=Other.m_pFinder->clone();
|
||||
}
|
||||
}
|
||||
m_Finder(Other.m_Finder) {}
|
||||
|
||||
// Constructor
|
||||
template<typename FinderT>
|
||||
find_iterator_base( FinderT Finder, int ) :
|
||||
m_pFinder( new virtual_finder_typed<IteratorT,FinderT>(Finder) ) {}
|
||||
m_Finder(Finder) {}
|
||||
|
||||
// Destructor
|
||||
~find_iterator_base()
|
||||
{
|
||||
if (m_pFinder) delete m_pFinder;
|
||||
}
|
||||
~find_iterator_base() {}
|
||||
|
||||
// Find operation
|
||||
match_type do_find(
|
||||
input_iterator_type Begin,
|
||||
input_iterator_type End ) const
|
||||
{
|
||||
if (m_pFinder)
|
||||
if (!m_Finder.empty())
|
||||
{
|
||||
return m_pFinder->do_find(Begin,End);
|
||||
return m_Finder(Begin,End);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -128,12 +70,12 @@ namespace boost {
|
||||
// Check
|
||||
bool is_null() const
|
||||
{
|
||||
return !m_pFinder;
|
||||
return m_Finder.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
// Finder
|
||||
virtual_finder<IteratorT>* m_pFinder;
|
||||
finder_type m_Finder;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -13,8 +13,11 @@
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/empty.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
@ -25,7 +28,7 @@ namespace boost {
|
||||
|
||||
// find a subsequence in the sequence ( functor )
|
||||
/*
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
If the find fails, functor returns <End,End>
|
||||
*/
|
||||
template<typename SearchIteratorT,typename PredicateT>
|
||||
@ -35,9 +38,9 @@ namespace boost {
|
||||
|
||||
// Construction
|
||||
template< typename SearchT >
|
||||
first_finderF( const SearchT& Search, PredicateT Comp ) :
|
||||
first_finderF( const SearchT& Search, PredicateT Comp ) :
|
||||
m_Search(begin(Search), end(Search)), m_Comp(Comp) {}
|
||||
first_finderF(
|
||||
first_finderF(
|
||||
search_iterator_type SearchBegin,
|
||||
search_iterator_type SearchEnd,
|
||||
PredicateT Comp ) :
|
||||
@ -46,8 +49,8 @@ namespace boost {
|
||||
// Operation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End ) const
|
||||
{
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
@ -58,8 +61,8 @@ namespace boost {
|
||||
OuterIt!=End;
|
||||
++OuterIt)
|
||||
{
|
||||
// Sanity check
|
||||
if( empty(m_Search) )
|
||||
// Sanity check
|
||||
if( boost::empty(m_Search) )
|
||||
return result_type( End, End );
|
||||
|
||||
input_iterator_type InnerIt=OuterIt;
|
||||
@ -68,7 +71,7 @@ namespace boost {
|
||||
InnerIt!=End && SubstrIt!=m_Search.end();
|
||||
++InnerIt,++SubstrIt)
|
||||
{
|
||||
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
|
||||
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
|
||||
break;
|
||||
}
|
||||
|
||||
@ -89,7 +92,7 @@ namespace boost {
|
||||
|
||||
// find the last match a subsequnce in the sequence ( functor )
|
||||
/*
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
If the find fails, returns <End,End>
|
||||
*/
|
||||
template<typename SearchIteratorT, typename PredicateT>
|
||||
@ -102,9 +105,9 @@ namespace boost {
|
||||
|
||||
// Construction
|
||||
template< typename SearchT >
|
||||
last_finderF( const SearchT& Search, PredicateT Comp ) :
|
||||
last_finderF( const SearchT& Search, PredicateT Comp ) :
|
||||
m_Search(begin(Search), end(Search)), m_Comp(Comp) {}
|
||||
last_finderF(
|
||||
last_finderF(
|
||||
search_iterator_type SearchBegin,
|
||||
search_iterator_type SearchEnd,
|
||||
PredicateT Comp ) :
|
||||
@ -113,34 +116,34 @@ namespace boost {
|
||||
// Operation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End ) const
|
||||
{
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
if( empty(m_Search) )
|
||||
if( boost::empty(m_Search) )
|
||||
return result_type( End, End );
|
||||
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<ForwardIteratorT>::iterator_category category;
|
||||
|
||||
return findit( Begin, End, category() );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// forward iterator
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::forward_iterator_tag ) const
|
||||
{
|
||||
typedef ForwardIteratorT input_iterator_type;
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
first_finder_type first_finder(
|
||||
first_finder_type first_finder(
|
||||
m_Search.begin(), m_Search.end(), m_Comp );
|
||||
|
||||
result_type M=first_finder( Begin, End );
|
||||
@ -158,9 +161,9 @@ namespace boost {
|
||||
// bidirectional iterator
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::bidirectional_iterator_tag ) const
|
||||
{
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
@ -178,7 +181,7 @@ namespace boost {
|
||||
InnerIt!=End && SubstrIt!=m_Search.end();
|
||||
++InnerIt,++SubstrIt)
|
||||
{
|
||||
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
|
||||
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
|
||||
break;
|
||||
}
|
||||
|
||||
@ -194,12 +197,12 @@ namespace boost {
|
||||
iterator_range<search_iterator_type> m_Search;
|
||||
PredicateT m_Comp;
|
||||
};
|
||||
|
||||
|
||||
// find n-th functor -----------------------------------------------//
|
||||
|
||||
// find the n-th match of a subsequnce in the sequence ( functor )
|
||||
/*
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
If the find fails, returns <End,End>
|
||||
*/
|
||||
template<typename SearchIteratorT, typename PredicateT>
|
||||
@ -212,50 +215,50 @@ namespace boost {
|
||||
|
||||
// Construction
|
||||
template< typename SearchT >
|
||||
nth_finderF(
|
||||
const SearchT& Search,
|
||||
nth_finderF(
|
||||
const SearchT& Search,
|
||||
unsigned int Nth,
|
||||
PredicateT Comp) :
|
||||
m_Search(begin(Search), end(Search)),
|
||||
PredicateT Comp) :
|
||||
m_Search(begin(Search), end(Search)),
|
||||
m_Nth(Nth),
|
||||
m_Comp(Comp) {}
|
||||
nth_finderF(
|
||||
nth_finderF(
|
||||
search_iterator_type SearchBegin,
|
||||
search_iterator_type SearchEnd,
|
||||
unsigned int Nth,
|
||||
PredicateT Comp) :
|
||||
m_Search(SearchBegin, SearchEnd),
|
||||
m_Search(SearchBegin, SearchEnd),
|
||||
m_Nth(Nth),
|
||||
m_Comp(Comp) {}
|
||||
|
||||
// Operation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End ) const
|
||||
{
|
||||
typedef ForwardIteratorT input_iterator_type;
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
// Sanity check
|
||||
if( empty(m_Search) )
|
||||
// Sanity check
|
||||
if( boost::empty(m_Search) )
|
||||
return result_type( End, End );
|
||||
|
||||
// Instantiate find funtor
|
||||
first_finder_type first_finder(
|
||||
// Instantiate find funtor
|
||||
first_finder_type first_finder(
|
||||
m_Search.begin(), m_Search.end(), m_Comp );
|
||||
|
||||
result_type M( Begin, Begin );
|
||||
|
||||
for( unsigned int n=0; n<=m_Nth; ++n )
|
||||
{
|
||||
// find next match
|
||||
// find next match
|
||||
M=first_finder( end(M), End );
|
||||
|
||||
if ( !M )
|
||||
{
|
||||
// Subsequence not found, return
|
||||
// Subsequence not found, return
|
||||
return M;
|
||||
}
|
||||
}
|
||||
@ -273,8 +276,8 @@ namespace boost {
|
||||
|
||||
// find a head in the sequence ( functor )
|
||||
/*
|
||||
This functor find a head of the specified range. For
|
||||
a specified N, the head is a subsequence of N starting
|
||||
This functor find a head of the specified range. For
|
||||
a specified N, the head is a subsequence of N starting
|
||||
elements of the range.
|
||||
*/
|
||||
struct head_finderF
|
||||
@ -285,8 +288,8 @@ namespace boost {
|
||||
// Operation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End ) const
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
@ -299,7 +302,7 @@ namespace boost {
|
||||
// Find operation implementation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::forward_iterator_tag ) const
|
||||
@ -309,15 +312,15 @@ namespace boost {
|
||||
|
||||
input_iterator_type It=Begin;
|
||||
for(
|
||||
unsigned int Index=0;
|
||||
unsigned int Index=0;
|
||||
Index<m_N && It!=End; ++Index,++It ) {};
|
||||
|
||||
|
||||
return result_type( Begin, It );
|
||||
}
|
||||
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::random_access_iterator_tag ) const
|
||||
@ -339,8 +342,8 @@ namespace boost {
|
||||
|
||||
// find a tail in the sequence ( functor )
|
||||
/*
|
||||
This functor find a tail of the specified range. For
|
||||
a specified N, the head is a subsequence of N starting
|
||||
This functor find a tail of the specified range. For
|
||||
a specified N, the head is a subsequence of N starting
|
||||
elements of the range.
|
||||
*/
|
||||
struct tail_finderF
|
||||
@ -351,8 +354,8 @@ namespace boost {
|
||||
// Operation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End ) const
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
@ -365,7 +368,7 @@ namespace boost {
|
||||
// Find operation implementation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::forward_iterator_tag ) const
|
||||
@ -373,10 +376,10 @@ namespace boost {
|
||||
typedef ForwardIteratorT input_iterator_type;
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
unsigned int Index=0;
|
||||
unsigned int Index=0;
|
||||
input_iterator_type It=Begin;
|
||||
input_iterator_type It2=Begin;
|
||||
|
||||
|
||||
// Advance It2 by N incremets
|
||||
for( Index=0; Index<m_N && It2!=End; ++Index,++It2 ) {};
|
||||
|
||||
@ -388,7 +391,7 @@ namespace boost {
|
||||
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::bidirectional_iterator_tag ) const
|
||||
@ -398,15 +401,15 @@ namespace boost {
|
||||
|
||||
input_iterator_type It=End;
|
||||
for(
|
||||
unsigned int Index=0;
|
||||
unsigned int Index=0;
|
||||
Index<m_N && It!=Begin; ++Index,--It ) {};
|
||||
|
||||
|
||||
return result_type( It, End );
|
||||
}
|
||||
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
findit(
|
||||
findit(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End,
|
||||
std::random_access_iterator_tag ) const
|
||||
@ -414,7 +417,7 @@ namespace boost {
|
||||
typedef ForwardIteratorT input_iterator_type;
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < m_N ) )
|
||||
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < m_N ) )
|
||||
return result_type( Begin, End );
|
||||
|
||||
return result_type( End-m_N, End );
|
||||
@ -434,29 +437,29 @@ namespace boost {
|
||||
with an exception that it return range instead of a single
|
||||
iterator.
|
||||
|
||||
If bCompress is set to true, adjacent matching tokens are
|
||||
If bCompress is set to true, adjacent matching tokens are
|
||||
concatenated into one match.
|
||||
*/
|
||||
template< typename PredicateT >
|
||||
struct token_finderF
|
||||
{
|
||||
// Construction
|
||||
token_finderF(
|
||||
PredicateT Pred,
|
||||
token_compress_mode_type eCompress=token_compress_off ) :
|
||||
token_finderF(
|
||||
PredicateT Pred,
|
||||
token_compress_mode_type eCompress=token_compress_off ) :
|
||||
m_Pred(Pred), m_eCompress(eCompress) {}
|
||||
|
||||
// Operation
|
||||
template< typename ForwardIteratorT >
|
||||
iterator_range<ForwardIteratorT>
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
operator()(
|
||||
ForwardIteratorT Begin,
|
||||
ForwardIteratorT End ) const
|
||||
{
|
||||
typedef iterator_range<ForwardIteratorT> result_type;
|
||||
|
||||
ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
|
||||
|
||||
|
||||
if( It==End )
|
||||
{
|
||||
return result_type( End, End );
|
||||
@ -468,11 +471,11 @@ namespace boost {
|
||||
if( m_eCompress==token_compress_on )
|
||||
{
|
||||
// Find first non-matching character
|
||||
while( m_Pred(*It2) && It2!=End ) ++It2;
|
||||
while( It2!=End && m_Pred(*It2) ) ++It2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Advance by one possition
|
||||
// Advance by one possition
|
||||
++It2;
|
||||
}
|
||||
|
||||
@ -499,21 +502,27 @@ namespace boost {
|
||||
typedef iterator_range<input_iterator_type> result_type;
|
||||
|
||||
// Construction
|
||||
range_finderF(
|
||||
input_iterator_type Begin,
|
||||
range_finderF(
|
||||
input_iterator_type Begin,
|
||||
input_iterator_type End ) : m_Range(Begin, End) {}
|
||||
|
||||
range_finderF(const iterator_range<input_iterator_type>& Range) :
|
||||
range_finderF(const iterator_range<input_iterator_type>& Range) :
|
||||
m_Range(Range) {}
|
||||
|
||||
// Operation
|
||||
template< typename ForwardIterator2T >
|
||||
iterator_range<ForwardIterator2T>
|
||||
operator()(
|
||||
ForwardIterator2T,
|
||||
iterator_range<ForwardIterator2T>
|
||||
operator()(
|
||||
ForwardIterator2T,
|
||||
ForwardIterator2T ) const
|
||||
{
|
||||
#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
|
||||
return iterator_range<const ForwardIterator2T>(this->m_Range);
|
||||
#elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
return iterator_range<ForwardIterator2T>(m_Range.begin(), m_Range.end());
|
||||
#else
|
||||
return m_Range;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -12,8 +12,10 @@
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
@ -29,7 +31,6 @@ namespace boost {
|
||||
typedef regex_search_result<IteratorT> type;
|
||||
typedef iterator_range<IteratorT> base_type;
|
||||
typedef BOOST_STRING_TYPENAME base_type::value_type value_type;
|
||||
typedef BOOST_STRING_TYPENAME base_type::reference reference;
|
||||
typedef BOOST_STRING_TYPENAME base_type::difference_type difference_type;
|
||||
typedef BOOST_STRING_TYPENAME base_type::const_iterator const_iterator;
|
||||
typedef BOOST_STRING_TYPENAME base_type::iterator iterator;
|
||||
|
@ -10,8 +10,12 @@
|
||||
#ifndef BOOST_STRING_FORMATTER_DETAIL_HPP
|
||||
#define BOOST_STRING_FORMATTER_DETAIL_HPP
|
||||
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/detail/util.hpp>
|
||||
|
||||
// generic replace functors -----------------------------------------------//
|
||||
@ -23,22 +27,30 @@ namespace boost {
|
||||
// const format functor ----------------------------------------------------//
|
||||
|
||||
// constant format functor
|
||||
template<typename CollectionT>
|
||||
template<typename RangeT>
|
||||
struct const_formatF
|
||||
{
|
||||
private:
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<CollectionT>::type format_iterator;
|
||||
range_const_iterator<RangeT>::type format_iterator;
|
||||
typedef iterator_range<format_iterator> result_type;
|
||||
|
||||
public:
|
||||
// Construction
|
||||
const_formatF(const CollectionT& Format) :
|
||||
const_formatF(const RangeT& Format) :
|
||||
m_Format(begin(Format), end(Format)) {}
|
||||
|
||||
// Operation
|
||||
template<typename Collection2T>
|
||||
const result_type& operator()(const Collection2T&) const
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
template<typename Range2T>
|
||||
result_type& operator()(const Range2T&)
|
||||
{
|
||||
return m_Format;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Range2T>
|
||||
const result_type& operator()(const Range2T&) const
|
||||
{
|
||||
return m_Format;
|
||||
}
|
||||
@ -50,14 +62,14 @@ namespace boost {
|
||||
// identity format functor ----------------------------------------------------//
|
||||
|
||||
// identity format functor
|
||||
template<typename CollectionT>
|
||||
template<typename RangeT>
|
||||
struct identity_formatF
|
||||
{
|
||||
// Operation
|
||||
template< typename Collection2T >
|
||||
const CollectionT& operator()(const Collection2T& Replace) const
|
||||
template< typename Range2T >
|
||||
const RangeT& operator()(const Range2T& Replace) const
|
||||
{
|
||||
return CollectionT(begin(Replace), end(Replace));
|
||||
return RangeT(begin(Replace), end(Replace));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,9 +13,7 @@
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/sequence_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/detail/sequence.hpp>
|
||||
|
||||
namespace boost {
|
||||
@ -123,6 +121,7 @@ namespace boost {
|
||||
ForwardIteratorT InsertIt,
|
||||
ForwardIteratorT SegmentBegin,
|
||||
ForwardIteratorT SegmentEnd )
|
||||
|
||||
{
|
||||
// Call replace to do the job
|
||||
replace( Input, InsertIt, SegmentBegin, Storage );
|
||||
|
@ -13,7 +13,9 @@
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/algorithm/string/sequence_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
@ -110,7 +112,14 @@ namespace boost {
|
||||
BOOST_STRING_TYPENAME InputT::iterator At=Input.erase( From, To );
|
||||
if ( Begin!=End )
|
||||
{
|
||||
Input.insert( At, Begin, End );
|
||||
if(!Input.empty())
|
||||
{
|
||||
Input.insert( At, Begin, End );
|
||||
}
|
||||
else
|
||||
{
|
||||
Input.insert( Input.begin(), Begin, End );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -172,7 +181,14 @@ namespace boost {
|
||||
BOOST_STRING_TYPENAME InputT::iterator To,
|
||||
const InsertT& Insert )
|
||||
{
|
||||
replace( Input, From, To, begin(Insert), end(Insert) );
|
||||
if(From!=To)
|
||||
{
|
||||
replace( Input, From, To, begin(Insert), end(Insert) );
|
||||
}
|
||||
else
|
||||
{
|
||||
insert( Input, From, begin(Insert), end(Insert) );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <functional>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
@ -22,7 +23,7 @@ namespace boost {
|
||||
// empty_container
|
||||
/*
|
||||
This class represents always empty container,
|
||||
containing elemets of type CharT.
|
||||
containing elements of type CharT.
|
||||
|
||||
It is supposed to be used in a const version only
|
||||
*/
|
||||
@ -92,7 +93,7 @@ namespace boost {
|
||||
{
|
||||
SeqT operator()( const iterator_range<IteratorT>& Range ) const
|
||||
{
|
||||
return copy_iterator_range<SeqT>(Range);
|
||||
return copy_range<SeqT>(Range);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,15 +11,20 @@
|
||||
#define BOOST_STRING_ERASE_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/find_format.hpp>
|
||||
#include <boost/algorithm/string/finder.hpp>
|
||||
#include <boost/algorithm/string/formatter.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines various erase algorithms. Each algorithm removes
|
||||
a part(s) of the input according to a searching criterium.
|
||||
part(s) of the input according to a searching criteria.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -29,21 +34,24 @@ namespace boost {
|
||||
|
||||
//! Erase range algorithm
|
||||
/*!
|
||||
Remove the given range from the input sequence.
|
||||
The result is copied to the given output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
Remove the given range from the input. The result is a modified copy of
|
||||
the input. It is returned as a sequence or copied to the output iterator.
|
||||
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param SearchRange A range in the input to be substituted
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param SearchRange A range in the input to be removed
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename OutputIteratorT, typename CollectionT>
|
||||
template<typename OutputIteratorT, typename RangeT>
|
||||
inline OutputIteratorT erase_range_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
const iterator_range<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<CollectionT>::type>& SearchRange )
|
||||
range_const_iterator<RangeT>::type>& SearchRange )
|
||||
{
|
||||
return find_format_copy(
|
||||
Output,
|
||||
@ -54,19 +62,14 @@ namespace boost {
|
||||
|
||||
//! Erase range algorithm
|
||||
/*!
|
||||
Remove the given range from the input sequence.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param SearchRange A range in the input to be substituted
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT erase_range_copy(
|
||||
const SequenceT& Input,
|
||||
const iterator_range<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<SequenceT>::type>& SearchRange )
|
||||
range_const_iterator<SequenceT>::type>& SearchRange )
|
||||
{
|
||||
return find_format_copy(
|
||||
Input,
|
||||
@ -76,18 +79,18 @@ namespace boost {
|
||||
|
||||
//! Erase range algorithm
|
||||
/*!
|
||||
Remove the given range from the input sequence.
|
||||
Remove the given range from the input.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param SearchRange A range in the input to be substituted
|
||||
\param SearchRange A range in the input to be removed
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline void erase_range(
|
||||
SequenceT& Input,
|
||||
const iterator_range<
|
||||
BOOST_STRING_TYPENAME
|
||||
iterator_of<SequenceT>::type>& SearchRange )
|
||||
range_iterator<SequenceT>::type>& SearchRange )
|
||||
{
|
||||
find_format(
|
||||
Input,
|
||||
@ -99,22 +102,26 @@ namespace boost {
|
||||
|
||||
//! Erase first algorithm
|
||||
/*!
|
||||
Remove the first match of the search sequence from the input.
|
||||
The result is copied to the given output iterator.
|
||||
Remove the first occurrence of the substring from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
H \param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT erase_first_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search )
|
||||
const Range1T& Input,
|
||||
const Range2T& Search )
|
||||
{
|
||||
return find_format_copy(
|
||||
Output,
|
||||
@ -125,17 +132,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase first algorithm
|
||||
/*!
|
||||
Remove the first match of the search sequence from the input.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT erase_first_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search )
|
||||
const RangeT& Search )
|
||||
{
|
||||
return find_format_copy(
|
||||
Input,
|
||||
@ -145,16 +147,16 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase first algorithm
|
||||
/*!
|
||||
Remove the first match of the search sequence from the input.
|
||||
Remove the first occurrence of the substring from the input.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void erase_first(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search )
|
||||
const RangeT& Search )
|
||||
{
|
||||
find_format(
|
||||
Input,
|
||||
@ -166,23 +168,28 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase first algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the first match of the search sequence from the input.
|
||||
The result is copied to the given output iterator. Searching is case insensitive.
|
||||
Remove the first occurrence of the substring from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT ierase_first_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
const Range1T& Input,
|
||||
const Range2T& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -194,18 +201,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase first algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the first match of the search sequence from the input.
|
||||
The result is a modified copy of the input. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT ierase_first_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -216,17 +217,17 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase first algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the first match of the search sequence from the input.
|
||||
Remove the first occurrence of the substring from the input.
|
||||
The input sequence is modified in-place. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void ierase_first(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
find_format(
|
||||
@ -239,22 +240,26 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase last algorithm
|
||||
/*!
|
||||
Remove the last match of the search sequence from the input.
|
||||
The result is copied to the given output iterator.
|
||||
Remove the last occurrence of the substring from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT erase_last_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search )
|
||||
const Range1T& Input,
|
||||
const Range2T& Search )
|
||||
{
|
||||
return find_format_copy(
|
||||
Output,
|
||||
@ -265,17 +270,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase last algorithm
|
||||
/*!
|
||||
Remove the last match of the search sequence from the input.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT erase_last_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search )
|
||||
const RangeT& Search )
|
||||
{
|
||||
return find_format_copy(
|
||||
Input,
|
||||
@ -285,16 +285,16 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase last algorithm
|
||||
/*!
|
||||
Remove the last match of the search sequence from the input.
|
||||
Remove the last occurrence of the substring from the input.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void erase_last(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search )
|
||||
const RangeT& Search )
|
||||
{
|
||||
find_format(
|
||||
Input,
|
||||
@ -306,23 +306,28 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase last algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the last match of the search sequence from the input.
|
||||
The result is copied to the given output iterator. Searching is case insensitive.
|
||||
Remove the last occurrence of the substring from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT ierase_last_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
const Range1T& Input,
|
||||
const Range2T& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -334,18 +339,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase last algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the last match of the search sequence from the input.
|
||||
The result is a modified copy of the input. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT ierase_last_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -356,17 +355,17 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase last algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the last match of the search sequence from the input.
|
||||
Remove the last occurrence of the substring from the input.
|
||||
The input sequence is modified in-place. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void ierase_last(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
find_format(
|
||||
@ -379,23 +378,28 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase nth algorithm
|
||||
/*!
|
||||
Remove the Nth match of the search sequence in the input.
|
||||
The result is copied to the given output iterator.
|
||||
Remove the Nth occurrence of the substring in the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\param Nth An index of the match to be replaced. The index is 0-based.
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT erase_nth_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
const Range1T& Input,
|
||||
const Range2T& Search,
|
||||
unsigned int Nth )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -407,18 +411,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase nth algorithm
|
||||
/*!
|
||||
Remove the Nth match of the search sequence in the input.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Nth An index of the match to be replaced. The index is 0-based.
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT erase_nth_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
unsigned int Nth )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -429,17 +427,17 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase nth algorithm
|
||||
/*!
|
||||
Remove the Nth match of the search sequence in the input.
|
||||
Remove the Nth occurrence of the substring in the input.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
\param Nth An index of the match to be replaced. The index is 0-based.
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void erase_nth(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
unsigned int Nth )
|
||||
{
|
||||
find_format(
|
||||
@ -452,24 +450,29 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase nth algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove the Nth match of the search sequence in the input.
|
||||
The result is copied to the given output iterator. Searching is case insensitive.
|
||||
Remove the Nth occurrence of the substring in the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
\param Nth An index of the match to be replaced. The index is 0-based.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT ierase_nth_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
const Range1T& Input,
|
||||
const Range2T& Search,
|
||||
unsigned int Nth,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
@ -482,19 +485,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase nth algorithm
|
||||
/*!
|
||||
Remove the Nth match of the search sequence in the input.
|
||||
The result is a modified copy of the input. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Nth An index of the match to be replaced. The index is 0-based.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT ierase_nth_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
unsigned int Nth,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
@ -506,18 +502,18 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase nth algorithm
|
||||
/*!
|
||||
Remove the Nth match of the search sequence in the input.
|
||||
Remove the Nth occurrence of the substring in the input.
|
||||
The input sequence is modified in-place. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
\param Nth An index of the match to be replaced. The index is 0-based.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void ierase_nth(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
unsigned int Nth,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
@ -532,22 +528,27 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase all algorithm
|
||||
/*!
|
||||
Remove all the occurrences of the search sequence from the input.
|
||||
The result is copied to the given output iterator.
|
||||
Remove all the occurrences of the string from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Search A substring to be searched for.
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT erase_all_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search )
|
||||
const Range1T& Input,
|
||||
const Range2T& Search )
|
||||
{
|
||||
return find_format_all_copy(
|
||||
Output,
|
||||
@ -558,17 +559,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase all algorithm
|
||||
/*!
|
||||
Remove all the occurrences of the search sequence from the input.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT erase_all_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search )
|
||||
const RangeT& Search )
|
||||
{
|
||||
return find_format_all_copy(
|
||||
Input,
|
||||
@ -578,16 +574,16 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase all algorithm
|
||||
/*!
|
||||
Remove all the occurrences of the search sequence from the input.
|
||||
Remove all the occurrences of the string from the input.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void erase_all(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search )
|
||||
const RangeT& Search )
|
||||
{
|
||||
find_format_all(
|
||||
Input,
|
||||
@ -599,23 +595,28 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase all algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove all the occurrences of the search sequence from the input.
|
||||
The result is copied to the given output iterator. Searching is case insensitive.
|
||||
Remove all the occurrences of the string from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename Collection1T,
|
||||
typename Collection2T>
|
||||
typename Range1T,
|
||||
typename Range2T>
|
||||
inline OutputIteratorT ierase_all_copy(
|
||||
OutputIteratorT Output,
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
const Range1T& Input,
|
||||
const Range2T& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return find_format_all_copy(
|
||||
@ -627,18 +628,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase all algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove all the occurrences of the search sequence from the input.
|
||||
The result is a modified copy of the input. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline SequenceT ierase_all_copy(
|
||||
const SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return find_format_all_copy(
|
||||
@ -649,17 +644,17 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase all algorithm ( case insensitive )
|
||||
/*!
|
||||
Remove all the occurrences of the search sequence from the input.
|
||||
Remove all the occurrences of the string from the input.
|
||||
The input sequence is modified in-place. Searching is case insensitive.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Input An input string
|
||||
\param Search A substring to be searched for.
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
*/
|
||||
template<typename SequenceT, typename CollectionT>
|
||||
template<typename SequenceT, typename RangeT>
|
||||
inline void ierase_all(
|
||||
SequenceT& Input,
|
||||
const CollectionT& Search,
|
||||
const RangeT& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
find_format_all(
|
||||
@ -672,21 +667,26 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase head algorithm
|
||||
/*!
|
||||
Remove the head from the input. Head is a prefix of a seqence of given size.
|
||||
If the sequence is shorter then required, whole sequence if
|
||||
considered to be the head. The result is copied to the given output iterator.
|
||||
Remove the head from the input. The head is a prefix of a sequence of given size.
|
||||
If the sequence is shorter then required, the whole string is
|
||||
considered to be the head. The result is a modified copy of the input.
|
||||
It is returned as a sequence or copied to the output iterator.
|
||||
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param N A length of the head
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param N Length of the head
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT>
|
||||
typename RangeT>
|
||||
inline OutputIteratorT erase_head_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
unsigned int N )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -698,13 +698,7 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase head algorithm
|
||||
/*!
|
||||
Remove the head from the input. Head is a prefix of a seqence of given size.
|
||||
If the sequence is shorter then required, whole sequence if
|
||||
considered to be the head. The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param N A length of the head
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT erase_head_copy(
|
||||
@ -719,12 +713,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase head algorithm
|
||||
/*!
|
||||
Remove the head from the input. Head is a prefix of a seqence of given size.
|
||||
If the sequence is shorter then required, whole sequence if
|
||||
Remove the head from the input. The head is a prefix of a sequence of given size.
|
||||
If the sequence is shorter then required, the whole string is
|
||||
considered to be the head. The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param N A length of the head
|
||||
\param Input An input string
|
||||
\param N Length of the head
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline void erase_head(
|
||||
@ -741,21 +735,26 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase tail algorithm
|
||||
/*!
|
||||
Remove the tail from the input. Tail is a suffix of a seqence of given size.
|
||||
If the sequence is shorter then required, whole sequence if
|
||||
considered to be the tail. The result is copied to the given output iterator.
|
||||
Remove the tail from the input. The tail is a suffix of a sequence of given size.
|
||||
If the sequence is shorter then required, the whole string is
|
||||
considered to be the tail.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param N A length of the head
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param N Length of the head
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT>
|
||||
typename RangeT>
|
||||
inline OutputIteratorT erase_tail_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
unsigned int N )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -767,13 +766,7 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase tail algorithm
|
||||
/*!
|
||||
Remove the tail from the input. Tail is a suffix of a seqence of given size.
|
||||
If the sequence is shorter then required, whole sequence is
|
||||
considered to be the tail. The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param N A length of the head
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT erase_tail_copy(
|
||||
@ -788,12 +781,12 @@ H \param Output A output iterator to which the result will be copied
|
||||
|
||||
//! Erase tail algorithm
|
||||
/*!
|
||||
Remove the tail from the input. Tail is a suffix of a seqence of given size.
|
||||
If the sequence is shorter then required, whole sequence is
|
||||
Remove the tail from the input. The tail is a suffix of a sequence of given size.
|
||||
If the sequence is shorter then required, the whole string is
|
||||
considered to be the tail. The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param N A length of the head
|
||||
\param Input An input string
|
||||
\param N Length of the head
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline void erase_tail(
|
||||
|
@ -11,15 +11,21 @@
|
||||
#define BOOST_STRING_FIND_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
#include <boost/range/result_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/finder.hpp>
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines a set of find algorithms. The algorithms are searching
|
||||
for a subsequence of the input. The result is given as an \c iterator_range
|
||||
for a substring of the input. The result is given as an \c iterator_range
|
||||
delimiting the substring.
|
||||
*/
|
||||
|
||||
@ -32,19 +38,19 @@ namespace boost {
|
||||
/*!
|
||||
Search the input using the given finder.
|
||||
|
||||
\param Input A collection which will be searched.
|
||||
\param Input A string which will be searched.
|
||||
\param Finder Finder object used for searching.
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c CollectionT::iterator or
|
||||
\c CollectionT::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c RangeT::iterator or
|
||||
\c RangeT::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
*/
|
||||
template<typename CollectionT, typename FinderT>
|
||||
template<typename RangeT, typename FinderT>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>
|
||||
find(
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
FinderT Finder)
|
||||
{
|
||||
return Finder(begin(Input),end(Input));
|
||||
@ -54,23 +60,24 @@ namespace boost {
|
||||
|
||||
//! Find first algorithm
|
||||
/*!
|
||||
Search for a first match of search sequence in the
|
||||
input collection.
|
||||
Search for the first occurence of the substring in the input.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Input A string which will be searched.
|
||||
\param Search A substring to be searched for.
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c CollectionT::iterator or
|
||||
\c CollectionT::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c RangeT::iterator or
|
||||
\c RangeT::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<Range1T>::type>
|
||||
find_first(
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search)
|
||||
Range1T& Input,
|
||||
const Range2T& Search)
|
||||
{
|
||||
return first_finder(Search)(
|
||||
begin(Input),end(Input));
|
||||
@ -78,24 +85,26 @@ namespace boost {
|
||||
|
||||
//! Find first algorithm ( case insensitive )
|
||||
/*!
|
||||
Search for a first match of search sequence in the
|
||||
input collection. Searching is case insensitive.
|
||||
Search for the first occurence of the substring in the input.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Input A string which will be searched.
|
||||
\param Search A substring to be searched for.
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Collection1T::iterator or
|
||||
\c Collection1T::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
\c Range1T::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<Range1T>::type>
|
||||
ifind_first(
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
Range1T& Input,
|
||||
const Range2T& Search,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return first_finder(Search,is_iequal(Loc))(
|
||||
@ -106,23 +115,24 @@ namespace boost {
|
||||
|
||||
//! Find last algorithm
|
||||
/*!
|
||||
Search for a last match of search sequence in the
|
||||
input collection.
|
||||
Search for the last occurence of the substring in the input.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Input A string which will be searched.
|
||||
\param Search A substring to be searched for.
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Collection1T::iterator or
|
||||
\c Collection1T::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
\c Range1T::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<Range1T>::type>
|
||||
find_last(
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search)
|
||||
Range1T& Input,
|
||||
const Range2T& Search)
|
||||
{
|
||||
return last_finder(Search)(
|
||||
begin(Input),end(Input));
|
||||
@ -130,24 +140,26 @@ namespace boost {
|
||||
|
||||
//! Find last algorithm ( case insensitive )
|
||||
/*!
|
||||
Search for a last match of search sequence in the
|
||||
input collection. Searching is case insensitive.
|
||||
Search for the last match a string in the input.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Input A string which will be searched.
|
||||
\param Search A substring to be searched for.
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Collection1T::iterator or
|
||||
\c Collection1T::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
\c Range1T::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<Range1T>::type>
|
||||
ifind_last(
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
Range1T& Input,
|
||||
const Range2T& Search,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return last_finder(Search, is_iequal(Loc))(
|
||||
@ -158,24 +170,24 @@ namespace boost {
|
||||
|
||||
//! Find n-th algorithm
|
||||
/*!
|
||||
Search for an n-th match of search sequence in the
|
||||
input collection.
|
||||
Search for the n-th (zero-indexed) occurence of the substring in the
|
||||
input.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Nth An index of the match to be found.
|
||||
\param Input A string which will be searched.
|
||||
\param Search A substring to be searched for.
|
||||
\param Nth An index (zero-indexed) of the match to be found.
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Collection1T::iterator or
|
||||
\c Collection1T::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
\c Range1T::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<Range1T>::type>
|
||||
find_nth(
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
Range1T& Input,
|
||||
const Range2T& Search,
|
||||
unsigned int Nth)
|
||||
{
|
||||
return nth_finder(Search,Nth)(
|
||||
@ -184,25 +196,28 @@ namespace boost {
|
||||
|
||||
//! Find n-th algorithm ( case insensitive ).
|
||||
/*!
|
||||
Search for an n-th match of search sequence in the
|
||||
input collection. Searching is case insensitive.
|
||||
Search for the n-th (zero-indexed) occurence of the substring in the
|
||||
input. Searching is case insensitive.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Nth An index of the match to be found.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Input A string which will be searched.
|
||||
\param Search A substring to be searched for.
|
||||
\param Nth An index (zero-indexed) of the match to be found.
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Collection1T::iterator or
|
||||
\c Collection1T::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
\c Range1T::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<Range1T>::type>
|
||||
ifind_nth(
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
Range1T& Input,
|
||||
const Range2T& Search,
|
||||
unsigned int Nth,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
@ -214,23 +229,25 @@ namespace boost {
|
||||
|
||||
//! Find head algorithm
|
||||
/*!
|
||||
Get the head of the input. Head is a prefix of
|
||||
a seqence of given size. If the sequence is shorter then required,
|
||||
whole sequence if considered to be the head.
|
||||
Get the head of the input. Head is a prefix of the string of the
|
||||
given size. If the input is shorter then required, whole input if considered
|
||||
to be the head.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param N A length of the head
|
||||
\param Input An input string
|
||||
\param N Length of the head
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Collection1T::iterator or
|
||||
\c Collection1T::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
\c Range1T::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename CollectionT>
|
||||
template<typename RangeT>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>
|
||||
find_head(
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
unsigned int N)
|
||||
{
|
||||
return head_finder(N)(
|
||||
@ -241,23 +258,26 @@ namespace boost {
|
||||
|
||||
//! Find tail algorithm
|
||||
/*!
|
||||
Get the tail of the input. Head is a suffix of
|
||||
a seqence of given size. If the sequence is shorter then required,
|
||||
whole sequence if considered to be the tail.
|
||||
Get the head of the input. Head is a suffix of the string of the
|
||||
given size. If the input is shorter then required, whole input if considered
|
||||
to be the tail.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param N A length of the tail
|
||||
\param Input An input string
|
||||
\param N Length of the tail
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c CollectionT::iterator or
|
||||
\c CollectionT::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c RangeT::iterator or
|
||||
\c RangeT::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename CollectionT>
|
||||
template<typename RangeT>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>
|
||||
find_tail(
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
unsigned int N)
|
||||
{
|
||||
return tail_finder(N)(
|
||||
@ -268,23 +288,26 @@ namespace boost {
|
||||
|
||||
//! Find token algorithm
|
||||
/*!
|
||||
Look for a given token in the collection. Token is specified by a predicate.
|
||||
If bCompressed is given, adjacent tokens are considered to be one match.
|
||||
Look for a given token in the string. Token is a character that matches the
|
||||
given predicate.
|
||||
If the "token compress mode" is enabled, adjacent tokens are considered to be one match.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Input A input string.
|
||||
\param Pred An unary predicate to identify a token
|
||||
\param eCompress Enable/Disable compressing of adjacent tokens
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c CollectionT::iterator or
|
||||
\c CollectionT::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c RangeT::iterator or
|
||||
\c RangeT::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename CollectionT, typename PredicateT>
|
||||
template<typename RangeT, typename PredicateT>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>
|
||||
find_token(
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
PredicateT Pred,
|
||||
token_compress_mode_type eCompress=token_compress_off)
|
||||
{
|
||||
|
@ -12,15 +12,18 @@
|
||||
|
||||
#include <deque>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/concept.hpp>
|
||||
#include <boost/algorithm/string/detail/find_format.hpp>
|
||||
#include <boost/algorithm/string/detail/find_format_all.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines generic replace algorithms. Each algorithm replaces
|
||||
a part(s) of the input. The part to be replaced is looked up using a Finder object.
|
||||
part(s) of the input. The part to be replaced is looked up using a Finder object.
|
||||
Result of finding is then used by a Formatter object to generate the replacement.
|
||||
*/
|
||||
|
||||
@ -33,33 +36,37 @@ namespace boost {
|
||||
/*!
|
||||
Use the Finder to search for a substring. Use the Formatter to format
|
||||
this substring and replace it in the input.
|
||||
The resulting sequence is copied to the given output iterator.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Finder A Finder object used to search for a match to be replaced
|
||||
\param Formatter A Formatter object used to format a match
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename FinderT,
|
||||
typename FormatterT>
|
||||
inline OutputIteratorT find_format_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
FinderT Finder,
|
||||
FormatterT Formatter )
|
||||
{
|
||||
// Concept check
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >();
|
||||
function_requires<
|
||||
FormatterConcept<
|
||||
FormatterT,
|
||||
FinderT,BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
|
||||
FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >();
|
||||
|
||||
return detail::find_format_copy_impl(
|
||||
Output,
|
||||
@ -71,14 +78,7 @@ namespace boost {
|
||||
|
||||
//! Generic replace algorithm
|
||||
/*!
|
||||
Use the Finder to search for a substring. Use the Formatter to format
|
||||
this substring and replace it in the input.
|
||||
The result is the modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Finder A Finder object used to search for a match to be replaced
|
||||
\param Formatter A Formatter object used to format a match
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
@ -92,11 +92,11 @@ namespace boost {
|
||||
// Concept check
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
function_requires<
|
||||
FormatterConcept<
|
||||
FormatterT,
|
||||
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
|
||||
return detail::find_format_copy_impl(
|
||||
Input,
|
||||
@ -126,11 +126,11 @@ namespace boost {
|
||||
// Concept check
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
function_requires<
|
||||
FormatterConcept<
|
||||
FormatterT,
|
||||
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
|
||||
detail::find_format_impl(
|
||||
Input,
|
||||
@ -147,33 +147,37 @@ namespace boost {
|
||||
Use the Finder to search for a substring. Use the Formatter to format
|
||||
this substring and replace it in the input. Repeat this for all matching
|
||||
substrings.
|
||||
The resulting sequence is copied to the given output iterator.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Finder A Finder object used to search for a match to be replaced
|
||||
\param Formatter A Formatter object used to format a match
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename FinderT,
|
||||
typename FormatterT>
|
||||
inline OutputIteratorT find_format_all_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
FinderT Finder,
|
||||
FormatterT Formatter)
|
||||
{
|
||||
// Concept check
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >();
|
||||
function_requires<
|
||||
FormatterConcept<
|
||||
FormatterT,
|
||||
FinderT,BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
|
||||
FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >();
|
||||
|
||||
return detail::find_format_all_copy_impl(
|
||||
Output,
|
||||
@ -185,15 +189,7 @@ namespace boost {
|
||||
|
||||
//! Generic replace all algorithm
|
||||
/*!
|
||||
Use the Finder to search for a substring. Use the Formatter to format
|
||||
this substring and replace it in the input. Repeat this for all matching
|
||||
substrings.
|
||||
The result is the modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Finder A Finder object used to search for a match to be replaced
|
||||
\param Formatter A Formatter object used to format a match
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
@ -207,11 +203,11 @@ namespace boost {
|
||||
// Concept check
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
function_requires<
|
||||
FormatterConcept<
|
||||
FormatterT,
|
||||
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
|
||||
return detail::find_format_all_copy_impl(
|
||||
Input,
|
||||
@ -242,11 +238,11 @@ namespace boost {
|
||||
// Concept check
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
function_requires<
|
||||
FormatterConcept<
|
||||
FormatterT,
|
||||
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
|
||||
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> >();
|
||||
|
||||
detail::find_format_all_impl(
|
||||
Input,
|
||||
|
@ -1,23 +1,32 @@
|
||||
// Boost string_algo library find_iterator.hpp header file ---------------------------//
|
||||
|
||||
// Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
// Copyright Pavol Droba 2002-2004. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_STRING_FIND_ITERATOR_HPP
|
||||
#define BOOST_STRING_FIND_ITERATOR_HPP
|
||||
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/detail/find_iterator.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/result_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/detail/find_iterator.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines find iterator classes. Find iterator repeatly applies a Finder
|
||||
to the specified input string to search for matches. Dereferencing
|
||||
the iterator yields the current match or a range between the last and the current
|
||||
match depending on the iterator used.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
@ -26,10 +35,10 @@ namespace boost {
|
||||
//! find_iterator
|
||||
/*!
|
||||
Find iterator encapsulates a Finder and allows
|
||||
an incremental searching in the sequence.
|
||||
for incremental searching in a string.
|
||||
Each increment moves the iterator to the next match.
|
||||
|
||||
Find iterator is readable forward traversal iterator.
|
||||
Find iterator is a readable forward traversal iterator.
|
||||
|
||||
Dereferencing the iterator yields an iterator_range delimiting
|
||||
the current match.
|
||||
@ -96,6 +105,22 @@ namespace boost {
|
||||
increment();
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
/*!
|
||||
Construct new find_iterator for a given finder
|
||||
and a range.
|
||||
*/
|
||||
template<typename FinderT, typename RangeT>
|
||||
find_iterator(
|
||||
RangeT& Col,
|
||||
FinderT Finder ) :
|
||||
detail::find_iterator_base<IteratorT>(Finder,0),
|
||||
m_Match(begin(Col),begin(Col)),
|
||||
m_End(end(Col))
|
||||
{
|
||||
increment();
|
||||
}
|
||||
|
||||
private:
|
||||
// iterator operations
|
||||
|
||||
@ -114,14 +139,13 @@ namespace boost {
|
||||
// comparison
|
||||
bool equal( const find_iterator& Other ) const
|
||||
{
|
||||
return
|
||||
bool bEof=eof();
|
||||
bool bOtherEof=Other.eof();
|
||||
|
||||
return bEof || bOtherEof ? bEof==bOtherEof :
|
||||
(
|
||||
m_Match==Other.m_Match &&
|
||||
m_End==Other.m_End
|
||||
)
|
||||
||
|
||||
(
|
||||
eof() && Other.eof()
|
||||
);
|
||||
}
|
||||
|
||||
@ -130,7 +154,7 @@ namespace boost {
|
||||
|
||||
//! Eof check
|
||||
/*!
|
||||
Check the eof condition. Eof condition means, that
|
||||
Check the eof condition. Eof condition means that
|
||||
there is nothing more to be searched i.e. find_iterator
|
||||
is after the last match.
|
||||
*/
|
||||
@ -152,17 +176,17 @@ namespace boost {
|
||||
|
||||
//! find iterator construction helper
|
||||
/*!
|
||||
* Construct a find iterator to iterate through the specified collection
|
||||
* Construct a find iterator to iterate through the specified string
|
||||
*/
|
||||
template<typename CollectionT, typename FinderT>
|
||||
template<typename RangeT, typename FinderT>
|
||||
inline find_iterator<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>
|
||||
make_find_iterator(
|
||||
CollectionT& Collection,
|
||||
RangeT& Collection,
|
||||
FinderT Finder)
|
||||
{
|
||||
return find_iterator<BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>(
|
||||
Collection.begin(), Collection.end(), Finder);
|
||||
return find_iterator<BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>(
|
||||
begin(Collection), end(Collection), Finder);
|
||||
}
|
||||
|
||||
// split iterator -----------------------------------------------//
|
||||
@ -170,11 +194,11 @@ namespace boost {
|
||||
//! split_iterator
|
||||
/*!
|
||||
Split iterator encapsulates a Finder and allows
|
||||
an incremental searching in the sequence.
|
||||
for incremental searching in a string.
|
||||
Unlike the find iterator, split iterator iterates
|
||||
through gasps between matches.
|
||||
through gaps between matches.
|
||||
|
||||
Find iterator is readable forward traversal iterator.
|
||||
Find iterator is a readable forward traversal iterator.
|
||||
|
||||
Dereferencing the iterator yields an iterator_range delimiting
|
||||
the current match.
|
||||
@ -216,17 +240,19 @@ namespace boost {
|
||||
split_iterator() {}
|
||||
//! Copy constructor
|
||||
/*!
|
||||
Construct a copy of the find_iterator
|
||||
Construct a copy of the split_iterator
|
||||
*/
|
||||
split_iterator( const split_iterator& Other ) :
|
||||
base_type(Other),
|
||||
m_Match(Other.m_Match),
|
||||
m_Next(Other.m_Next),
|
||||
m_End(Other.m_End) {}
|
||||
m_End(Other.m_End),
|
||||
m_bEof(false)
|
||||
{}
|
||||
|
||||
//! Constructor
|
||||
/*!
|
||||
Construct new find_iterator for a given finder
|
||||
Construct new split_iterator for a given finder
|
||||
and a range.
|
||||
*/
|
||||
template<typename FinderT>
|
||||
@ -237,10 +263,29 @@ namespace boost {
|
||||
detail::find_iterator_base<IteratorT>(Finder,0),
|
||||
m_Match(Begin,Begin),
|
||||
m_Next(Begin),
|
||||
m_End(End)
|
||||
m_End(End),
|
||||
m_bEof(false)
|
||||
{
|
||||
increment();
|
||||
}
|
||||
//! Constructor
|
||||
/*!
|
||||
Construct new split_iterator for a given finder
|
||||
and a collection.
|
||||
*/
|
||||
template<typename FinderT, typename RangeT>
|
||||
split_iterator(
|
||||
RangeT& Col,
|
||||
FinderT Finder ) :
|
||||
detail::find_iterator_base<IteratorT>(Finder,0),
|
||||
m_Match(begin(Col),begin(Col)),
|
||||
m_Next(begin(Col)),
|
||||
m_End(end(Col)),
|
||||
m_bEof(false)
|
||||
{
|
||||
increment();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// iterator operations
|
||||
@ -255,6 +300,16 @@ namespace boost {
|
||||
void increment()
|
||||
{
|
||||
match_type FindMatch=this->do_find( m_Next, m_End );
|
||||
|
||||
if(FindMatch.begin()==m_End && FindMatch.end()==m_End)
|
||||
{
|
||||
if(m_Match.end()==m_End)
|
||||
{
|
||||
// Mark iterator as eof
|
||||
m_bEof=true;
|
||||
}
|
||||
}
|
||||
|
||||
m_Match=match_type( m_Next, FindMatch.begin() );
|
||||
m_Next=FindMatch.end();
|
||||
}
|
||||
@ -262,15 +317,14 @@ namespace boost {
|
||||
// comparison
|
||||
bool equal( const split_iterator& Other ) const
|
||||
{
|
||||
return
|
||||
bool bEof=eof();
|
||||
bool bOtherEof=Other.eof();
|
||||
|
||||
return bEof || bOtherEof ? bEof==bOtherEof :
|
||||
(
|
||||
m_Match==Other.m_Match &&
|
||||
m_Next==Other.m_Next &&
|
||||
m_End==Other.m_End
|
||||
)
|
||||
||
|
||||
(
|
||||
eof() && Other.eof()
|
||||
m_End==Other.m_End
|
||||
);
|
||||
}
|
||||
|
||||
@ -279,18 +333,13 @@ namespace boost {
|
||||
|
||||
//! Eof check
|
||||
/*!
|
||||
Check the eof condition. Eof condition means, that
|
||||
Check the eof condition. Eof condition means that
|
||||
there is nothing more to be searched i.e. find_iterator
|
||||
is after the last match.
|
||||
*/
|
||||
bool eof() const
|
||||
{
|
||||
return
|
||||
this->is_null() ||
|
||||
(
|
||||
m_Match.begin() == m_End &&
|
||||
m_Match.end() == m_End
|
||||
);
|
||||
return this->is_null() || m_bEof;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -298,21 +347,22 @@ namespace boost {
|
||||
match_type m_Match;
|
||||
input_iterator_type m_Next;
|
||||
input_iterator_type m_End;
|
||||
bool m_bEof;
|
||||
};
|
||||
|
||||
//! split iterator construction helper
|
||||
/*!
|
||||
* Construct a split iterator to iterate through the specified collection
|
||||
*/
|
||||
template<typename CollectionT, typename FinderT>
|
||||
template<typename RangeT, typename FinderT>
|
||||
inline split_iterator<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>
|
||||
make_split_iterator(
|
||||
CollectionT& Collection,
|
||||
RangeT& Collection,
|
||||
FinderT Finder)
|
||||
{
|
||||
return split_iterator<BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>(
|
||||
Collection.begin(), Collection.end(), Finder);
|
||||
return split_iterator<BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type>(
|
||||
begin(Collection), end(Collection), Finder);
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,16 +11,20 @@
|
||||
#define BOOST_STRING_FINDER_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/constants.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/detail/finder.hpp>
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines Finder generators. Finder object is a functor which is able to
|
||||
find a subsequence matching a specific criterium in an input
|
||||
sequence.
|
||||
find a substring matching a specific criteria in the input.
|
||||
Finders are used as a pluggable components for replace, find
|
||||
and split facilities. This header contains generator functions
|
||||
for finders provided in this library.
|
||||
@ -34,40 +38,33 @@ namespace boost {
|
||||
//! "First" finder
|
||||
/*!
|
||||
Construct the \c first_finder. The finder searches for the first
|
||||
occurrence of the search sequence in a given input.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
occurrence of the string in a given input.
|
||||
The result is given as an \c iterator_range delimiting the match.
|
||||
|
||||
\param Search A sequence to be searched for.
|
||||
\param Search A substring to be searched for.
|
||||
\param Comp An element comparison predicate
|
||||
\return An instance of the \c first_finder object
|
||||
*/
|
||||
template<typename ContainerT>
|
||||
inline detail::first_finderF<
|
||||
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
|
||||
BOOST_STRING_TYPENAME range_const_iterator<ContainerT>::type,
|
||||
is_equal>
|
||||
first_finder( const ContainerT& Search )
|
||||
{
|
||||
return
|
||||
detail::first_finderF<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<ContainerT>::type,
|
||||
range_const_iterator<ContainerT>::type,
|
||||
is_equal>( Search, is_equal() ) ;
|
||||
}
|
||||
|
||||
//! "First" finder
|
||||
/*!
|
||||
Construct the \c first_finder. The finder searches for the first
|
||||
occurrence of the search sequence in a given input.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
|
||||
Elements are compared using the given predicate.
|
||||
|
||||
\param Search A sequence to be searched for.
|
||||
\param Comp An element comparison predicate
|
||||
\return An instance of the \c first_finder object
|
||||
\overload
|
||||
*/
|
||||
template<typename ContainerT,typename PredicateT>
|
||||
inline detail::first_finderF<
|
||||
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
|
||||
BOOST_STRING_TYPENAME range_const_iterator<ContainerT>::type,
|
||||
PredicateT>
|
||||
first_finder(
|
||||
const ContainerT& Search, PredicateT Comp )
|
||||
@ -75,69 +72,63 @@ namespace boost {
|
||||
return
|
||||
detail::first_finderF<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<ContainerT>::type,
|
||||
range_const_iterator<ContainerT>::type,
|
||||
PredicateT>( Search, Comp );
|
||||
}
|
||||
|
||||
//! "Last" finder
|
||||
/*!
|
||||
Construct the \c last_finder. The finder searches for the last
|
||||
occurrence of the search sequence in a given input.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
occurrence of the string in a given input.
|
||||
The result is given as an \c iterator_range delimiting the match.
|
||||
|
||||
\param Search A sequence to be searched for.
|
||||
\param Search A substring to be searched for.
|
||||
\param Comp An element comparison predicate
|
||||
\return An instance of the \c last_finder object
|
||||
*/
|
||||
template<typename ContainerT>
|
||||
inline detail::last_finderF<
|
||||
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
|
||||
BOOST_STRING_TYPENAME range_const_iterator<ContainerT>::type,
|
||||
is_equal>
|
||||
last_finder( const ContainerT& Search )
|
||||
{
|
||||
return
|
||||
detail::last_finderF<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<ContainerT>::type,
|
||||
range_const_iterator<ContainerT>::type,
|
||||
is_equal>( Search, is_equal() );
|
||||
}
|
||||
//! "Last" finder
|
||||
/*!
|
||||
Construct the \c last_finder. The finder searches for the last
|
||||
occurrence of the search sequence in a given input.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
|
||||
Elements are compared using the given predicate.
|
||||
|
||||
\param Search A sequence to be searched for.
|
||||
\param Comp An element comparison predicate
|
||||
\return An instance of the \c last_finder object
|
||||
\overload
|
||||
*/
|
||||
template<typename ContainerT, typename PredicateT>
|
||||
inline detail::last_finderF<
|
||||
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
|
||||
BOOST_STRING_TYPENAME range_const_iterator<ContainerT>::type,
|
||||
PredicateT>
|
||||
last_finder( const ContainerT& Search, PredicateT Comp )
|
||||
{
|
||||
return
|
||||
detail::last_finderF<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<ContainerT>::type,
|
||||
range_const_iterator<ContainerT>::type,
|
||||
PredicateT>( Search, Comp ) ;
|
||||
}
|
||||
|
||||
//! "Nth" finder
|
||||
/*!
|
||||
Construct the \c nth_finder. The finder searches for the n-th
|
||||
occurrence of the search sequence in a given input.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
Construct the \c nth_finder. The finder searches for the n-th (zero-indexed)
|
||||
occurrence of the string in a given input.
|
||||
The result is given as an \c iterator_range delimiting the match.
|
||||
|
||||
\param Search A sequence to be searched for.
|
||||
\param Search A substring to be searched for.
|
||||
\param Nth An index of the match to be find
|
||||
\param Comp An element comparison predicate
|
||||
\return An instance of the \c nth_finder object
|
||||
*/
|
||||
template<typename ContainerT>
|
||||
inline detail::nth_finderF<
|
||||
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
|
||||
BOOST_STRING_TYPENAME range_const_iterator<ContainerT>::type,
|
||||
is_equal>
|
||||
nth_finder(
|
||||
const ContainerT& Search,
|
||||
@ -146,25 +137,16 @@ namespace boost {
|
||||
return
|
||||
detail::nth_finderF<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<ContainerT>::type,
|
||||
range_const_iterator<ContainerT>::type,
|
||||
is_equal>( Search, Nth, is_equal() ) ;
|
||||
}
|
||||
//! "Nth" finder
|
||||
/*!
|
||||
Construct the \c nth_finder. The finder searches for the n-th
|
||||
occurrence of the search sequence in a given input.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
|
||||
Elements are compared using the given predicate.
|
||||
|
||||
\param Search A sequence to be searched for.
|
||||
\param Nth An index of the match to be find
|
||||
\param Comp An element comparison predicate
|
||||
\return An instance of the \c nth_finder object
|
||||
\overload
|
||||
*/
|
||||
template<typename ContainerT, typename PredicateT>
|
||||
inline detail::nth_finderF<
|
||||
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
|
||||
BOOST_STRING_TYPENAME range_const_iterator<ContainerT>::type,
|
||||
PredicateT>
|
||||
nth_finder(
|
||||
const ContainerT& Search,
|
||||
@ -174,17 +156,17 @@ namespace boost {
|
||||
return
|
||||
detail::nth_finderF<
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<ContainerT>::type,
|
||||
range_const_iterator<ContainerT>::type,
|
||||
PredicateT>( Search, Nth, Comp );
|
||||
}
|
||||
|
||||
//! "Head" finder
|
||||
/*!
|
||||
Construct the \c head_finder. The finder returns a head of a given
|
||||
input. Head is a prefix of a sequence up to n elements in
|
||||
input. The head is a prefix of a string up to n elements in
|
||||
size. If an input has less then n elements, whole input is
|
||||
considered a head.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
The result is given as an \c iterator_range delimiting the match.
|
||||
|
||||
\param N The size of the head
|
||||
\return An instance of the \c head_finder object
|
||||
@ -198,10 +180,10 @@ namespace boost {
|
||||
//! "Tail" finder
|
||||
/*!
|
||||
Construct the \c tail_finder. The finder returns a tail of a given
|
||||
input. Tail is a suffix of the sequence up to n elements in
|
||||
input. The tail is a suffix of a string up to n elements in
|
||||
size. If an input has less then n elements, whole input is
|
||||
considered a head.
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
The result is given as an \c iterator_range delimiting the match.
|
||||
|
||||
\param N The size of the head
|
||||
\return An instance of the \c tail_finder object
|
||||
@ -219,12 +201,12 @@ namespace boost {
|
||||
algorithm, with an exception that it return a range of
|
||||
instead of a single iterator.
|
||||
|
||||
If bCompress is set to true, adjacent matching tokens are
|
||||
If "compress token mode" is enabled, adjacent matching tokens are
|
||||
concatenated into one match. Thus the finder can be used to
|
||||
search for continuous segments of elements satisfying the
|
||||
search for continuous segments of characters satisfying the
|
||||
given predicate.
|
||||
|
||||
The result is given as a \c iterator_range delimiting the match.
|
||||
The result is given as an \c iterator_range delimiting the match.
|
||||
|
||||
\param Pred An element selection predicate
|
||||
\param eCompress Compress flag
|
||||
@ -247,6 +229,7 @@ namespace boost {
|
||||
|
||||
\param Begin Beginning of the range
|
||||
\param End End of the range
|
||||
\param Range The range.
|
||||
\return An instance of the \c range_finger object
|
||||
*/
|
||||
template< typename ForwardIteratorT >
|
||||
@ -259,9 +242,7 @@ namespace boost {
|
||||
}
|
||||
|
||||
//! "Range" finder
|
||||
/*!
|
||||
\param Range The range.
|
||||
|
||||
/*!
|
||||
\overload
|
||||
*/
|
||||
template< typename ForwardIteratorT >
|
||||
|
@ -11,25 +11,26 @@
|
||||
#define BOOST_STRING_FORMATTER_HPP
|
||||
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
#include <boost/algorithm/string/detail/formatter.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines formatter generators. Formatter is a functor which formats
|
||||
a string according to give parameters. A Formatter works
|
||||
Defines Formatter generators. Formatter is a functor which formats
|
||||
a string according to given parameters. A Formatter works
|
||||
in conjunction with a Finder. A Finder can provide additional information
|
||||
for a specific Formatter. An example of such a cooperation is reger_finder
|
||||
for a specific Formatter. An example of such a cooperation is regex_finder
|
||||
and regex_formatter.
|
||||
|
||||
Formatters are used by as a pluggable components for replace facilities.
|
||||
Formatters are used as pluggable components for replace facilities.
|
||||
This header contains generator functions for the Formatters provided in this library.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
// generic formaters ---------------------------------------------------------------//
|
||||
// generic formatters ---------------------------------------------------------------//
|
||||
|
||||
//! Constant formatter
|
||||
/*!
|
||||
@ -39,11 +40,11 @@ namespace boost {
|
||||
\param Format A predefined value used as a result for formating
|
||||
\return An instance of the \c const_formatter object.
|
||||
*/
|
||||
template<typename CollectionT>
|
||||
inline detail::const_formatF<CollectionT>
|
||||
const_formatter(const CollectionT& Format)
|
||||
template<typename RangeT>
|
||||
inline detail::const_formatF<RangeT>
|
||||
const_formatter(const RangeT& Format)
|
||||
{
|
||||
return detail::const_formatF<CollectionT>(Format);
|
||||
return detail::const_formatF<RangeT>(Format);
|
||||
}
|
||||
|
||||
//! Identity formatter
|
||||
@ -53,29 +54,29 @@ namespace boost {
|
||||
|
||||
\return An instance of the \c identity_formatter object.
|
||||
*/
|
||||
template<typename CollectionT>
|
||||
inline detail::identity_formatF<CollectionT>
|
||||
template<typename RangeT>
|
||||
inline detail::identity_formatF<RangeT>
|
||||
identity_formatter()
|
||||
{
|
||||
return detail::identity_formatF<CollectionT>();
|
||||
return detail::identity_formatF<RangeT>();
|
||||
}
|
||||
|
||||
//! Empty formatter
|
||||
/*!
|
||||
Construct the \c empty_formatter. Empty formater always returns an empty
|
||||
Construct the \c empty_formatter. Empty formatter always returns an empty
|
||||
sequence.
|
||||
|
||||
\param Input container used to select a correct value_type for the
|
||||
resulting empty_container<>.
|
||||
\return An instance of the \c empty_formatter object.
|
||||
*/
|
||||
template<typename CollectionT>
|
||||
template<typename RangeT>
|
||||
inline detail::empty_formatF<
|
||||
BOOST_STRING_TYPENAME value_type_of<CollectionT>::type>
|
||||
empty_formatter(const CollectionT& Input)
|
||||
BOOST_STRING_TYPENAME range_value<RangeT>::type>
|
||||
empty_formatter(const RangeT&)
|
||||
{
|
||||
return detail::empty_formatF<
|
||||
BOOST_STRING_TYPENAME value_type_of<CollectionT>::type>();
|
||||
BOOST_STRING_TYPENAME range_value<RangeT>::type>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,8 +14,13 @@
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/result_iterator.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
|
||||
#include <boost/algorithm/string/concept.hpp>
|
||||
#include <boost/algorithm/string/find_iterator.hpp>
|
||||
#include <boost/algorithm/string/detail/util.hpp>
|
||||
@ -23,12 +28,12 @@
|
||||
/*! \file
|
||||
Defines generic split algorithms. Split algorithms can be
|
||||
used to divide a sequence into several part according
|
||||
to a given criterium. Result is given as a 'container
|
||||
to a given criteria. Result is given as a 'container
|
||||
of containers' where elements are copies or references
|
||||
to extracted parts.
|
||||
|
||||
There are two algorithms provided. One iterates over matching
|
||||
substrings, the other one over the gasps between these matches.
|
||||
substrings, the other one over the gaps between these matches.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -55,40 +60,47 @@ namespace boost {
|
||||
\param Finder A Finder object used for searching
|
||||
\return A reference the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
*/
|
||||
template<
|
||||
typename SequenceSequenceT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename FinderT >
|
||||
inline SequenceSequenceT&
|
||||
iter_find(
|
||||
SequenceSequenceT& Result,
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
FinderT Finder )
|
||||
{
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type> >();
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
result_iterator_of<CollectionT>::type input_iterator_type;
|
||||
range_result_iterator<RangeT>::type input_iterator_type;
|
||||
typedef find_iterator<input_iterator_type> find_iterator_type;
|
||||
typedef detail::copy_iterator_rangeF<
|
||||
BOOST_STRING_TYPENAME
|
||||
value_type_of<SequenceSequenceT>::type,
|
||||
range_value<SequenceSequenceT>::type,
|
||||
input_iterator_type> copy_range_type;
|
||||
|
||||
input_iterator_type InputEnd=end(Input);
|
||||
|
||||
SequenceSequenceT Tmp(
|
||||
typedef transform_iterator<copy_range_type, find_iterator_type>
|
||||
transform_iter_type;
|
||||
|
||||
transform_iter_type itBegin=
|
||||
make_transform_iterator(
|
||||
find_iterator_type( begin(Input), InputEnd, Finder ),
|
||||
copy_range_type() ),
|
||||
copy_range_type());
|
||||
|
||||
transform_iter_type itEnd=
|
||||
make_transform_iterator(
|
||||
find_iterator_type(),
|
||||
copy_range_type() ) );
|
||||
copy_range_type());
|
||||
|
||||
SequenceSequenceT Tmp(itBegin, itEnd);
|
||||
|
||||
Result.swap(Tmp);
|
||||
return Result;
|
||||
}
|
||||
@ -115,40 +127,47 @@ namespace boost {
|
||||
\param Finder A finder object used for searching
|
||||
\return A reference the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
*/
|
||||
template<
|
||||
typename SequenceSequenceT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename FinderT >
|
||||
inline SequenceSequenceT&
|
||||
iter_split(
|
||||
SequenceSequenceT& Result,
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
FinderT Finder )
|
||||
{
|
||||
function_requires<
|
||||
FinderConcept<FinderT,
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type> >();
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type> >();
|
||||
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
result_iterator_of<CollectionT>::type input_iterator_type;
|
||||
range_result_iterator<RangeT>::type input_iterator_type;
|
||||
typedef split_iterator<input_iterator_type> find_iterator_type;
|
||||
typedef detail::copy_iterator_rangeF<
|
||||
BOOST_STRING_TYPENAME
|
||||
value_type_of<SequenceSequenceT>::type,
|
||||
range_value<SequenceSequenceT>::type,
|
||||
input_iterator_type> copy_range_type;
|
||||
|
||||
input_iterator_type InputEnd=end(Input);
|
||||
|
||||
SequenceSequenceT Tmp(
|
||||
typedef transform_iterator<copy_range_type, find_iterator_type>
|
||||
transform_iter_type;
|
||||
|
||||
transform_iter_type itBegin=
|
||||
make_transform_iterator(
|
||||
find_iterator_type( begin(Input), InputEnd, Finder ),
|
||||
copy_range_type() ),
|
||||
copy_range_type() );
|
||||
|
||||
transform_iter_type itEnd=
|
||||
make_transform_iterator(
|
||||
find_iterator_type(),
|
||||
copy_range_type() ) );
|
||||
copy_range_type() );
|
||||
|
||||
SequenceSequenceT Tmp(itBegin, itEnd);
|
||||
|
||||
Result.swap(Tmp);
|
||||
return Result;
|
||||
}
|
||||
|
@ -1,295 +0,0 @@
|
||||
// Boost string_algo library iterator_range.hpp header file ---------------------------//
|
||||
|
||||
// Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_STRING_ITERATOR_RANGE_HPP
|
||||
#define BOOST_STRING_ITERATOR_RANGE_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines the \c iterator_class and related functions.
|
||||
\c iterator_range is a simple wrapper of iterator pair idiom. It provides
|
||||
a rich subset of Container interface.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
// iterator range template class -----------------------------------------//
|
||||
|
||||
//! iterator_range class
|
||||
/*!
|
||||
An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
|
||||
An iterator_range can be passed to an algorithm which requires a sequence as an input.
|
||||
For example, the \c toupper() function may be used most frequently on strings,
|
||||
but can also be used on iterator_ranges:
|
||||
|
||||
\code
|
||||
boost::tolower( find( s, "UPPERCASE STRING" ) );
|
||||
\endcode
|
||||
|
||||
Many algorithms working with sequences take a pair of iterators,
|
||||
delimiting a working range, as an arguments. The \c iterator_range class is an
|
||||
encapsulation of a range identified by a pair of iterators.
|
||||
It provides a collection interface,
|
||||
so it is possible to pass an instance to an algorithm requiring a collection as an input.
|
||||
*/
|
||||
template<typename IteratorT>
|
||||
class iterator_range
|
||||
{
|
||||
public:
|
||||
//! this type
|
||||
typedef iterator_range<IteratorT> type;
|
||||
//! Encapsulated value type
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<IteratorT>::value_type value_type;
|
||||
//! Reference type
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<IteratorT>::reference reference;
|
||||
//! Difference type
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<IteratorT>::difference_type difference_type;
|
||||
//! Size type
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<IteratorT>::difference_type size_type;
|
||||
|
||||
//! const_iterator type
|
||||
/*!
|
||||
There is no distinction between const_iterator and iterator.
|
||||
These typedefs are provides to fulfill container interface
|
||||
*/
|
||||
typedef IteratorT const_iterator;
|
||||
//! iterator type
|
||||
typedef IteratorT iterator;
|
||||
|
||||
//! Default constructor
|
||||
iterator_range() {}
|
||||
|
||||
//! Constructor from a pair of iterators
|
||||
iterator_range( iterator Begin, iterator End ) :
|
||||
m_Begin(Begin), m_End(End) {}
|
||||
|
||||
//! Constructor from a std::pair
|
||||
iterator_range( const std::pair<IteratorT,IteratorT>& Range ) :
|
||||
m_Begin(Range.first), m_End(Range.second) {}
|
||||
|
||||
//! Copy constructor
|
||||
iterator_range( const iterator_range& Other ) :
|
||||
m_Begin(Other.begin()), m_End(Other.end()) {}
|
||||
|
||||
//! Templated copy constructor
|
||||
/*!
|
||||
This constructor is provided to allow conversion between
|
||||
const and mutable iterator instances of this class template
|
||||
*/
|
||||
template< typename OtherItT >
|
||||
iterator_range( const iterator_range<OtherItT>& Other ) :
|
||||
m_Begin(Other.begin()), m_End(Other.end()) {}
|
||||
|
||||
//! Assignment operator
|
||||
iterator_range& operator=( const iterator_range& Other )
|
||||
{
|
||||
m_Begin=Other.begin(); m_End=Other.end();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Assignment operator ( templated version )
|
||||
template< typename OtherItT >
|
||||
iterator_range& operator=( const iterator_range<OtherItT>& Other )
|
||||
{
|
||||
m_Begin=Other.begin(); m_End=Other.end();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Comparison operator ( equal )
|
||||
/*!
|
||||
Compare operands for equality
|
||||
*/
|
||||
template< typename OtherItT >
|
||||
bool operator==( const iterator_range<OtherItT>& Other ) const
|
||||
{
|
||||
return m_Begin==Other.begin() && m_End==Other.end();
|
||||
}
|
||||
|
||||
//! Comparison operator ( not-equal )
|
||||
/*!
|
||||
Compare operands for non-equality
|
||||
*/
|
||||
template< typename OtherItT >
|
||||
bool operator!=( const iterator_range<OtherItT>& Other ) const
|
||||
{
|
||||
return m_Begin!=Other.begin() || m_End!=Other.end();
|
||||
}
|
||||
|
||||
//! begin access
|
||||
/*!
|
||||
Retrieve the begin iterator
|
||||
*/
|
||||
IteratorT begin() const
|
||||
{
|
||||
return m_Begin;
|
||||
}
|
||||
|
||||
//! end access
|
||||
/*!
|
||||
Retrieve the end iterator
|
||||
*/
|
||||
IteratorT end() const
|
||||
{
|
||||
return m_End;
|
||||
}
|
||||
|
||||
//! Empty container test
|
||||
/*!
|
||||
Test whenever the range is empty
|
||||
*/
|
||||
bool empty() const
|
||||
{
|
||||
return m_Begin==m_End;
|
||||
}
|
||||
|
||||
//! Size of the range
|
||||
/*!
|
||||
Retrieve the size of the range
|
||||
*/
|
||||
difference_type size() const
|
||||
{
|
||||
return std::distance( m_Begin, m_End );
|
||||
}
|
||||
|
||||
//! Swap
|
||||
/*!
|
||||
Swap two ranges
|
||||
*/
|
||||
void swap( iterator_range& Other )
|
||||
{
|
||||
std::swap( m_Begin, Other.begin() );
|
||||
std::swap( m_End, Other.end() );
|
||||
}
|
||||
|
||||
//! Safe bool conversion
|
||||
/*!
|
||||
Check whenever the range is empty.
|
||||
Allows to use construction like this:
|
||||
\code
|
||||
iterator_range r;
|
||||
if (!r)
|
||||
{
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
typedef iterator (iterator_range::*unspecified_bool_type) () const;
|
||||
operator unspecified_bool_type() const
|
||||
{
|
||||
return empty()? 0: &iterator_range::end;
|
||||
}
|
||||
|
||||
private:
|
||||
// begin and end iterators
|
||||
IteratorT m_Begin;
|
||||
IteratorT m_End;
|
||||
};
|
||||
|
||||
// iterator range free-standing operators ---------------------------//
|
||||
|
||||
//! iterator_range output operator
|
||||
/*!
|
||||
Output the range to an ostream. Elements are outputed
|
||||
in a sequence without separators.
|
||||
*/
|
||||
template< typename IteratorT, typename Elem, typename Traits >
|
||||
std::basic_ostream<Elem,Traits>& operator<<(
|
||||
std::basic_ostream<Elem, Traits>& Os,
|
||||
const iterator_range<IteratorT>& Range )
|
||||
{
|
||||
std::copy(Range.begin(), Range.end(), std::ostream_iterator<Elem>(Os));
|
||||
|
||||
return Os;
|
||||
}
|
||||
|
||||
|
||||
// iterator range utilities -----------------------------------------//
|
||||
|
||||
//! iterator_range construct helper
|
||||
/*!
|
||||
Construct an \c iterator_range from a pair of iterators
|
||||
|
||||
\param Begin A begin iterator
|
||||
\param End An end iterator
|
||||
\return iterator_range object
|
||||
*/
|
||||
template< typename IteratorT >
|
||||
inline iterator_range< IteratorT > make_iterator_range( IteratorT Begin, IteratorT End )
|
||||
{
|
||||
return iterator_range<IteratorT>( Begin, End );
|
||||
}
|
||||
|
||||
//! iterator_range construct helper
|
||||
/*!
|
||||
Construct an \c iterator_range from a \c std::pair<> containing the begin
|
||||
and end iterators.
|
||||
|
||||
\param Pair A \c std::pair<> with begin and end iterators
|
||||
\return \c iterator_range object
|
||||
*/
|
||||
template< typename IteratorT >
|
||||
inline iterator_range< IteratorT > make_iterator_range( const std::pair<IteratorT,IteratorT>& Pair )
|
||||
{
|
||||
return iterator_range<IteratorT>( Pair.first, Pair.second );
|
||||
}
|
||||
|
||||
//! copy a range into a sequence
|
||||
/*!
|
||||
Construct a new sequence of the specified type from the elements
|
||||
in the given range
|
||||
|
||||
\param Range An input range
|
||||
\return New sequence
|
||||
*/
|
||||
template< typename SeqT, typename IteratorT >
|
||||
inline SeqT copy_iterator_range( const iterator_range<IteratorT>& Range )
|
||||
{
|
||||
return SeqT( Range.begin(), Range.end() );
|
||||
}
|
||||
|
||||
//! transform a range into a sequence
|
||||
/*!
|
||||
Create a new sequence from the elements in the range, transformed
|
||||
by a function
|
||||
|
||||
\param Range An input range
|
||||
\param Func Transformation function
|
||||
\return New sequence
|
||||
*/
|
||||
template< typename SeqT, typename IteratorT, typename FuncT >
|
||||
inline SeqT transform_iterator_range( const iterator_range<IteratorT>& Range, FuncT Func )
|
||||
{
|
||||
SeqT Seq;
|
||||
std::transform( Range.begin(), Range.end(), std::back_inserter(Seq), Func );
|
||||
return Seq;
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
|
||||
// pull names to the namespace boost
|
||||
using algorithm::iterator_range;
|
||||
using algorithm::make_iterator_range;
|
||||
using algorithm::copy_iterator_range;
|
||||
using algorithm::transform_iterator_range;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_STRING_ITERATOR_RANGE_HPP
|
@ -11,18 +11,24 @@
|
||||
#define BOOST_STRING_PREDICATE_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/find.hpp>
|
||||
#include <boost/algorithm/string/detail/predicate.hpp>
|
||||
|
||||
/*! \file boost/algorithm/string/predicate.hpp
|
||||
Defines string-related predicates.
|
||||
The predicates are resolving if a substring is contained in the input string
|
||||
under various conditions. If a string starts with the substring, ends with the
|
||||
The predicates determine whether a substring is contained in the input string
|
||||
under various conditions: a string starts with the substring, ends with the
|
||||
substring, simply contains the substring or if both strings are equal.
|
||||
In addition the algorithm \c all() checks all elements of a container to satisfy a
|
||||
Additionaly the algorithm \c all() checks all elements of a container to satisfy a
|
||||
condition.
|
||||
|
||||
All predicates provide the strong exception guarantee.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -32,24 +38,28 @@ namespace boost {
|
||||
|
||||
//! 'Starts with' predicate
|
||||
/*!
|
||||
This predicate holds when the test collection is a prefix of the Input.
|
||||
In other word, if the input starts with the test.
|
||||
This predicate holds when the test string is a prefix of the Input.
|
||||
In other words, if the input starts with the test.
|
||||
When the optional predicate is specified, it is used for character-wise
|
||||
comparison.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Comp An element comparison predicate
|
||||
\return A result of the test
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T, typename PredicateT>
|
||||
template<typename Range1T, typename Range2T, typename PredicateT>
|
||||
inline bool starts_with(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
PredicateT Comp)
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<Collection1T>::type Iterator1T;
|
||||
range_const_iterator<Range1T>::type Iterator1T;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<Collection2T>::type Iterator2T;
|
||||
range_const_iterator<Range2T>::type Iterator2T;
|
||||
|
||||
Iterator1T InputEnd=end(Input);
|
||||
Iterator2T TestEnd=end(Test);
|
||||
@ -69,36 +79,33 @@ namespace boost {
|
||||
|
||||
//! 'Starts with' predicate
|
||||
/*!
|
||||
This predicate holds when the test container is a prefix of the Input.
|
||||
In other words, if the input starts with the test.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\return A result of the test
|
||||
\overload
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool starts_with(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test)
|
||||
const Range1T& Input,
|
||||
const Range2T& Test)
|
||||
{
|
||||
return starts_with(Input, Test, is_equal());
|
||||
}
|
||||
|
||||
//! 'Starts with' predicate ( case insensitive )
|
||||
/*!
|
||||
This predicate holds when the test container is a prefix of the Input.
|
||||
In other word, if the input starts with the test.
|
||||
This predicate holds when the test string is a prefix of the Input.
|
||||
In other words, if the input starts with the test.
|
||||
Elements are compared case insensitively.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A result of the test
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool istarts_with(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return starts_with(Input, Test, is_iequal(Loc));
|
||||
@ -109,22 +116,27 @@ namespace boost {
|
||||
|
||||
//! 'Ends with' predicate
|
||||
/*!
|
||||
This predicate holds when the test container is a suffix of the Input.
|
||||
In other word, if the input ends with the test.
|
||||
This predicate holds when the test string is a suffix of the Input.
|
||||
In other words, if the input ends with the test.
|
||||
When the optional predicate is specified, it is used for character-wise
|
||||
comparison.
|
||||
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Comp An element comparison predicate
|
||||
\return A result of the test
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T, typename PredicateT>
|
||||
template<typename Range1T, typename Range2T, typename PredicateT>
|
||||
inline bool ends_with(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
PredicateT Comp)
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<Collection1T>::type Iterator1T;
|
||||
range_const_iterator<Range1T>::type Iterator1T;
|
||||
typedef BOOST_STRING_TYPENAME boost::detail::
|
||||
iterator_traits<Iterator1T>::iterator_category category;
|
||||
|
||||
@ -141,17 +153,12 @@ namespace boost {
|
||||
|
||||
//! 'Ends with' predicate
|
||||
/*!
|
||||
This predicate holds when the test container is a suffix of the Input.
|
||||
In other word, if the input ends with the test.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\return A result of the test
|
||||
\overload
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool ends_with(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test)
|
||||
const Range1T& Input,
|
||||
const Range2T& Test)
|
||||
{
|
||||
return ends_with(Input, Test, is_equal());
|
||||
}
|
||||
@ -159,18 +166,20 @@ namespace boost {
|
||||
//! 'Ends with' predicate ( case insensitive )
|
||||
/*!
|
||||
This predicate holds when the test container is a suffix of the Input.
|
||||
In other word, if the input ends with the test.
|
||||
In other words, if the input ends with the test.
|
||||
Elements are compared case insensitively.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A result of the test
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool iends_with(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return ends_with(Input, Test, is_iequal(Loc));
|
||||
@ -181,16 +190,20 @@ namespace boost {
|
||||
//! 'Contains' predicate
|
||||
/*!
|
||||
This predicate holds when the test container is contained in the Input.
|
||||
|
||||
When the optional predicate is specified, it is used for character-wise
|
||||
comparison.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Comp An element comparison predicate
|
||||
\return A result of the test
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T, typename PredicateT>
|
||||
template<typename Range1T, typename Range2T, typename PredicateT>
|
||||
inline bool contains(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
PredicateT Comp)
|
||||
{
|
||||
if (empty(Test))
|
||||
@ -199,21 +212,19 @@ namespace boost {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (first_finder(Test,Comp)(begin(Input), end(Input)));
|
||||
// Use the temporary variable to make VACPP happy
|
||||
bool bResult=(first_finder(Test,Comp)(begin(Input), end(Input)));
|
||||
return bResult;
|
||||
}
|
||||
|
||||
//! 'Contains' predicate
|
||||
/*!
|
||||
This predicate holds when the test container is contained in the Input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\return A result of the test
|
||||
\overload
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool contains(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test)
|
||||
const Range1T& Input,
|
||||
const Range2T& Test)
|
||||
{
|
||||
return contains(Input, Test, is_equal());
|
||||
}
|
||||
@ -225,13 +236,15 @@ namespace boost {
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A result of the test
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool icontains(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return contains(Input, Test, is_iequal(Loc));
|
||||
@ -243,22 +256,28 @@ namespace boost {
|
||||
/*!
|
||||
This predicate holds when the test container is equal to the
|
||||
input container i.e. all elements in both containers are same.
|
||||
|
||||
When the optional predicate is specified, it is used for character-wise
|
||||
comparison.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Comp An element comparison predicate
|
||||
\return A result of the test
|
||||
\return The result of the test
|
||||
|
||||
\note This is a two-way version of \c std::equal algorithm
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T, typename PredicateT>
|
||||
template<typename Range1T, typename Range2T, typename PredicateT>
|
||||
inline bool equals(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
PredicateT Comp)
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<Collection1T>::type Iterator1T;
|
||||
range_const_iterator<Range1T>::type Iterator1T;
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<Collection2T>::type Iterator2T;
|
||||
range_const_iterator<Range2T>::type Iterator2T;
|
||||
|
||||
Iterator1T InputEnd=end(Input);
|
||||
Iterator2T TestEnd=end(Test);
|
||||
@ -278,19 +297,12 @@ namespace boost {
|
||||
|
||||
//! 'Equals' predicate
|
||||
/*!
|
||||
This predicate holds when the test container is equal to the
|
||||
input container i.e. all elements in both containers are same.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\return A result of the test
|
||||
|
||||
\note This is two-way version of \c std::equal algorithm
|
||||
\overload
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool equals(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test)
|
||||
const Range1T& Input,
|
||||
const Range2T& Test)
|
||||
{
|
||||
return equals(Input, Test, is_equal());
|
||||
}
|
||||
@ -303,15 +315,17 @@ namespace boost {
|
||||
|
||||
\param Input An input sequence
|
||||
\param Test A test sequence
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\return A result of the test
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return The result of the test
|
||||
|
||||
\note This is two-way version of \c std::equal algorithm
|
||||
\note This is a two-way version of \c std::equal algorithm
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename Collection1T, typename Collection2T>
|
||||
template<typename Range1T, typename Range2T>
|
||||
inline bool iequals(
|
||||
const Collection1T& Input,
|
||||
const Collection2T& Test,
|
||||
const Range1T& Input,
|
||||
const Range2T& Test,
|
||||
const std::locale& Loc=std::locale())
|
||||
{
|
||||
return equals(Input, Test, is_iequal(Loc));
|
||||
@ -326,15 +340,17 @@ namespace boost {
|
||||
|
||||
\param Input An input sequence
|
||||
\param Pred A predicate
|
||||
\return A result of the test
|
||||
\return The result of the test
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename CollectionT, typename PredicateT>
|
||||
template<typename RangeT, typename PredicateT>
|
||||
inline bool all(
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
PredicateT Pred)
|
||||
{
|
||||
typedef BOOST_STRING_TYPENAME
|
||||
const_iterator_of<CollectionT>::type Iterator1T;
|
||||
range_const_iterator<RangeT>::type Iterator1T;
|
||||
|
||||
Iterator1T InputEnd=end(Input);
|
||||
for( Iterator1T It=begin(Input); It!=InputEnd; ++It)
|
||||
|
41
include/boost/algorithm/string/predicate_facade.hpp
Normal file
41
include/boost/algorithm/string/predicate_facade.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Boost string_algo library predicate_facade.hpp header file ---------------------------//
|
||||
|
||||
// Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_STRING_PREDICATE_FACADE_HPP
|
||||
#define BOOST_STRING_PREDICATE_FACADE_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
|
||||
/*
|
||||
\file boost/algorith/string/predicate_facade.hpp
|
||||
This file containes predicate_facade definition. This template class is used
|
||||
to identify classification predicates, so they can be combined using
|
||||
composition operators.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
// predicate facade ------------------------------------------------------//
|
||||
|
||||
//! Predicate facade
|
||||
/*!
|
||||
This class allows to recognize classification
|
||||
predicates, so that they can be combined using
|
||||
composition operators.
|
||||
Every classification predicate must be derived from this class.
|
||||
*/
|
||||
template<typename Derived>
|
||||
struct predicate_facade {};
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP
|
@ -12,15 +12,19 @@
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/result_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/find_format.hpp>
|
||||
#include <boost/algorithm/string/regex_find_format.hpp>
|
||||
#include <boost/algorithm/string/formatter.hpp>
|
||||
#include <boost/algorithm/string/iter_find.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines regex variant of the algorithms.
|
||||
Defines regex variants of the algorithms.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -30,26 +34,28 @@ namespace boost {
|
||||
|
||||
//! Find regex algorithm
|
||||
/*!
|
||||
Search for a subsequence matching the given regex in the input.
|
||||
Search for a substring matching the given regex in the input.
|
||||
|
||||
\param Input A container which will be searched.
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c InputContainerT::iterator or
|
||||
\c InputContainerT::const_iterator, depending on the constness of
|
||||
Returned iterator is either \c RangeT::iterator or
|
||||
\c RangeT::const_iterator, depending on the constness of
|
||||
the input parameter.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT>
|
||||
typename RegexTraitsT>
|
||||
inline iterator_range<
|
||||
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type >
|
||||
BOOST_STRING_TYPENAME range_result_iterator<RangeT>::type >
|
||||
find_regex(
|
||||
CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return regex_finder(Rx,Flags)(
|
||||
@ -60,26 +66,31 @@ namespace boost {
|
||||
|
||||
//! Replace regex algorithm
|
||||
/*!
|
||||
Search for a subsequence matching given regex and format it with
|
||||
the specified format. The result is copied to the given output iterator.
|
||||
Search for a substring matching given regex and format it with
|
||||
the specified format.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Format Regex format definition
|
||||
\param Flags Regex options
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT,
|
||||
typename RegexTraitsT,
|
||||
typename FormatStringTraitsT, typename FormatStringAllocatorT >
|
||||
inline OutputIteratorT replace_regex_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
|
||||
match_flag_type Flags=match_default | format_default )
|
||||
{
|
||||
@ -92,23 +103,16 @@ namespace boost {
|
||||
|
||||
//! Replace regex algorithm
|
||||
/*!
|
||||
Search for a subsequence matching given regex and format it with
|
||||
the specified format. The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Rx A regular expression
|
||||
\param Format Regex format definition
|
||||
\param Flags Regex options
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT,
|
||||
typename RegexTraitsT,
|
||||
typename FormatStringTraitsT, typename FormatStringAllocatorT >
|
||||
inline SequenceT replace_regex_copy(
|
||||
const SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
|
||||
match_flag_type Flags=match_default | format_default )
|
||||
{
|
||||
@ -120,10 +124,10 @@ namespace boost {
|
||||
|
||||
//! Replace regex algorithm
|
||||
/*!
|
||||
Search for a subsequence matching given regex and format it with
|
||||
the specified format. The input sequence is modified in-place.
|
||||
Search for a substring matching given regex and format it with
|
||||
the specified format. The input string is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Format Regex format definition
|
||||
\param Flags Regex options
|
||||
@ -131,11 +135,11 @@ namespace boost {
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT,
|
||||
typename RegexTraitsT,
|
||||
typename FormatStringTraitsT, typename FormatStringAllocatorT >
|
||||
inline void replace_regex(
|
||||
SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
|
||||
match_flag_type Flags=match_default | format_default )
|
||||
{
|
||||
@ -149,26 +153,30 @@ namespace boost {
|
||||
|
||||
//! Replace all regex algorithm
|
||||
/*!
|
||||
Format all subsequences, matching given regex, with the specified format.
|
||||
The result is copied to the given output iterator.
|
||||
Format all substrings, matching given regex, with the specified format.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Format Regex format definition
|
||||
\param Flags Regex options
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT,
|
||||
typename RegexTraitsT,
|
||||
typename FormatStringTraitsT, typename FormatStringAllocatorT >
|
||||
inline OutputIteratorT replace_all_regex_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
|
||||
match_flag_type Flags=match_default | format_default )
|
||||
{
|
||||
@ -181,23 +189,16 @@ namespace boost {
|
||||
|
||||
//! Replace all regex algorithm
|
||||
/*!
|
||||
Format all subsequences, mathing given regex, with the specified format.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Rx A regular expression
|
||||
\param Format Regex format definition
|
||||
\param Flags Regex options
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT,
|
||||
typename RegexTraitsT,
|
||||
typename FormatStringTraitsT, typename FormatStringAllocatorT >
|
||||
inline SequenceT replace_all_regex_copy(
|
||||
const SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
|
||||
match_flag_type Flags=match_default | format_default )
|
||||
{
|
||||
@ -209,22 +210,22 @@ namespace boost {
|
||||
|
||||
//! Replace all regex algorithm
|
||||
/*!
|
||||
Format all subsequences, matching given regex, with the specified format.
|
||||
The input sequence is modified in-place.
|
||||
Format all substrings, matching given regex, with the specified format.
|
||||
The input string is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Format Regex format definition
|
||||
\param Flags Regex options
|
||||
\param Flags Regex options
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT,
|
||||
typename RegexTraitsT,
|
||||
typename FormatStringTraitsT, typename FormatStringAllocatorT >
|
||||
inline void replace_all_regex(
|
||||
SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
|
||||
match_flag_type Flags=match_default | format_default )
|
||||
{
|
||||
@ -238,24 +239,28 @@ namespace boost {
|
||||
|
||||
//! Erase regex algorithm
|
||||
/*!
|
||||
Remove a subsequence matching given regex from the input.
|
||||
The result is copied to the given output iterator.
|
||||
Remove a substring matching given regex from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return An output iterator pointing just after last inserted character
|
||||
*/
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline OutputIteratorT erase_regex_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -267,21 +272,15 @@ namespace boost {
|
||||
|
||||
//! Erase regex algorithm
|
||||
/*!
|
||||
Remove a subsequence matching given regex from the input.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline SequenceT erase_regex_copy(
|
||||
const SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return find_format_copy(
|
||||
@ -292,20 +291,20 @@ namespace boost {
|
||||
|
||||
//! Erase regex algorithm
|
||||
/*!
|
||||
Remove a subsequence matching given regex from the input.
|
||||
The input sequence is modified in-place.
|
||||
Remove a substring matching given regex from the input.
|
||||
The input string is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline void erase_regex(
|
||||
SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
find_format(
|
||||
@ -318,24 +317,29 @@ namespace boost {
|
||||
|
||||
//! Erase all regex algorithm
|
||||
/*!
|
||||
Erase all subsequences, matching given regex, from the input.
|
||||
The result is copied to the given output iterator.
|
||||
Erase all substrings, matching given regex, from the input.
|
||||
The result is a modified copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator.
|
||||
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input sequence
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return An output iterator pointing just after the last inserted character or
|
||||
a modified copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename OutputIteratorT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline OutputIteratorT erase_all_regex_copy(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return find_format_all_copy(
|
||||
@ -347,21 +351,15 @@ namespace boost {
|
||||
|
||||
//! Erase all regex algorithm
|
||||
/*!
|
||||
Erase all subsequences, matching given regex, from the input.
|
||||
The result is a modified copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return A modified copy of the input
|
||||
\overload
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline SequenceT erase_all_regex_copy(
|
||||
const SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return find_format_all_copy(
|
||||
@ -372,20 +370,20 @@ namespace boost {
|
||||
|
||||
//! Erase all regex algorithm
|
||||
/*!
|
||||
Erase all subsequences, matching given regex, from the input.
|
||||
The input sequence is modified in-place.
|
||||
Erase all substrings, matching given regex, from the input.
|
||||
The input string is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Input An input string
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
*/
|
||||
template<
|
||||
typename SequenceT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT>
|
||||
typename RegexTraitsT>
|
||||
inline void erase_all_regex(
|
||||
SequenceT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
find_format_all(
|
||||
@ -399,33 +397,34 @@ namespace boost {
|
||||
//! Find all regex algorithm
|
||||
/*!
|
||||
This algorithm finds all substrings matching the give regex
|
||||
in the input. The result is given as a 'container of containers'.
|
||||
Each match of the search sequence is represented by one
|
||||
element in the result.
|
||||
in the input.
|
||||
|
||||
Each part is copied and added as a new element to the output container.
|
||||
Thus the result container must be able to hold copies
|
||||
of the matches (in a compatible structure like std::string) or
|
||||
a reference to it (e.g. using the iterator range class).
|
||||
Examples of such a container are \c std::vector<std::string>
|
||||
or \c std::list<boost::iterator_range<std::string::iterator>>
|
||||
|
||||
\param Result A 'container container' to container the result of search.
|
||||
Both outer and inner container must have constructor taking a pair
|
||||
of iterators as an argument.
|
||||
Typical type of the result is
|
||||
\c std::vector<boost::iterator_range<iterator>>.
|
||||
(each element of such a vector will container a range delimiting
|
||||
a match).
|
||||
\param Result A container that can hold copies of references to the substrings.
|
||||
\param Input A container which will be searched.
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return A reference to the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename SequenceSequenceT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline SequenceSequenceT& find_all_regex(
|
||||
SequenceSequenceT& Result,
|
||||
const CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return iter_find(
|
||||
@ -438,33 +437,35 @@ namespace boost {
|
||||
|
||||
//! Split regex algorithm
|
||||
/*!
|
||||
Tokenize expression. This function is equivalent of C strtok. Input
|
||||
Tokenize expression. This function is equivalent to C strtok. Input
|
||||
sequence is split into tokens, separated by separators. Separator
|
||||
is an every match of the given regex.
|
||||
|
||||
\param Result A 'container container' to container the result of search.
|
||||
Both outer and inner container must have constructor taking a pair
|
||||
of iterators as an argument.
|
||||
Typical type of the result is
|
||||
'c std::vector<boost::iterator_range<iterator>>.
|
||||
(each element of such a vector will container a range delimiting
|
||||
a match).
|
||||
Each part is copied and added as a new element to the output container.
|
||||
Thus the result container must be able to hold copies
|
||||
of the matches (in a compatible structure like std::string) or
|
||||
a reference to it (e.g. using the iterator range class).
|
||||
Examples of such a container are \c std::vector<std::string>
|
||||
or \c std::list<boost::iterator_range<std::string::iterator>>
|
||||
|
||||
\param Result A container that can hold copies of references to the substrings.
|
||||
\param Input A container which will be searched.
|
||||
\param Rx A regular expression
|
||||
\param Flags Regex options
|
||||
\return A reference to the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<
|
||||
typename SequenceSequenceT,
|
||||
typename CollectionT,
|
||||
typename RangeT,
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT >
|
||||
typename RegexTraitsT >
|
||||
inline SequenceSequenceT& split_regex(
|
||||
SequenceSequenceT& Result,
|
||||
const CollectionT& Input,
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const RangeT& Input,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type Flags=match_default )
|
||||
{
|
||||
return iter_split(
|
||||
|
@ -16,9 +16,9 @@
|
||||
#include <boost/algorithm/string/detail/formatter_regex.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines the \c refex_finder and \c regex_formatter generators. These two functors
|
||||
Defines the \c regex_finder and \c regex_formatter generators. These two functors
|
||||
are designed to work together. \c regex_formatter uses additional information
|
||||
about a match contained in the reger_finder search result.
|
||||
about a match contained in the regex_finder search result.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -28,7 +28,7 @@ namespace boost {
|
||||
|
||||
//! "Regex" finder
|
||||
/*!
|
||||
Construct the \c regex_finder. Finder uses regex engine to search
|
||||
Construct the \c regex_finder. Finder uses the regex engine to search
|
||||
for a match.
|
||||
Result is given in \c regex_search_result. This is an extension
|
||||
of the iterator_range. In addition it containes match results
|
||||
@ -40,22 +40,22 @@ namespace boost {
|
||||
*/
|
||||
template<
|
||||
typename CharT,
|
||||
typename RegexTraitsT, typename RegexAllocatorT>
|
||||
inline detail::find_regexF< reg_expression<CharT, RegexTraitsT, RegexAllocatorT> >
|
||||
typename RegexTraitsT>
|
||||
inline detail::find_regexF< basic_regex<CharT, RegexTraitsT> >
|
||||
regex_finder(
|
||||
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
|
||||
const basic_regex<CharT, RegexTraitsT>& Rx,
|
||||
match_flag_type MatchFlags=match_default )
|
||||
{
|
||||
return detail::
|
||||
find_regexF<
|
||||
reg_expression<CharT, RegexTraitsT, RegexAllocatorT> >( Rx, MatchFlags );
|
||||
basic_regex<CharT, RegexTraitsT> >( Rx, MatchFlags );
|
||||
}
|
||||
|
||||
// regex_formater ---------------------------------------------//
|
||||
|
||||
//! Regex formatter
|
||||
/*!
|
||||
Construct the \c regex_formatter. Regex formatter uses regex engine to
|
||||
Construct the \c regex_formatter. Regex formatter uses the regex engine to
|
||||
format a match found by the \c regex_finder.
|
||||
This formatted it designed to closely cooperate with \c regex_finder.
|
||||
|
||||
@ -78,6 +78,11 @@ namespace boost {
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
|
||||
// pull the names to the boost namespace
|
||||
using algorithm::regex_finder;
|
||||
using algorithm::regex_formatter;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,12 +22,12 @@
|
||||
For lacking compilers, it is possible of define an override for a specific tester
|
||||
function.
|
||||
|
||||
Due to language restriction, it is not currently possible to define specialization for
|
||||
stl containers without including the coresponding header. To decrease the overhead
|
||||
needed by this inclusion, user can selectively include specialization
|
||||
Due to a language restriction, it is not currently possible to define specializations for
|
||||
stl containers without including the corresponding header. To decrease the overhead
|
||||
needed by this inclusion, user can selectively include a specialization
|
||||
header for a specific container. They are located in boost/algorithm/string/stl
|
||||
directory. Alternatively she can include boost/algorithm/string/std_collection_traits.hpp
|
||||
header which contains specialization for all stl containers.
|
||||
header which contains specializations for all stl containers.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -39,7 +39,7 @@ namespace boost {
|
||||
|
||||
//! Native replace tester
|
||||
/*!
|
||||
Declare an override of this tester function with return
|
||||
Declare an override of this tester function with return
|
||||
type boost::string_algo::yes_type for a sequence with this property.
|
||||
|
||||
\return yes_type if the container has basic_string like native replace
|
||||
@ -49,31 +49,31 @@ namespace boost {
|
||||
|
||||
//! Stable iterators tester
|
||||
/*!
|
||||
Declare an override of this tester function with return
|
||||
Declare an override of this tester function with return
|
||||
type boost::string_algo::yes_type for a sequence with this property.
|
||||
|
||||
\return yes_type if the seqeunce's insert/replace/erase methods do not invalidate
|
||||
\return yes_type if the sequence's insert/replace/erase methods do not invalidate
|
||||
existing iterators.
|
||||
*/
|
||||
no_type has_stable_iterators_tester(...);
|
||||
no_type has_stable_iterators_tester(...);
|
||||
|
||||
//! const time insert tester
|
||||
/*!
|
||||
Declare an override of this tester function with return
|
||||
Declare an override of this tester function with return
|
||||
type boost::string_algo::yes_type for a sequence with this property.
|
||||
|
||||
\return yes_type if the sequence's insert method is working in constant time
|
||||
*/
|
||||
no_type has_const_time_insert_tester(...);
|
||||
no_type has_const_time_insert_tester(...);
|
||||
|
||||
//! const time erase tester
|
||||
/*!
|
||||
Declare an override of this tester function with return
|
||||
Declare an override of this tester function with return
|
||||
type boost::string_algo::yes_type for a sequence with this property.
|
||||
|
||||
\return yes_type if the sequence's erase method is working in constant time
|
||||
*/
|
||||
no_type has_const_time_erase_tester(...);
|
||||
no_type has_const_time_erase_tester(...);
|
||||
|
||||
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
@ -89,21 +89,25 @@ namespace boost {
|
||||
private:
|
||||
static T* t;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
sizeof(has_native_replace_tester(t))==sizeof(yes_type) ) );
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
public:
|
||||
public:
|
||||
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = false };
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
|
||||
typedef mpl::bool_<value> type;
|
||||
|
||||
typedef mpl::bool_<has_native_replace<T>::value> type;
|
||||
};
|
||||
|
||||
|
||||
//! Stable iterators trait
|
||||
/*!
|
||||
This trait specifies that the sequence has stable iterators. It means,
|
||||
This trait specifies that the sequence has stable iterators. It means
|
||||
that operations like insert/erase/replace do not invalidate iterators.
|
||||
*/
|
||||
template< typename T >
|
||||
@ -113,20 +117,24 @@ namespace boost {
|
||||
private:
|
||||
static T* t;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
sizeof(has_stable_iterators_tester(t))==sizeof(yes_type) ) );
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
public:
|
||||
public:
|
||||
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = false };
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
typedef mpl::bool_<value> type;
|
||||
typedef mpl::bool_<has_stable_iterators<T>::value> type;
|
||||
};
|
||||
|
||||
|
||||
//! Const time insert trait
|
||||
/*!
|
||||
This trait specifies that the sequence's insert method has
|
||||
This trait specifies that the sequence's insert method has
|
||||
constant time complexity.
|
||||
*/
|
||||
template< typename T >
|
||||
@ -136,20 +144,24 @@ namespace boost {
|
||||
private:
|
||||
static T* t;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
sizeof(has_const_time_insert_tester(t))==sizeof(yes_type) ) );
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
public:
|
||||
public:
|
||||
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = false };
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
typedef mpl::bool_<value> type;
|
||||
typedef mpl::bool_<has_const_time_insert<T>::value> type;
|
||||
};
|
||||
|
||||
|
||||
//! Const time erase trait
|
||||
/*!
|
||||
This trait specifies that the sequence's erase method has
|
||||
This trait specifies that the sequence's erase method has
|
||||
constant time complexity.
|
||||
*/
|
||||
template< typename T >
|
||||
@ -159,14 +171,18 @@ namespace boost {
|
||||
private:
|
||||
static T* t;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
BOOST_STATIC_CONSTANT(bool, value=(
|
||||
sizeof(has_const_time_erase_tester(t))==sizeof(yes_type) ) );
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
public:
|
||||
public:
|
||||
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = false };
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(bool, value=false);
|
||||
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
typedef mpl::bool_<value> type;
|
||||
typedef mpl::bool_<has_const_time_erase<T>::value> type;
|
||||
};
|
||||
|
||||
} // namespace algorithm
|
||||
|
@ -11,20 +11,23 @@
|
||||
#define BOOST_STRING_SPLIT_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
|
||||
#include <boost/algorithm/string/iter_find.hpp>
|
||||
#include <boost/algorithm/string/finder.hpp>
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
|
||||
/*! \file
|
||||
Defines basic split algorithms.
|
||||
Split algorithms can be used to divide a sequence
|
||||
into several parts according to a given criterium.
|
||||
Result is given as a 'container of containers' where
|
||||
elements are copies or references to extracted parts.
|
||||
This file contains some common specializations of generic
|
||||
algorithms contained in the file split2.hpp
|
||||
Split algorithms can be used to divide a string
|
||||
into several parts according to given criteria.
|
||||
|
||||
Each part is copied and added as a new element to the
|
||||
output container.
|
||||
Thus the result container must be able to hold copies
|
||||
of the matches (in a compatible structure like std::string) or
|
||||
a reference to it (e.g. using the iterator range class).
|
||||
Examples of such a container are \c std::vector<std::string>
|
||||
or \c std::list<boost::iterator_range<std::string::iterator>>
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
@ -34,29 +37,31 @@ namespace boost {
|
||||
|
||||
//! Find all algorithm
|
||||
/*!
|
||||
This algorithm finds all occurrences of the search sequence
|
||||
in the input. A result is given as a 'container of containers'.
|
||||
Each match of the search sequence is represented by one
|
||||
element in the result.
|
||||
This algorithm finds all occurrences of the search string
|
||||
in the input.
|
||||
|
||||
Each part is copied and added as a new element to the
|
||||
output container.
|
||||
Thus the result container must be able to hold copies
|
||||
of the matches (in a compatible structure like std::string) or
|
||||
a reference to it (e.g. using the iterator range class).
|
||||
Examples of such a container are \c std::vector<std::string>
|
||||
or \c std::list<boost::iterator_range<std::string::iterator>>
|
||||
|
||||
\param Result A 'container container' to container the result of search.
|
||||
Both outer and inner container must have constructor taking a pair
|
||||
of iterators as an argument.
|
||||
Typical type of the result is
|
||||
\c std::vector<boost::iterator_range<iterator>).
|
||||
(each element of such a vector will container a range delimiting
|
||||
a match).
|
||||
\param Result A container that can hold copies of references to the substrings
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Search A substring to be searched for.
|
||||
\return A reference the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template< typename SequenceSequenceT, typename Collection1T, typename Collection2T >
|
||||
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
|
||||
inline SequenceSequenceT& find_all(
|
||||
SequenceSequenceT& Result,
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search)
|
||||
Range1T& Input,
|
||||
const Range2T& Search)
|
||||
{
|
||||
return iter_find(
|
||||
Result,
|
||||
@ -66,30 +71,32 @@ namespace boost {
|
||||
|
||||
//! Find all algorithm ( case insensitive )
|
||||
/*!
|
||||
This algorithm finds all occurrences of the search sequence
|
||||
in the input. A result is given as a 'container of containers'.
|
||||
Each match of the search sequence is represented by one
|
||||
element in the result. Searching is case insensitive.
|
||||
This algorithm finds all occurrences of the search string
|
||||
in the input.
|
||||
Each part is copied and added as a new element to the
|
||||
output container. Thus the result container must be able to hold copies
|
||||
of the matches (in a compatible structure like std::string) or
|
||||
a reference to it (e.g. using the iterator range class).
|
||||
Examples of such a container are \c std::vector<std::string>
|
||||
or \c std::list<boost::iterator_range<std::string::iterator>>
|
||||
|
||||
\param Result A 'container container' to container the result of search.
|
||||
Both outer and inner container must have constructor taking a pair
|
||||
of iterators as an argument.
|
||||
Typical type of the result is
|
||||
\c std::vector<boost::iterator_range<iterator>>.
|
||||
(each element of such a vector will container a range delimiting
|
||||
a match).
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Result A container that can hold copies of references to the substrings
|
||||
\param Input A container which will be searched.
|
||||
\param Search A string to be searched for.
|
||||
\param Loc a locale used for case insensitive comparison
|
||||
\param Search A substring to be searched for.
|
||||
\param Loc A locale used for case insensitive comparison
|
||||
\return A reference the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template< typename SequenceSequenceT, typename Collection1T, typename Collection2T >
|
||||
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
|
||||
inline SequenceSequenceT& ifind_all(
|
||||
SequenceSequenceT& Result,
|
||||
Collection1T& Input,
|
||||
const Collection2T& Search,
|
||||
Range1T& Input,
|
||||
const Range2T& Search,
|
||||
const std::locale& Loc=std::locale() )
|
||||
{
|
||||
return iter_find(
|
||||
@ -103,18 +110,19 @@ namespace boost {
|
||||
|
||||
//! Split algorithm
|
||||
/*!
|
||||
Tokenize expression. This function is equivalent of C strtok. Input
|
||||
Tokenize expression. This function is equivalent to C strtok. Input
|
||||
sequence is split into tokens, separated by separators. Separators
|
||||
are given in the mean of predicate.
|
||||
|
||||
\param Result A 'container container' to container the result of search.
|
||||
Both outer and inner container must have constructor taking a pair
|
||||
of iterators as an argument.
|
||||
Typical type of the result is
|
||||
\c std::vector<boost::iterator_range<iterator>>.
|
||||
(each element of such a vector will container a range delimiting
|
||||
a match).
|
||||
are given by means of the predicate.
|
||||
|
||||
Each part is copied and added as a new element to the
|
||||
output container.
|
||||
Thus the result container must be able to hold copies
|
||||
of the matches (in a compatible structure like std::string) or
|
||||
a reference to it (e.g. using the iterator range class).
|
||||
Examples of such a container are \c std::vector<std::string>
|
||||
or \c std::list<boost::iterator_range<std::string::iterator>>
|
||||
|
||||
\param Result A container that can hold copies of references to the substrings
|
||||
\param Input A container which will be searched.
|
||||
\param Pred A predicate to identify separators. This predicate is
|
||||
supposed to return true if a given element is a separator.
|
||||
@ -123,12 +131,14 @@ namespace boost {
|
||||
delimit a token.
|
||||
\return A reference the result
|
||||
|
||||
\note Prior content of the result will be overridden.
|
||||
\note Prior content of the result will be overwritten.
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template< typename SequenceSequenceT, typename CollectionT, typename PredicateT >
|
||||
template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
|
||||
inline SequenceSequenceT& split(
|
||||
SequenceSequenceT& Result,
|
||||
CollectionT& Input,
|
||||
RangeT& Input,
|
||||
PredicateT Pred,
|
||||
token_compress_mode_type eCompress=token_compress_off )
|
||||
{
|
||||
|
@ -33,38 +33,50 @@ namespace boost {
|
||||
template<typename T, typename AllocT>
|
||||
yes_type has_const_time_erase_tester( const ::std::list<T,AllocT>* );
|
||||
|
||||
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
// stable iterators trait
|
||||
|
||||
// stable iterators trait
|
||||
template<typename T, typename AllocT>
|
||||
class has_stable_iterators< ::std::list<T,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<has_stable_iterators<T>::value> type;
|
||||
};
|
||||
|
||||
// const time insert trait
|
||||
// const time insert trait
|
||||
template<typename T, typename AllocT>
|
||||
class has_const_time_insert< ::std::list<T,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<has_const_time_insert<T>::value> type;
|
||||
};
|
||||
|
||||
// const time erase trait
|
||||
// const time erase trait
|
||||
template<typename T, typename AllocT>
|
||||
class has_const_time_erase< ::std::list<T,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<has_const_time_erase<T>::value> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace boost
|
||||
|
||||
|
@ -43,8 +43,12 @@ namespace boost {
|
||||
template<typename T, typename TraitsT, typename AllocT>
|
||||
class has_native_replace< std::rope<T,TraitsT,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
|
||||
@ -52,8 +56,12 @@ namespace boost {
|
||||
template<typename T, typename TraitsT, typename AllocT>
|
||||
class has_stable_iterators< std::rope<T,TraitsT,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
|
||||
@ -61,8 +69,12 @@ namespace boost {
|
||||
template<typename T, typename TraitsT, typename AllocT>
|
||||
class has_const_time_insert< std::rope<T,TraitsT,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
|
||||
@ -70,8 +82,12 @@ namespace boost {
|
||||
template<typename T, typename TraitsT, typename AllocT>
|
||||
class has_const_time_erase< std::rope<T,TraitsT,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
#endif
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef BOOST_STRING_STD_SLIST_TRAITS_HPP
|
||||
#define BOOST_STRING_STD_SLIST_TRAITS_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/yes_no_type.hpp>
|
||||
#include <slist>
|
||||
#include <boost/algorithm/string/sequence_traits.hpp>
|
||||
@ -23,43 +24,55 @@ namespace boost {
|
||||
|
||||
// stable iterators tester
|
||||
template<typename T, typename AllocT>
|
||||
yes_type has_stable_iterators_tester( const std::slist<T,AllocT>* );
|
||||
yes_type has_stable_iterators_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
|
||||
|
||||
// const time insert tester
|
||||
template<typename T, typename AllocT>
|
||||
yes_type has_const_time_insert_tester( const std::slist<T,AllocT>* );
|
||||
yes_type has_const_time_insert_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
|
||||
|
||||
// const time erase tester
|
||||
template<typename T, typename AllocT>
|
||||
yes_type has_const_time_erase_tester( const std::slist<T,AllocT>* );
|
||||
yes_type has_const_time_erase_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
|
||||
// stable iterators trait
|
||||
template<typename T, typename AllocT>
|
||||
class has_stable_iterators< std::slist<T,AllocT> >
|
||||
class has_stable_iterators< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<has_stable_iterators<T>::value> type;
|
||||
};
|
||||
|
||||
// const time insert trait
|
||||
template<typename T, typename AllocT>
|
||||
class has_const_time_insert< std::slist<T,AllocT> >
|
||||
class has_const_time_insert< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<has_const_time_insert<T>::value> type;
|
||||
};
|
||||
|
||||
// const time erase trait
|
||||
template<typename T, typename AllocT>
|
||||
class has_const_time_erase< std::slist<T,AllocT> >
|
||||
class has_const_time_erase< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true };
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
typedef mpl::bool_<has_const_time_erase<T>::value> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -31,9 +31,14 @@ namespace boost {
|
||||
template<typename T, typename TraitsT, typename AllocT>
|
||||
class has_native_replace< std::basic_string<T, TraitsT, AllocT> >
|
||||
{
|
||||
public:
|
||||
public:
|
||||
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
enum { value = true } ;
|
||||
#else
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
typedef mpl::bool_<value> type;
|
||||
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
|
||||
|
||||
typedef mpl::bool_<has_native_replace<T>::value> type;
|
||||
};
|
||||
|
||||
|
||||
|
@ -11,7 +11,11 @@
|
||||
#define BOOST_STRING_TRIM_HPP
|
||||
|
||||
#include <boost/algorithm/string/config.hpp>
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
|
||||
#include <boost/algorithm/string/detail/trim.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <locale>
|
||||
@ -21,10 +25,10 @@
|
||||
Trim algorithms are used to remove trailing and leading spaces from a
|
||||
sequence (string). Space is recognized using given locales.
|
||||
|
||||
Parametric (\c _if) variants use predicate (functor) to select which characters
|
||||
Parametric (\c _if) variants use a predicate (functor) to select which characters
|
||||
are to be trimmed..
|
||||
Functions take a selection predicate as a parameter, which is used to determine
|
||||
if a character is a space. Common predicates are provided in classification.hpp header.
|
||||
whether a character is a space. Common predicates are provided in classification.hpp header.
|
||||
|
||||
*/
|
||||
|
||||
@ -36,23 +40,28 @@ namespace boost {
|
||||
|
||||
//! Left trim - parametric
|
||||
/*!
|
||||
Remove all leading spaces from the input. Supplied predicate
|
||||
is used to determine which character is a space.
|
||||
The result is copied to the given output iterator.
|
||||
Remove all leading spaces from the input.
|
||||
The supplied predicate is used to determine which characters are considered spaces.
|
||||
The result is a trimmed copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input collection
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename OutputIteratorT, typename CollectionT, typename PredicateT>
|
||||
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
|
||||
inline OutputIteratorT trim_left_copy_if(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
PredicateT IsSpace)
|
||||
{
|
||||
std::copy(
|
||||
detail::trim_begin(
|
||||
::boost::algorithm::detail::trim_begin(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace ),
|
||||
@ -64,19 +73,13 @@ namespace boost {
|
||||
|
||||
//! Left trim - parametric
|
||||
/*!
|
||||
Remove all leading spaces from the input. Supplied predicate
|
||||
is used to determine which character is a space.
|
||||
The result is a trimmed copy if the input
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\return A trimmed copy if the input
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline SequenceT trim_left_copy_if(const SequenceT& Input, PredicateT IsSpace)
|
||||
{
|
||||
return SequenceT(
|
||||
detail::trim_begin(
|
||||
::boost::algorithm::detail::trim_begin(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace ),
|
||||
@ -86,11 +89,13 @@ namespace boost {
|
||||
//! Left trim - parametric
|
||||
/*!
|
||||
Remove all leading spaces from the input.
|
||||
The result is a trimmed copy if the input
|
||||
The result is a trimmed copy of the input.
|
||||
|
||||
\param Input An input sequence
|
||||
\param Loc a locale used for 'space' classification
|
||||
\return A trimmed copy if the input
|
||||
\return A trimmed copy of the input
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT trim_left_copy(const SequenceT& Input, const std::locale& Loc=std::locale())
|
||||
@ -103,8 +108,8 @@ namespace boost {
|
||||
|
||||
//! Left trim
|
||||
/*!
|
||||
Remove all leading spaces from the input. Supplied predicate
|
||||
is used to determine which character is a space.
|
||||
Remove all leading spaces from the input. The supplied predicate is
|
||||
used to determine which characters are considered spaces.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
@ -115,7 +120,7 @@ namespace boost {
|
||||
{
|
||||
Input.erase(
|
||||
begin(Input),
|
||||
detail::trim_begin(
|
||||
::boost::algorithm::detail::trim_begin(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace));
|
||||
@ -141,24 +146,29 @@ namespace boost {
|
||||
|
||||
//! Right trim - parametric
|
||||
/*!
|
||||
Remove all trailing spaces from the input. Supplied predicate
|
||||
is used to determine which character is a space.
|
||||
The result is copied to the given output iterator.
|
||||
Remove all trailing spaces from the input.
|
||||
The supplied predicate is used to determine which characters are considered spaces.
|
||||
The result is a trimmed copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input collection
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename OutputIteratorT, typename CollectionT, typename PredicateT>
|
||||
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
|
||||
inline OutputIteratorT trim_right_copy_if(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
PredicateT IsSpace )
|
||||
{
|
||||
std::copy(
|
||||
begin(Input),
|
||||
detail::trim_end(
|
||||
::boost::algorithm::detail::trim_end(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace ),
|
||||
@ -169,20 +179,14 @@ namespace boost {
|
||||
|
||||
//! Right trim - parametric
|
||||
/*!
|
||||
Remove all trailing spaces from the input. Supplied predicate
|
||||
is used to determine which character is a space.
|
||||
The result is a trimmed copy if the input
|
||||
|
||||
\param Input An input Sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\return A trimmed copy if the input
|
||||
*/
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline SequenceT trim_right_copy_if(const SequenceT& Input, PredicateT IsSpace)
|
||||
{
|
||||
return SequenceT(
|
||||
begin(Input),
|
||||
detail::trim_end(
|
||||
::boost::algorithm::detail::trim_end(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace)
|
||||
@ -192,12 +196,14 @@ namespace boost {
|
||||
//! Right trim
|
||||
/*!
|
||||
Remove all trailing spaces from the input.
|
||||
The result is a trimmed copy if the input
|
||||
The result is a trimmed copy of the input
|
||||
|
||||
\param Input An input sequence
|
||||
\param Loc A locale used for 'space' classification
|
||||
\return A trimmed copy if the input
|
||||
*/
|
||||
\return A trimmed copy of the input
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT trim_right_copy(const SequenceT& Input, const std::locale& Loc=std::locale())
|
||||
{
|
||||
@ -210,8 +216,8 @@ namespace boost {
|
||||
|
||||
//! Right trim - parametric
|
||||
/*!
|
||||
Remove all trailing spaces from the input. Supplied predicate
|
||||
is used to determine which character is a space.
|
||||
Remove all trailing spaces from the input.
|
||||
The supplied predicate is used to determine which characters are considered spaces.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
@ -221,7 +227,7 @@ namespace boost {
|
||||
inline void trim_right_if(SequenceT& Input, PredicateT IsSpace)
|
||||
{
|
||||
Input.erase(
|
||||
detail::trim_end(
|
||||
::boost::algorithm::detail::trim_end(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace ),
|
||||
@ -251,23 +257,28 @@ namespace boost {
|
||||
//! Trim - parametric
|
||||
/*!
|
||||
Remove all trailing and leading spaces from the input.
|
||||
Supplied predicate is used to determine which character is a space.
|
||||
The result is copied to the given output iterator.
|
||||
The supplied predicate is used to determine which characters are considered spaces.
|
||||
The result is a trimmed copy of the input. It is returned as a sequence
|
||||
or copied to the output iterator
|
||||
|
||||
\param Output A output iterator to which the result will be copied
|
||||
\param Input An input collection
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\return An output iterator pointing just after last inserted character
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
|
||||
\note The second variant of this function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename OutputIteratorT, typename CollectionT, typename PredicateT>
|
||||
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
|
||||
inline OutputIteratorT trim_copy_if(
|
||||
OutputIteratorT Output,
|
||||
const CollectionT& Input,
|
||||
const RangeT& Input,
|
||||
PredicateT IsSpace)
|
||||
{
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<CollectionT>::type TrimEnd=
|
||||
detail::trim_end(
|
||||
range_const_iterator<RangeT>::type TrimEnd=
|
||||
::boost::algorithm::detail::trim_end(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace);
|
||||
@ -284,20 +295,14 @@ namespace boost {
|
||||
|
||||
//! Trim - parametric
|
||||
/*!
|
||||
Remove all leading and trailing spaces from the input.
|
||||
Supplied predicate is used to determine which character is a space.
|
||||
The result is a trimmed copy if the input
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\return A trimmed copy if the input
|
||||
*/
|
||||
\overload
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline SequenceT trim_copy_if(const SequenceT& Input, PredicateT IsSpace)
|
||||
{
|
||||
BOOST_STRING_TYPENAME
|
||||
const_iterator_of<SequenceT>::type TrimEnd=
|
||||
detail::trim_end(
|
||||
range_const_iterator<SequenceT>::type TrimEnd=
|
||||
::boost::algorithm::detail::trim_end(
|
||||
begin(Input),
|
||||
end(Input),
|
||||
IsSpace);
|
||||
@ -314,11 +319,13 @@ namespace boost {
|
||||
//! Trim
|
||||
/*!
|
||||
Remove all leading and trailing spaces from the input.
|
||||
The result is a trimmed copy if the input
|
||||
The result is a trimmed copy of the input
|
||||
|
||||
\param Input An input sequence
|
||||
\param Loc A locale used for 'space' classification
|
||||
\return A trimmed copy if the input
|
||||
\return A trimmed copy of the input
|
||||
|
||||
\note This function provides the strong exception-safety guarantee
|
||||
*/
|
||||
template<typename SequenceT>
|
||||
inline SequenceT trim_copy( const SequenceT& Input, const std::locale& Loc=std::locale() )
|
||||
@ -332,7 +339,7 @@ namespace boost {
|
||||
//! Trim
|
||||
/*!
|
||||
Remove all leading and trailing spaces from the input.
|
||||
Supplied predicate is used to determine which character is a space.
|
||||
The supplied predicate is used to determine which characters are considered spaces.
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
|
@ -14,7 +14,7 @@ namespace boost {
|
||||
namespace algorithm {
|
||||
|
||||
// taken from boost mailing-list
|
||||
// when yes_no_type will become officialy
|
||||
// when yes_no_type will become officially
|
||||
// a part of boost distribution, this header
|
||||
// will be deprecated
|
||||
template<int I> struct size_descriptor
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Boost string_algo library string_algo.hpp header file ---------------------------//
|
||||
// Boost string_algo library string_regex.hpp header file ---------------------------//
|
||||
|
||||
// (C) Copyright Pavol Droba 2002-2003. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
// Copyright Pavol Droba 2002-2004. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
@ -12,11 +12,11 @@
|
||||
|
||||
/*! \file
|
||||
Cumulative include for string_algo library.
|
||||
In addtion to string_algo.hpp, it contains also regex-related stuff.
|
||||
In addtion to string.hpp contains also regex-related stuff.
|
||||
*/
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/string_algo.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
|
||||
#endif // BOOST_STRING_ALGO_REGEX_HPP
|
||||
|
@ -1,52 +0,0 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 February 2004
|
||||
Initial version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_MINMAX_HPP
|
||||
#define BOOST_MINMAX_HPP
|
||||
|
||||
#include <algorithm> // for std::min and std::max
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template< typename T >
|
||||
inline T const & std_min( T const & a, T const & b )
|
||||
{
|
||||
using std::min;
|
||||
|
||||
return min BOOST_PREVENT_MACRO_SUBSTITUTION ( a, b );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline T const & std_max( T const & a, T const & b )
|
||||
{
|
||||
using std::max;
|
||||
|
||||
return max BOOST_PREVENT_MACRO_SUBSTITUTION ( a, b );
|
||||
}
|
||||
|
||||
// Overloads for unsigned long to work around a bug in the Borland headers
|
||||
#ifdef __BORLANDC__
|
||||
inline unsigned long const & std_min( unsigned long const & a, unsigned long const & b )
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
inline unsigned long const & std_max( unsigned long const & a, unsigned long const & b )
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_MINMAX_HPP
|
524
minmax/doc/minmax_benchs.html
Normal file
524
minmax/doc/minmax_benchs.html
Normal file
@ -0,0 +1,524 @@
|
||||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
|
||||
<meta name="Author" content="Herve Bronnimann">
|
||||
<meta name="Description" content="Small library to propose minmax_element algorithm.">
|
||||
<title>Boost minmax library</title>
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
|
||||
|
||||
<center>
|
||||
<h1>
|
||||
Minmax_element Performance</h1></center>
|
||||
|
||||
<h3>
|
||||
<a NAME="Performance"></a><b>About performance</b></h3>
|
||||
Of course, there are many factors that affect the performance of an algorithm.
|
||||
The number of comparison is only one, but also branch prediction, pipelining,
|
||||
locality of reference (affects cache efficiency), etc. In practice,
|
||||
we observe that when the iterator type is a pointer,
|
||||
<tt>boost::minmax_element</tt>
|
||||
is only a tad slower than
|
||||
<tt>std::min_element</tt>, and is even faster
|
||||
than
|
||||
<tt>boost::first_min_last_max_element</tt>! This is even more true
|
||||
for slower iterators (<tt>list<>::iterator</tt> or
|
||||
<tt>map<>iterator</tt>
|
||||
for instance). The following experiments were conducted on a Pentium III
|
||||
500 Mhz running Linux and compiled with g++, version 2.95.2, flags -O3.
|
||||
In the tables, we use different distributions: <i>Identical</i> means that
|
||||
all the elements are identical, <i>2-valued</i> means that we replace the
|
||||
second half of the identical elements by a distinct element, <i>increasing</i>
|
||||
means that all the elements are distinct and in increasing order, <i>decrea</i>sing
|
||||
is the reverse, and <i>random</i> is produced by random_shuffle.
|
||||
<br>
|
||||
The program that created these tables is included in the distribution,
|
||||
under <a href="../example/minmax_timer.cpp">minmax_timer.cpp</a>
|
||||
<br>
|
||||
<center><table BORDER NOSAVE >
|
||||
<tr NOSAVE>
|
||||
<td NOSAVE><b>vector<int>::iterator</b></td>
|
||||
|
||||
<td>Identical</td>
|
||||
|
||||
<td>2-valued</td>
|
||||
|
||||
<td>Increasing</td>
|
||||
|
||||
<td>Decreasing</td>
|
||||
|
||||
<td>Random</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::min_element</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>22.94M/s</td>
|
||||
|
||||
<td>22.94M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::max_element</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>22.94M/s</td>
|
||||
|
||||
<td>22.62M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_min_element</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>23.04M/s</td>
|
||||
|
||||
<td>23.04M/s</td>
|
||||
|
||||
<td>22.94M/s</td>
|
||||
|
||||
<td>22.83M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_element</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>22.83M/s</td>
|
||||
|
||||
<td>16.23M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_max_element</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>23.04M/s</td>
|
||||
|
||||
<td>22.93M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_max_element</td>
|
||||
|
||||
<td>23.26M/s</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>23.15M/s</td>
|
||||
|
||||
<td>22.94M/s</td>
|
||||
|
||||
<td>16.18M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::minmax_element</td>
|
||||
|
||||
<td>21.83M/s</td>
|
||||
|
||||
<td>21.83M/s</td>
|
||||
|
||||
<td>21.83M/s</td>
|
||||
|
||||
<td>21.55M/s</td>
|
||||
|
||||
<td>17.79M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_min_last_max_element</td>
|
||||
|
||||
<td>18.52M/s</td>
|
||||
|
||||
<td>18.38M/s</td>
|
||||
|
||||
<td>18.38M/s</td>
|
||||
|
||||
<td>18.94M/s</td>
|
||||
|
||||
<td>16.29M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_first_max_element</td>
|
||||
|
||||
<td>20.08M/s</td>
|
||||
|
||||
<td>20.83M/s</td>
|
||||
|
||||
<td>20.75M/s</td>
|
||||
|
||||
<td>19.76M/s</td>
|
||||
|
||||
<td>15.87M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_last_max_element</td>
|
||||
|
||||
<td>18.66M/s</td>
|
||||
|
||||
<td>19.69M/s</td>
|
||||
|
||||
<td>19.69M/s</td>
|
||||
|
||||
<td>19.23M/s</td>
|
||||
|
||||
<td>15.77M/s</td>
|
||||
</tr>
|
||||
|
||||
<caption ALIGN=BOTTOM>Number of elements per second for standard vector
|
||||
container iterators</caption>
|
||||
</table></center>
|
||||
|
||||
<center><table BORDER NOSAVE >
|
||||
<tr NOSAVE>
|
||||
<td NOSAVE><b>list<int>::iterator</b></td>
|
||||
|
||||
<td>Identical</td>
|
||||
|
||||
<td>2-valued</td>
|
||||
|
||||
<td>Increasing</td>
|
||||
|
||||
<td>Decreasing</td>
|
||||
|
||||
<td>Random</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::min_element</td>
|
||||
|
||||
<td>5.8M/s</td>
|
||||
|
||||
<td>5.8M/s</td>
|
||||
|
||||
<td>5.80M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::max_element</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.78M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
|
||||
<td>5.75M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_min_element</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.79M/s</td>
|
||||
|
||||
<td>5.75M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_element</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.80M/s</td>
|
||||
|
||||
<td>5.79M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
|
||||
<td>5.03M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_max_element</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.80M/s</td>
|
||||
|
||||
<td>5.78M/s</td>
|
||||
|
||||
<td>5.74M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_max_element</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.80M/s</td>
|
||||
|
||||
<td>5.79M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
|
||||
<td>5.07M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::minmax_element</td>
|
||||
|
||||
<td>5.68M/s</td>
|
||||
|
||||
<td>5.80M/s</td>
|
||||
|
||||
<td>5.66M/s</td>
|
||||
|
||||
<td>5.74M/s</td>
|
||||
|
||||
<td>5.30M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_min_last_max_element</td>
|
||||
|
||||
<td>5.79M/s</td>
|
||||
|
||||
<td>5.81M/s</td>
|
||||
|
||||
<td>5.78M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
|
||||
<td>5.04M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_first_max_element</td>
|
||||
|
||||
<td>5.69M/s</td>
|
||||
|
||||
<td>5.79M/s</td>
|
||||
|
||||
<td>5.69M/s</td>
|
||||
|
||||
<td>5.73M/s</td>
|
||||
|
||||
<td>4.84M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_last_max_element</td>
|
||||
|
||||
<td>5.61M/s</td>
|
||||
|
||||
<td>5.79M/s</td>
|
||||
|
||||
<td>5.64M/s</td>
|
||||
|
||||
<td>5.74M/s</td>
|
||||
|
||||
<td>4.75M/s</td>
|
||||
</tr>
|
||||
|
||||
<caption ALIGN=BOTTOM>Runtimes for standard list container iterators</caption>
|
||||
</table></center>
|
||||
|
||||
<center><table BORDER NOSAVE >
|
||||
<tr NOSAVE>
|
||||
<td NOSAVE><b>multiset<int>::iterator</b></td>
|
||||
|
||||
<td>Identical</td>
|
||||
|
||||
<td>2-valued</td>
|
||||
|
||||
<td>Increasing</td>
|
||||
|
||||
<td>Decreasing</td>
|
||||
|
||||
<td>Random</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::min_element</td>
|
||||
|
||||
<td>4.03M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.02M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>2.97M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>std::max_element3.007M</td>
|
||||
|
||||
<td>4.02M/s</td>
|
||||
|
||||
<td>4.02M/s</td>
|
||||
|
||||
<td>4.01M/s</td>
|
||||
|
||||
<td>4.02M/s</td>
|
||||
|
||||
<td>2.96M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_min_element</td>
|
||||
|
||||
<td>4.01M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.03M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>3.01M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_element</td>
|
||||
|
||||
<td>4.03M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>3.00M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_max_element</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.06M/s</td>
|
||||
|
||||
<td>3.01M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_max_element</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>4.03M/s</td>
|
||||
|
||||
<td>4.04M/s</td>
|
||||
|
||||
<td>3.00M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::minmax_element</td>
|
||||
|
||||
<td>3.98M/s</td>
|
||||
|
||||
<td>3.99M/s</td>
|
||||
|
||||
<td>3.98M/s</td>
|
||||
|
||||
<td>3.99M/s</td>
|
||||
|
||||
<td>3.00M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::first_min_last_max_element</td>
|
||||
|
||||
<td>3.99M/s</td>
|
||||
|
||||
<td>3.98M/s</td>
|
||||
|
||||
<td>3.97M/s</td>
|
||||
|
||||
<td>3.99M/s</td>
|
||||
|
||||
<td>2.99M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_first_max_element</td>
|
||||
|
||||
<td>3.97M/s</td>
|
||||
|
||||
<td>3.98M/s</td>
|
||||
|
||||
<td>3.96M/s</td>
|
||||
|
||||
<td>3.98M/s</td>
|
||||
|
||||
<td>3.00M/s</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>boost::last_min_last_max_element</td>
|
||||
|
||||
<td>4.00M/s</td>
|
||||
|
||||
<td>4.00M/s</td>
|
||||
|
||||
<td>4.00M/s</td>
|
||||
|
||||
<td>4.02M/s</td>
|
||||
|
||||
<td>2.97M/s</td>
|
||||
</tr>
|
||||
|
||||
<caption ALIGN=BOTTOM>Runtimes for standard set/multiset container iterators</caption>
|
||||
</table></center>
|
||||
|
||||
<hr SIZE="6">
|
||||
<br>Last modified 2004-06-28
|
||||
<p><font face="Arial,Helvetica"><font size=-1>© Copyright Hervé
|
||||
Brönnimann, Polytechnic University, 2002--2004.
|
||||
Use, modification, and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</font></font>
|
||||
</body>
|
||||
</html>
|
127
minmax/doc/minmax_synopsis.html
Normal file
127
minmax/doc/minmax_synopsis.html
Normal file
@ -0,0 +1,127 @@
|
||||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
|
||||
<meta name="Author" content="Herve Bronnimann">
|
||||
<meta name="Description" content="Small library to propose minmax_element algorithm.">
|
||||
<title>Boost minmax library synopsis</title>
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
|
||||
|
||||
<center>
|
||||
<h1>
|
||||
Minmax_element complete synopsis</h1></center>
|
||||
|
||||
<h3>
|
||||
Synopsis of <tt><boost/algorithm/minmax.hpp></tt></h3>
|
||||
|
||||
<pre>#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
tuple<T const&, T const&> >
|
||||
minmax(const T& a, const T& b);
|
||||
|
||||
template <class T, class <a href="http://www.sgi.com/tech/stl/ BinaryPredicate.html">BinaryPredicate</a>>
|
||||
tuple<T const&, T const&> >
|
||||
minmax(const T& a, const T& b, BinaryPredicate comp);
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>
|
||||
Synopsis of <tt><boost/algorithm/minmax_element.hpp></tt></h3>
|
||||
|
||||
<pre>#include <utility> //for std::pair
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
minmax_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
minmax_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
// Variants
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
first_min_first_max_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
first_min_first_max_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
first_min_last_max_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
first_min_last_max_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
last_min_first_max_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
last_min_first_max_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
last_min_last_max_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
last_min_last_max_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
}</pre>
|
||||
|
||||
<hr SIZE="6">
|
||||
<br>Last modified 2002-07-01
|
||||
<p><font face="Arial,Helvetica"><font size=-1>© Copyright Hervé
|
||||
Brönnimann, Polytechnic University, 2002--2004.
|
||||
Use, modification, and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</font></font>
|
||||
</body>
|
||||
</html>
|
14
minmax/example/Jamfile
Normal file
14
minmax/example/Jamfile
Normal file
@ -0,0 +1,14 @@
|
||||
# Boost.Minmax Library Example Jamfile
|
||||
#
|
||||
# Copyright (C) 2002--2004, Herve Bronnimann
|
||||
#
|
||||
# Use, modification, and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
subproject libs/algorithm/minmax/example ;
|
||||
|
||||
exe minmax_ex : minmax_ex.cpp ;
|
||||
exe minmax_timer : minmax_timer.cpp ;
|
||||
|
36
minmax/example/minmax_ex.cpp
Normal file
36
minmax/example/minmax_ex.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// (C) Copyright Herve Bronnimann 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/algorithm/minmax.hpp>
|
||||
#include <boost/algorithm/minmax_element.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// Demonstrating minmax()
|
||||
boost::tuple<int const&, int const&> result1 = boost::minmax(1, 0);
|
||||
assert( result1.get<0>() == 0 );
|
||||
assert( result1.get<1>() == 1 );
|
||||
|
||||
|
||||
// Demonstrating minmax_element()
|
||||
list<int> L;
|
||||
typedef list<int>::const_iterator iterator;
|
||||
generate_n(front_inserter(L), 1000, rand);
|
||||
pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end());
|
||||
|
||||
cout << "The smallest element is " << *(result2.first) << endl;
|
||||
cout << "The largest element is " << *(result2.second) << endl;
|
||||
|
||||
assert( result2.first == std::min_element(L.begin(), L.end()) );
|
||||
assert( result2.second == std::max_element(L.begin(), L.end()) );
|
||||
}
|
212
minmax/example/minmax_timer.cpp
Normal file
212
minmax/example/minmax_timer.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
// (C) Copyright Herve Bronnimann 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
// What's the proper BOOST_ flag for <iomanip.h> vs <ios>
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/timer.hpp>
|
||||
#include <boost/algorithm/minmax.hpp>
|
||||
|
||||
template <class T1, class T2>
|
||||
void tie(std::pair<T1, T2> p, T1& min, T2& max)
|
||||
{
|
||||
min = p.first; max = p.second;
|
||||
}
|
||||
|
||||
template <class Value>
|
||||
struct less_count : std::less<Value> {
|
||||
less_count(less_count<Value> const& lc) : _M_counter(lc._M_counter) {}
|
||||
less_count(int& counter) : _M_counter(counter) {}
|
||||
bool operator()(Value const& a, Value const& b) const {
|
||||
++_M_counter;
|
||||
return std::less<Value>::operator()(a,b);
|
||||
}
|
||||
void reset() {
|
||||
_M_counter = 0;
|
||||
}
|
||||
private:
|
||||
int& _M_counter;
|
||||
};
|
||||
|
||||
inline int opt_min_count(int n) {
|
||||
return (n==0) ? 0 : n-1;
|
||||
}
|
||||
inline int opt_minmax_count(int n) {
|
||||
if (n < 2) return 0;
|
||||
if (n == 2) return 1;
|
||||
return (n%2 == 0) ? 3*(n/2)-1 : 3*(n/2)+1;
|
||||
}
|
||||
inline int opt_boost_minmax_count(int n) {
|
||||
if (n < 2) return 0;
|
||||
if (n == 2) return 1;
|
||||
return (n%2 == 0) ? 3*(n/2)-2 : 3*(n/2);
|
||||
}
|
||||
|
||||
int repeats = 10;
|
||||
|
||||
#define TIMER( n, cmd , cmdname ) \
|
||||
t.restart(); \
|
||||
for (int i=0; i<repeats; ++i) { cmd ; } \
|
||||
std::cout << " " << std::setprecision(4) \
|
||||
<< (double)n*repeats/t.elapsed()/1.0E6 \
|
||||
<< "M items/sec " << cmdname << "\n"
|
||||
|
||||
#define CTIMER( n, cmd , cmdname, count, opt ) \
|
||||
t.restart(); lc.reset(); \
|
||||
for (int i=0; i<repeats; ++i) { cmd ; } \
|
||||
std::cout << " " << std::setprecision(4) \
|
||||
<< (double)n*repeats/t.elapsed()/1.0E6 \
|
||||
<< "M items/sec " << cmdname \
|
||||
<< " ("<< (count)/repeats << " vs " << opt << ")\n"
|
||||
|
||||
template <class CIterator>
|
||||
void test_minmax_element(CIterator first, CIterator last, int n, char* name)
|
||||
{
|
||||
typedef typename std::iterator_traits<CIterator>::value_type vtype;
|
||||
boost::timer t;
|
||||
|
||||
std::cout << " ON " << name << " WITH OPERATOR<()\n";
|
||||
TIMER( n, std::min_element(first, last),
|
||||
"std::min_element" << name << "");
|
||||
TIMER( n, std::max_element(first, last),
|
||||
"std::max_element" << name << "");
|
||||
TIMER( n, boost::first_min_element(first, last),
|
||||
"boost::first_min_element" << name << "");
|
||||
TIMER( n, boost::last_min_element(first, last),
|
||||
"boost::last_min_element" << name << " ");
|
||||
TIMER( n, boost::first_max_element(first, last),
|
||||
"boost::first_max_element" << name << "");
|
||||
TIMER( n, boost::last_max_element(first, last),
|
||||
"boost::last_max_element" << name << " ");
|
||||
TIMER( n, boost::minmax_element(first, last),
|
||||
"boost::minmax_element" << name << " ");
|
||||
TIMER( n, boost::first_min_last_max_element(first, last),
|
||||
"boost::first_min_last_max_element" << name << "");
|
||||
TIMER( n, boost::last_min_first_max_element(first, last),
|
||||
"boost::last_min_first_max_element" << name << "");
|
||||
TIMER( n, boost::last_min_last_max_element(first, last),
|
||||
"boost::last_min_last_max_element" << name << " ");
|
||||
|
||||
#define pred std::bind2nd( std::greater<vtype>(), vtype(10) )
|
||||
TIMER( n, boost::min_element_if(first, last, pred),
|
||||
"boost::min_element_if" << name << "");
|
||||
TIMER( n, boost::max_element_if(first, last, pred),
|
||||
"boost::max_element_if" << name << "");
|
||||
TIMER( n, std::min_element(boost::make_filter_iterator(first, last, pred),
|
||||
boost::make_filter_iterator(last, last, pred)),
|
||||
"std::min_element_with_filter_iterator" << name << "");
|
||||
TIMER( n, std::max_element(boost::make_filter_iterator(first, last, pred),
|
||||
boost::make_filter_iterator(last, last, pred)),
|
||||
"std::max_element_if_with_filter_iterator" << name << "");
|
||||
#undef pred
|
||||
|
||||
int counter = 0;
|
||||
less_count<vtype> lc(counter);
|
||||
std::cout << " ON " << name << " WITH LESS<> AND COUNTING COMPARISONS\n";
|
||||
CTIMER( n, std::min_element(first, last, lc),
|
||||
"std::min_element" << name << " ",
|
||||
counter, opt_min_count(n) );
|
||||
CTIMER( n, std::max_element(first, last, lc),
|
||||
"std::max_element" << name << " ",
|
||||
counter, opt_min_count(n) );
|
||||
CTIMER( n, boost::first_min_element(first, last, lc),
|
||||
"boost::first_min_element" << name << "",
|
||||
counter, opt_min_count(n) );
|
||||
CTIMER( n, boost::last_min_element(first, last, lc),
|
||||
"boost::last_max_element" << name << " ",
|
||||
counter, opt_min_count(n) );
|
||||
CTIMER( n, boost::first_max_element(first, last, lc),
|
||||
"boost::first_min_element" << name << "",
|
||||
counter, opt_min_count(n) );
|
||||
CTIMER( n, boost::last_max_element(first, last, lc),
|
||||
"boost::last_max_element" << name << " ",
|
||||
counter, opt_min_count(n) );
|
||||
CTIMER( n, boost::minmax_element(first, last, lc),
|
||||
"boost::minmax_element" << name << " ",
|
||||
counter, opt_minmax_count(n) );
|
||||
CTIMER( n, boost::first_min_last_max_element(first, last, lc),
|
||||
"boost::first_min_last_max_element" << name << "",
|
||||
counter, opt_boost_minmax_count(n) );
|
||||
CTIMER( n, boost::last_min_first_max_element(first, last, lc),
|
||||
"boost::last_min_first_max_element" << name << "",
|
||||
counter, opt_boost_minmax_count(n) );
|
||||
CTIMER( n, boost::last_min_last_max_element(first, last, lc),
|
||||
"boost::last_min_last_max_element" << name << " ",
|
||||
counter, opt_minmax_count(n) );
|
||||
}
|
||||
|
||||
template <class Container, class Iterator, class Value>
|
||||
void test_container(Iterator first, Iterator last, int n, char* name)
|
||||
{
|
||||
Container c(first, last);
|
||||
typename Container::iterator fit(c.begin()), lit(c.end());
|
||||
test_minmax_element(fit, lit, n, name);
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
void test_range(Iterator first, Iterator last, int n)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type Value;
|
||||
// Test various containers with these values
|
||||
test_container< std::vector<Value>, Iterator, Value >(first, last, n, "<vector>");
|
||||
#ifndef ONLY_VECTOR
|
||||
test_container< std::list<Value>, Iterator, Value >(first, last, n, "<list> ");
|
||||
test_container< std::multiset<Value>, Iterator, Value >(first, last, n, "<set> ");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Value>
|
||||
void test(int n)
|
||||
{
|
||||
// Populate test vector with identical values
|
||||
std::cout << "IDENTICAL VALUES... \n";
|
||||
std::vector<Value> test_vector(n, Value(1));
|
||||
typename std::vector<Value>::iterator first( test_vector.begin() );
|
||||
typename std::vector<Value>::iterator last( test_vector.end() );
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with two values
|
||||
std::cout << "TWO DISTINCT VALUES...\n";
|
||||
typename std::vector<Value>::iterator middle( first + n/2 );
|
||||
std::fill(middle, last, Value(2));
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with increasing values
|
||||
std::cout << "INCREASING VALUES... \n";
|
||||
std::fill(first, last, Value(1));
|
||||
std::accumulate(first, last, Value(0));
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with decreasing values
|
||||
std::cout << "DECREASING VALUES... \n";
|
||||
std::reverse(first, last);
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with random values
|
||||
std::cout << "RANDOM VALUES... \n";
|
||||
std::random_shuffle(first, last);
|
||||
test_range(first, last, n);
|
||||
}
|
||||
|
||||
int
|
||||
main(char argc, char** argv)
|
||||
{
|
||||
int n = 100;
|
||||
if (argc > 1) n = atoi(argv[1]);
|
||||
if (argc > 2) repeats = atoi(argv[2]);
|
||||
|
||||
test<int>(n);
|
||||
|
||||
return 0;
|
||||
}
|
528
minmax/index.html
Normal file
528
minmax/index.html
Normal file
@ -0,0 +1,528 @@
|
||||
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css">
|
||||
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<META name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
|
||||
<META name="Author" content="Herve Bronnimann">
|
||||
<META name="Description" content="Small library to propose minmax_element algorithm.">
|
||||
<title>Boost Minmax library</title>
|
||||
</HEAD>
|
||||
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
|
||||
|
||||
<h2><img src="../../../boost.png" WIDTH="276" HEIGHT="86">Header <<A
|
||||
HREF="../../../boost/algorithm/minmax.hpp">boost/algorithm/minmax.hpp</A>> </H2>
|
||||
|
||||
<quote>
|
||||
<b>
|
||||
<a href="#minmax_element">Motivation</a><br>
|
||||
<a href="#synopsis">Synopsis</a><br>
|
||||
<a href="#description">Function templates description</a><br>
|
||||
<a href="#definition">Definition</a><br>
|
||||
<a href="#reqs">Requirements on types</a><br>
|
||||
<a href="#precond">Preconditions</a><br>
|
||||
<a href="#postcond">Postconditions</a><br>
|
||||
<a href="#complexity">Complexity</a><br>
|
||||
<a href="#example">Example</a><br>
|
||||
<a href="#notes">Notes</a><br>
|
||||
<a href="#rationale">Rationale</a><br>
|
||||
<a href="#perf">Note about performance</a><br>
|
||||
<a href="#acks">Acknowledgements</a>
|
||||
</b>
|
||||
</quote>
|
||||
|
||||
|
||||
<a name="minmax_element">
|
||||
<h3>
|
||||
Motivation</h3>
|
||||
|
||||
<p>The minmax library is composed of two headers, <a
|
||||
href="../../../boost/algorithm/minmax.hpp"><boost/algorithm/minmax.hpp></a>
|
||||
and <a
|
||||
href="../../../boost/algorithm/minmax_element.hpp"><boost/algorithm/minmax_element.hpp></a>.
|
||||
(See <a href="#two_headers">rationale</a>.)
|
||||
The problem solved by this library is that simultaneous min and max
|
||||
computation requires
|
||||
only one comparison, but using <tt>std::min</tt> and <tt>std::max</tt>
|
||||
forces two comparisons. Worse, to compute the minimum and
|
||||
maximum elements of a range of <tt>n</tt> elements requires only
|
||||
<tt>3n/2+1</tt> comparisons, instead of the <tt>2n</tt> (in two passes)
|
||||
forced by <tt>std::min_element</tt> and <tt>std::max_element</tt>.
|
||||
I always thought it is a waste to have to call two functions to compute the
|
||||
extent of a range, performing two passes over the input, when one should
|
||||
be enough. The present library solves both problems.</p>
|
||||
|
||||
<p>The first file implements the function templates
|
||||
<tt>minmax</tt>
|
||||
as straightforward extensions of the C++
|
||||
standard. As it returns a pair of <tt>const&</tt>, we must use the <a
|
||||
href=:../../../../tuple/index.html>Boost.tuple</a> library to construct such
|
||||
pairs. (Please note: the intent is not to fix the known defaults of
|
||||
<tt>std::min</tt>
|
||||
and <tt>std::max</tt>, but to add one more algorithms that combines both; see the
|
||||
<a href="#no-fix">rationale</a>.)</p>
|
||||
|
||||
<p>The second file implements the function templates
|
||||
<tt>minmax_element</tt>. In a
|
||||
second part, it also proposes variants that can usually not be computed by
|
||||
the minmax algorithm, and which are more flexible in case some elements are equal.
|
||||
Those variants could have been also provided with policy-based design,
|
||||
but I ruled against that (see <a href="#no-policy">rationale</a>).
|
||||
</p>
|
||||
|
||||
<p>If you are interested about
|
||||
<a href="doc/minmax_benchs.html">performance</a>,
|
||||
you will see that <tt>minmax_element</tt> is just slightly less efficient
|
||||
than a single <tt>min_element</tt> or <tt>max_element</tt>, and thus
|
||||
twice as efficient as two separate calls to <tt>min_element</tt> and
|
||||
<tt>max_element</tt>. From a
|
||||
theoretical standpoint,
|
||||
all the <tt>minmax_element</tt> functions perform at most
|
||||
<tt>3n/2+1</tt>
|
||||
comparisons and exactly n increments of the
|
||||
<tt>ForwardIterator</tt>.</p>
|
||||
</a>
|
||||
|
||||
<a name="synopsis">
|
||||
<h3>
|
||||
Synopsis of <tt><boost/algorithm/minmax.hpp></tt></h3>
|
||||
|
||||
<pre>#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
tuple<T const&, T const&> >
|
||||
minmax(const T& a, const T& b);
|
||||
|
||||
template <class T, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
tuple<T const&, T const&> >
|
||||
minmax(const T& a, const T& b, BinaryPredicate comp);
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>
|
||||
Synopsis of <tt><boost/algorithm/minmax_element.hpp></tt></h3>
|
||||
|
||||
<pre>#include <utility> // for std::pair
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
minmax_element(ForwardIterator first, ForwardIterator last);
|
||||
|
||||
template <class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
|
||||
std::pair<ForwardIterator,ForwardIterator>
|
||||
minmax_element(ForwardIterator first, ForwardIterator last,
|
||||
BinaryPredicate comp);
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
In addition, there are a bunch of extensions which specify
|
||||
which element(s) you want to pick in case of equal elements. They are:
|
||||
<ul>
|
||||
<li><tt>first_min_element</tt> and <tt>last_min_element</tt></li>
|
||||
<li><tt>first_max_element</tt> and <tt>last_max_element</tt></li>
|
||||
<li><tt>first_min_first_max_element</tt>,
|
||||
<tt>first_min_last_max_element</tt>,
|
||||
<tt>last_min_first_max_element</tt>, and
|
||||
<tt>last_min_last_max_element</tt></li>
|
||||
</ul>
|
||||
I won't bore you with the complete synopsis, they have exactly the same
|
||||
declaration as their corresponding <tt>_element</tt> function. Still,
|
||||
you can find the complete synopsis <a href="doc/minmax_synopsis.html">here</a>.
|
||||
</a>
|
||||
|
||||
<a name="description">
|
||||
<h3>
|
||||
Function templates description</h3>
|
||||
The <tt>minmax</tt> algorithm returns a pair <tt>p</tt> containing either
|
||||
<i>(a,b)</i>
|
||||
or <i>(b,a)</i>, such that <tt>p.first<p.second</tt> in the first version,
|
||||
or <tt>comp(p.first,p.second)</tt> in the second version. If the elements
|
||||
are equivalent, the pair <i>(a,b) </i>is returned. <a href="#Note1">[1]</a>
|
||||
<p>The <tt>minmax_element </tt>is semantically equivalent to <tt>first_min_first_max_element</tt>.
|
||||
<p><tt>First_min_element</tt> and <tt>first_max_element</tt> find the smallest
|
||||
and largest elements in the range <tt>[first, last)</tt>. If there are
|
||||
several instance of these elements, the first one is returned. They are
|
||||
identical to
|
||||
<tt>std::min_element</tt> and <tt>std::max_element</tt>and
|
||||
are only included in this library for symmetry.
|
||||
<p><tt>Last_min_element</tt> and <tt>last_max_element</tt> find the smallest
|
||||
and largest elements in the range <tt>[first, last)</tt>. They are almost
|
||||
identical to
|
||||
<tt>std::min_element</tt> and <tt>std::max_element</tt>, except
|
||||
that they return the last instance of the largest element (and not the
|
||||
first, as <tt>first_min_element</tt> and <tt>last_max_element</tt> would).
|
||||
<p>The family of algorithms comprising <tt>first_min_first_max_element</tt>,
|
||||
<tt>first_min_first_max_element</tt>,
|
||||
<tt>first_min_first_max_element</tt>,
|
||||
and <tt>first_min_first_max_element</tt> can be described generically as
|
||||
follows (using <i><tt>which</tt></i> and
|
||||
<i><tt>what</tt></i> for <tt>first</tt>
|
||||
or <tt>last</tt>): <tt><i>which</i>_min_<i>what</i>_max_element</tt> finds
|
||||
the (first or last, according to <i><tt>which</tt></i>) smallest element
|
||||
and the (first or last, according to <i><tt>what</tt></i>) largest element
|
||||
in the range
|
||||
<tt>[first, last)</tt>. The first version is semantically
|
||||
equivalent to:
|
||||
<pre><tt> std::make_pair(boost::<i>which</i>_min_element(first,last),
|
||||
boost::<i>what</i>_max_element(first,last))</tt>,</pre>
|
||||
and the second version to:
|
||||
<pre><tt> std::make_pair(boost::<i>which</i>_min_element(first,last,comp),
|
||||
boost::<i>what</i>_max_element(first,last,comp))</tt>.</pre>
|
||||
|
||||
<p><br><b><i>Note</i></b>: the <tt>first_min_last_max_element</tt> can also be described
|
||||
as finding the first and last elements in the range if it were stably sorted.
|
||||
</a>
|
||||
|
||||
<a name="definition">
|
||||
<h3>
|
||||
Definition</h3>
|
||||
Defined in <a href="../../../boost/algorithm/minmax.hpp">minmax.hpp</a>
|
||||
and
|
||||
in <a href="../../../boost/algorithm/minmax_element.hpp">minmax_element.hpp</a>.
|
||||
</a>
|
||||
|
||||
<a name="reqs">
|
||||
<h3>
|
||||
Requirements on types</h3>
|
||||
For minmax, <tt>T</tt> must be a model of <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
|
||||
Comparable</a>.
|
||||
<p>For all the other function templates, versions with two template parameters:
|
||||
<ul>
|
||||
<li>
|
||||
<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
|
||||
Iterator</a>.</li>
|
||||
|
||||
<li>
|
||||
<tt>ForwardIterator</tt>'s value type is <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
|
||||
Comparable</a>.</li>
|
||||
</ul>
|
||||
For the versions with three template parameters:
|
||||
<ul>
|
||||
<li>
|
||||
<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
|
||||
Iterator</a>.</li>
|
||||
|
||||
<li>
|
||||
<tt>BinaryPredicate</tt> is a model of <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary
|
||||
Predicate</a>.</li>
|
||||
|
||||
<li>
|
||||
<tt>ForwardIterator</tt>'s value type is convertible to <tt>BinaryPredicate</tt>'s
|
||||
first argument type and second argument type.</li>
|
||||
</ul>
|
||||
</a>
|
||||
|
||||
<a name="precond">
|
||||
<h3>
|
||||
Preconditions</h3>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<tt>[first, last)</tt> is a valid range.</li>
|
||||
</ul>
|
||||
</a>
|
||||
|
||||
<a name="postcond">
|
||||
<h3>
|
||||
Postconditions</h3>
|
||||
In addition to the semantic description above. for <tt>minmax_element</tt>
|
||||
and all the <tt><i>which</i>_min_<i>what</i>_max_element</tt>
|
||||
variants, the return value is
|
||||
<tt>last</tt> or <tt>std::make_pair(last,last)</tt>
|
||||
if and only if <tt>[first, last)</tt> is an empty range. Otherwise, the
|
||||
return value or both members of the resulting pair are iterators in the
|
||||
range
|
||||
<tt>[first, last)</tt>.
|
||||
</a>
|
||||
|
||||
<a name="complexity">
|
||||
<h3>
|
||||
<a NAME="Complexity"></a>Complexity</h3>
|
||||
Minmax performs a single comparison and is otherwise of constant complexity.
|
||||
The use of <tt>boost::tuple<T const&></tt> prevents copy
|
||||
constructors in case the arguments are passed by reference.
|
||||
<p>The complexity of all the other algorithms is linear. They all perform
|
||||
exactly n increment operations, and zero comparisons if <tt>[first,last)</tt>
|
||||
is empty, otherwise :
|
||||
<ul>
|
||||
<li>
|
||||
all the <tt>min_element</tt> and <tt>max_element</tt> variants perform
|
||||
exactly<tt>(n-1)</tt> comparisons,</li>
|
||||
|
||||
<li>
|
||||
<tt>minmax_element</tt> , <tt>first_min_first_max_element</tt>, and <tt>last_min_last_max_element</tt>
|
||||
perform at most <tt>3(n/2)-1</tt> comparisons if <tt>n</tt> is even and
|
||||
non-zero, and at most <tt>3(n/2)+1</tt> if <tt>n</tt> is odd,
|
||||
<a href="#Note2">[2]</a></li>
|
||||
|
||||
<li>
|
||||
<tt>first_min_last_max_element</tt>, and <tt>last_min_first_max_element</tt>
|
||||
perform exactly <tt>3n/2-2</tt> comparisons if n is even and non-zero,
|
||||
and at most <tt>3(n/2)</tt> if <tt>n</tt> is odd,
|
||||
<a href="#Note1">[3]</a></li>
|
||||
</ul>
|
||||
where <tt>n</tt> is the number of elements in <tt>[first,last)</tt>.
|
||||
</a>
|
||||
|
||||
<a name="example">
|
||||
<h3>
|
||||
Example</h3>
|
||||
This example is included in the distribution in the examples section of
|
||||
the library under
|
||||
<a href="example/minmax_ex.cpp">minmax_ex.cpp</a>.
|
||||
|
||||
<pre>int main()
|
||||
{
|
||||
using namespace std;
|
||||
boost::tuple<int const&, int const&> result1 = boost::minmax(1, 0);
|
||||
|
||||
assert( result1.get<0>() == 0 );
|
||||
assert( result1.get<1>() == 1 );
|
||||
|
||||
<a href="http://www.sgi.com/tech/stl/List.html">list</a><int> L;
|
||||
<a href="http://www.sgi.com/tech/stl/generate_n.html">generate_n</a>(<a href="http://www.sgi.com/tech/stl/front_insert_iterator.html">front_inserter</a>(L), 1000, rand);
|
||||
|
||||
typedef list<int>::const_iterator iterator;
|
||||
pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end());
|
||||
cout << "The smallest element is " << *(result2.first) << endl;
|
||||
cout << "The largest element is " << *(result2.second) << endl;
|
||||
|
||||
assert( result2.first == std::min_element(L.begin(), L.end());
|
||||
assert( result2.second == std::max_element(L.begin(), L.end());
|
||||
}</pre>
|
||||
</a>
|
||||
|
||||
<a name="notes">
|
||||
<h3>
|
||||
Notes</h3>
|
||||
<a NAME="Note1"></a><a href="#Note1">[1]</a> We do not support
|
||||
idioms such as <tt><a href="../../tuple/doc/tuple_users_guide.html#tiers">tie</a>(a,b)=minmax(a,b)</tt>
|
||||
to order two elements <tt>a</tt>, <tt>b</tt>, although this would have
|
||||
the desired effect if we returned a reference instead of a constant
|
||||
reference. The reason is that two unnecessary assignments are
|
||||
performed if a and b are in order. It is better to stick to <tt>if (b<a)
|
||||
swap(a,b)</tt> to achieve that effect.
|
||||
<p><a NAME="Note2"></a><a href="#Note2">[2]</a> These algorithms always
|
||||
perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
|
||||
the number of comparisons in any case (Cormen, Leiserson, Rivest: "Introduction
|
||||
to Algorithms", section 9.1, Exercise 9.1-). The algorithms essentially compare
|
||||
the elements in pairs, performing 1 comparison for the first two elements,
|
||||
then 3 comparisons for each remaining pair of elements (one to order the
|
||||
elements and one for updating each the minimum and and the maximum). When
|
||||
the number of elements is odd, the last one needs to be compared to the
|
||||
current minimum and also to the current maximum. In addition, for <tt>minmax</tt>,
|
||||
in cases where equality of the two members in the pair could occur, and
|
||||
the update stores the second, we save the first to check at the end if
|
||||
the update should have stored the first (in case of equality). It's hard
|
||||
to predict if the last comparison is performed or not, hence the at most
|
||||
in both cases.
|
||||
<p><a NAME="Note3"></a><a href="#Note3">[3]</a> These algorithms always
|
||||
perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
|
||||
the number of comparisons in any case. The method is the same as in note
|
||||
<a href="#Note2">[2]</a>
|
||||
above, and like above, when the number of elements is odd, the last one
|
||||
needs to be compared to the current minimum and also to the current maximum.
|
||||
We can avoid the latter comparison if the former is successful, hence the
|
||||
<i>at
|
||||
most</i> instead of <i>exactly</i> in the odd case.
|
||||
</a>
|
||||
|
||||
<a name="rationale">
|
||||
<h3>
|
||||
<b>Rationale:</b></h3>
|
||||
|
||||
<a name="two_headers">
|
||||
<h4><b>Why not a single header <tt>&boost/algorithm/minmax.hpp></tt>?</b></h4>
|
||||
<p>This was the design originally proposed and approved in the formal
|
||||
review. As the need for Boost.tuple became clear (due to the limitations
|
||||
of <tt>std::pair</tt>), it became also annoying to require another
|
||||
library for <tt>minmax_element</tt> which does not need it. Hence the
|
||||
separation into two header files.</p>
|
||||
|
||||
<a name="no-fix">
|
||||
<h4><b>Your minmax suffers from the same problems as std::min and
|
||||
std::max.</b></h4>
|
||||
<p>I am aware of the problems with std::min and
|
||||
std::max, and all the debate that has been going on (please consult
|
||||
<a href="http://www.cuj.com/experts/1904/alexandr.htm?topic=experts&topic=experts">Alexandrescu's
|
||||
paper</a> and the links therein). But I don't see the purpose of this
|
||||
library as fixing something that is part of the C++ standard. I humbly
|
||||
think it's beyond the scope of this library. Rather, I am
|
||||
following the way of the standard in simply providing one more function
|
||||
of the same family. If someone else wants to fix std::min, their fix
|
||||
would probably apply to boost::minmax as well.</p>
|
||||
</a>
|
||||
|
||||
<h4><b>Why no <tt>min/max_element_if</tt>?</b></h4>
|
||||
<p>In a first version of the library, I proposed <tt>_if</tt> versions of
|
||||
all the algorithms (well, not all, because that would be too much).
|
||||
However, there is simply no reason to do so, and all the versions I had
|
||||
were just as fast implemented using the excellent
|
||||
<tt><boost/iterator_adaptors.hpp></tt> library. Namely, a call to
|
||||
<tt>min_element_if(first, last, pred)</tt> would be just as well
|
||||
implemented by:
|
||||
<pre>
|
||||
// equivalent to min_element_if(first, last, pred)
|
||||
min_element(boost::make_filter_iterator(first, last, pred),
|
||||
boost::make_filter_iterator(last, last, pred));
|
||||
</pre>
|
||||
Arguably, the <tt>min_element_if</tt> version is somewhat shorter, but
|
||||
the overhead of iterator adaptors is not large, and they get rid of a
|
||||
lot of code (think of all the combinations between first/last and
|
||||
doubling them with _if variants!).</p>
|
||||
|
||||
<h4><b>Discussion: about std::max_element</b></h4>
|
||||
<p>This rationale is somewhat historical, but explains why there are all
|
||||
these <tt>first/last_min/max_element</tt> functions.</p>
|
||||
<p>The C++ standard mandates that <tt>std::min_element</tt> and <tt>std::max_element</tt>
|
||||
return the first instance of the smallest and largest elements (as opposed
|
||||
to, say, the last). This arbitrary choice has some consistency: In the
|
||||
case of v of type vector<int>, for instance, it is true that <tt>std::min_element(v.begin(),v.end(),std::less<int>())
|
||||
== std::max_element(v.begin(),v.end(),std::greater<int>())</tt>.
|
||||
<p>There is of course nothing wrong with this: it's simply a matter of
|
||||
choice. Yet another way to specify min_element and max_element is to define
|
||||
them as the first and the last elements if the range was stably sorted.
|
||||
(The <i>stable</i> sort is necessary to disambiguate between iterators
|
||||
that have the same value.) In that case, min should return the first instance
|
||||
and max should return the last. Then, both functions are related by
|
||||
<tt>reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less<int>()))
|
||||
==
|
||||
std::last_max_element(v.rbegin(),v.rend(),std::greater<int>())</tt>.
|
||||
This definition is subtly different from the previous one.</p>
|
||||
<p>The definition problem surfaces when one tries to design a minmax_element,
|
||||
using the procedure proposed in (Cormen, Leiserson, Rivest: "Introduction
|
||||
to Algorithms", section 9.1). It <i>should</i> be possible to derive an
|
||||
algorithm using only <tt>3n/2</tt> comparisons if <tt>[first,last) </tt>has
|
||||
<tt>n</tt>
|
||||
elements, but if one tries to write a function called <tt>first_min_first_max_element()</tt>
|
||||
which returns both <tt>std::min_element</tt> and <tt>std::max_element</tt>
|
||||
in a pair, the trivial implementation does not work. The problem, rather
|
||||
subtly, is about equal elements: I had to think for a while to find a
|
||||
way to perform only three
|
||||
comparisons per pair and return the first min and first max elements.
|
||||
For a long time, it seemed any
|
||||
attempts at doing so would consume four comparisons per pair in the worst
|
||||
case. This implementation achieves three.</p>
|
||||
<p>It is not possible (or even desirable) to change the meaning of
|
||||
<tt>max_element</tt>,
|
||||
but it is still beneficial to provide a function called <tt>minmax_element</tt>,
|
||||
which returns a pair of <tt>min_element</tt> and <tt>max_element</tt>.
|
||||
Although it is easy enough to call <tt>min_element</tt> and <tt>max_element</tt>,
|
||||
this performs
|
||||
<tt>2(n-1)</tt> comparisons, and necessitates <b>two</b>
|
||||
passes over the input. In contrast,
|
||||
<tt>minmax_element</tt> will perform
|
||||
the fewer comparisons and perform a <b>single</b> pass over the input.
|
||||
The savings can be significant when the iterator type is not a raw pointer,
|
||||
or even is just a model of the InputIterator concept (although in that
|
||||
case the interface would have to be
|
||||
changed, as the return type could not be copied, so one could e.g.
|
||||
return a value).</p>
|
||||
<p>In order to benefit from all the variants of the algorithm, I propose
|
||||
to introduce both <tt>first_min_element</tt> and <tt>last_min_element</tt>,
|
||||
and their counterparts <tt>first_max_element</tt> and <tt>last_max_element</tt>.
|
||||
Then I also propose all the variants algorithms: <tt>first_min_last_max_element</tt>
|
||||
and <tt>last_min_first_max_element</tt>, which perform only at most <tt>3n/2</tt>
|
||||
comparisons, and only a single pass on the input. In fact, it can be proven
|
||||
that computing minmax requires at least <tt>3(n/2)-2</tt> comparisons in
|
||||
any instance of the problem (Cormen, Leiserson, Rivest, 2nd edition, section
|
||||
9.1). The implementation I give does not perform unnecessary comparisons
|
||||
(whose result could have been computed by transitivity from previous
|
||||
comparisons).</p>
|
||||
<p>It appears that <tt>first_min_last_max_element</tt> may be just a tad
|
||||
slower than
|
||||
<tt>first_min_element</tt> alone, still much less than <tt>first_min_element</tt>
|
||||
and
|
||||
<tt>last_max_element</tt> called separately. <a href="#Performance">[2]</a>
|
||||
|
||||
<h4><b>Why algorithms and not accumulators?</b></h4>
|
||||
<p>The minmax algorithms are useful in computing the extent of a range.
|
||||
In computer graphics, we need a bounding box of a set of objects.
|
||||
In that case the need for a single pass is even more stringent
|
||||
as all three directions must be done at once. Food for thoughts: there
|
||||
is matter for a nice generic programming library with stackable <tt>update_min</tt>
|
||||
and <tt>update_max</tt> function objects which store a reference to the
|
||||
<tt>min_result</tt>and
|
||||
<tt>max_result</tt> variables, in conjunction with the <tt>for_each</tt>
|
||||
algorithm).</p>
|
||||
<p>I believe many standard sequential algorithms could be reformulated
|
||||
with accumulators (and many others, such as in statistics, expectation /
|
||||
variance / etc.). It seems that there is room for another library, but I
|
||||
do not see it competing with minmax, rather extending several algorithms
|
||||
(including minmax) to the accumulator framework. However, I felt it is
|
||||
beyond the scope of this library to provide such accumulators.</p>
|
||||
|
||||
<a NAME="no-policy">
|
||||
<h4><b>This first/last is a perfect application for a policy-based
|
||||
design.</b></h4>
|
||||
<p>True, and I could have gone that way, with the default policy for
|
||||
<tt>min_element</tt> and <tt>max_element</tt> to pick the first
|
||||
occurence of the result. This would have thinned the number of
|
||||
combinations of the minmax_element variants. But it would also have
|
||||
meant to change the interface of <tt>boost::minmax_element</tt>.
|
||||
One of the goals of the <tt>minmax_element</tt> algorithm is its
|
||||
eventual addition to the C++ standard, in connection with
|
||||
<tt>std::min_element</tt> and <tt>std::max_element</tt>
|
||||
(and I feel that it would be quite natural
|
||||
given the shortness of the implementation, and the not quite trivial
|
||||
detail which is needed to get it right). So changing the interface by
|
||||
adding policies would have meant unfortunately to depart from the
|
||||
standard and created an obstacle towards that goal. Besides, the code
|
||||
remains rather readable and simple without policies. So I am quite happy
|
||||
to keep it like this.
|
||||
</p></a>
|
||||
</a>
|
||||
|
||||
<a name="perf">
|
||||
<a href="doc/minmax_benchs.html"><h3><b>About performance</b></h3></a>
|
||||
</a>
|
||||
|
||||
<a name="acks">
|
||||
<h3>
|
||||
Acknowledgements</h3>
|
||||
My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>)
|
||||
who had <tt>minmax_element</tt> as an assignment helped clarify the issues,
|
||||
and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>.
|
||||
The identification of the issue surrounding <tt>max_element</tt> is solely
|
||||
my own.
|
||||
<p>One <tt>minmax_element</tt> implementation, which performs <tt>3(n/2)+O(log
|
||||
n)</tt> comparisons on the average when the elements are <tt>random_shuffle</tt>d,
|
||||
was suggested by my student Marc Glisse. The current one, which performs
|
||||
<tt>3(n/2)+1</tt>
|
||||
comparisons in the worst case, was suggested by John Iacono.<p>
|
||||
<p>Finally, Matthew Wilson and Jeremy Siek contributed pre-review
|
||||
comments, while Gennadiy Rozental, John Maddock, Craig Henderson, Gary
|
||||
Powell participated in the review of the library, managed by Thomas
|
||||
Witt. In particular, Gennadiy suggested a factorization of the code;
|
||||
while I haven't followed it all the way, his suggestions do make the
|
||||
code more readable and still work with older compilers.
|
||||
Late after the review, as I finally scrounged to add the library for a
|
||||
release, Eric Niebler noted the bad behavior of <tt>std::pair</tt> for
|
||||
<tt>minmax</tt> and suggested to use Boost.tuple instead.
|
||||
All my thanks for the excellent advice and reviews from all.
|
||||
<h3>
|
||||
See also</h3>
|
||||
<tt><a href="http://www.sgi.com/tech/stl/min.html">min</a></tt>, <tt><a href="http://www.sgi.com/tech/stl/max.html">max</a></tt>,
|
||||
<tt><a href="http://www.sgi.com/tech/stl/min_element.html">min_element</a></tt>,
|
||||
<tt><a href="http://www.sgi.com/tech/stl/max_element.html">max_element</a></tt>,
|
||||
<tt><a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
|
||||
Comparable</a></tt>,
|
||||
<tt><a href="http://www.sgi.com/tech/stl/sort.html">sort</a></tt>,
|
||||
<tt><a href="http://www.sgi.com/tech/stl/nth_element.html">nth_element</a></tt>
|
||||
.
|
||||
<hr SIZE="6">
|
||||
<br>Last modified 2004-07-01
|
||||
<p><font face="Arial,Helvetica"><font size=-1>© Copyright Hervé
|
||||
Brönnimann, Polytechnic University, 2002--2004.
|
||||
Use, modification, and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</font></font>
|
||||
</body>
|
||||
</html>
|
33
minmax/test/Jamfile
Normal file
33
minmax/test/Jamfile
Normal file
@ -0,0 +1,33 @@
|
||||
# Boost.Minmax Library Test Jamfile
|
||||
#
|
||||
# Copyright (C) 2002--2004, Herve Bronnimann
|
||||
#
|
||||
# Use, modification, and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
subproject libs/algorithm/minmax/test ;
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
# Make tests run by default.
|
||||
DEPENDS all : test ;
|
||||
|
||||
{
|
||||
test-suite algorithm/minmax
|
||||
: [ run
|
||||
minmax_element_test.cpp
|
||||
: :
|
||||
:
|
||||
: minmax_element
|
||||
]
|
||||
[ run
|
||||
minmax_test.cpp
|
||||
: :
|
||||
:
|
||||
: minmax
|
||||
]
|
||||
;
|
||||
}
|
20
minmax/test/Jamfile.v2
Normal file
20
minmax/test/Jamfile.v2
Normal file
@ -0,0 +1,20 @@
|
||||
# Boost.Minmax Library test Jamfile
|
||||
#
|
||||
# Copyright (C) 2002--2004, Herve Bronnimann
|
||||
#
|
||||
# Use, modification, and distribution is subject to the Boost Software
|
||||
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
|
||||
import testing ;
|
||||
|
||||
{
|
||||
test-suite algorithm/minmax:
|
||||
: [ run minmax_element_test.cpp
|
||||
: : : : minmax_element ]
|
||||
[ run minmax_test.cpp
|
||||
: : : : minmax ]
|
||||
;
|
||||
}
|
||||
|
241
minmax/test/minmax_element_test.cpp
Normal file
241
minmax/test/minmax_element_test.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
// (C) Copyright Herve Bronnimann 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <boost/config.hpp> /* prevents some nasty warns in MSVC */
|
||||
#include <boost/algorithm/minmax_element.hpp>
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
|
||||
class custom {
|
||||
int m_x;
|
||||
friend bool operator<(custom const& x, custom const& y);
|
||||
public:
|
||||
explicit custom(int x = 0) : m_x(x) {}
|
||||
custom(custom const& y) : m_x(y.m_x) {}
|
||||
custom operator+(custom const& y) const { return custom(m_x+y.m_x); }
|
||||
custom& operator+=(custom const& y) { m_x += y.m_x; return *this; }
|
||||
};
|
||||
|
||||
bool operator< (custom const& x, custom const& y)
|
||||
{
|
||||
return x.m_x < y.m_x;
|
||||
}
|
||||
|
||||
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(custom)
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct iterator_traits<int*> {
|
||||
typedef random_access_iterator_tag iterator_category;
|
||||
typedef int value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator_traits<custom*> {
|
||||
typedef random_access_iterator_tag iterator_category;
|
||||
typedef custom value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
void tie(std::pair<T1, T2> p, T3& first, T4& second)
|
||||
{
|
||||
first = T3(p.first); second = T4(p.second);
|
||||
}
|
||||
|
||||
template <class Value>
|
||||
struct less_count : std::less<Value> {
|
||||
typedef std::less<Value> Base;
|
||||
less_count(less_count<Value> const& lc) : m_counter(lc.m_counter) {}
|
||||
less_count(int& counter) : m_counter(counter) {}
|
||||
bool operator()(Value const& a, Value const& b) const {
|
||||
++m_counter;
|
||||
return Base::operator()(a,b);
|
||||
}
|
||||
void reset() {
|
||||
m_counter = 0;
|
||||
}
|
||||
private:
|
||||
int& m_counter;
|
||||
};
|
||||
|
||||
inline int opt_min_count(int n) {
|
||||
return (n==0) ? 0 : n-1;
|
||||
}
|
||||
inline int opt_minmax_count(int n) {
|
||||
if (n < 2) return 0;
|
||||
if (n == 2) return 2;
|
||||
return (n%2 == 0) ? 3*(n/2)-1 : 3*(n/2)+1;
|
||||
}
|
||||
inline int opt_boost_minmax_count(int n) {
|
||||
if (n < 2) return 0;
|
||||
if (n == 2) return 1;
|
||||
return (n%2 == 0) ? 3*(n/2)-2 : 3*(n/2);
|
||||
}
|
||||
|
||||
#define CHECK_EQUAL_ITERATORS( left, right, first ) \
|
||||
BOOST_CHECK_EQUAL( std::distance( first, left ), std::distance( first, right ) )
|
||||
|
||||
template <class CIterator>
|
||||
void test_minmax(CIterator first, CIterator last, int n)
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
typedef typename std::iterator_traits<CIterator>::value_type Value;
|
||||
typedef boost::reverse_iterator<CIterator> RCIterator;
|
||||
// assume that CIterator is BidirectionalIter
|
||||
CIterator min, max;
|
||||
RCIterator rfirst(last), rlast(first), rmin, rmax;
|
||||
int counter = 0;
|
||||
less_count<Value> lc(counter);
|
||||
|
||||
// standard extensions
|
||||
// first version, operator<
|
||||
tie( boost::minmax_element(first, last), min, max );
|
||||
|
||||
CHECK_EQUAL_ITERATORS( min, std::min_element(first, last), first );
|
||||
CHECK_EQUAL_ITERATORS( max, std::max_element(first, last), first );
|
||||
|
||||
// second version, comp function object (keeps a counter!)
|
||||
lc.reset();
|
||||
tie( boost::minmax_element(first, last, lc), min, max );
|
||||
BOOST_CHECK( counter <= opt_minmax_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( min, std::min_element(first, last, lc), first );
|
||||
CHECK_EQUAL_ITERATORS( max, std::max_element(first, last, lc), first );
|
||||
|
||||
// boost extensions
|
||||
// first version, operator<
|
||||
CHECK_EQUAL_ITERATORS( boost::first_min_element(first, last), std::min_element(first, last), first );
|
||||
rmin = RCIterator(boost::last_min_element(first, last));
|
||||
rmin = (rmin == rfirst) ? rlast : --rmin;
|
||||
CHECK_EQUAL_ITERATORS( rmin, std::min_element(rfirst, rlast), rfirst );
|
||||
CHECK_EQUAL_ITERATORS( boost::first_max_element(first, last), std::max_element(first, last), first );
|
||||
rmax = RCIterator(boost::last_max_element(first, last));
|
||||
rmax = (rmax == rfirst) ? rlast : --rmax;
|
||||
CHECK_EQUAL_ITERATORS( rmax, std::max_element(rfirst, rlast), rfirst );
|
||||
tie( boost::first_min_last_max_element(first, last), min, max );
|
||||
CHECK_EQUAL_ITERATORS( min, boost::first_min_element(first, last), first );
|
||||
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last), first );
|
||||
tie( boost::last_min_first_max_element(first, last), min, max );
|
||||
CHECK_EQUAL_ITERATORS( min, boost::last_min_element(first, last), first );
|
||||
CHECK_EQUAL_ITERATORS( max, boost::first_max_element(first, last), first );
|
||||
tie( boost::last_min_last_max_element(first, last), min, max );
|
||||
CHECK_EQUAL_ITERATORS( min, boost::last_min_element(first, last), first );
|
||||
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last), first );
|
||||
|
||||
// second version, comp function object (keeps a counter!)
|
||||
lc.reset();
|
||||
min = boost::first_min_element(first, last, lc);
|
||||
BOOST_CHECK( counter <= opt_min_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( min, std::min_element(first, last, lc), first );
|
||||
lc.reset();
|
||||
rmin = RCIterator(boost::last_min_element(first, last, lc));
|
||||
rmin = (rmin == rfirst) ? rlast : --rmin;
|
||||
BOOST_CHECK( counter <= opt_min_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( rmin, std::min_element(rfirst, rlast, lc), rfirst );
|
||||
lc.reset();
|
||||
max = boost::first_max_element(first, last, lc);
|
||||
BOOST_CHECK( counter <= opt_min_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( max, std::max_element(first, last, lc), first );
|
||||
lc.reset();
|
||||
rmax = RCIterator(boost::last_max_element(first, last, lc));
|
||||
rmax = (rmax == rfirst) ? rlast : --rmax;
|
||||
BOOST_CHECK( counter <= opt_min_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( rmax, std::max_element(rfirst, rlast, lc), rfirst );
|
||||
lc.reset();
|
||||
tie( boost::first_min_last_max_element(first, last, lc), min, max );
|
||||
BOOST_CHECK( counter <= opt_boost_minmax_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( min, boost::first_min_element(first, last, lc), first );
|
||||
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last, lc), first );
|
||||
lc.reset();
|
||||
tie( boost::last_min_first_max_element(first, last, lc), min, max );
|
||||
BOOST_CHECK( counter <= opt_boost_minmax_count(n) );
|
||||
BOOST_CHECK( min == boost::last_min_element(first, last, lc) );
|
||||
CHECK_EQUAL_ITERATORS( max, boost::first_max_element(first, last, lc), first );
|
||||
lc.reset();
|
||||
tie( boost::last_min_last_max_element(first, last, lc), min, max );
|
||||
BOOST_CHECK( counter <= opt_minmax_count(n) );
|
||||
CHECK_EQUAL_ITERATORS( min, boost::last_min_element(first, last, lc), first );
|
||||
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last, lc), first );
|
||||
}
|
||||
|
||||
template <class Container, class Iterator, class Value>
|
||||
void test_container(Iterator first, Iterator last, int n,
|
||||
Container* dummy = 0
|
||||
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Value) )
|
||||
{
|
||||
Container c(first, last);
|
||||
test_minmax(c.begin(), c.end(), n);
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
void test_range(Iterator first, Iterator last, int n)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iterator>::value_type Value;
|
||||
// Test various containers with these values
|
||||
test_container< std::vector<Value>, Iterator, Value >(first, last, n);
|
||||
test_container< std::list<Value>, Iterator, Value >(first, last, n);
|
||||
test_container< std::set<Value>, Iterator, Value >(first, last, n);
|
||||
}
|
||||
|
||||
template <class Value>
|
||||
void test(int n BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Value))
|
||||
{
|
||||
// Populate test vector with identical values
|
||||
std::vector<Value> test_vector(n, Value(1));
|
||||
typename std::vector<Value>::iterator first( test_vector.begin() );
|
||||
typename std::vector<Value>::iterator last( test_vector.end() );
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with two values
|
||||
typename std::vector<Value>::iterator middle( first + n/2 );
|
||||
std::fill(middle, last, Value(2));
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with increasing values
|
||||
std::accumulate(first, last, Value(0));
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with decreasing values
|
||||
std::reverse(first, last);
|
||||
test_range(first, last, n);
|
||||
|
||||
// Populate test vector with random values
|
||||
std::random_shuffle(first, last);
|
||||
test_range(first, last, n);
|
||||
}
|
||||
|
||||
int test_main( int argc, char* argv[] )
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
using std::atoi;
|
||||
#endif
|
||||
|
||||
int n = 100;
|
||||
if (argc > 1) n = atoi(argv[1]);
|
||||
|
||||
test<int>(n);
|
||||
test<custom>(n);
|
||||
|
||||
return 0;
|
||||
}
|
85
minmax/test/minmax_test.cpp
Normal file
85
minmax/test/minmax_test.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
// (C) Copyright Herve Bronnimann 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/minmax.hpp>
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
class custom {
|
||||
int m_x;
|
||||
friend std::ostream& operator<<(std::ostream& str, custom const& x);
|
||||
public:
|
||||
explicit custom(int x = 0) : m_x(x) {}
|
||||
custom(custom const& y) : m_x(y.m_x) {}
|
||||
bool operator==(custom const& y) const { return m_x == y.m_x; }
|
||||
bool operator<(custom const& y) const { return m_x < y.m_x; }
|
||||
custom operator+(custom const& y) const { return custom(m_x+y.m_x); }
|
||||
custom& operator+=(custom const& y) { m_x += y.m_x; return *this; }
|
||||
};
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& str, custom const& x)
|
||||
{
|
||||
return str << x.m_x;
|
||||
}
|
||||
|
||||
template <class Value>
|
||||
struct less_count : std::less<Value> {
|
||||
typedef std::less<Value> Base;
|
||||
less_count(less_count<Value> const& lc) : m_counter(lc.m_counter) {}
|
||||
less_count(int& counter) : m_counter(counter) {}
|
||||
bool operator()(Value const& a, Value const& b) const {
|
||||
++m_counter;
|
||||
return Base::operator()(a,b);
|
||||
}
|
||||
void reset() {
|
||||
m_counter = 0;
|
||||
}
|
||||
private:
|
||||
int& m_counter;
|
||||
};
|
||||
|
||||
using namespace boost;
|
||||
|
||||
template <class Value>
|
||||
void test(BOOST_EXPLICIT_TEMPLATE_TYPE(Value))
|
||||
{
|
||||
Value zero(0), one(1);
|
||||
int counter = 0;
|
||||
less_count<Value> lc(counter);
|
||||
|
||||
// Test functionality
|
||||
tuple<Value const&, Value const&> result1 = minmax(zero, one);
|
||||
BOOST_CHECK_EQUAL( get<0>(result1), zero );
|
||||
BOOST_CHECK_EQUAL( get<1>(result1), one );
|
||||
|
||||
tuple<Value const&, Value const&> result2 = minmax(one, zero);
|
||||
BOOST_CHECK_EQUAL( get<0>(result2), zero );
|
||||
BOOST_CHECK_EQUAL( get<1>(result2), one );
|
||||
|
||||
// Test functionality and number of comparisons
|
||||
lc.reset();
|
||||
tuple<Value const&, Value const&> result3 = minmax(zero, one, lc );
|
||||
BOOST_CHECK_EQUAL( get<0>(result3), zero );
|
||||
BOOST_CHECK_EQUAL( get<1>(result3), one );
|
||||
BOOST_CHECK_EQUAL( counter, 1 );
|
||||
|
||||
lc.reset();
|
||||
tuple<Value const&, Value const&> result4 = minmax(one, zero, lc );
|
||||
BOOST_CHECK_EQUAL( get<0>(result4), zero );
|
||||
BOOST_CHECK_EQUAL( get<1>(result4), one );
|
||||
BOOST_CHECK_EQUAL( counter, 1);
|
||||
}
|
||||
|
||||
int test_main( int , char* [] )
|
||||
{
|
||||
test<int>(); // ("builtin");
|
||||
test<custom>(); // ("custom ");
|
||||
|
||||
return 0;
|
||||
}
|
@ -3,45 +3,40 @@
|
||||
# Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
# distribution is subject to the Boost Software License, Version
|
||||
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# htt../..//www.boost.org/LICENSE_1_0.txt)
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# See htt../..//www.boost.org for updates, documentation, and revision history.
|
||||
# See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
project boost/libs/algorithm/string/doc ;
|
||||
import toolset ;
|
||||
toolset.using doxygen ;
|
||||
|
||||
doxygen reference
|
||||
boostbook string_algo : string_algo.xml ;
|
||||
|
||||
doxygen autodoc
|
||||
:
|
||||
../../../../boost/algorithm/string.hpp
|
||||
../../../../boost/algorithm/string_regex.hpp
|
||||
[ glob ../../../../boost/algorithm/string.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string_regex.hpp ]
|
||||
|
||||
../../../../boost/algorithm/string/classification.hpp
|
||||
../../../../boost/algorithm/string/iterator_range.hpp
|
||||
../../../../boost/algorithm/string/sequence_traits.hpp
|
||||
../../../../boost/algorithm/string/std_containers_traits.hpp
|
||||
../../../../boost/algorithm/string/container_traits.hpp
|
||||
../../../../boost/algorithm/string/concept.hpp
|
||||
../../../../boost/algorithm/string/compare.hpp
|
||||
../../../../boost/algorithm/string/constants.hpp
|
||||
|
||||
../../../../boost/algorithm/string/case_conv.hpp
|
||||
|
||||
../../../../boost/algorithm/string/find.hpp
|
||||
../../../../boost/algorithm/string/finder.hpp
|
||||
../../../../boost/algorithm/string/find_iterator.hpp
|
||||
|
||||
../../../../boost/algorithm/string/trim.hpp
|
||||
|
||||
../../../../boost/algorithm/string/predicate.hpp
|
||||
../../../../boost/algorithm/string/split.hpp
|
||||
../../../../boost/algorithm/string/iter_find.hpp
|
||||
|
||||
../../../../boost/algorithm/string/erase.hpp
|
||||
../../../../boost/algorithm/string/replace.hpp
|
||||
../../../../boost/algorithm/string/find_format.hpp
|
||||
../../../../boost/algorithm/string/formatter.hpp
|
||||
|
||||
../../../../boost/algorithm/string/regex.hpp
|
||||
../../../../boost/algorithm/string/regex_find_format.hpp
|
||||
[ glob ../../../../boost/algorithm/string/classification.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/iterator_range.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/sequence_traits.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/std_containers_traits.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/concept.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/compare.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/constants.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/case_conv.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/find.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/finder.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/find_iterator.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/trim.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/predicate.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/split.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/erase.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/replace.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/find_format.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/formatter.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/regex.hpp ]
|
||||
[ glob ../../../../boost/algorithm/string/regex_find_format.hpp ]
|
||||
:
|
||||
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
|
||||
<doxygen:param>EXTRACT_PRIVATE=NO
|
||||
@ -52,10 +47,6 @@ doxygen reference
|
||||
<doxygen:param>PREDEFINED="BOOST_STRING_TYPENAME=typename \"BOOST_STATIC_CONSTANT(type,var)=static const type var;\""
|
||||
;
|
||||
|
||||
boostbook string_algo
|
||||
:
|
||||
string_algo.xml
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<title>Concepts</title>
|
||||
|
||||
<using-namespace name="boost"/>
|
||||
<using-namespace name="boost::string_algo"/>
|
||||
<using-namespace name="boost::algorithm"/>
|
||||
|
||||
<section>
|
||||
<title>Definitions</title>
|
||||
@ -75,9 +75,9 @@
|
||||
</table>
|
||||
|
||||
<para>
|
||||
Various algorithms need to perform a searching in a container and a Finder is a generalization of such
|
||||
Various algorithms need to perform a search in a container and a Finder is a generalization of such
|
||||
search operations that allows algorithms to abstract from searching. For instance, generic replace
|
||||
algorithms can replace any part of the input, and the finder is used to select the desired one.
|
||||
algorithms can replace any part of the input, and the Finder is used to select the desired one.
|
||||
</para>
|
||||
<para>
|
||||
Note, that it is only required that the finder works with a particular iterator type. However,
|
||||
@ -106,7 +106,7 @@ struct simple_finder
|
||||
</programlisting>
|
||||
</listitem>
|
||||
<listitem>
|
||||
Function Finder. Finder can be any function object. That means, an ordinary function with the
|
||||
Function Finder. Finder can be any function object. That is, any ordinary function with the
|
||||
required signature can be used as well. However, such a function can be used only for
|
||||
a specific iterator type.
|
||||
|
||||
@ -166,7 +166,7 @@ boost::iterator_range<std::string> simple_finder(
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Formatter implemented as a class. This Formatter does not perform any formating and
|
||||
returns repackaged match. <code>operator()</code>
|
||||
returns the match, repackaged. <code>operator()</code>
|
||||
is templated, so that the Formatter can be used on any Finder type.
|
||||
|
||||
<programlisting>
|
||||
|
@ -6,8 +6,14 @@
|
||||
<section id="string_algo.ack">
|
||||
<title>Acknowledgments</title>
|
||||
<para>
|
||||
Thanks for everybody who gave suggestions and comments. Especially to Thorsten Ottosen, Jeff Garland
|
||||
and the other boost members who participated.
|
||||
The author would like to thank everybody who gave suggestions and comments. Especially valuable
|
||||
were the contributions of Thorsten Ottosen, Jeff Garland and the other boost members who participated
|
||||
in the review process, namely David Abrahams, Daniel Frey, Beman Dawes, John Maddock, David B.Held, Pavel Vozenilek
|
||||
and many other.
|
||||
</para>
|
||||
<para>
|
||||
Additional thanks go to Stefan Slapeta and Toon Knapen, who have been very resourceful in solving various
|
||||
portability issues.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -5,171 +5,62 @@
|
||||
<title>Design Topics</title>
|
||||
|
||||
<using-namespace name="boost"/>
|
||||
<using-namespace name="boost::string_algo"/>
|
||||
|
||||
<section id="string_algo.iterator_range">
|
||||
<title><code>iterator_range</code> class</title>
|
||||
<using-namespace name="boost::algorithm"/>
|
||||
|
||||
<section id="string_algo.string">
|
||||
<title>String Representation</title>
|
||||
|
||||
<para>
|
||||
An <classname>iterator_range</classname> is an encapsulation of a pair of iterators that
|
||||
delimit a sequence (or, a range). This concept is widely used by
|
||||
sequence manipulating algorithms. Although being so useful, there no direct support
|
||||
for it in the standard library (The closest thing is that some algorithms return a pair of iterators).
|
||||
Instead all STL algorithms have two distinct parameters for beginning and end of a range. This design
|
||||
is natural for implementation of generic algorithms, but it forbids to work with a range as a single value.
|
||||
</para>
|
||||
<para>
|
||||
It is possible to encapsulate a range in <code>std::pair<></code>, but
|
||||
the <code>std::pair<></code> is a too generic encapsulation, so it is not best match for a range.
|
||||
For instance, it does not enforce that begin and end iterators are of the same type.
|
||||
As the name suggest, this library works mainly with strings. However, in the context of this library,
|
||||
a string is not restricted to any particular implementation (like <code>std::basic_string</code>),
|
||||
rather it is a concept. This allows the algorithms in this library to be reused for any string type,
|
||||
that satisfies the given requirements.
|
||||
</para>
|
||||
<para>
|
||||
Naturally the range concept is heavily used also in this library. During the development of
|
||||
the library, it was discovered, that there is a need for a reasonable encapsulation for it.
|
||||
A core part of the library deals with substring searching algorithms. Any such an algorithm,
|
||||
returns a range delimiting the result of the search. <code>std::pair<></code> was considered as
|
||||
unsuitable. Therefore the <code>iterator_range</code> was defined.
|
||||
<emphasis role="bold">Definition:</emphasis> A string is a
|
||||
<ulink url="../../libs/range/doc/range.html">range</ulink> of characters accessible in sequential
|
||||
ordered fashion. Character is any value type with "cheap" copying and assignment.
|
||||
</para>
|
||||
<para>
|
||||
The intention of the <code>iterator_range</code> class is to manage a range as a single value and provide
|
||||
a basic interface for common operations. Its interface is similar to that of container.
|
||||
In addition of <code>begin()</code>
|
||||
and <code>end()</code> accessors, it has member functions for checking if the range is empty,
|
||||
or to determine the size of the range. It has also a set of member typedefs that extract
|
||||
type information from the encapsulated iterators. As such, the interface is compatible with
|
||||
the <link linkend="string_algo.container_traits">container traits</link> requirements so
|
||||
it is possible to use this class as a parameter to many algorithms in this library.
|
||||
First requirement of string-type is that it must accessible using
|
||||
<ulink url="../../libs/range/index.html">Boost.Range</ulink>. This facility allows to access
|
||||
the elements inside the string in a uniform iterator-based fashion.
|
||||
This is sufficient for our library
|
||||
</para>
|
||||
<para>
|
||||
Second requirement defines the way in which the characters are stored in the string. Algorithms in
|
||||
this library work with an assumption that copying a character is cheaper then allocating extra
|
||||
storage to cache results. This is a natural assumption for common character types. Algorithms will
|
||||
work even if this requirement is not satisfied, however at the cost of performance degradation.
|
||||
<para>
|
||||
</para>
|
||||
In addition some algorithms have additional requirements on the string-type. Particularly, it is required
|
||||
that an algorithm can create a new string of the given type. In this case, it is required that
|
||||
the type satisfies the sequence (Std §23.1.1) requirements.
|
||||
</para>
|
||||
<para>
|
||||
In the reference and also in the code, requirement on the string type is designated by the name of
|
||||
template argument. <code>RangeT</code> means that the basic range requirements must hold.
|
||||
<code>SequenceT</code> designates extended sequence requirements.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="string_algo.container_traits">
|
||||
<title>Container Traits</title>
|
||||
|
||||
<para>
|
||||
Container traits provide uniform access to different types of containers.
|
||||
This functionality allows to write generic algorithms which work with several
|
||||
different kinds of containers. For this library it means, that, for instance,
|
||||
many algorithms work with <code>std::string</code> as well as with <code>char[]</code>.
|
||||
</para>
|
||||
<para>
|
||||
The following container types are supported:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Standard containers
|
||||
</listitem>
|
||||
<listitem>
|
||||
Built-in arrays (like int[])
|
||||
</listitem>
|
||||
<listitem>
|
||||
Null terminated strings (this includes char[],wchar_t[],char*, and wchar_t*)
|
||||
</listitem>
|
||||
<listitem>
|
||||
std::pair<iterator,iterator>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Container traits support a subset of container concept (Std §23.1). This subset
|
||||
can be described as an input container concept, e.g. a container with an immutable content.
|
||||
Its definition can be found in the header <headername>boost/string_algo/container_traits.hpp</headername>.
|
||||
</para>
|
||||
<para>
|
||||
In the table C denotes a container and c is an object of C.
|
||||
</para>
|
||||
<table>
|
||||
<title>Container Traits</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Name</entry>
|
||||
<entry>Standard container equivalent</entry>
|
||||
<entry>Description</entry>
|
||||
</row>Maeterlinck
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><classname>container_value_type<C></classname>::type</entry>
|
||||
<entry><code>C::value_type</code></entry>
|
||||
<entry>Type of contained values</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_difference_type<C></classname>::type</entry>
|
||||
<entry><code>C::difference_type</code></entry>
|
||||
<entry>difference type of the container</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_iterator<C></classname>::type</entry>
|
||||
<entry><code>C::iterator</code></entry>
|
||||
<entry>iterator type of the container</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_const_iterator<C></classname>::type</entry>
|
||||
<entry><code>C::const_iterator</code></entry>
|
||||
<entry>const_iterator type of the container</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_result_iterator<C></classname>::type</entry>
|
||||
<entry></entry>
|
||||
<entry>
|
||||
result_iterator type of the container. This type maps to <code>C::iterator</code>
|
||||
for mutable container and <code>C::const_iterator</code> for const containers.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><functionname>begin(c)</functionname></entry>
|
||||
<entry><code>c.begin()</code></entry>
|
||||
<entry>
|
||||
Gets the iterator pointing to the start of the container.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><functionname>end(c)</functionname></entry>
|
||||
<entry><code>c.end()</code></entry>
|
||||
<entry>
|
||||
Gets the iterator pointing to the end of the container.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><functionname>size(c)</functionname></entry>
|
||||
<entry><code>c.size()</code></entry>
|
||||
<entry>
|
||||
Gets the size of the container.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><functionname>empty(c)</functionname></entry>
|
||||
<entry><code>c.empty()</code></entry>
|
||||
<entry>
|
||||
Checks if the container is empty.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
The container traits are only a temporary part of this library. There is a plan for a separate submission
|
||||
of a container_traits library to Boost. Once it gets accepted, String Algorithm Library will be adopted to
|
||||
use it and the internal implementation will be deprecated.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
<section id="string_algo.sequence_traits">
|
||||
<title>Sequence Traits</title>
|
||||
|
||||
<para>
|
||||
Major difference between <code>std::list</code> and <code>std::vector</code> is not in the interfaces
|
||||
they provide, rather in the inner details of the class and the way how it performs
|
||||
various operation. The problem is that it is not possible to infer this difference from the
|
||||
The major difference between <code>std::list</code> and <code>std::vector</code> is not in the interfaces
|
||||
they provide, but rather in the inner details of the class and the way how it performs
|
||||
various operations. The problem is that it is not possible to infer this difference from the
|
||||
definitions of classes without some special mechanism.
|
||||
However some algorithms can run significantly faster with the knowledge of the properties
|
||||
However, some algorithms can run significantly faster with the knowledge of the properties
|
||||
of a particular container.
|
||||
</para>
|
||||
<para>
|
||||
Sequence traits allows one to specify additional properties of a sequence container (see Std.§32.2).
|
||||
Sequence traits allow one to specify additional properties of a sequence container (see Std.§32.2).
|
||||
These properties are then used by algorithms to select optimized handling for some operations.
|
||||
The sequence traits are declared in the header
|
||||
<headername>boost/string_algo/sequence_traits.hpp</headername>.
|
||||
<headername>boost/algorithm/string/sequence_traits.hpp</headername>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -186,11 +77,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><classname>sequence_has_native_replace<C></classname>::value</entry>
|
||||
<entry><classname>has_native_replace<C></classname>::value</entry>
|
||||
<entry>Specifies that the sequence has std::string like replace method</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>sequence_has_stable_iterators<C></classname>::value</entry>
|
||||
<entry><classname>has_stable_iterators<C></classname>::value</entry>
|
||||
<entry>
|
||||
Specifies that the sequence has stable iterators. It means,
|
||||
that operations like <code>insert</code>/<code>erase</code>/<code>replace</code>
|
||||
@ -198,14 +89,14 @@
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>sequence_has_const_time_insert<C></classname>::value</entry>
|
||||
<entry><classname>has_const_time_insert<C></classname>::value</entry>
|
||||
<entry>
|
||||
Specifies that the insert method of the sequence has
|
||||
constant time complexity.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>sequence_has_const_time_erase<C></classname>::value</entry>
|
||||
<entry><classname>has_const_time_erase<C></classname>::value</entry>
|
||||
<entry>
|
||||
Specifies that the erase method of the sequence has constant time complexity
|
||||
</entry>
|
||||
@ -243,7 +134,7 @@
|
||||
Currently the library contains only naive implementation of find algorithms with complexity
|
||||
O(n * m) where n is the size of the input sequence and m is the size of the search sequence.
|
||||
There are algorithms with complexity O(n), but for smaller sequence a constant overhead is
|
||||
rather big. For small m << n (m magnitued smaller than n) the current implementation
|
||||
rather big. For small m << n (m by magnitude smaller than n) the current implementation
|
||||
provides acceptable efficiency.
|
||||
Even the C++ standard defines the required complexity for search algorithm as O(n * m).
|
||||
It is possible that a future version of library will also contain algorithms with linear
|
||||
@ -263,19 +154,63 @@
|
||||
</para>
|
||||
<para>
|
||||
As usual, the implementation of the lower layer is designed to work with a generic sequence while
|
||||
taking an advantage of specific features if possible
|
||||
taking advantage of specific features if possible
|
||||
(by using <link linkend="string_algo.sequence_traits">Sequence traits</link>)
|
||||
</para>
|
||||
</section>
|
||||
<section id="string_algo.split">
|
||||
<title>Split Algorithms</title>
|
||||
<title>Find Iterators & Split Algorithms</title>
|
||||
|
||||
<para>
|
||||
Split algorithms are a logical extension of <link linkend="string_algo.find">find facility</link>.
|
||||
Instead of searching for one match, the whole input is searched. The result of the search is then used
|
||||
to partition the input. It depends on the algorithms which parts are returned as the result of
|
||||
split operations. It can be the matching parts (<functionname>find_all()</functionname>) of the parts in
|
||||
between (<functionname>split()</functionname>).
|
||||
Find iterators are a logical extension of the <link linkend="string_algo.find">find facility</link>.
|
||||
Instead of searching for one match, the whole input can be iteratively searched for multiple matches.
|
||||
The result of the search is then used to partition the input. It depends on the algorithms which parts
|
||||
are returned as the result. They can be the matching parts (<classname>find_iterator</classname>) of the parts in
|
||||
between (<classname>split_iterator</classname>).
|
||||
</para>
|
||||
<para>
|
||||
In addition the split algorithms like <functionname>find_all()</functionname> and <functionname>split()</functionname>
|
||||
can simplify the common operations. They use a find iterator to search the whole input and copy the
|
||||
matches they found into the supplied container.
|
||||
</para>
|
||||
</section>
|
||||
<section id="string_algo.exception">
|
||||
<title>Exception Safety</title>
|
||||
|
||||
<para>
|
||||
The library requires that all operations on types used as template
|
||||
or function arguments provide the <emphasis>basic exception-safety guarantee</emphasis>.
|
||||
In turn, all functions and algorithms in this library, except where stated
|
||||
otherwise, will provide the <emphasis>basic exception-safety guarantee</emphasis>.
|
||||
In other words:
|
||||
The library maintains its invariants and does not leak resources in
|
||||
the face of exceptions. Some library operations give stronger
|
||||
guarantees, which are documented on an individual basis.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Some functions can provide the <emphasis>strong exception-safety guarantee</emphasis>.
|
||||
That means that following statements are true:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
If an exception is thrown, there are no effects other than those
|
||||
of the function
|
||||
</listitem>
|
||||
<listitem>
|
||||
If an exception is thrown other than by the function, there are no effects
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
This guarantee can be provided under the condition that the operations
|
||||
on the types used for arguments for these functions either
|
||||
provide the strong exception guarantee or do not alter the global state .
|
||||
</para>
|
||||
<para>
|
||||
In the reference, under the term <emphasis>strong exception-safety guarantee</emphasis>, we mean the
|
||||
guarantee as defined above.
|
||||
</para>
|
||||
<para>
|
||||
For more information about the exception safety topics, follow this
|
||||
<ulink url="../../more/generic_exception_safety.html">link</ulink>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -8,8 +8,8 @@
|
||||
<para>
|
||||
The whole library is provided in headers. Regex variants of some algorithms,
|
||||
however, are dependent on the <libraryname>Boost.Regex</libraryname> library. All such algorithms are
|
||||
separated in <headername>boost/string_algo/regex.hpp</headername>.
|
||||
If this header is used, an application must be linked with the <libraryname>Boost.Regex</libraryname>
|
||||
separated in <headername>boost/algorithm/string_regex.hpp</headername>.
|
||||
If this header is used, the application must be linked with the <libraryname>Boost.Regex</libraryname>
|
||||
library.
|
||||
</para>
|
||||
</section>
|
||||
@ -17,7 +17,7 @@
|
||||
<section>
|
||||
<title>Examples</title>
|
||||
<para>
|
||||
Examples showing the basic usage of the library can be found in the libs/string_algo/example
|
||||
Examples showing the basic usage of the library can be found in the libs/algorithm/string/example
|
||||
directory. There is a separate file for the each part of the library. Please follow the boost
|
||||
build guidelines to build examples using the bjam. To successfully build regex examples
|
||||
the <libraryname>Boost.Regex</libraryname> library is required.
|
||||
@ -27,7 +27,7 @@
|
||||
<section>
|
||||
<title>Tests</title>
|
||||
<para>
|
||||
A full set of test cases for the library is located in the libs/string_algo/test directory.
|
||||
A full set of test cases for the library is located in the libs/algorithm/string/test directory.
|
||||
The test cases can be executed using the boost build system. For the tests of regular
|
||||
expression variants of algorithms, the <libraryname>Boost.Regex</libraryname> library is required.
|
||||
</para>
|
||||
@ -44,12 +44,16 @@
|
||||
<listitem>GCC 3.2</listitem>
|
||||
<listitem>GCC 3.3.1</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
See <ulink url="http://boost.sourceforge.net/regression-logs/">Boost regression tables</ulink>
|
||||
for additional info for a particular compiler.
|
||||
</para>
|
||||
<para>
|
||||
There are known limitation on platforms not supporting partial template specialization.
|
||||
Library depends on correctly implemented std::iterator_traits class. If a standard library provided
|
||||
with compiler is broken, the String Algorithm Library cannot function properly. Usually it implies
|
||||
that primitive pointer iterators are not working with the library functions.
|
||||
Library depends on correctly implemented <code>std::iterator_traits</code> class.
|
||||
If a standard library provided with compiler is broken, the String Algorithm Library
|
||||
cannot function properly. Usually it implies that primitive pointer iterators are not
|
||||
working with the library functions.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
38
string/doc/external_concepts.html
Normal file
38
string/doc/external_concepts.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title> Concepts and External Concepts </title><meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1"></head> <body><table ><tr ><td ><img src="../../../../boost.png" width="100%" border="0"></td><td ><h1 >Concepts and External Concepts</h1></td></tr></table><p >Generic programming in C++ is characterized by the use of function and class templates where
|
||||
the template parameter(s) must satisfy certain requirements.Often these
|
||||
requirements are so important that we give them a name: we call
|
||||
such a set of type requirements a <b>concept</b>. We say that a type <i>
|
||||
conforms to a concept</i> or that it <i>is a model of a concept</i> if it
|
||||
satisfies all of those requirements. The concept can be specified as a set
|
||||
of member functions with well-defined semantics
|
||||
and a set of nested typedefs with well-defined properties.</p><p >Often it much more flexible to provide free-standing functions and typedefs
|
||||
which provides the exact same semantics (but a different syntax) as
|
||||
specified
|
||||
by the concept. This allows generic code to treat different types <i> as if
|
||||
</i> they fulfilled the concept. In this case we say that the concept has
|
||||
been <b> externalized </b> or that the new requirements constitutes an <b>external
|
||||
concept </b>. We say that a type <i> conforms to an external concept </i>
|
||||
or that it <i> is a model of an external concept </i>. A concept may exist
|
||||
without a corresponding external concept and conversely.</p><p >Whenever a concept specifies a member function, the corresponding external
|
||||
concept
|
||||
must specify a free-standing function of the same name, same return type and
|
||||
the same argument list except there is an extra first argument which must
|
||||
be of the type (or a reference to that type) that is to fulfill the external
|
||||
concept. If the corresonding member function has any cv-qulifiers, the
|
||||
first argument must have the same cv-qualifiers. Whenever a concept
|
||||
specifies a nested typedef, the corresponding external concept
|
||||
specifies a <b>type-generator</b>, that is, a type with a nested typedef
|
||||
named <code>type</code>. The type-generator has the name as the nested typedef with
|
||||
<code>_of</code> appended.
|
||||
The converse relationship of an external concept and its corresponding concept
|
||||
also holds.</p><p ><b ><i >Example:</i></b></p><p >A type <code>T</code> fulfills the FooConcept if it
|
||||
has the follwing public members:</p><code> void T::foo( int ) const; <br>
|
||||
int T::bar(); <br>
|
||||
typedef <i>implementation defined </i> foo_type;</code><p >The corresponding external concept is the ExternalFooConcept.</p><p >A type <code>T</code> fullfills the ExternalFooConcept if these
|
||||
free-standing functions and type-generators exists:</p><code>void foo( const T&, int ); <br>
|
||||
int bar( T& ); <br>
|
||||
foo_type_of< T >::type;</code> <br> <br><hr size="1" ><h3 >Literature</h3><ul ><li > <a href="http://www.boost.org/more/generic_programming.html#type_generator" target="_self" >Type Generators</a> </li><li > <a href="http://www.boost.org/more/generic_programming.html#concept" target="_self" >Concepts</a> </li><li > <a href="http://www.sgi.com/tech/stl/stl_introduction.html" target="_self" >Concepts and SGI STL</a> </li></ul><hr size="1" ><p >© Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk).
|
||||
Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears
|
||||
in all copies. This software is provided "as is" without express or implied warranty, and with no
|
||||
claim as to its suitability for any purpose.</p><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></body></html>
|
||||
<!-- Copyright Dezide Aps 2003-2004 -->
|
@ -13,28 +13,30 @@
|
||||
</para>
|
||||
<para>
|
||||
The implementation is not restricted to work with a particular container
|
||||
(like a <code>std::basic_string</code>), rather it is as generic as
|
||||
(like <code>std::basic_string</code>), rather it is as generic as
|
||||
possible. This generalization is not compromising the performance since
|
||||
algorithms are using container specific features when it means a performance
|
||||
gain.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">
|
||||
Important note: In this documentation we use term <emphasis>string</emphasis> to
|
||||
designate a sequence of <emphasis>characters</emphasis> stored in an arbitrary container.
|
||||
A <emphasis>string</emphasis> is not restricted to <code>std::basic_string</code> and
|
||||
<emphasis>character</emphasis> does not have to be <code>char</code> or <code>wchar_t</code>,
|
||||
although these are most common candidates.
|
||||
</emphasis>
|
||||
Consult the <link linkend="string_algo.design">design chapter</link> to see precise specification of
|
||||
supported string types.
|
||||
</para>
|
||||
<para>
|
||||
The library has layered structure to simplify the usage without sacrificing the
|
||||
generalization.
|
||||
|
||||
The easy-to-use interface, defined in the namespace <code>boost</code>, represents the first layer.
|
||||
Algorithms and classes defined here do not offer a lot of customization opportunities
|
||||
rather they are provided in more different variants, so a user can chose the
|
||||
one that suits her needs.
|
||||
|
||||
The second layer, defined in the namespace <code>boost::string_algo</code>, on the
|
||||
other hand, is generic. Basically it contains the same set of algorithms as the first layer,
|
||||
but the interface is more flexible and allows more customization, but it is harder to use.
|
||||
The first layer is implemented as set of wrappers around the second layer.
|
||||
The library interface functions and classes are defined in namespace <code>boost::algorithm</code>, and
|
||||
they are lifted into namespace <code>boost</code> via using declaration.
|
||||
</para>
|
||||
<para>
|
||||
The documentation is divided into several sections. For a quick start read the
|
||||
<link linkend="string_algo.usage">Usage</link> section.
|
||||
<link linkend="string_algo.usage">Usage</link> section followed by
|
||||
<link linkend="string_algo.quickref">Quick Reference</link>.
|
||||
<link linkend="string_algo.design">The Design Topics</link>,
|
||||
<link linkend="string_algo.concept">Concepts</link> and <link linkend="string_algo.rationale">Rationale</link>
|
||||
provide some explanation about the library design and structure an explain how it should be used.
|
||||
|
686
string/doc/quickref.xml
Normal file
686
string/doc/quickref.xml
Normal file
@ -0,0 +1,686 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
||||
<section id="string_algo.quickref" last-revision="$Date$">
|
||||
<title>Quick Reference</title>
|
||||
|
||||
<using-namespace name="boost"/>
|
||||
<using-namespace name="boost::algorithm"/>
|
||||
|
||||
<section>
|
||||
<title>Algorithms</title>
|
||||
|
||||
<table>
|
||||
<title>Case Conversion</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Algorithm name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Functions</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><code>to_upper</code></entry>
|
||||
<entry>Convert a string to upper case</entry>
|
||||
<entry>
|
||||
<functionname>to_upper_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>to_upper()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>to_lower</code></entry>
|
||||
<entry>Convert a string to lower case</entry>
|
||||
<entry>
|
||||
<functionname>to_lower_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>to_lower()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table>
|
||||
<title>Trimming</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Algorithm name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Functions</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><code>trim_left</code></entry>
|
||||
<entry>Remove leading spaces from a string</entry>
|
||||
<entry>
|
||||
<functionname>trim_left_copy_if()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_left_if()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_left_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_left()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>trim_right</code></entry>
|
||||
<entry>Remove trailing spaces from a string</entry>
|
||||
<entry>
|
||||
<functionname>trim_right_copy_if()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_right_if()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_right_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_right()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>trim</code></entry>
|
||||
<entry>Remove leading and trailing spaces from a string</entry>
|
||||
<entry>
|
||||
<functionname>trim_copy_if()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_if()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>trim()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table>
|
||||
<title>Predicates</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Algorithm name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Functions</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><code>starts_with</code></entry>
|
||||
<entry>Check if a string is a prefix of the other one</entry>
|
||||
<entry>
|
||||
<functionname>starts_with()</functionname>
|
||||
<sbr/>
|
||||
<functionname>istarts_with()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>ends_with</code></entry>
|
||||
<entry>Check if a string is a suffix of the other one</entry>
|
||||
<entry>
|
||||
<functionname>ends_with()</functionname>
|
||||
<sbr/>
|
||||
<functionname>iends_with()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>contains</code></entry>
|
||||
<entry>Check if a string is contained of the other one</entry>
|
||||
<entry>
|
||||
<functionname>contains()</functionname>
|
||||
<sbr/>
|
||||
<functionname>icontains()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>equals</code></entry>
|
||||
<entry>Check if two strings are equal</entry>
|
||||
<entry>
|
||||
<functionname>equals()</functionname>
|
||||
<sbr/>
|
||||
<functionname>iequals()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>all</code></entry>
|
||||
<entry>Check if all elements of a string satisfy the given predicate</entry>
|
||||
<entry>
|
||||
<functionname>all()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table>
|
||||
<title>Find algorithms</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Algorithm name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Functions</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>find_first</entry>
|
||||
<entry>Find the first occurrence of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>find_first()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ifind_first()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_last</entry>
|
||||
<entry>Find the last occurrence of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>find_last()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ifind_last()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_nth</entry>
|
||||
<entry>Find the nth (zero-indexed) occurrence of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>find_nth()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ifind_nth()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_head</entry>
|
||||
<entry>Retrieve the head of a string</entry>
|
||||
<entry>
|
||||
<functionname>find_head()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_tail</entry>
|
||||
<entry>Retrieve the tail of a string</entry>
|
||||
<entry>
|
||||
<functionname>find_tail()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_token</entry>
|
||||
<entry>Find first matching token in the string</entry>
|
||||
<entry>
|
||||
<functionname>find_token()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_regex</entry>
|
||||
<entry>Use the regular expression to search the string</entry>
|
||||
<entry>
|
||||
<functionname>find_regex()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find</entry>
|
||||
<entry>Generic find algorithm</entry>
|
||||
<entry>
|
||||
<functionname>find()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table>
|
||||
<title>Erase/Replace</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Algorithm name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Functions</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>replace/erase_first</entry>
|
||||
<entry>Replace/Erase the first occurrence of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>replace_first()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_first_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_first()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_first_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_first()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_first_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_first()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_first_copy()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_last</entry>
|
||||
<entry>Replace/Erase the last occurrence of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>replace_last()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_last_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_last()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_last_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_last()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_last_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_last()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_last_copy()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_nth</entry>
|
||||
<entry>Replace/Erase the nth (zero-indexed) occurrence of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>replace_nth()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_nth_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_nth()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_nth_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_nth()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_nth_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_nth()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_nth_copy()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_all</entry>
|
||||
<entry>Replace/Erase the all occurrences of a string in the input</entry>
|
||||
<entry>
|
||||
<functionname>replace_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_all_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ireplace_all_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_all_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ierase_all_copy()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_head</entry>
|
||||
<entry>Replace/Erase the head of the input</entry>
|
||||
<entry>
|
||||
<functionname>replace_head()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_head_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_head()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_head_copy()</functionname>
|
||||
<sbr/>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_tail</entry>
|
||||
<entry>Replace/Erase the tail of the input</entry>
|
||||
<entry>
|
||||
<functionname>replace_tail()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_tail_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_tail()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_tail_copy()</functionname>
|
||||
<sbr/>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_regex</entry>
|
||||
<entry>Replace/Erase a substring matching the given regular expression</entry>
|
||||
<entry>
|
||||
<functionname>replace_regex()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_regex_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_regex()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_regex_copy()</functionname>
|
||||
<sbr/>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>replace/erase_regex_all</entry>
|
||||
<entry>Replace/Erase all substrings matching the given regular expression</entry>
|
||||
<entry>
|
||||
<functionname>replace_all_regex()</functionname>
|
||||
<sbr/>
|
||||
<functionname>replace_all_regex_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_all_regex()</functionname>
|
||||
<sbr/>
|
||||
<functionname>erase_all_regex_copy()</functionname>
|
||||
<sbr/>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>find_format</entry>
|
||||
<entry>Generic replace algorithm</entry>
|
||||
<entry>
|
||||
<functionname>find_format()</functionname>
|
||||
<sbr/>
|
||||
<functionname>find_format_copy()</functionname>
|
||||
<sbr/>
|
||||
<functionname>find_format_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>find_format_all_copy()()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table>
|
||||
<title>Split</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Algorithm name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Functions</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>find_all</entry>
|
||||
<entry>Find/Extract all matching substrings in the input</entry>
|
||||
<entry>
|
||||
<functionname>find_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>ifind_all()</functionname>
|
||||
<sbr/>
|
||||
<functionname>find_all_regex()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>split</entry>
|
||||
<entry>Split input into parts</entry>
|
||||
<entry>
|
||||
<functionname>split()</functionname>
|
||||
<sbr/>
|
||||
<functionname>split_regex()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
<section>
|
||||
<title>Finders and Formatters</title>
|
||||
|
||||
<table>
|
||||
<title>Finders</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Finder</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Generators</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>first_finder</entry>
|
||||
<entry>Search for the first match of the string in an input</entry>
|
||||
<entry>
|
||||
<functionname>first_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>last_finder</entry>
|
||||
<entry>Search for the last match of the string in an input</entry>
|
||||
<entry>
|
||||
<functionname>last_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>nth_finder</entry>
|
||||
<entry>Search for the nth (zero-indexed) match of the string in an input</entry>
|
||||
<entry>
|
||||
<functionname>nth_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>head_finder</entry>
|
||||
<entry>Retrieve the head of an input</entry>
|
||||
<entry>
|
||||
<functionname>head_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>tail_finder</entry>
|
||||
<entry>Retrieve the tail of an input</entry>
|
||||
<entry>
|
||||
<functionname>tail_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>token_finder</entry>
|
||||
<entry>Search for a matching token in an input</entry>
|
||||
<entry>
|
||||
<functionname>token_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>range_finder</entry>
|
||||
<entry>Do no search, always returns the given range</entry>
|
||||
<entry>
|
||||
<functionname>range_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>regex_finder</entry>
|
||||
<entry>Search for a substring matching the given regex</entry>
|
||||
<entry>
|
||||
<functionname>regex_finder()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<title>Formatters</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Formatter</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Generators</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>const_formatter</entry>
|
||||
<entry>Constant formatter. Always return the specified string</entry>
|
||||
<entry>
|
||||
<functionname>const_formatter()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>identity_formatter</entry>
|
||||
<entry>Identity formatter. Return unmodified input input</entry>
|
||||
<entry>
|
||||
<functionname>identity_formatter()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>empty_formatter</entry>
|
||||
<entry>Null formatter. Always return an empty string</entry>
|
||||
<entry>
|
||||
<functionname>empty_formatter()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>regex_formatter</entry>
|
||||
<entry>Regex formatter. Format regex match using the specification in the format string</entry>
|
||||
<entry>
|
||||
<functionname>regex_formatter()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
<section>
|
||||
<title>Iterators</title>
|
||||
|
||||
<table>
|
||||
<title>Find Iterators</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Iterator name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Iterator class</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>find_iterator</entry>
|
||||
<entry>Iterates through matching substrings in the input</entry>
|
||||
<entry>
|
||||
<classname>find_iterator</classname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>split_iterator</entry>
|
||||
<entry>Iterates through gaps between matching substrings in the input</entry>
|
||||
<entry>
|
||||
<classname>split_iterator</classname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Classification</title>
|
||||
|
||||
<table>
|
||||
<title>Predicates</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Predicate name</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Generator</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>is_classified</entry>
|
||||
<entry>Generic <code>ctype</code> mask based classification</entry>
|
||||
<entry>
|
||||
<functionname>is_classified()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_space</entry>
|
||||
<entry>Recognize spaces</entry>
|
||||
<entry>
|
||||
<functionname>is_space()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_alnum</entry>
|
||||
<entry>Recognize alphanumeric characters</entry>
|
||||
<entry>
|
||||
<functionname>is_alnum()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_alpha</entry>
|
||||
<entry>Recognize letters</entry>
|
||||
<entry>
|
||||
<functionname>is_alpha()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_cntrl</entry>
|
||||
<entry>Recognize control characters</entry>
|
||||
<entry>
|
||||
<functionname>is_cntrl()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_digit</entry>
|
||||
<entry>Recognize decimal digits</entry>
|
||||
<entry>
|
||||
<functionname>is_digit()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_graph</entry>
|
||||
<entry>Recognize graphical characters</entry>
|
||||
<entry>
|
||||
<functionname>is_graph()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_lower</entry>
|
||||
<entry>Recognize lower case characters</entry>
|
||||
<entry>
|
||||
<functionname>is_lower()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_print</entry>
|
||||
<entry>Recognize printable characters</entry>
|
||||
<entry>
|
||||
<functionname>is_print()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_punct</entry>
|
||||
<entry>Recognize punctuation characters</entry>
|
||||
<entry>
|
||||
<functionname>is_punct()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_upper</entry>
|
||||
<entry>Recognize uppercase characters</entry>
|
||||
<entry>
|
||||
<functionname>is_upper()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>is_xdigit</entry>
|
||||
<entry>Recognize hexadecimal digits</entry>
|
||||
<entry>
|
||||
<functionname>is_xdigit()</functionname>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
@ -5,39 +5,9 @@
|
||||
<title>Rationale</title>
|
||||
|
||||
<using-namespace name="boost"/>
|
||||
<using-namespace name="boost::string_algo"/>
|
||||
<using-namespace name="boost::algorithm"/>
|
||||
|
||||
<section id="string_algo.structure">
|
||||
<title>Library structure</title>
|
||||
|
||||
<para>
|
||||
When designing a library it is always a problem to find a balance between generalization
|
||||
and usability. A generic utility can have a wider range of usage with more options for extensibility,
|
||||
but it can also bring unwanted complexity for everyday usage.
|
||||
</para>
|
||||
<para>
|
||||
Imagine a library for drawing geometric objects. It can contain one generic function <code>draw()</code>
|
||||
with many parameters specifying what to draw, like size, number of edges, shape etc.
|
||||
This would allow you to draw almost anything, but usually a user only needs to draw
|
||||
only a triangle or a square and she will have to specify this simple request in a
|
||||
very complicated way.For this purpose two functions, <code>draw_triangle()</code> and
|
||||
<code>draw_square()</code>, would suit much better then a generic <code>draw()</code> function.
|
||||
</para>
|
||||
<para>
|
||||
The String Algorithm Library solves this problem by dividing the interface into two layers.
|
||||
The first layer (defined in the namespace boost) contains ready to use algorithms specialized
|
||||
for common tasks. They are provided in multiple variants to better suit specific needs.
|
||||
The second layer (defined in the namespace <code>boost::string_algo</code>), provides generic interfaces with
|
||||
more options for extending and tunning.
|
||||
<para>
|
||||
</para>
|
||||
For instance, a <functionname>boost::trim()</functionname> algorithm trims spaces from
|
||||
an input string. When there is a need to trim something else, there is
|
||||
<functionname>boost::string_algo::trim()</functionname> which interface allows one to specify a
|
||||
predicate which selects the characters to be removed.
|
||||
</para>
|
||||
</section>
|
||||
<section it="string_algo.locale">
|
||||
<section it="string_algo.locale">
|
||||
<title>Locales</title>
|
||||
|
||||
<para>
|
||||
@ -49,15 +19,15 @@
|
||||
C++ allows to work with multiple different instances of locales at once. If an algorithm
|
||||
manipulates some data in a way that requires the usage of locales, there must be a way
|
||||
to specify them. However, one instance of locales is sufficient for most of the applications,
|
||||
and for a user it could be very tedious to specify which locales to use on every place
|
||||
and for a user it could be very tedious to specify which locales to use at every place
|
||||
where it is needed.
|
||||
</para>
|
||||
<para>
|
||||
Fortunately, the C++ standard allows to specify the <emphasis>global</emphasis> locales (using static member
|
||||
function <code>std:locale::global()</code>). When instantiating an
|
||||
<code>std::locale</code> class without explicit information, the instance will
|
||||
be initialized with the <emphasis>global</emphasis> locale. It means, that if an algorithm needs a locale,
|
||||
it should have an <code>std::locale</code> parameter with default value <code>std::locale()</code>.
|
||||
be initialized with the <emphasis>global</emphasis> locale. This implies, that if an algorithm needs a locale,
|
||||
it should have an <code>std::locale</code> parameter defaulting to <code>std::locale()</code>.
|
||||
If a user needs to specify locales explicitly, she can do so. Otherwise the <emphasis>global</emphasis>
|
||||
locales are used.
|
||||
</para>
|
||||
@ -67,9 +37,9 @@
|
||||
|
||||
<para>
|
||||
Regular expressions are an essential part of text processing. For this reason, the library
|
||||
provides also regex variants of some algorithms. The library does not try to replace
|
||||
<libraryname>Boost.Regex</libraryname>, but it merely wraps its functionality in a new interface.
|
||||
As a part of this library regex algorithms integrate smoothly with other components which
|
||||
also provides regex variants of some algorithms. The library does not attempt to replace
|
||||
<libraryname>Boost.Regex</libraryname>; it merely wraps its functionality in a new interface.
|
||||
As a part of this library, regex algorithms integrate smoothly with other components, which
|
||||
brings additional value.
|
||||
</para>
|
||||
</section>
|
||||
|
17
string/doc/release_notes.xml
Normal file
17
string/doc/release_notes.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
||||
<section id="string_algo.release_notes" last-revision="$Date$">
|
||||
<title>Release Notes</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">1.32</emphasis></para>
|
||||
<para>Initial release in Boost</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">1.33</emphasis></para>
|
||||
<para>Internal version of collection traits removed, library adapted to Boost.Range</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
||||
<library name="string_algo" dirname="string_algo" xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
<library name="String Algorithms" dirname="algorithm/string" xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
id="string_algo" last-revision="$Date$">
|
||||
<libraryinfo>
|
||||
<author>
|
||||
@ -12,6 +12,7 @@
|
||||
<copyright>
|
||||
<year>2002</year>
|
||||
<year>2003</year>
|
||||
<year>2004</year>
|
||||
<holder>Pavol Droba</holder>
|
||||
</copyright>
|
||||
|
||||
@ -24,17 +25,20 @@
|
||||
</legalnotice>
|
||||
|
||||
<librarypurpose>
|
||||
A set of generic string-related algorithms and utilities.
|
||||
A set of generic string-related algorithms and utilities
|
||||
</librarypurpose>
|
||||
<librarycategory name="category:algoritms"/>
|
||||
<librarycategory name="category:string-text"/>
|
||||
</libraryinfo>
|
||||
|
||||
<title>Boost String Algorithms Library</title>
|
||||
<xi:include href="intro.xml"/>
|
||||
<xi:include href="release_notes.xml"/>
|
||||
<xi:include href="usage.xml"/>
|
||||
<xi:include href="quickref.xml"/>
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="concept.xml"/>
|
||||
<xi:include href="reference.boostbook"/>
|
||||
<xi:include href="autodoc.boostbook"/>
|
||||
<xi:include href="rationale.xml"/>
|
||||
<xi:include href="environment.xml"/>
|
||||
<xi:include href="credits.xml"/>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<title>Usage</title>
|
||||
|
||||
<using-namespace name="boost"/>
|
||||
<using-namespace name="boost::string_algo"/>
|
||||
<using-namespace name="boost::algorithm"/>
|
||||
|
||||
|
||||
<section>
|
||||
@ -15,17 +15,20 @@
|
||||
Using the algorithms is straightforward. Let us have a look at the first example:
|
||||
</para>
|
||||
<programlisting>
|
||||
#include <boost/string_algo.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
namespace sa=boost::string_algo
|
||||
|
||||
// ...
|
||||
|
||||
string str1(" hello world! ");
|
||||
trim( to_upper(str1) ); // str1 == "HELLO WORLD!"
|
||||
to_upper(str1); // str1 == " HELLO WORLD! "
|
||||
trim(str1); // str1 == "HELLO WORLD!"
|
||||
|
||||
string str2=ireplace_first_copy(str1,"hello","goodbye"); // str2 == "goodbye WORLD!"
|
||||
string str2=
|
||||
to_lower_copy(
|
||||
ireplace_first_copy(
|
||||
str1,"hello","goodbye")); // str2 == "goodbye world!"
|
||||
</programlisting>
|
||||
<para>
|
||||
This example converts str1 to upper case and trims spaces from the start and the end
|
||||
@ -35,19 +38,19 @@
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Container parameters:</emphasis>
|
||||
Unlike the STL algorithms, parameters are not specified only in form
|
||||
Unlike in the STL algorithms, parameters are not specified only in the form
|
||||
of iterators. The STL convention allows for great flexibility,
|
||||
but it has several limitation. It is not possible to <emphasis>stack</emphasis> algorithms together,
|
||||
because a container is passed in two parameters, so it is not possible to use
|
||||
but it has several limitations. It is not possible to <emphasis>stack</emphasis> algorithms together,
|
||||
because a container is passed in two parameters. Therefore it is not possible to use
|
||||
a return value from another algorithm. It is considerably easier to write
|
||||
<code>to_lower(str1)</code>, then <code>to_lower(str1.begin(), str1.end())</code>.
|
||||
<code>to_lower(str1)</code>, than <code>to_lower(str1.begin(), str1.end())</code>.
|
||||
</para>
|
||||
<para>
|
||||
The magic of <link linkend="string_algo.container_traits">container_traits</link>
|
||||
provides a uniform way of handling different containers.
|
||||
The magic of <ulink url="../../libs/range/index.html">Boost.Range</ulink>
|
||||
provides a uniform way of handling different string types.
|
||||
If there is a need to pass a pair of iterators,
|
||||
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link>
|
||||
can be used to package iterators into a structure with the container interface.
|
||||
<ulink url="../../libs/range/doc/utility_class.html"><code>boost::iterator_range</code></ulink>
|
||||
can be used to package iterators into a structure with a compatible interface.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@ -61,27 +64,26 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Algorithm stacking:</emphasis>
|
||||
Copy versions return a transformed input as a result. Mutable variants return
|
||||
a reference to the input. Thus both versions allow a simple chaining of
|
||||
transformations within one expression (i.e. one can write
|
||||
<code>trim_copy(to_upper_copy(s))</code> as well as <code>trim(to_upper(s))</code>).
|
||||
Copy versions return a transformed input as a result, thus allow a simple chaining of
|
||||
transformations within one expression (i.e. one can write <code>trim_copy(to_upper_copy(s))</code>).
|
||||
Mutable versions have <code>void</code> return, to avoid misuse.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis role="bold">Naming:</emphasis>
|
||||
Naming follows the conventions from the Standard C++ Library. If there is a
|
||||
copy and mutable version of the same algorithm, the mutable version has no suffix
|
||||
and the copy version has suffix <emphasis>_copy</emphasis>.
|
||||
Some algorithms have prefix <emphasis>i</emphasis>
|
||||
copy and a mutable version of the same algorithm, the mutable version has no suffix
|
||||
and the copy version has the suffix <emphasis>_copy</emphasis>.
|
||||
Some algorithms have the prefix <emphasis>i</emphasis>
|
||||
(e.g. <functionname>ifind_first()</functionname>).
|
||||
This prefix identifies that the algorithm works in a case-insensitive manner.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
To use the library, include the <headername>boost/string_algo.hpp</headername> header.
|
||||
To use the library, include the <headername>boost/algorithm/string.hpp</headername> header.
|
||||
If the regex related functions are needed, include the
|
||||
<headername>boost/string_algo_regex.hpp</headername> header.
|
||||
<headername>boost/algorithm/string_regex.hpp</headername> header.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@ -97,7 +99,10 @@
|
||||
</programlisting>
|
||||
<para>
|
||||
<functionname>to_upper()</functionname> and <functionname>to_lower()</functionname> convert the case of
|
||||
characters in a container using a specified locale.
|
||||
characters in a string using a specified locale.
|
||||
</para>
|
||||
<para>
|
||||
For more information see the reference for <headername>boost/algorithm/string/case_conv.hpp</headername>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@ -125,28 +130,32 @@
|
||||
char text1[]="hello world!";
|
||||
cout
|
||||
<< text1
|
||||
<< all( text1, is_lower<char>() )? "is": "is not"
|
||||
<< "written in the lower case"
|
||||
<< all( text1, is_lower() )? "is": "is not"
|
||||
<< " written in the lower case"
|
||||
<< endl; // prints "hello world! is written in the lower case"
|
||||
</programlisting>
|
||||
<para>
|
||||
The predicates are resolving if a substring is contained in the input string
|
||||
under various conditions. The conditions are if a string starts with the substring,
|
||||
The predicates determine whether if a substring is contained in the input string
|
||||
under various conditions. The conditions are: a string starts with the substring,
|
||||
ends with the substring,
|
||||
simply contains the substring or if both strings are equal. See the reference for
|
||||
<headername>boost/string_algo/predicate.hpp</headername> for more details.
|
||||
<headername>boost/algorithm/string/predicate.hpp</headername> for more details.
|
||||
</para>
|
||||
<para>
|
||||
In addition the algorithm <functionname>all()</functionname> checks
|
||||
all elements of a container to satisfy a condition specified by a predicate.
|
||||
This predicate can be any unary predicate, but the library provides a bunch of
|
||||
useful string-related predicates ready for use.
|
||||
These are located in the <headername>boost/string_algo/classification.hpp</headername> header.
|
||||
useful string-related predicates and combinators ready for use.
|
||||
These are located in the <headername>boost/algorithm/string/classification.hpp</headername> header.
|
||||
Classification predicates can be combined using logical combinators to form
|
||||
a more complex expressions. For example: <code>is_from_range('a','z') || is_digit()</code>
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Trimming</title>
|
||||
|
||||
<para>
|
||||
When parsing the input of a user, strings usually have unwanted leading or trailing
|
||||
When parsing the input from a user, strings usually have unwanted leading or trailing
|
||||
characters. To get rid of them, we need trim functions:
|
||||
</para>
|
||||
<programlisting>
|
||||
@ -157,15 +166,15 @@
|
||||
|
||||
string phone="00423333444";
|
||||
// remove leading 0 from the phone number
|
||||
sa::trim_left(phone,is_any_of<char>("0")); // phone == "423333444"
|
||||
trim_left_if(phone,is_any_of("0")); // phone == "423333444"
|
||||
</programlisting>
|
||||
<para>
|
||||
It is possible to trim the spaces on the right, on the left or on the both sides of a string.
|
||||
And for those cases when there is a need to remove something else than blank space, the
|
||||
<code>string_algo</code> namespace contains generic versions of the trim algorithms. Using these,
|
||||
a user can specify a functor which will select the <emphasis>space</emphasis> to be removed. It is possible to use
|
||||
classification predicates like <functionname>is_digit()</functionname> mentioned in the previous paragraph.
|
||||
See the reference for the <headername>boost/string_algo/trim.hpp</headername>.
|
||||
It is possible to trim the spaces on the right, on the left or on both sides of a string.
|
||||
And for those cases when there is a need to remove something else than blank space, there
|
||||
are <emphasis>_if</emphasis> variants. Using these, a user can specify a functor which will
|
||||
select the <emphasis>space</emphasis> to be removed. It is possible to use classification
|
||||
predicates like <functionname>is_digit()</functionname> mentioned in the previous paragraph.
|
||||
See the reference for the <headername>boost/algorithm/string/trim.hpp</headername>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
@ -182,28 +191,38 @@
|
||||
// text = "hello dommy!"
|
||||
|
||||
to_upper(result); // text == "hello doMMy!"
|
||||
|
||||
// iterator_range is convertible to bool
|
||||
if(find_first(text, "dolly"))
|
||||
{
|
||||
cout << "Dolly is there" << endl;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
We have used <functionname>find_last()</functionname> to search the <code>text</code> for "ll".
|
||||
The result is given in the <link linkend="string_algo.iterator_range"><code>iterator_range</code></link>.
|
||||
The result is given in the <ulink url="../../libs/range/doc/utility_class.html"><code>boost::iterator_range</code></ulink>.
|
||||
This range delimits the
|
||||
part of the input which satisfies the find criteria. In our example it is the last occurrence of "ll".
|
||||
|
||||
As we can see, input of the <functionname>find_last()</functionname> algorithm can be also
|
||||
char[] because this type is supported by
|
||||
<link linkend="string_algo.container_traits">container_traits</link>.
|
||||
<ulink url="../../libs/range/index.html">Boost.Range</ulink>.
|
||||
|
||||
Following lines transform the result. Notice, that
|
||||
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link> have familiar
|
||||
The following lines transform the result. Notice that
|
||||
<ulink url="../../libs/range/doc/utility_class.html"><code>boost::iterator_range</code></ulink> has familiar
|
||||
<code>begin()</code> and <code>end()</code> methods, so it can be used like any other STL container.
|
||||
Also it is convertible to bool therefore it is easy to use find algorithms for a simple containment checking.
|
||||
</para>
|
||||
<para>
|
||||
Find algorithms are located in <headername>boost/algorithm/string/find.hpp</headername>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Replace Algorithms</title>
|
||||
<para>
|
||||
Find algorithms can be used for searching for a specific part of the sequence. Replace goes one step
|
||||
Find algorithms can be used for searching for a specific part of string. Replace goes one step
|
||||
further. After a matching part is found, it is substituted with something else. The substitution is computed
|
||||
from an original, using some transformation.
|
||||
from the original, using some transformation.
|
||||
</para>
|
||||
<programlisting>
|
||||
string str1="Hello Dolly, Hello World!"
|
||||
@ -216,7 +235,7 @@
|
||||
For the complete list of replace and erase functions see the
|
||||
<link linkend="string_algo.reference">reference</link>.
|
||||
There is a lot of predefined function for common usage, however, the library allows you to
|
||||
define a custom <code>replace()</code> that suits a specific need. There is a generic <functionname>replace()</functionname>
|
||||
define a custom <code>replace()</code> that suits a specific need. There is a generic <functionname>find_format()</functionname>
|
||||
function which takes two parameters.
|
||||
The first one is a <link linkend="string_algo.finder_concept">Finder</link> object, the second one is
|
||||
a <link linkend="string_algo.formatter_concept">Formatter</link> object.
|
||||
@ -224,14 +243,81 @@
|
||||
takes the result of the Finder (usually a reference to the found substring) and creates a
|
||||
substitute for it. Replace algorithm puts these two together and makes the desired substitution.
|
||||
</para>
|
||||
<para>
|
||||
Check <headername>boost/algorithm/string/replace.hpp</headername>, <headername>boost/algorithm/string/erase.hpp</headername> and
|
||||
<headername>boost/algorithm/string/find_format.hpp</headername> for reference.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Find Iterator</title>
|
||||
|
||||
<para>
|
||||
An extension to find algorithms it the Find Iterator. Instead of searching for just a one part of a string,
|
||||
the find iterator allows us to iterate over the substrings matching the specified criteria.
|
||||
This facility is using the <link linkend="string_algo.finder_concept">Finder</link> to incrementally
|
||||
search the string.
|
||||
Dereferencing a find iterator yields an <ulink url="../../libs/range/doc/utility_class.html"><code>boost::iterator_range</code></ulink>
|
||||
object, that delimits the current match.
|
||||
</para>
|
||||
<para>
|
||||
There are two iterators provided <classname>find_iterator</classname> and
|
||||
<classname>split_iterator</classname>. The former iterates over substrings that are found using the specified
|
||||
Finder. The latter iterates over the gaps between these substrings.
|
||||
</para>
|
||||
<programlisting>
|
||||
string str1("abc-*-ABC-*-aBc");
|
||||
// Find all 'abc' substrings (ignoring the case)
|
||||
// Create a find_iterator
|
||||
typedef find_iterator<string::iterator> string_find_iterator;
|
||||
for(string_find_iterator It=
|
||||
make_find_iterator(str1, first_finder("abc", is_iequal()));
|
||||
It!=string_find_iterator();
|
||||
++It)
|
||||
{
|
||||
cout << copy_range<std::string>(*It) << endl;
|
||||
}
|
||||
|
||||
// Output will be:
|
||||
// abc
|
||||
// ABC
|
||||
// aBC
|
||||
|
||||
typedef split_iterator<string::iterator> string_split_iterator;
|
||||
for(string_find_iterator It=
|
||||
make_split_iterator(str1, first_finder("-*-", is_iequal()));
|
||||
It!=string_find_iterator();
|
||||
++It)
|
||||
{
|
||||
cout << copy_range<std::string>(*It) << endl;
|
||||
}
|
||||
|
||||
// Output will be:
|
||||
// abc
|
||||
// ABC
|
||||
// aBC
|
||||
</programlisting>
|
||||
<para>
|
||||
Note that the find iterators have only one template parameter. It is the base iterator type.
|
||||
The Finder is specified at runtime. This allows us to typedef a find iterator for
|
||||
common string types and reuse it. Additionally make_*_iterator functions help
|
||||
to construct a find iterator for a particular range.
|
||||
</para>
|
||||
<para>
|
||||
See the reference in <headername>boost/algorithm/string/find_iterator.hpp</headername>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Split</title>
|
||||
|
||||
<para>
|
||||
Split algorithms allow one to divide a sequence into parts. Each part represents a
|
||||
<emphasis>token</emphasis> and tokens are separated by <emphasis>separators</emphasis>.
|
||||
One can either search for tokens or search for separators:
|
||||
Split algorithms are an extension to the find iterator for one common usage scenario.
|
||||
These algorithms use a find iterator and store all matches into the provided
|
||||
container. This container must be able to hold copies (e.g. <code>std::string</code>) or
|
||||
references (e.g. <code>iterator_range</code>) of the extracted substrings.
|
||||
</para>
|
||||
<para>
|
||||
Two algorithms are provided. <functionname>find_all()</functionname> finds all copies
|
||||
of a string in the input. <functionname>split()</functionname> splits the input into parts.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
@ -242,34 +328,26 @@
|
||||
find_vector_type FindVec; // #1: Search for separators
|
||||
ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] }
|
||||
|
||||
typdef vector< string > split_vector_type;
|
||||
typedef vector< string > split_vector_type;
|
||||
|
||||
split_vector_type SplitVec; // #2: Search for tokens
|
||||
split( SplitVec, str1, is_any_of<char>("-*") ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
|
||||
split( SplitVec, str1, is_any_of("-*") ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
|
||||
</programlisting>
|
||||
<para>
|
||||
<code>[hello]</code> designates an <code>iterator_range</code> delimiting this substring.
|
||||
</para>
|
||||
<para>
|
||||
The result of a split algorithm is a <emphasis>container of containers</emphasis>. There is only one restriction:
|
||||
The inner container type must be able to hold extracted parts of the input sequence. This example
|
||||
shows the special case where the inner container is an
|
||||
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link>
|
||||
instead of e.g. <code>std::string</code>. This way, a user gets a reference
|
||||
(in the form of iterators) delimiting the parts of the input sequence. Otherwise, a copy of
|
||||
each extracted part is created and added to the outer container.
|
||||
First example show how to construct a container to hold references to all extracted
|
||||
substrings. Algorithm <functionname>ifind_all()</functionname> puts into FindVec references
|
||||
to all substrings that are in case-insensitive manner equal to "abc".
|
||||
</para>
|
||||
<para>
|
||||
So to recap, there are two basic algorithms: <functionname>find_all()</functionname>
|
||||
returns extracts the parts
|
||||
matching the specification whereas <functionname>split()</functionname> uses the matching
|
||||
parts as delimiters, and extracts the parts in between them.
|
||||
Second example uses <functionname>split()</functionname> to split string str1 into parts
|
||||
separated by characters '-' or '*'. These parts are then put into the SplitVec.
|
||||
It is possible to specify if adjacent separators are concatenated or not.
|
||||
</para>
|
||||
<para>
|
||||
Generalizations of these two algorithms are called <functionname>iter_find()</functionname> and
|
||||
<functionname>iter_split()</functionname>. They take a
|
||||
<link linkend="string_algo.finder_concept">Finder</link> object, as an argument to search for
|
||||
the substring.
|
||||
</para>
|
||||
</section>
|
||||
More information can be found in the reference: <headername>boost/algorithm/string/split.hpp</headername>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -49,7 +49,7 @@ int main()
|
||||
cout << "\";.,\" are all punctuation characters" << endl;
|
||||
}
|
||||
|
||||
// Classification predicated can be combined
|
||||
// Classification predicates can be combined
|
||||
if ( all("abcxxx", is_any_of("xabc") && !is_space() ) )
|
||||
{
|
||||
cout << "true" << endl;
|
||||
|
@ -10,9 +10,10 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/erase.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
//#include <boost/algorithm/string/replace.hpp>
|
||||
//#include <boost/algorithm/string/erase.hpp>
|
||||
//#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
//Following two includes contain second-layer function.
|
||||
//They are already included by first-layer header
|
||||
|
@ -24,7 +24,7 @@ using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
// replace mark specification, specialize for a specific element type
|
||||
template< typename T > T repeat_mark() { return std::numeric_limits<T>::max(); };
|
||||
template< typename T > T repeat_mark() { return (std::numeric_limits<T>::max)(); };
|
||||
|
||||
// Compression -----------------------------------------------------------------------
|
||||
|
||||
@ -59,7 +59,7 @@ struct find_compressF
|
||||
{
|
||||
input_iterator_type It2=It++;
|
||||
|
||||
if ( It==End || Cnt>=std::numeric_limits<value_type>::max() )
|
||||
if ( It==End || Cnt>=(std::numeric_limits<value_type>::max)() )
|
||||
{
|
||||
return result_type( MStart, It );
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
#include <boost/algorithm/string/iterator_range.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/find_iterator.hpp>
|
||||
@ -36,7 +35,7 @@ int main()
|
||||
It!=string_find_iterator();
|
||||
++It)
|
||||
{
|
||||
cout << copy_iterator_range<std::string>(*It) << endl;
|
||||
cout << copy_range<std::string>(*It) << endl;
|
||||
// shift all chars in the match by one
|
||||
transform(
|
||||
It->begin(), It->end(),
|
||||
|
9
string/index.html
Normal file
9
string/index.html
Normal file
@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/string_algo.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../../../doc/html/string_algo.html">../../doc/html/string_algo.html</a>
|
||||
</body>
|
||||
</html>
|
@ -16,47 +16,53 @@ import testing ;
|
||||
DEPENDS all : test ;
|
||||
|
||||
{
|
||||
test-suite string_algo
|
||||
: [ run
|
||||
container_test.cpp
|
||||
: :
|
||||
:
|
||||
: container
|
||||
]
|
||||
[ run
|
||||
test-suite algorithm/string
|
||||
: [ run
|
||||
trim_test.cpp
|
||||
: :
|
||||
:
|
||||
std::locale-support
|
||||
std::facet-support
|
||||
: trim
|
||||
]
|
||||
[ run
|
||||
conv_test.cpp
|
||||
: :
|
||||
:
|
||||
std::locale-support
|
||||
std::facet-support
|
||||
: conv
|
||||
]
|
||||
[ run
|
||||
predicate_test.cpp
|
||||
: :
|
||||
:
|
||||
std::locale-support
|
||||
std::facet-support
|
||||
: predicate
|
||||
]
|
||||
[ run
|
||||
find_test.cpp
|
||||
: :
|
||||
:
|
||||
std::locale-support
|
||||
std::facet-support
|
||||
: find
|
||||
]
|
||||
[ run
|
||||
split_test.cpp
|
||||
: :
|
||||
:
|
||||
std::locale-support
|
||||
std::facet-support
|
||||
: split
|
||||
]
|
||||
[ run
|
||||
replace_test.cpp
|
||||
: :
|
||||
:
|
||||
std::locale-support
|
||||
std::facet-support
|
||||
: replace
|
||||
]
|
||||
[ run
|
||||
|
57
string/test/Jamfile.v2
Normal file
57
string/test/Jamfile.v2
Normal file
@ -0,0 +1,57 @@
|
||||
# Boost string_algo library test suite Jamfile ----------------------------
|
||||
#
|
||||
# Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
# distribution is subject to the Boost Software License, Version
|
||||
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
import testing ;
|
||||
|
||||
test-suite algorithm/string
|
||||
: [ run
|
||||
trim_test.cpp
|
||||
: :
|
||||
:
|
||||
: trim
|
||||
]
|
||||
[ run
|
||||
conv_test.cpp
|
||||
: :
|
||||
:
|
||||
: conv
|
||||
]
|
||||
[ run
|
||||
predicate_test.cpp
|
||||
: :
|
||||
:
|
||||
: predicate
|
||||
]
|
||||
[ run
|
||||
find_test.cpp
|
||||
: :
|
||||
:
|
||||
: find
|
||||
]
|
||||
[ run
|
||||
split_test.cpp
|
||||
: :
|
||||
:
|
||||
: split
|
||||
]
|
||||
[ run
|
||||
replace_test.cpp
|
||||
: :
|
||||
:
|
||||
: replace
|
||||
]
|
||||
[ run
|
||||
regex_test.cpp
|
||||
../../../regex/build//boost_regex
|
||||
: :
|
||||
:
|
||||
: regex
|
||||
]
|
||||
;
|
||||
|
@ -1,127 +0,0 @@
|
||||
// Boost string_algo library substr_test.cpp file ------------------//
|
||||
|
||||
// Copyright Pavol Droba 2002-2003. Use, modification and
|
||||
// distribution is subject to the Boost Software License, Version
|
||||
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/algorithm/string/collection_traits.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
// equals predicate is used for result comparison
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
// test tools
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
namespace algo = ::boost::algorithm;
|
||||
|
||||
template< typename T >
|
||||
void argument_cv_test( const T& C, const string& strResult )
|
||||
{
|
||||
BOOST_CHECK( equals( make_iterator_range(algo::begin(C),algo::end(C)), strResult ) );
|
||||
BOOST_CHECK( algo::size(C)==strResult.size() );
|
||||
BOOST_CHECK( algo::empty(C)==strResult.empty() );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void argument_test( T& C, const string& strResult )
|
||||
{
|
||||
BOOST_CHECK( equals( make_iterator_range(algo::begin(C),algo::end(C)), strResult ) );
|
||||
BOOST_CHECK( algo::size(C)==strResult.size() );
|
||||
BOOST_CHECK( algo::empty(C)==strResult.empty() );
|
||||
}
|
||||
|
||||
void container_test()
|
||||
{
|
||||
BOOST_CHECKPOINT( "type test" );
|
||||
|
||||
// types test
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<string>::type,
|
||||
string::iterator>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<const string>::type,
|
||||
string::const_iterator>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<char[4]>::type, char*>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<const char[4]>::type,
|
||||
const char*>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<char*>::type, char*>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<const char*>::type,
|
||||
const char*>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<
|
||||
pair<string::iterator, string::iterator> >::type, string::iterator>::value) );
|
||||
BOOST_REQUIRE( (is_same<
|
||||
algo::result_iterator_of<
|
||||
const pair<string::iterator, string::iterator> >::type,
|
||||
string::iterator>::value) );
|
||||
|
||||
BOOST_CHECKPOINT( "non-empty sequence test" );
|
||||
|
||||
string str1("abc");
|
||||
vector<char> vec1( str1.begin(), str1.end() );
|
||||
pair<string::iterator, string::iterator> pair1=
|
||||
make_pair( str1.begin(), str1.end() );
|
||||
char ach1[]="abc";
|
||||
char *pch1="abc";
|
||||
|
||||
// begin/end tests
|
||||
argument_cv_test( str1, "abc" );
|
||||
argument_test( str1, "abc" );
|
||||
argument_cv_test( vec1, "abc" );
|
||||
argument_test( vec1, "abc" );
|
||||
argument_cv_test( pair1, "abc" );
|
||||
argument_test( pair1, "abc" );
|
||||
argument_cv_test( ach1, "abc" );
|
||||
argument_test( ach1, "abc" );
|
||||
argument_cv_test( pch1, "abc" );
|
||||
argument_test( pch1, "abc" );
|
||||
|
||||
BOOST_CHECKPOINT( "empty sequence test" );
|
||||
|
||||
string str2;
|
||||
vector<char> vec2( str2.begin(), str2.end() );
|
||||
pair<string::iterator, string::iterator> pair2=
|
||||
make_pair( str2.begin(), str2.end() );
|
||||
char ach2[]="";
|
||||
char *pch2=0;
|
||||
|
||||
// begin/end tests
|
||||
argument_cv_test( str2, "" );
|
||||
argument_test( str2, "" );
|
||||
argument_cv_test( vec2, "" );
|
||||
argument_test( vec2, "" );
|
||||
argument_cv_test( pair2, "" );
|
||||
argument_test( pair2, "" );
|
||||
argument_cv_test( ach2, "" );
|
||||
argument_test( ach2, "" );
|
||||
argument_cv_test( pch2, "" );
|
||||
argument_test( pch2, "" );
|
||||
};
|
||||
|
||||
|
||||
// test main
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
container_test();
|
||||
|
||||
return 0;
|
||||
}
|
@ -7,13 +7,14 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
using namespace std;
|
||||
@ -81,8 +82,8 @@ void conv_test()
|
||||
to_upper( str3 );
|
||||
BOOST_CHECK( str3=="" );
|
||||
|
||||
free(pch1);
|
||||
free(pch2);
|
||||
delete[] pch1;
|
||||
delete[] pch2;
|
||||
}
|
||||
|
||||
// test main
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/find.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
@ -15,8 +18,6 @@
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <boost/algorithm/string/find.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
using namespace std;
|
||||
@ -27,7 +28,7 @@ void find_test()
|
||||
string str1("123abcxXxabcXxXabc321");
|
||||
string str2("abc");
|
||||
string str3("");
|
||||
char* pch1="123abcxxxabcXXXabc321";
|
||||
const char* pch1="123abcxxxabcXXXabc321";
|
||||
vector<int> vec1( str1.begin(), str1.end() );
|
||||
|
||||
// find results ------------------------------------------------------------//
|
||||
@ -47,18 +48,18 @@ void find_test()
|
||||
|
||||
nc_result=find_first( str1, string("abc") );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_result=find_first( const_cast<const string&>(str1), str2 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_result=ifind_first( const_cast<const string&>(str1), "xXX" );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 6) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 9) );
|
||||
( (cv_result.begin()-str1.begin()) == 6) &&
|
||||
( (cv_result.end()-str1.begin()) == 9) );
|
||||
|
||||
ch_result=find_first( pch1, "abc" );
|
||||
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) );
|
||||
@ -68,18 +69,18 @@ void find_test()
|
||||
|
||||
nc_result=find_last( str1, string("abc") );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 15) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 18) );
|
||||
( (nc_result.begin()-str1.begin()) == 15) &&
|
||||
( (nc_result.end()-str1.begin()) == 18) );
|
||||
|
||||
cv_result=find_last( const_cast<const string&>(str1), str2 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 15) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 18) );
|
||||
( (cv_result.begin()-str1.begin()) == 15) &&
|
||||
( (cv_result.end()-str1.begin()) == 18) );
|
||||
|
||||
cv_result=ifind_last( const_cast<const string&>(str1), "XXx" );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 12) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 15) );
|
||||
( (cv_result.begin()-str1.begin()) == 12) &&
|
||||
( (cv_result.end()-str1.begin()) == 15) );
|
||||
|
||||
ch_result=find_last( pch1, "abc" );
|
||||
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 15) && ( (ch_result.end() - pch1 ) == 18 ) );
|
||||
@ -89,18 +90,18 @@ void find_test()
|
||||
|
||||
nc_result=find_nth( str1, string("abc"), 1 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 9) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 12) );
|
||||
( (nc_result.begin()-str1.begin()) == 9) &&
|
||||
( (nc_result.end()-str1.begin()) == 12) );
|
||||
|
||||
cv_result=find_nth( const_cast<const string&>(str1), str2, 1 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 9) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 12) );
|
||||
( (cv_result.begin()-str1.begin()) == 9) &&
|
||||
( (cv_result.end()-str1.begin()) == 12) );
|
||||
|
||||
cv_result=ifind_nth( const_cast<const string&>(str1), "xxx", 1 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 12) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 15) );
|
||||
( (cv_result.begin()-str1.begin()) == 12) &&
|
||||
( (cv_result.end()-str1.begin()) == 15) );
|
||||
|
||||
ch_result=find_nth( pch1, "abc", 1 );
|
||||
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 9) && ( (ch_result.end() - pch1 ) == 12 ) );
|
||||
@ -110,13 +111,13 @@ void find_test()
|
||||
|
||||
nc_result=find_head( str1, 6 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 0) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 0) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_result=find_head( const_cast<const string&>(str1), 6 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 0) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 0) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
ch_result=find_head( pch1, 6 );
|
||||
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 0 ) && ( (ch_result.end() - pch1 ) == 6 ) );
|
||||
@ -126,13 +127,13 @@ void find_test()
|
||||
|
||||
nc_result=find_tail( str1, 6 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 15) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 21) );
|
||||
( (nc_result.begin()-str1.begin()) == 15) &&
|
||||
( (nc_result.end()-str1.begin()) == 21) );
|
||||
|
||||
cv_result=find_tail( const_cast<const string&>(str1), 6 );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 15) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 21) );
|
||||
( (cv_result.begin()-str1.begin()) == 15) &&
|
||||
( (cv_result.end()-str1.begin()) == 21) );
|
||||
|
||||
ch_result=find_tail( pch1, 6 );
|
||||
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 15 ) && ( (ch_result.end() - pch1 ) == 21 ) );
|
||||
@ -142,23 +143,23 @@ void find_test()
|
||||
|
||||
nc_result=find_token( str1, is_any_of("abc"), token_compress_on );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_on );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
nc_result=find_token( str1, is_any_of("abc"), token_compress_off );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 4) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 4) );
|
||||
|
||||
cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_off );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 4) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 4) );
|
||||
|
||||
ch_result=find_token( pch1, is_any_of("abc"), token_compress_off );
|
||||
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 3 ) && ( (ch_result.end() - pch1 ) == 4 ) );
|
||||
@ -168,26 +169,26 @@ void find_test()
|
||||
|
||||
nc_result=find(str1, first_finder(string("abc")));
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_result=find(const_cast<const string&>(str1), first_finder(str2) );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
// multi-type comparison test
|
||||
BOOST_CHECKPOINT( "multi-type" );
|
||||
|
||||
nc_vresult=find_first( vec1, string("abc") );
|
||||
BOOST_CHECK(
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.begin()) == 3) &&
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_vresult=find_first( const_cast<const vector<int>&>(vec1), str2 );
|
||||
BOOST_CHECK(
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.begin()) == 3) &&
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
// overflow test
|
||||
BOOST_CHECKPOINT( "overflow" );
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
@ -14,8 +17,6 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
@ -7,6 +7,9 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/algorithm/string/sequence_traits.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
@ -14,8 +17,6 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/sequence_traits.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
using namespace std;
|
||||
@ -24,7 +25,7 @@ using namespace boost;
|
||||
static void find_test()
|
||||
{
|
||||
string str1("123a1cxxxa23cXXXa456c321");
|
||||
char* pch1="123a1cxxxa23cXXXa456c321";
|
||||
const char* pch1="123a1cxxxa23cXXXa456c321";
|
||||
regex rx("a[0-9]+c");
|
||||
vector<int> vec1( str1.begin(), str1.end() );
|
||||
vector<string> tokens;
|
||||
@ -41,13 +42,13 @@ static void find_test()
|
||||
// basic tests
|
||||
nc_result=find_regex( str1, rx );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_result=find_regex( str1, rx );
|
||||
BOOST_CHECK(
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
|
||||
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
ch_result=find_regex( pch1, rx );
|
||||
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) );
|
||||
@ -55,13 +56,13 @@ static void find_test()
|
||||
// multi-type comparison test
|
||||
nc_vresult=find_regex( vec1, rx );
|
||||
BOOST_CHECK(
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.begin()) == 3) &&
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.end()) == 6) );
|
||||
( (nc_result.begin()-str1.begin()) == 3) &&
|
||||
( (nc_result.end()-str1.begin()) == 6) );
|
||||
|
||||
cv_vresult=find_regex( vec1, rx );
|
||||
BOOST_CHECK(
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.begin()) == 3) &&
|
||||
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.end()) == 6) );
|
||||
( (cv_result.begin()-str1.begin()) == 3) &&
|
||||
( (cv_result.end()-str1.begin()) == 6) );
|
||||
|
||||
// find_all_regex test
|
||||
find_all_regex( tokens, str1, rx );
|
||||
|
@ -7,6 +7,11 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/erase.hpp>
|
||||
#include <boost/algorithm/string/std/list_traits.hpp>
|
||||
#include <boost/algorithm/string/std/string_traits.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
@ -15,16 +20,10 @@
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/algorithm/string/std/list_traits.hpp>
|
||||
#include <boost/algorithm/string/std/string_traits.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/erase.hpp>
|
||||
|
||||
// equals predicate is used for result comparison
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/preprocessor/seq/enum.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
@ -51,6 +50,7 @@ void sequence_traits_test()
|
||||
}
|
||||
|
||||
// Combine tests for all variants of the algorithm
|
||||
#define C_ ,
|
||||
#define TEST_ALGO( Algo, Input, Params, Output ) \
|
||||
{\
|
||||
BOOST_CHECKPOINT( #Algo " - Copy" );\
|
||||
@ -58,12 +58,12 @@ void sequence_traits_test()
|
||||
string str1(Input);\
|
||||
\
|
||||
/* Copy test */ \
|
||||
BOOST_CHECK( Algo##_copy( str1, BOOST_PP_SEQ_ENUM( Params ) )==Output );\
|
||||
BOOST_CHECK( Algo##_copy( str1, Params )==Output );\
|
||||
\
|
||||
BOOST_CHECKPOINT( #Algo " - Iterator" );\
|
||||
/* Iterator test */\
|
||||
string strout;\
|
||||
Algo##_copy( back_inserter(strout), str1, BOOST_PP_SEQ_ENUM( Params ) );\
|
||||
Algo##_copy( back_inserter(strout), str1, Params );\
|
||||
BOOST_CHECK( strout==Output ); \
|
||||
\
|
||||
/* In-place test */\
|
||||
@ -71,98 +71,116 @@ void sequence_traits_test()
|
||||
list<char> list1( str1.begin(), str1.end() );\
|
||||
\
|
||||
BOOST_CHECKPOINT( #Algo " - Inplace(string)" );\
|
||||
Algo( str1, BOOST_PP_SEQ_ENUM( Params ) ); \
|
||||
Algo( str1, Params ); \
|
||||
BOOST_CHECK( equals( str1, Output ) ); \
|
||||
\
|
||||
BOOST_CHECKPOINT( #Algo " - Inplace(vector)" );\
|
||||
Algo( vec1, BOOST_PP_SEQ_ENUM( Params ) ); \
|
||||
Algo( vec1, Params ); \
|
||||
BOOST_CHECK( equals( vec1, Output ) );\
|
||||
\
|
||||
BOOST_CHECKPOINT( #Algo " - Inplace(list)" );\
|
||||
Algo( list1, BOOST_PP_SEQ_ENUM( Params ) ); \
|
||||
Algo( list1, Params ); \
|
||||
BOOST_CHECK( equals( list1, Output ) );\
|
||||
}
|
||||
|
||||
void replace_test()
|
||||
void replace_first_test()
|
||||
{
|
||||
// replace first
|
||||
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("YYY")), string("1YYY3abc2") );
|
||||
TEST_ALGO( ireplace_first, "1AbC3abc2", ("aBc")("YYY"), string("1YYY3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("Z")), string("1Z3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("XXXX")), string("1XXXX3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", (string(""))(string("XXXX")), string("1abc3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", ("")("XXXX"), string("1abc3abc2") );
|
||||
TEST_ALGO( replace_first, "", (string(""))(string("XXXX")), string("") );
|
||||
TEST_ALGO( erase_first, "1abc3abc2", (string("abc")), string("13abc2") );
|
||||
TEST_ALGO( ierase_first, "1aBc3abc2", ("abC"), "13abc2" );
|
||||
TEST_ALGO( erase_first, "1abc3abc2", ("abc"), "13abc2" );
|
||||
TEST_ALGO( erase_first, "1abc3abc2", (string("")), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_first, "", (string("abc")), string("") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("YYY"), string("1YYY3abc2") );
|
||||
TEST_ALGO( ireplace_first, "1AbC3abc2", "aBc" C_ "YYY", string("1YYY3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("Z"), string("1Z3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("XXXX"), string("1XXXX3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", string("") C_ string("XXXX"), string("1abc3abc2") );
|
||||
TEST_ALGO( replace_first, "1abc3abc2", "" C_ "XXXX", string("1abc3abc2") );
|
||||
TEST_ALGO( replace_first, "", string("") C_ string("XXXX"), string("") );
|
||||
TEST_ALGO( erase_first, "1abc3abc2", string("abc"), string("13abc2") );
|
||||
TEST_ALGO( ierase_first, "1aBc3abc2", "abC", "13abc2" );
|
||||
TEST_ALGO( erase_first, "1abc3abc2", "abc", "13abc2" );
|
||||
TEST_ALGO( erase_first, "1abc3abc2", string(""), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_first, "", string("abc"), string("") );
|
||||
}
|
||||
|
||||
void replace_last_test()
|
||||
{
|
||||
// replace last
|
||||
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("YYY")), string("1abc3YYY2") );
|
||||
TEST_ALGO( ireplace_last, "1abc3AbC2", ("aBc")("YYY"), string("1abc3YYY2") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("Z")), string("1abc3Z2") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("XXXX")), string("1abc3XXXX2") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", ("abc")("XXXX"), string("1abc3XXXX2") );
|
||||
TEST_ALGO( replace_last, "", (string(""))(string("XXXX")), string("") );
|
||||
TEST_ALGO( erase_last, "1abc3abc2", (string("abc")), string("1abc32") );
|
||||
TEST_ALGO( ierase_last, "1aBc3aBc2", ("ABC"), string("1aBc32") );
|
||||
TEST_ALGO( erase_last, "1abc3abc2", ("abc"), string("1abc32") );
|
||||
TEST_ALGO( erase_last, "1abc3abc2", (string("")), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_last, "", (string("abc")), string("") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("YYY"), string("1abc3YYY2") );
|
||||
TEST_ALGO( ireplace_last, "1abc3AbC2", "aBc" C_ "YYY", string("1abc3YYY2") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("Z"), string("1abc3Z2") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("XXXX"), string("1abc3XXXX2") );
|
||||
TEST_ALGO( replace_last, "1abc3abc2", "abc" C_ "XXXX", string("1abc3XXXX2") );
|
||||
TEST_ALGO( replace_last, "", string("") C_ string("XXXX"), string("") );
|
||||
TEST_ALGO( erase_last, "1abc3abc2", string("abc"), string("1abc32") );
|
||||
TEST_ALGO( ierase_last, "1aBc3aBc2", "ABC", string("1aBc32") );
|
||||
TEST_ALGO( erase_last, "1abc3abc2", "abc", string("1abc32") );
|
||||
TEST_ALGO( erase_last, "1abc3abc2", string(""), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_last, "", string("abc"), string("") );
|
||||
}
|
||||
|
||||
void replace_all_test()
|
||||
{
|
||||
// replace all
|
||||
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("YYY")), string("1YYY3YYY2") );
|
||||
TEST_ALGO( ireplace_all, "1aBc3AbC2", ("abC")("YYY"), string("1YYY3YYY2") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("Z")), string("1Z3Z2") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("XXXX")), string("1XXXX3XXXX2") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", ("abc")("XXXX"), string("1XXXX3XXXX2") );
|
||||
TEST_ALGO( replace_all, "", (string(""))(string("XXXX")), string("") );
|
||||
TEST_ALGO( erase_all, "1abc3abc2", (string("abc")), string("132") );
|
||||
TEST_ALGO( ierase_all, "1aBc3aBc2", ("aBC"), string("132") );
|
||||
TEST_ALGO( erase_all, "1abc3abc2", ("abc"), string("132") );
|
||||
TEST_ALGO( erase_all, "1abc3abc2", (string("")), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_all, "", (string("abc")), string("") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("YYY"), string("1YYY3YYY2") );
|
||||
TEST_ALGO( ireplace_all, "1aBc3AbC2", "abC" C_ "YYY", string("1YYY3YYY2") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("Z"), string("1Z3Z2") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("XXXX"), string("1XXXX3XXXX2") );
|
||||
TEST_ALGO( replace_all, "1abc3abc2", "abc" C_ "XXXX", string("1XXXX3XXXX2") );
|
||||
TEST_ALGO( replace_all, "", string("") C_ string("XXXX"), string("") );
|
||||
TEST_ALGO( erase_all, "1abc3abc2", string("abc"), string("132") );
|
||||
TEST_ALGO( ierase_all, "1aBc3aBc2", "aBC", string("132") );
|
||||
TEST_ALGO( erase_all, "1abc3abc2", "abc", string("132") );
|
||||
TEST_ALGO( erase_all, "1abc3abc2", string(""), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_all, "", string("abc"), string("") );
|
||||
}
|
||||
|
||||
void replace_nth_test()
|
||||
{
|
||||
// replace nth
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("YYY")), string("1YYY3abc2") );
|
||||
TEST_ALGO( ireplace_nth, "1AbC3abc2", ("aBc")(0)("YYY"), string("1YYY3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("Z")), string("1Z3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("XXXX")), string("1XXXX3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", ("abc")(0)("XXXX"), string("1XXXX3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", (string(""))(0)(string("XXXX")), string("1abc3abc2") );
|
||||
TEST_ALGO( replace_nth, "", (string(""))(0)(string("XXXX")), string("") );
|
||||
TEST_ALGO( erase_nth, "1abc3abc2", (string("abc"))(0), string("13abc2") );
|
||||
TEST_ALGO( ierase_nth, "1aBc3aBc2", ("ABC")(0), string("13aBc2") );
|
||||
TEST_ALGO( erase_nth, "1abc3abc2", ("abc")(0), string("13abc2") );
|
||||
TEST_ALGO( erase_nth, "1abc3abc2", (string(""))(0), string("1abc3abc2") );
|
||||
TEST_ALGO( erase_nth, "", (string("abc"))(0), string("") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(1)(string("YYY")), string("1abc3YYY2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(2)(string("YYY")), string("1abc3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("YYY"), string("1YYY3abc2") );
|
||||
TEST_ALGO( ireplace_nth, "1AbC3abc2", "aBc" C_ 0 C_ "YYY", string("1YYY3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("Z"), string("1Z3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("XXXX"), string("1XXXX3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ 0 C_ "XXXX", string("1XXXX3abc2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", string("") C_ 0 C_ string("XXXX"), string("1abc3abc2") );
|
||||
TEST_ALGO( replace_nth, "", string("") C_ 0 C_ string("XXXX"), string("") );
|
||||
TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ 0, string("13abc2") );
|
||||
TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ 0, string("13aBc2") );
|
||||
TEST_ALGO( erase_nth, "1abc3abc2", "abc" C_ 0, string("13abc2") );
|
||||
TEST_ALGO( erase_nth, "1abc3abc2", string("") C_ 0, string("1abc3abc2") );
|
||||
TEST_ALGO( erase_nth, "", string("abc") C_ 0, string("") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 1 C_ string("YYY"), string("1abc3YYY2") );
|
||||
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 2 C_ string("YYY"), string("1abc3abc2") );
|
||||
}
|
||||
|
||||
void replace_head_test()
|
||||
{
|
||||
// replace head
|
||||
TEST_ALGO( replace_head, "abc3abc2", (3)(string("YYY")), string("YYY3abc2") );
|
||||
TEST_ALGO( replace_head, "abc3abc2", (3)("YYY"), string("YYY3abc2") );
|
||||
TEST_ALGO( replace_head, "abc", (3)(string("Z")), string("Z") );
|
||||
TEST_ALGO( replace_head, "abc", (6)(string("XXXX")), string("XXXX") );
|
||||
TEST_ALGO( replace_head, "abc3abc2", (0)(string("XXXX")), string("abc3abc2") );
|
||||
TEST_ALGO( replace_head, "", (4)(string("XXXX")), string("") );
|
||||
TEST_ALGO( erase_head, "abc3abc2", (3), string("3abc2") );
|
||||
TEST_ALGO( erase_head, "abc3abc2", (0), string("abc3abc2") );
|
||||
TEST_ALGO( erase_head, "", (4), string("") );
|
||||
TEST_ALGO( replace_head, "abc3abc2", 3 C_ string("YYY"), string("YYY3abc2") );
|
||||
TEST_ALGO( replace_head, "abc3abc2", 3 C_ "YYY", string("YYY3abc2") );
|
||||
TEST_ALGO( replace_head, "abc", 3 C_ string("Z"), string("Z") );
|
||||
TEST_ALGO( replace_head, "abc", 6 C_ string("XXXX"), string("XXXX") );
|
||||
TEST_ALGO( replace_head, "abc3abc2", 0 C_ string("XXXX"), string("abc3abc2") );
|
||||
TEST_ALGO( replace_head, "", 4 C_ string("XXXX"), string("") );
|
||||
TEST_ALGO( erase_head, "abc3abc2", 3, string("3abc2") );
|
||||
TEST_ALGO( erase_head, "abc3abc2", 0, string("abc3abc2") );
|
||||
TEST_ALGO( erase_head, "", 4, string("") );
|
||||
}
|
||||
|
||||
void replace_tail_test()
|
||||
{
|
||||
// replace tail
|
||||
TEST_ALGO( replace_tail, "abc3abc", (3)(string("YYY")), string("abc3YYY") );
|
||||
TEST_ALGO( replace_tail, "abc3abc", (3)("YYY"), string("abc3YYY") );
|
||||
TEST_ALGO( replace_tail, "abc", (3)(string("Z")), string("Z") );
|
||||
TEST_ALGO( replace_tail, "abc", (6)(string("XXXX")), string("XXXX") );
|
||||
TEST_ALGO( replace_tail, "abc3abc", (0)(string("XXXX")), string("abc3abc") );
|
||||
TEST_ALGO( replace_tail, "", (4)(string("XXXX")), string("") );
|
||||
TEST_ALGO( erase_tail, "abc3abc", (3), string("abc3") );
|
||||
TEST_ALGO( erase_tail, "abc3abc", (0), string("abc3abc") );
|
||||
TEST_ALGO( erase_tail, "", (4), string("") );
|
||||
TEST_ALGO( replace_tail, "abc3abc", 3 C_ string("YYY"), string("abc3YYY") );
|
||||
TEST_ALGO( replace_tail, "abc3abc", 3 C_ "YYY", string("abc3YYY") );
|
||||
TEST_ALGO( replace_tail, "abc", 3 C_ string("Z"), string("Z") );
|
||||
TEST_ALGO( replace_tail, "abc", 6 C_ string("XXXX"), string("XXXX") );
|
||||
TEST_ALGO( replace_tail, "abc3abc", 0 C_ string("XXXX"), string("abc3abc") );
|
||||
TEST_ALGO( replace_tail, "", 4 C_ string("XXXX"), string("") );
|
||||
TEST_ALGO( erase_tail, "abc3abc", 3, string("abc3") );
|
||||
TEST_ALGO( erase_tail, "abc3abc", 0, string("abc3abc") );
|
||||
TEST_ALGO( erase_tail, "", 4, string("") );
|
||||
}
|
||||
|
||||
void replace_range_test()
|
||||
{
|
||||
// replace_range
|
||||
{
|
||||
BOOST_CHECKPOINT( "replace_range" );
|
||||
@ -210,8 +228,11 @@ void replace_test()
|
||||
make_iterator_range(str1.begin()+1, str1.begin()+4));
|
||||
BOOST_CHECK( str1==string("13abc2") );
|
||||
}
|
||||
}
|
||||
|
||||
// container traits complatibility tests
|
||||
void collection_comp_test()
|
||||
{
|
||||
// container traits compatibility tests
|
||||
{
|
||||
string strout;
|
||||
replace_first_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" );
|
||||
@ -248,7 +269,14 @@ void replace_test()
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
sequence_traits_test();
|
||||
replace_test();
|
||||
|
||||
replace_first_test();
|
||||
replace_last_test();
|
||||
replace_all_test();
|
||||
replace_nth_test();
|
||||
replace_head_test();
|
||||
replace_tail_test();
|
||||
replace_range_test();
|
||||
collection_comp_test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,6 +7,11 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
// equals predicate is used for result comparison
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
@ -15,11 +20,6 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
|
||||
// equals predicate is used for result comparison
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
@ -38,22 +38,32 @@ void deep_compare( const T1& X, const T2& Y )
|
||||
void iterator_test()
|
||||
{
|
||||
string str1("xx-abc--xx-abb");
|
||||
string str2("Xx-abc--xX-abb");
|
||||
string str2("Xx-abc--xX-abb-xx");
|
||||
string str3("xx");
|
||||
char* pch1="xx-abc--xx-abb";
|
||||
const char* pch1="xx-abc--xx-abb";
|
||||
vector<string> tokens;
|
||||
vector< vector<int> > vtokens;
|
||||
|
||||
// find_all tests
|
||||
find_all(
|
||||
tokens,
|
||||
pch1,
|
||||
"xx" );
|
||||
|
||||
BOOST_REQUIRE( tokens.size()==2 );
|
||||
BOOST_CHECK( tokens[0]==string("xx") );
|
||||
BOOST_CHECK( tokens[1]==string("xx") );
|
||||
|
||||
ifind_all(
|
||||
tokens,
|
||||
str2,
|
||||
"xx" );
|
||||
|
||||
BOOST_REQUIRE( tokens.size()==2 );
|
||||
BOOST_REQUIRE( tokens.size()==3 );
|
||||
BOOST_CHECK( tokens[0]==string("Xx") );
|
||||
BOOST_CHECK( tokens[1]==string("xX") );
|
||||
BOOST_CHECK( tokens[2]==string("xx") );
|
||||
|
||||
// find_all tests
|
||||
find_all(
|
||||
tokens,
|
||||
str1,
|
||||
@ -63,7 +73,6 @@ void iterator_test()
|
||||
BOOST_CHECK( tokens[0]==string("xx") );
|
||||
BOOST_CHECK( tokens[1]==string("xx") );
|
||||
|
||||
|
||||
find_all(
|
||||
vtokens,
|
||||
str1,
|
||||
@ -73,14 +82,15 @@ void iterator_test()
|
||||
// split tests
|
||||
split(
|
||||
tokens,
|
||||
str1,
|
||||
is_any_of("x"),
|
||||
str2,
|
||||
is_any_of("xX"),
|
||||
token_compress_on );
|
||||
|
||||
BOOST_REQUIRE( tokens.size()==3 );
|
||||
BOOST_REQUIRE( tokens.size()==4 );
|
||||
BOOST_CHECK( tokens[0]==string("") );
|
||||
BOOST_CHECK( tokens[1]==string("-abc--") );
|
||||
BOOST_CHECK( tokens[2]==string("-abb") );
|
||||
BOOST_CHECK( tokens[2]==string("-abb-") );
|
||||
BOOST_CHECK( tokens[3]==string("") );
|
||||
|
||||
split(
|
||||
tokens,
|
||||
|
@ -7,12 +7,13 @@
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
// Include unit test framework
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
Reference in New Issue
Block a user