Compare commits

...

36 Commits

Author SHA1 Message Date
280f150bfb optional_optimization branch
[SVN r77091]
2012-02-22 10:37:27 +00:00
dfaea65083 Fix (even more) test failures in Boost.Algorithm
[SVN r77076]
2012-02-20 15:22:04 +00:00
eb8291e0aa Fix some test (more) failures in Boost.Algorithm
[SVN r77073]
2012-02-19 16:17:27 +00:00
f023127c99 Fix some test failures in Boost.Algorithm
[SVN r77070]
2012-02-18 17:26:08 +00:00
43c01ff2bc Added c++11 algorithms to Boost.Algorithm
[SVN r77060]
2012-02-18 07:17:39 +00:00
8bfaa6dad3 Added QuickRef entries for 'is_any_of' and 'is_from_range'
[SVN r76526]
2012-01-15 16:47:48 +00:00
6fbc7401d5 should correct #3634; will close when merged to release
[SVN r76435]
2012-01-12 18:35:06 +00:00
d518994247 Initial checkin of Boost.Algorithm searching and clamp code and tests; docs and more Algos coming
[SVN r76388]
2012-01-09 17:21:04 +00:00
ba417e875a Qualified two calls to memcpy to work around a C++Builder bug; Refs #4811
[SVN r76213]
2011-12-28 19:14:18 +00:00
e92d471817 Comment updated
[SVN r72350]
2011-06-02 20:08:16 +00:00
34c49f856c trim_fill algorithm added
[SVN r72338]
2011-06-01 22:00:22 +00:00
caea7bd125 trim_all test fixed
[SVN r68173]
2011-01-15 18:37:46 +00:00
81b04cde96 Revert [67111] (addition of boost/detail/iomanip.hpp) and all the commits that depend on it. ([68137], [68140], [68141], [68154], and [68165]).
[SVN r68168]
2011-01-15 08:11:51 +00:00
276073ca64 tabs removed
[SVN r68162]
2011-01-14 23:12:32 +00:00
a7f5bdd781 trim_all algorithm added
[SVN r68161]
2011-01-14 23:06:14 +00:00
0c0a866f07 Replacing the use of <iomanip> with <boost/detail/iomanip.hpp> across Boost.
On Linux, GNU's libstdc++, which is the default stdlib for icc and clang,
cannot parse the <iomanip> header in version 4.5+ (which thankfully neither
compiler advises the use of yet), as it's original C++98-friendly
implementation has been replaced with a gnu++0x implementation.
<boost/detail/iomanip.hpp> is a portable implementation of <iomanip>, providing
boost::detail::setfill, boost::detail::setbase, boost::detail::setw,
boost::detail::setprecision, boost::detail::setiosflags and
boost::detail::resetiosflags. 



[SVN r68140]
2011-01-14 02:35:58 +00:00
9d25072f2f dissect formatter and tests added
[SVN r68124]
2011-01-13 21:21:37 +00:00
823b199df3 Fix typo. Fixes #4937.
[SVN r67106]
2010-12-08 17:37:52 +00:00
fecd440527 Fix some links I missed in string algorithms
[SVN r66278]
2010-10-30 15:53:41 +00:00
3325d3a3f8 Link fixes.
[SVN r66273]
2010-10-30 14:32:50 +00:00
ebf104c127 test for empty string split added
[SVN r66221]
2010-10-27 20:42:22 +00:00
3b76763807 fixed the empty string handling for the split iterator
[SVN r66220]
2010-10-27 20:40:37 +00:00
62df1eb048 Fix #4551,#4553,#4575 by removing unused parameter.
[SVN r65004]
2010-08-25 20:01:38 +00:00
f5dd47883f Update various libraries' documentation build.
Mostly to use the images and css files under doc/src instead of
doc/html, usually be deleting the settings in order to use the defaults.
Also add 'boost.root' to some builds in order to fix links which rely on
it.

[SVN r63146]
2010-06-20 18:00:48 +00:00
9d68c4280c Fix license per inspection report.
[SVN r62814]
2010-06-11 19:52:26 +00:00
1e8b3ee752 Make to_upperF and to_lowerF assignable. Fixes #3161.
[SVN r62697]
2010-06-09 23:23:56 +00:00
42147c8385 Copy m_bEof in the split_iterator copy constructor. Fixes #4271
[SVN r62696]
2010-06-09 23:12:56 +00:00
672775545d Avoid calling the formatter with an invalid match. Fixes #2777
[SVN r62695]
2010-06-09 23:04:24 +00:00
46ed1bf987 Assign the iterator returned by std::copy back to Output, so that string algorithms will work with iterators other than inserters
[SVN r62694]
2010-06-09 21:12:06 +00:00
6289ed7f98 Trim the correct string. Fixes #3860
[SVN r62692]
2010-06-09 20:42:46 +00:00
8e97668b1f Tail not head. Fixes #3314
[SVN r62690]
2010-06-09 20:31:26 +00:00
e7c23d2f13 Tail not head. Fixes #2124
[SVN r62689]
2010-06-09 20:26:36 +00:00
a1e7512012 Use result_type instead of sig for predicates. Fixes #2868
[SVN r62688]
2010-06-09 20:16:21 +00:00
31b5842441 Typo.
[SVN r62461]
2010-06-06 07:18:24 +00:00
4515bc182e Fix example. Fixes #4206
[SVN r61931]
2010-05-12 12:56:16 +00:00
7e2e6856cc Remove duplicate closing angle brackets. Fixes #4198
[SVN r61856]
2010-05-08 18:27:44 +00:00
74 changed files with 48739 additions and 91 deletions

22
example/Jamfile.v2 Normal file
View File

@ -0,0 +1,22 @@
# Boost algorithm library example programs Jamfile
#
# Copyright Marshall Clow 2010-2012. 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.
project /boost/algorithm/example
: requirements
<include>../../../
<optimization>speed
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
<toolset>msvc:<define>NOMINMAX
<link>static
:
;
exe clamp_example : clamp_example.cpp ;
exe search_example : search_example.cpp ;

54
example/clamp_example.cpp Normal file
View File

@ -0,0 +1,54 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <string>
#include <iostream> // for cout, etc
#include <boost/algorithm/clamp.hpp>
namespace ba = boost::algorithm;
bool compare_string_lengths ( const std::string &one, const std::string &two )
{
return one.length () < two.length ();
}
int main ( int /*argc*/, char * /*argv*/ [] ) {
// Clamp takes a value and two "fenceposts", and brings the value "between" the fenceposts.
// If the input value is "between" the fenceposts, then it is returned unchanged.
std::cout << "Clamping 5 to between [1, 10] -> " << ba::clamp ( 5, 1, 10 ) << std::endl;
// If the input value is out side the range of the fenceposts, it "brought into" range.
std::cout << "Clamping 15 to between [1, 10] -> " << ba::clamp ( 15, 1, 10 ) << std::endl;
std::cout << "Clamping -15 to between [1, 10] -> " << ba::clamp ( -15, 1, 10 ) << std::endl;
// It doesn't just work for ints
std::cout << "Clamping 5.1 to between [1, 10] -> " << ba::clamp ( 5.1, 1.0, 10.0 ) << std::endl;
{
std::string one ( "Lower Bound" ), two ( "upper bound!" ), test1 ( "test#" ), test2 ( "#test" );
std::cout << "Clamping '" << test1 << "' between ['" << one << "' and '" << two << "'] -> '" <<
ba::clamp ( test1, one, two ) << "'" << std::endl;
std::cout << "Clamping '" << test2 << "' between ['" << one << "' and '" << two << "'] -> '" <<
ba::clamp ( test2, one, two ) << "'" << std::endl;
// There is also a predicate based version, if you want to compare objects in your own way
std::cout << "Clamping '" << test1 << "' between ['" << one << "' and '" << two << "'] (comparing lengths) -> '" <<
ba::clamp ( test1, one, two, compare_string_lengths ) << "'" << std::endl;
std::cout << "Clamping '" << test2 << "' between ['" << one << "' and '" << two << "'] (comparing lengths) -> '" <<
ba::clamp ( test2, one, two, compare_string_lengths ) << "'" << std::endl;
}
// Sometimes, though, you don't get quite what you expect
// This is because the two double arguments get converted to int
std::cout << "Somewhat unexpected: clamp ( 12, 14.7, 15.9 ) --> " << ba::clamp ( 12, 14.7, 15.9 ) << std::endl;
std::cout << "Expected: clamp ((double)12, 14.7, 15.9 ) --> " << ba::clamp ((double) 12, 14.7, 15.9 ) << std::endl;
return 0;
}

View File

@ -0,0 +1,57 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <string>
#include <iostream> // for cout, etc.
#include <boost/algorithm/searching/boyer_moore.hpp>
#include <boost/algorithm/searching/boyer_moore_horspool.hpp>
#include <boost/algorithm/searching/knuth_morris_pratt.hpp>
namespace ba = boost::algorithm;
const std::string haystack ( "ABACAB is it everywhere!" );
const std::string needle1 ( "ACAB" );
const std::string needle2 ( "not ABA" );
int main ( int /*argc*/, char * /*argv*/ [] ) {
// In search.hpp, there are generic implementations of three classic sequence search
// algorithms. They all have the same (dual) interface.
// There is a procedural interface, based on std::search:
if ( ba::boyer_moore_search ( haystack.begin (), haystack.end (), needle1.begin (), needle1.end ()) != haystack.end ())
std::cout << "Found '" << needle1 << "' in '" << haystack << "' (boyer-moore 1)" << std::endl;
else
std::cout << "Did NOT find '" << needle1 << "' in '" << haystack << "' (boyer-moore 1)" << std::endl;
// If you plan on searching for the same pattern in several different data sets,
// you can create a search object and use that over and over again - amortizing the setup
// costs across several searches
ba::boyer_moore<std::string::const_iterator> search1 ( needle1.begin (), needle1.end ());
if ( search1 ( haystack.begin (), haystack.end ()) != haystack.end ())
std::cout << "Found '" << needle1 << "' in '" << haystack << "' (boyer-moore 2)" << std::endl;
else
std::cout << "Did NOT find '" << needle1 << "' in '" << haystack << "' (boyer-moore 2)" << std::endl;
// There is also an implementation of boyer-moore-horspool searching
if ( ba::boyer_moore_horspool_search ( haystack.begin (), haystack.end (), needle1.begin (), needle1.end ()) != haystack.end ())
std::cout << "Found '" << needle1 << "' in '" << haystack << "' (boyer-moore-horspool)" << std::endl;
else
std::cout << "Did NOT find '" << needle1 << "' in '" << haystack << "' (boyer-moore-horspool)" << std::endl;
// And also the knuth-pratt-morris search algorithm
if ( ba::knuth_morris_pratt_search ( haystack.begin (), haystack.end (), needle1.begin (), needle1.end ()) != haystack.end ())
std::cout << "Found '" << needle1 << "' in '" << haystack << "' (knuth_morris_pratt)" << std::endl;
else
std::cout << "Did NOT find '" << needle1 << "' in '" << haystack << "' (knuth_morris_pratt)" << std::endl;
return 0;
}

175
include/boost/algorithm/clamp.hpp Executable file
View File

@ -0,0 +1,175 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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:
27 June 2009 mtc First version
23 Oct 2010 mtc Added predicate version
*/
/// \file clamp.hpp
/// \brief Clamp algorithm
/// \author Marshall Clow
///
/// Suggested by olafvdspek in https://svn.boost.org/trac/boost/ticket/3215
#ifndef BOOST_ALGORITHM_CLAMP_HPP
#define BOOST_ALGORITHM_CLAMP_HPP
#include <functional> // For std::less
#include <iterator> // For std::iterator_traits
#include <cassert>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/mpl/identity.hpp> // for identity
#include <boost/utility/enable_if.hpp> // for boost::disable_if
namespace boost { namespace algorithm {
/// \fn clamp ( T const& val,
/// typename boost::mpl::identity<T>::type const& lo,
/// typename boost::mpl::identity<T>::type const& hi, Pred p )
/// \return the value "val" brought into the range [ lo, hi ]
/// using the comparison predicate p.
/// If p ( val, lo ) return lo.
/// If p ( hi, val ) return hi.
/// Otherwise, return the original value.
///
/// \param val The value to be clamped
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
///
template<typename T, typename Pred>
T const & clamp ( T const& val,
typename boost::mpl::identity<T>::type const & lo,
typename boost::mpl::identity<T>::type const & hi, Pred p )
{
// assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they might be equal
return p ( val, lo ) ? lo : p ( hi, val ) ? hi : val;
}
/// \fn clamp ( T const& val,
/// typename boost::mpl::identity<T>::type const& lo,
/// typename boost::mpl::identity<T>::type const& hi )
/// \return the value "val" brought into the range [ lo, hi ].
/// If the value is less than lo, return lo.
/// If the value is greater than "hi", return hi.
/// Otherwise, return the original value.
///
/// \param val The value to be clamped
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
///
template<typename T>
T const& clamp ( const T& val,
typename boost::mpl::identity<T>::type const & lo,
typename boost::mpl::identity<T>::type const & hi )
{
return (clamp) ( val, lo, hi, std::less<T>());
}
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type lo,
/// std::iterator_traits<InputIterator>::value_type hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
///
/// \param first The start of the range of values
/// \param last One past the end of the range of input values
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
///
template<typename InputIterator, typename OutputIterator>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type lo,
typename std::iterator_traits<InputIterator>::value_type hi )
{
// this could also be written with bind and std::transform
while ( first != last )
*out++ = clamp ( *first++, lo, hi );
return out;
}
/// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
///
/// \param r The range of values to be clamped
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
///
template<typename Range, typename OutputIterator>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi )
{
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi );
}
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
/// std::iterator_traits<InputIterator>::value_type lo,
/// std::iterator_traits<InputIterator>::value_type hi, Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p.
///
/// \param first The start of the range of values
/// \param last One past the end of the range of input values
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
///
template<typename InputIterator, typename OutputIterator, typename Pred>
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
typename std::iterator_traits<InputIterator>::value_type lo,
typename std::iterator_traits<InputIterator>::value_type hi, Pred p )
{
// this could also be written with bind and std::transform
while ( first != last )
*out++ = clamp ( *first++, lo, hi, p );
return out;
}
/// \fn clamp_range ( const Range &r, OutputIterator out,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi,
/// Pred p )
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
/// using the comparison predicate p.
///
/// \param r The range of values to be clamped
/// \param out An output iterator to write the clamped values into
/// \param lo The lower bound of the range to be clamped to
/// \param hi The upper bound of the range to be clamped to
/// \param p A predicate to use to compare the values.
/// p ( a, b ) returns a boolean.
//
// Disable this template if the first two parameters are the same type;
// In that case, the user will get the two iterator version.
template<typename Range, typename OutputIterator, typename Pred>
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
clamp_range ( const Range &r, OutputIterator out,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi,
Pred p )
{
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p );
}
}}
#endif // BOOST_ALGORITHM_CLAMP_HPP

View File

@ -0,0 +1,90 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
*/
/// \file all_of.hpp
/// \brief Test ranges to see if all elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ALL_OF_HPP
#define BOOST_ALGORITHM_ALL_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of all_of if it is available
using std::all_of; // Section 25.2.1
#else
/// \fn all_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if all elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template<typename InputIterator, typename Predicate>
bool all_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
return false;
return true;
}
#endif
/// \fn all_of ( const Range &r, Predicate p )
/// \return true if all elements in the range satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool all_of ( const Range &r, Predicate p )
{
return boost::algorithm::all_of ( boost::begin (r), boost::end (r), p );
}
/// \fn all_of_equal ( InputIterator first, InputIterator last, const T &val )
/// \return true if all elements in [first, last) are equal to 'val'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename T>
bool all_of_equal ( InputIterator first, InputIterator last, const T &val )
{
for ( ; first != last; ++first )
if ( val != *first )
return false;
return true;
}
/// \fn all_of_equal ( const Range &r, const T &val )
/// \return true if all elements in the range are equal to 'val'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename T>
bool all_of_equal ( const Range &r, const T &val )
{
return boost::algorithm::all_of_equal ( boost::begin (r), boost::end (r), val );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ALL_OF_HPP

View File

@ -0,0 +1,89 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
/// \file
/// \brief Test ranges to see if any elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ANY_OF_HPP
#define BOOST_ALGORITHM_ANY_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
// Use the C++11 versions of any_of if it is available
#if __cplusplus >= 201103L
using std::any_of; // Section 25.2.2
#else
/// \fn any_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if any of the elements in [first, last) satisfy the predicate
/// \note returns false on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
template<typename InputIterator, typename Predicate>
bool any_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( p(*first))
return true;
return false;
}
#endif
/// \fn any_of ( const Range &r, Predicate p )
/// \return true if any elements in the range satisfy the predicate 'p'
/// \note returns false on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool any_of ( const Range &r, Predicate p )
{
return boost::algorithm::any_of (boost::begin (r), boost::end (r), p);
}
/// \fn any_of_equal ( InputIterator first, InputIterator last, const V &val )
/// \return true if any of the elements in [first, last) are equal to 'val'
/// \note returns false on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename V>
bool any_of_equal ( InputIterator first, InputIterator last, const V &val )
{
for ( ; first != last; ++first )
if ( val == *first )
return true;
return false;
}
/// \fn any_of_equal ( const Range &r, const V &val )
/// \return true if any of the elements in the range are equal to 'val'
/// \note returns false on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename V>
bool any_of_equal ( const Range &r, const V &val )
{
return boost::algorithm::any_of_equal (boost::begin (r), boost::end (r), val);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ANY_OF_HPP

View File

@ -0,0 +1,133 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
*/
/// \file copy_if.hpp
/// \brief Copy a subset of a sequence to a new sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_COPY_IF_HPP
#define BOOST_ALGORITHM_COPY_IF_HPP
#include <algorithm> // for std::copy_if, if available
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of copy_if if it is available
using std::copy_if; // Section 25.3.1
#else
/// \fn copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements from the input range that satisfy the
/// predicate to the output range.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template<typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
{
for ( ; first != last; ++first )
if (p(*first))
*result++ = first;
return result;
}
#endif
/// \fn copy_if ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements from the input range that satisfy the
/// predicate to the output range.
/// \return The updated output iterator
///
/// \param r The input range
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename OutputIterator, typename Predicate>
OutputIterator copy_if ( const Range &r, OutputIterator result, Predicate p )
{
return boost::algorithm::copy_if (boost::begin (r), boost::end(r), result, p);
}
/// \fn copy_while ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that
/// satisfy the predicate to the output range.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator copy_while ( InputIterator first, InputIterator last,
OutputIterator result, Predicate p )
{
for ( ; first != last && p(*first); ++first )
*result++ = first;
return result;
}
/// \fn copy_while ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that
/// satisfy the predicate to the output range.
/// \return The updated output iterator
///
/// \param r The input range
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename OutputIterator, typename Predicate>
OutputIterator copy_while ( const Range &r, OutputIterator result, Predicate p )
{
return boost::algorithm::copy_while (boost::begin (r), boost::end(r), result, p);
}
/// \fn copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that do not
/// satisfy the predicate to the output range.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
{
for ( ; first != last && !p(*first); ++first )
*result++ = first;
return result;
}
/// \fn copy_until ( const Range &r, OutputIterator result, Predicate p )
/// \brief Copies all the elements at the start of the input range that do not
/// satisfy the predicate to the output range.
/// \return The updated output iterator
///
/// \param r The input range
/// \param result An output iterator to write the results into
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename OutputIterator, typename Predicate>
OutputIterator copy_until ( const Range &r, OutputIterator result, Predicate p )
{
return boost::algorithm::copy_until (boost::begin (r), boost::end(r), result, p);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_COPY_IF_HPP

View File

@ -0,0 +1,44 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
*/
/// \file copy_n.hpp
/// \brief Copy n items from one sequence to another
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_COPY_N_HPP
#define BOOST_ALGORITHM_COPY_N_HPP
#include <algorithm> // for std::copy_n, if available
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of copy_n if it is available
using std::copy_n; // Section 25.3.1
#else
/// \fn copy_n ( InputIterator first, Size n, OutputIterator result )
/// \brief Copies exactly n (n > 0) elements from the range starting at first to
/// the range starting at result.
/// \return The updated output iterator
///
/// \param first The start of the input sequence
/// \param n The number of elements to copy
/// \param result An output iterator to write the results into
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template <typename InputIterator, typename Size, typename OutputIterator>
OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result )
{
for ( ; n > 0; --n, ++first, ++result )
*result = *first;
return result;
}
#endif
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_COPY_IF_HPP

View File

@ -0,0 +1,60 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
*/
/// \file find_if_not.hpp
/// \brief Find the first element in a sequence that does not satisfy a predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_FIND_IF_NOT_HPP
#define BOOST_ALGORITHM_FIND_IF_NOT_HPP
#include <algorithm> // for std::find_if_not, if it exists
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of find_if_not if it is available
using std::find_if_not; // Section 25.2.5
#else
/// \fn find_if_not(InputIterator first, InputIterator last, Predicate p)
/// \brief Finds the first element in the sequence that does not satisfy the predicate.
/// \return The iterator pointing to the desired element.
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the range
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template<typename InputIterator, typename Predicate>
InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( !p(*first))
break;
return first;
}
#endif
/// \fn find_if_not ( const Range &r, Predicate p )
/// \brief Finds the first element in the sequence that does not satisfy the predicate.
/// \return The iterator pointing to the desired element.
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
typename boost::range_iterator<const Range>::type find_if_not ( const Range &r, Predicate p )
{
return boost::algorithm::find_if_not (boost::begin (r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_FIND_IF_NOT_HPP

View File

@ -0,0 +1,74 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
*/
/// \file iota.hpp
/// \brief Generate an increasing series
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IOTA_HPP
#define BOOST_ALGORITHM_IOTA_HPP
#include <numeric>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of iota if it is available
using std::iota; // Section 26.7.6
#else
/// \fn iota ( ForwardIterator first, ForwardIterator last, T value )
/// \brief Generates an increasing sequence of values, and stores them in [first, last)
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param value The initial value of the sequence to be generated
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template <typename ForwardIterator, typename T>
void iota ( ForwardIterator first, ForwardIterator last, T value )
{
for ( ; first != last; ++first, ++value )
*first = value;
}
#endif
/// \fn iota ( Range &r, T value )
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
///
/// \param r The input range
/// \param value The initial value of the sequence to be generated
///
template <typename Range, typename T>
void iota ( Range &r, T value )
{
boost::algorithm::iota (boost::begin(r), boost::end(r), value);
}
/// \fn iota_n ( OutputIterator out, T value, std::size_t n )
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
///
/// \param out An output iterator to write the results into
/// \param value The initial value of the sequence to be generated
/// \param n The number of items to write
///
template <typename OutputIterator, typename T>
OutputIterator iota_n ( OutputIterator out, T value, std::size_t n )
{
while ( n-- > 0 )
*out++ = value++;
return out;
}
}}
#endif // BOOST_ALGORITHM_IOTA_HPP

View File

@ -0,0 +1,65 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
*/
/// \file is_partitioned.hpp
/// \brief Tell if a sequence is partitioned
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PARTITIONED_HPP
#define BOOST_ALGORITHM_IS_PARTITIONED_HPP
#include <algorithm> // for std::is_partitioned, if available
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of iota if it is available
using std::is_partitioned; // Section 25.3.13
#else
/// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
/// \brief Tests to see if a sequence is partititioned according to a predicate
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p The predicicate to test the values with
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template <typename InputIterator, typename UnaryPredicate>
bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
{
// Run through the part that satisfy the predicate
for ( ; first != last; ++first )
if ( !p (*first))
break;
// Now the part that does not satisfy the predicate
for ( ; first != last; ++first )
if ( p (*first))
return false;
return true;
}
#endif
/// \fn is_partitioned ( const Range &r, UnaryPredicate p )
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
///
/// \param r The input range
/// \param p The predicicate to test the values with
///
template <typename Range, typename UnaryPredicate>
bool is_partitioned ( const Range &r, UnaryPredicate p )
{
return boost::algorithm::is_partitioned (boost::begin(r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_IS_PARTITIONED_HPP

View File

@ -0,0 +1,139 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
*/
/// \file is_permutation.hpp
/// \brief Is a sequence a permutation of another sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP
#define BOOST_ALGORITHM_IS_PERMUTATION_HPP
#include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
#include <utility> // for std::make_pair
#include <functional> // for std::equal_to
#include <iterator>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/tr1/tr1/tuple> // for tie
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of is_permutation if it is available
using std::is_permutation; // Section 25.2.12
#else
/// \cond DOXYGEN_HIDE
namespace detail {
template <typename Predicate, typename Iterator>
struct value_predicate {
value_predicate ( Predicate p, Iterator it ) : p_ ( p ), it_ ( it ) {}
template <typename T1>
bool operator () ( const T1 &t1 ) const { return p_ ( *it_, t1 ); }
private:
Predicate &p_;
Iterator it_;
};
}
/// \endcond
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p )
/// \brief Tests to see if a the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \param p The predicate to compare elements with
///
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, BinaryPredicate p )
{
// Skip the common prefix (if any)
// std::tie (first1, first2) = std::mismatch (first1, last1, first2, p);
std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2, p);
first1 = eq.first;
first2 = eq.second;
if ( first1 != last1 ) {
// Create last2
ForwardIterator2 last2 = first2;
std::advance ( last2, std::distance (first1, last1));
// for each unique value in the sequence [first1,last1), count how many times
// it occurs, and make sure it occurs the same number of times in [first2, last2)
for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) {
detail::value_predicate<BinaryPredicate, ForwardIterator1> pred ( p, iter );
/* For each value we haven't seen yet... */
if ( std::find_if ( first1, iter, pred ) == iter ) {
std::size_t dest_count = std::count_if ( first2, last2, pred );
if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred ))
return false;
}
}
}
return true;
}
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 )
/// \brief Tests to see if a the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param first2 The start of the second sequence
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template< class ForwardIterator1, class ForwardIterator2 >
bool is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 )
{
// How should I deal with the idea that ForwardIterator1::value_type
// and ForwardIterator2::value_type could be different? Define my own comparison predicate?
return boost::algorithm::is_permutation ( first, last, first2,
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ());
}
#endif
/// \fn is_permutation ( const Range &r, ForwardIterator first2 )
/// \brief Tests to see if a the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param r The input range
/// \param first2 The start of the second sequence
template <typename Range, typename ForwardIterator>
bool is_permutation ( const Range &r, ForwardIterator first2 )
{
return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2 );
}
/// \fn is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
/// \brief Tests to see if a the sequence [first,last) is a permutation of the sequence starting at first2
///
/// \param r The input range
/// \param first2 The start of the second sequence
/// \param pred The predicate to compare elements with
///
// Disable this template when the first two parameters are the same type
// That way the non-range version will be chosen.
template <typename Range, typename ForwardIterator, typename BinaryPredicate>
typename boost::disable_if_c<boost::is_same<Range, ForwardIterator>::value, bool>::type
is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
{
return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2, pred );
}
}}
#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP

View File

@ -0,0 +1,87 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
*/
/// \file none_of.hpp
/// \brief Test ranges to see if no elements match a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_NONE_OF_HPP
#define BOOST_ALGORITHM_NONE_OF_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
// Use the C++11 versions of the none_of if it is available
#if __cplusplus >= 201103L
using std::none_of; // Section 25.2.3
#else
/// \fn none_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if none of the elements in [first, last) satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
template<typename InputIterator, typename Predicate>
bool none_of ( InputIterator first, InputIterator last, Predicate p )
{
for ( ; first != last; ++first )
if ( p(*first))
return false;
return true;
}
#endif
/// \fn none_of ( const Range &r, Predicate p )
/// \return true if none of the elements in the range satisfy the predicate 'p'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool none_of ( const Range &r, Predicate p )
{
return boost::algorithm::none_of (boost::begin (r), boost::end (r), p );
}
/// \fn none_of_equal ( InputIterator first, InputIterator last, const V &val )
/// \return true if none of the elements in [first, last) are equal to 'val'
/// \note returns true on an empty range
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename V>
bool none_of_equal ( InputIterator first, InputIterator last, const V &val )
{
for ( ; first != last; ++first )
if ( val == *first )
return false;
return true;
}
/// \fn none_of_equal ( const Range &r, const V &val )
/// \return true if none of the elements in the range are equal to 'val'
/// \note returns true on an empty range
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename V>
bool none_of_equal ( const Range &r, const V & val )
{
return boost::algorithm::none_of_equal (boost::begin (r), boost::end (r), val);
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_NONE_OF_HPP

View File

@ -0,0 +1,82 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
*/
/// \file one_of.hpp
/// \brief Test ranges to see if only one element matches a value or predicate.
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_ONE_OF_HPP
#define BOOST_ALGORITHM_ONE_OF_HPP
#include <algorithm> // for std::find and std::find_if
#include <boost/algorithm/cxx11/none_of.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
/// \fn one_of ( InputIterator first, InputIterator last, Predicate p )
/// \return true if the predicate 'p' is true for exactly one item in [first, last).
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p A predicate for testing the elements of the sequence
///
template<typename InputIterator, typename Predicate>
bool one_of ( InputIterator first, InputIterator last, Predicate p )
{
InputIterator i = std::find_if (first, last, p);
if (i == last)
return false; // Didn't occur at all
return boost::algorithm::none_of (++i, last, p);
}
/// \fn one_of ( const Range &r, Predicate p )
/// \return true if the predicate 'p' is true for exactly one item in the range.
///
/// \param r The input range
/// \param p A predicate for testing the elements of the range
///
template<typename Range, typename Predicate>
bool one_of ( const Range &r, Predicate p )
{
return boost::algorithm::one_of ( boost::begin (r), boost::end (r), p );
}
/// \fn one_of_equal ( InputIterator first, InputIterator last, const V &val )
/// \return true if the value 'val' exists only once in [first, last).
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param val A value to compare against
///
template<typename InputIterator, typename V>
bool one_of_equal ( InputIterator first, InputIterator last, const V &val )
{
InputIterator i = std::find (first, last, val); // find first occurrence of 'val'
if (i == last)
return false; // Didn't occur at all
return boost::algorithm::none_of_equal (++i, last, val);
}
/// \fn one_of_equal ( const Range &r, const V &val )
/// \return true if the value 'val' exists only once in the range.
///
/// \param r The input range
/// \param val A value to compare against
///
template<typename Range, typename V>
bool one_of_equal ( const Range &r, const V &val )
{
return boost::algorithm::one_of_equal ( boost::begin (r), boost::end (r), val );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_ALL_HPP

View File

@ -0,0 +1,286 @@
// Copyright (c) 2010 Nuovation System Designs, LLC
// Grant Erickson <gerickson@nuovations.com>
//
// Reworked somewhat by Marshall Clow; August 2010
//
// Distributed under 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 latest version.
//
#ifndef BOOST_ALGORITHM_ORDERED_HPP
#define BOOST_ALGORITHM_ORDERED_HPP
#include <algorithm>
#include <functional>
#include <iterator>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of iota if it is available
using std::is_sorted_until; // Section 25.4.1.5
using std::is_sorted; // Section 25.4.1.5
#else
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
/// \return the point in the sequence [first, last) where the elements are unordered
/// (according to the comparison predicate 'p').
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename ForwardIterator, typename Pred>
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
{
if ( first == last ) return last; // the empty sequence is ordered
ForwardIterator next = first;
while ( ++next != last )
{
if ( !p ( *first, *next ))
return next;
first = next;
}
return last;
}
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last )
/// \return the point in the sequence [first, last) where the elements are unordered
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
template <typename ForwardIterator>
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted_until ( first, last, std::less_equal<value_type>());
}
/// \fn is_sorted ( ForwardIterator first, ForwardIterator last, Pred p )
/// \return whether or not the entire sequence is sorted
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename ForwardIterator, typename Pred>
bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p )
{
return boost::algorithm::is_sorted_until (first, last, p) == last;
}
/// \fn is_sorted ( ForwardIterator first, ForwardIterator last )
/// \return whether or not the entire sequence is sorted
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
template <typename ForwardIterator>
bool is_sorted ( ForwardIterator first, ForwardIterator last )
{
return boost::algorithm::is_sorted_until (first, last) == last;
}
#endif
///
/// -- Range based versions of the C++11 functions
///
/// \fn is_sorted_until ( const R &range, Pred p )
/// \return the point in the range R where the elements are unordered
/// (according to the comparison predicate 'p').
///
/// \param range The range to be tested.
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename R, typename Pred>
typename boost::lazy_disable_if_c<
boost::is_same<R, Pred>::value,
typename boost::range_iterator<const R>
>::type is_sorted_until ( const R &range, Pred p )
{
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ), p );
}
/// \fn is_sorted_until ( const R &range )
/// \return the point in the range R where the elements are unordered
///
/// \param range The range to be tested.
///
template <typename R>
typename boost::range_iterator<const R>::type is_sorted_until ( const R &range )
{
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_sorted ( const R &range, Pred p )
/// \return whether or not the entire range R is sorted
/// (according to the comparison predicate 'p').
///
/// \param range The range to be tested.
/// \param p A binary predicate that returns true if two elements are ordered.
///
template <typename R, typename Pred>
bool is_sorted ( const R &range, Pred p )
{
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ), p );
}
/// \fn is_sorted ( const R &range )
/// \return whether or not the entire range R is sorted
///
/// \param range The range to be tested.
///
template <typename R, typename Pred>
bool is_sorted ( const R &range )
{
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ));
}
///
/// -- Range based versions of the C++11 functions
///
/// \fn is_increasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is increasing; i.e, each item is greater than or
/// equal to the previous one.
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_increasing instead.
template <typename ForwardIterator>
bool is_increasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::less_equal<value_type>());
}
/// \fn is_increasing ( const R &range )
/// \return true if the entire sequence is increasing; i.e, each item is greater than or
/// equal to the previous one.
///
/// \param range The range to be tested.
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_increasing instead.
template <typename R>
bool is_increasing ( const R &range )
{
return is_increasing ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_decreasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is decreasing; i.e, each item is less than
/// or equal to the previous one.
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_decreasing instead.
template <typename ForwardIterator>
bool is_decreasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::greater_equal<value_type>());
}
/// \fn is_decreasing ( const R &range )
/// \return true if the entire sequence is decreasing; i.e, each item is less than
/// or equal to the previous one.
///
/// \param range The range to be tested.
///
/// \note This function will return true for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_strictly_decreasing instead.
template <typename R>
bool is_decreasing ( const R &range )
{
return is_decreasing ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is strictly increasing; i.e, each item is greater
/// than the previous one
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_increasing instead.
template <typename ForwardIterator>
bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::less<value_type>());
}
/// \fn is_strictly_increasing ( const R &range )
/// \return true if the entire sequence is strictly increasing; i.e, each item is greater
/// than the previous one
///
/// \param range The range to be tested.
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_increasing instead.
template <typename R>
bool is_strictly_increasing ( const R &range )
{
return is_strictly_increasing ( boost::begin ( range ), boost::end ( range ));
}
/// \fn is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
/// \return true if the entire sequence is strictly decreasing; i.e, each item is less than
/// the previous one
///
/// \param first The start of the sequence to be tested.
/// \param last One past the end of the sequence
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_decreasing instead.
template <typename ForwardIterator>
bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
{
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
return boost::algorithm::is_sorted (first, last, std::greater<value_type>());
}
/// \fn is_strictly_decreasing ( const R &range )
/// \return true if the entire sequence is strictly decreasing; i.e, each item is less than
/// the previous one
///
/// \param range The range to be tested.
///
/// \note This function will return false for sequences that contain items that compare
/// equal. If that is not what you intended, you should use is_decreasing instead.
template <typename R>
bool is_strictly_decreasing ( const R &range )
{
return is_strictly_decreasing ( boost::begin ( range ), boost::end ( range ));
}
}} // namespace boost
#endif // BOOST_ALGORITHM_ORDERED_HPP

View File

@ -0,0 +1,77 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
*/
/// \file partition_copy.hpp
/// \brief Copy a subset of a sequence to a new sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_PARTITION_COPY_HPP
#define BOOST_ALGORITHM_PARTITION_COPY_HPP
#include <utility> // for make_pair
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of partition_copy if it is available
using std::partition_copy; // Section 25.3.13
#else
/// \fn partition_copy ( InputIterator first, InputIterator last,
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
/// \brief Copies the elements that satisfy the predicate p from the range [first, last)
/// to the range beginning at d_first_true, and
/// copies the elements that do not satisfy p to the range beginning at d_first_false.
///
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param out_true An output iterator to write the elements that satisfy the predicate into
/// \param out_false An output iterator to write the elements that do not satisfy the predicate into
/// \param p A predicate for dividing the elements of the input sequence.
///
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template <typename InputIterator,
typename OutputIterator1, typename OutputIterator2, typename UnaryPredicate>
std::pair<OutputIterator1, OutputIterator2>
partition_copy ( InputIterator first, InputIterator last,
OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
{
for ( ; first != last; ++first )
if ( p (*first))
*out_true++ = *first;
else
*out_false++ = *first;
return std::pair<OutputIterator1, OutputIterator2> ( out_true, out_false );
}
#endif
/// \fn partition_copy ( const Range &r,
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
///
/// \param r The input range
/// \param out_true An output iterator to write the elements that satisfy the predicate into
/// \param out_false An output iterator to write the elements that do not satisfy the predicate into
/// \param p A predicate for dividing the elements of the input sequence.
///
template <typename Range, typename OutputIterator1, typename OutputIterator2,
typename UnaryPredicate>
std::pair<OutputIterator1, OutputIterator2>
partition_copy ( const Range &r, OutputIterator1 out_true, OutputIterator2 out_false,
UnaryPredicate p )
{
return boost::algorithm::partition_copy
(boost::begin(r), boost::end(r), out_true, out_false, p );
}
}} // namespace boost and algorithm
#endif // BOOST_ALGORITHM_PARTITION_COPY_HPP

View File

@ -0,0 +1,72 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
*/
/// \file partition_point.hpp
/// \brief Find the partition point in a sequence
/// \author Marshall Clow
#ifndef BOOST_ALGORITHM_PARTITION_POINT_HPP
#define BOOST_ALGORITHM_PARTITION_POINT_HPP
#include <algorithm> // for std::partition_point, if available
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost { namespace algorithm {
#if __cplusplus >= 201103L
// Use the C++11 versions of iota if it is available
using std::partition_point; // Section 25.3.13
#else
/// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
/// \brief Given a partitioned range, returns the partition point, i.e, the first element
/// that does not satisfy p
///
/// \param first The start of the input sequence
/// \param last One past the end of the input sequence
/// \param p The predicate to test the values with
/// \note This function is part of the C++2011 standard library.
/// We will use the standard one if it is available,
/// otherwise we have our own implementation.
template <typename ForwardIterator, typename Predicate>
ForwardIterator partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
{
std::size_t dist = std::distance ( first, last );
while ( first != last ) {
std::size_t d2 = dist / 2;
ForwardIterator ret_val = first;
std::advance (ret_val, d2);
if (p (*ret_val)) {
first = ++ret_val;
dist -= d2 + 1;
}
else {
last = ret_val;
dist = d2;
}
}
return first;
}
#endif
/// \fn partition_point ( Range &r, Predicate p )
/// \brief Given a partitioned range, returns the partition point
///
/// \param r The input range
/// \param p The predicate to test the values with
///
template <typename Range, typename Predicate>
typename boost::range_iterator<Range> partition_point ( Range &r, Predicate p )
{
return boost::algorithm::partition_point (boost::begin(r), boost::end(r), p);
}
}}
#endif // BOOST_ALGORITHM_PARTITION_POINT_HPP

View File

@ -0,0 +1,268 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP
#define BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP
#include <iterator> // for std::iterator_traits
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/bm_traits.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp>
namespace boost { namespace algorithm {
/*
A templated version of the boyer-moore searching algorithm.
References:
http://www.cs.utexas.edu/users/moore/best-ideas/string-searching/
http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
Explanations: boostinspect:noascii (test tool complains)
http://en.wikipedia.org/wiki/BoyerMoore_string_search_algorithm
http://www.movsd.com/bm.htm
http://www.cs.ucdavis.edu/~gusfield/cs224f09/bnotes.pdf
The Boyer-Moore search algorithm uses two tables, a "bad character" table
to tell how far to skip ahead when it hits a character that is not in the pattern,
and a "good character" table to tell how far to skip ahead when it hits a
mismatch on a character that _is_ in the pattern.
Requirements:
* Random access iterators
* The two iterator types (patIter and corpusIter) must
"point to" the same underlying type and be comparable.
* Additional requirements may be imposed but the skip table, such as:
** Numeric type (array-based skip table)
** Hashable type (map-based skip table)
*/
template <typename patIter, typename traits = detail::BM_traits<patIter> >
class boyer_moore {
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
public:
boyer_moore ( patIter first, patIter last )
: pat_first ( first ), pat_last ( last ),
k_pattern_length ( std::distance ( pat_first, pat_last )),
skip_ ( k_pattern_length, -1 ),
suffix_ ( k_pattern_length + 1 )
{
this->build_skip_table ( first, last );
this->build_suffix_table ( first, last );
}
~boyer_moore () {}
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
///
template <typename corpusIter>
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
BOOST_STATIC_ASSERT (( boost::is_same<
typename std::iterator_traits<patIter>::value_type,
typename std::iterator_traits<corpusIter>::value_type>::value ));
if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it!
if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
// If the pattern is larger than the corpus, we can't find it!
if ( k_corpus_length < k_pattern_length )
return corpus_last;
// Do the search
return this->do_search ( corpus_first, corpus_last );
}
template <typename Range>
typename boost::range_iterator<Range>::type operator () ( Range &r ) const {
return (*this) (boost::begin(r), boost::end(r));
}
private:
/// \cond DOXYGEN_HIDE
patIter pat_first, pat_last;
const difference_type k_pattern_length;
typename traits::skip_table_t skip_;
std::vector <difference_type> suffix_;
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last ) const {
/* ---- Do the matching ---- */
corpusIter curPos = corpus_first;
const corpusIter lastPos = corpus_last - k_pattern_length;
difference_type j, k, m;
while ( curPos <= lastPos ) {
/* while ( std::distance ( curPos, corpus_last ) >= k_pattern_length ) { */
// Do we match right where we are?
j = k_pattern_length;
while ( pat_first [j-1] == curPos [j-1] ) {
j--;
// We matched - we're done!
if ( j == 0 )
return curPos;
}
// Since we didn't match, figure out how far to skip forward
k = skip_ [ curPos [ j - 1 ]];
m = j - k - 1;
if ( k < j && m > suffix_ [ j ] )
curPos += m;
else
curPos += suffix_ [ j ];
}
return corpus_last; // We didn't find anything
}
void build_skip_table ( patIter first, patIter last ) {
for ( std::size_t i = 0; first != last; ++first, ++i )
skip_.insert ( *first, i );
}
template<typename Iter, typename Container>
void compute_bm_prefix ( Iter pat_first, Iter pat_last, Container &prefix ) {
const std::size_t count = std::distance ( pat_first, pat_last );
BOOST_ASSERT ( count > 0 );
BOOST_ASSERT ( prefix.size () == count );
prefix[0] = 0;
std::size_t k = 0;
for ( std::size_t i = 1; i < count; ++i ) {
BOOST_ASSERT ( k < count );
while ( k > 0 && ( pat_first[k] != pat_first[i] )) {
BOOST_ASSERT ( k < count );
k = prefix [ k - 1 ];
}
if ( pat_first[k] == pat_first[i] )
k++;
prefix [ i ] = k;
}
}
void build_suffix_table ( patIter pat_first, patIter pat_last ) {
const std::size_t count = (std::size_t) std::distance ( pat_first, pat_last );
if ( count > 0 ) { // empty pattern
std::vector<typename std::iterator_traits<patIter>::value_type> reversed(count);
(void) std::reverse_copy ( pat_first, pat_last, reversed.begin ());
std::vector<difference_type> prefix (count);
compute_bm_prefix ( pat_first, pat_last, prefix );
std::vector<difference_type> prefix_reversed (count);
compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed );
for ( std::size_t i = 0; i <= count; i++ )
suffix_[i] = count - prefix [count-1];
for ( std::size_t i = 0; i < count; i++ ) {
const std::size_t j = count - prefix_reversed[i];
const difference_type k = i - prefix_reversed[i] + 1;
if (suffix_[j] > k)
suffix_[j] = k;
}
}
}
/// \endcond
};
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
Use a bit of TMP to disambiguate the 3-argument templates */
/// \fn boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern.
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
/// \param pat_last One past the end of the data to search for
///
template <typename patIter, typename corpusIter>
corpusIter boyer_moore_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last )
{
boyer_moore<patIter> bm ( pat_first, pat_last );
return bm ( corpus_first, corpus_last );
}
template <typename PatternRange, typename corpusIter>
corpusIter boyer_moore_search (
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
{
typedef typename boost::range_iterator<PatternRange> pattern_iterator;
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
return bm ( corpus_first, corpus_last );
}
template <typename patIter, typename CorpusRange>
typename boost::lazy_disable_if_c<
boost::is_same<CorpusRange, patIter>::value, typename boost::range_iterator<CorpusRange> >
::type
boyer_moore_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
{
boyer_moore<patIter> bm ( pat_first, pat_last );
return bm (boost::begin (corpus), boost::end (corpus));
}
template <typename PatternRange, typename CorpusRange>
typename boost::range_iterator<CorpusRange>::type
boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern )
{
typedef typename boost::range_iterator<PatternRange> pattern_iterator;
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
return bm (boost::begin (corpus), boost::end (corpus));
}
// Creator functions -- take a pattern range, return an object
template <typename Range>
boost::algorithm::boyer_moore<typename boost::range_iterator<const Range>::type>
make_boyer_moore ( const Range &r ) {
return boost::algorithm::boyer_moore
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
}
template <typename Range>
boost::algorithm::boyer_moore<typename boost::range_iterator<Range>::type>
make_boyer_moore ( Range &r ) {
return boost::algorithm::boyer_moore
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
}
}}
#endif // BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP

View File

@ -0,0 +1,141 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
#define BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
#include <iterator> // for std::iterator_traits
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/bm_traits.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp>
// #define BOOST_ALGORITHM_BOYER_MOORE_HORSPOOL_DEBUG_HPP
namespace boost { namespace algorithm {
/*
A templated version of the boyer-moore-horspool searching algorithm.
Requirements:
* Random access iterators
* The two iterator types (patIter and corpusIter) must
"point to" the same underlying type.
* Additional requirements may be imposed buy the skip table, such as:
** Numeric type (array-based skip table)
** Hashable type (map-based skip table)
http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
*/
template <typename patIter, typename traits = detail::BM_traits<patIter> >
class boyer_moore_horspool {
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
public:
boyer_moore_horspool ( patIter first, patIter last )
: pat_first ( first ), pat_last ( last ),
k_pattern_length ( std::distance ( pat_first, pat_last )),
skip_ ( k_pattern_length, k_pattern_length ) {
// Build the skip table
std::size_t i = 0;
if ( first != last ) // empty pattern?
for ( patIter iter = first; iter != last-1; ++iter, ++i )
skip_.insert ( *iter, k_pattern_length - 1 - i );
#ifdef BOOST_ALGORITHM_BOYER_MOORE_HORSPOOL_DEBUG_HPP
skip_.PrintSkipTable ();
#endif
}
~boyer_moore_horspool () {}
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
BOOST_STATIC_ASSERT (( boost::is_same<
typename std::iterator_traits<patIter>::value_type,
typename std::iterator_traits<corpusIter>::value_type>::value ));
if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it!
if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
// If the pattern is larger than the corpus, we can't find it!
if ( k_corpus_length < k_pattern_length )
return corpus_last;
// Do the search
return this->do_search ( corpus_first, corpus_last );
}
private:
/// \cond DOXYGEN_HIDE
patIter pat_first, pat_last;
const difference_type k_pattern_length;
typename traits::skip_table_t skip_;
/// \fn do_search ( corpusIter corpus_first, corpusIter corpus_last )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param k_corpus_length The length of the corpus to search
///
template <typename corpusIter>
corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last ) const {
corpusIter curPos = corpus_first;
const corpusIter lastPos = corpus_last - k_pattern_length;
while ( curPos <= lastPos ) {
// Do we match right where we are?
std::size_t j = k_pattern_length - 1;
while ( pat_first [j] == curPos [j] ) {
// We matched - we're done!
if ( j == 0 )
return curPos;
j--;
}
curPos += skip_ [ curPos [ k_pattern_length - 1 ]];
}
return corpus_last;
}
// \endcond
};
/// \fn boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern.
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
/// \param pat_last One past the end of the data to search for
///
template <typename patIter, typename corpusIter>
corpusIter boyer_moore_horspool_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last ) {
boyer_moore_horspool<patIter> bmh ( pat_first, pat_last );
return bmh ( corpus_first, corpus_last );
}
}}
#endif // BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP

View File

@ -0,0 +1,105 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
#define BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
#include <climits> // for CHAR_BIT
#include <vector>
#include <iterator> // for std::iterator_traits
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/array.hpp>
#include <boost/tr1/tr1/unordered_map>
#include <boost/algorithm/searching/detail/debugging.hpp>
namespace boost { namespace algorithm { namespace detail {
//
// Default implementations of the skip tables for B-M and B-M-H
//
template<typename key_type, typename value_type, bool /*useArray*/> class skip_table;
// General case for data searching other than bytes; use a map
template<typename key_type, typename value_type>
class skip_table<key_type, value_type, false> {
private:
typedef std::tr1::unordered_map<key_type, value_type> skip_map;
const value_type k_default_value;
skip_map skip_;
public:
skip_table ( std::size_t patSize, value_type default_value )
: k_default_value ( default_value ), skip_ ( patSize ) {}
void insert ( key_type key, value_type val ) {
skip_ [ key ] = val; // Would skip_.insert (val) be better here?
}
value_type operator [] ( key_type key ) const {
typename skip_map::const_iterator it = skip_.find ( key );
return it == skip_.end () ? k_default_value : it->second;
}
void PrintSkipTable () const {
std::cout << "BM(H) Skip Table <unordered_map>:" << std::endl;
for ( typename skip_map::const_iterator it = skip_.begin (); it != skip_.end (); ++it )
if ( it->second != k_default_value )
std::cout << " " << it->first << ": " << it->second << std::endl;
std::cout << std::endl;
}
};
// Special case small numeric values; use an array
template<typename key_type, typename value_type>
class skip_table<key_type, value_type, true> {
private:
typedef typename boost::make_unsigned<key_type>::type unsigned_key_type;
typedef boost::array<value_type, 1U << (CHAR_BIT * sizeof(key_type))> skip_map;
skip_map skip_;
const value_type k_default_value;
public:
skip_table ( std::size_t patSize, value_type default_value ) : k_default_value ( default_value ) {
std::fill_n ( skip_.begin(), skip_.size(), default_value );
}
void insert ( key_type key, value_type val ) {
skip_ [ static_cast<unsigned_key_type> ( key ) ] = val;
}
value_type operator [] ( key_type key ) const {
return skip_ [ static_cast<unsigned_key_type> ( key ) ];
}
void PrintSkipTable () const {
std::cout << "BM(H) Skip Table <boost:array>:" << std::endl;
for ( typename skip_map::const_iterator it = skip_.begin (); it != skip_.end (); ++it )
if ( *it != k_default_value )
std::cout << " " << std::distance (skip_.begin (), it) << ": " << *it << std::endl;
std::cout << std::endl;
}
};
template<typename Iterator>
struct BM_traits {
typedef typename std::iterator_traits<Iterator>::difference_type value_type;
typedef typename std::iterator_traits<Iterator>::value_type key_type;
typedef boost::algorithm::detail::skip_table<key_type, value_type,
boost::is_integral<key_type>::value && (sizeof(key_type)==1)> skip_table_t;
};
}}} // namespaces
#endif // BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP

View File

@ -0,0 +1,30 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
#define BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
#include <iostream>
/// \cond DOXYGEN_HIDE
namespace boost { namespace algorithm { namespace detail {
// Debugging support
template <typename Iter>
void PrintTable ( Iter first, Iter last ) {
std::cout << std::distance ( first, last ) << ": { ";
for ( Iter iter = first; iter != last; ++iter )
std::cout << *iter << " ";
std::cout << "}" << std::endl;
}
}}}
/// \endcond
#endif // BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP

View File

@ -0,0 +1,200 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#ifndef BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
#define BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
#include <vector>
#include <iterator> // for std::iterator_traits
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp>
// #define BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_DEBUG
namespace boost { namespace algorithm {
// #define NEW_KMP
/*
A templated version of the Knuth-Morris-Pratt searching algorithm.
Requirements:
* Random-access iterators
* The two iterator types (I1 and I2) must "point to" the same underlying type.
http://en.wikipedia.org/wiki/KnuthMorrisPratt_algorithm
http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm
*/
template <typename patIter>
class knuth_morris_pratt {
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
public:
knuth_morris_pratt ( patIter first, patIter last )
: pat_first ( first ), pat_last ( last ),
k_pattern_length ( std::distance ( pat_first, pat_last )),
skip_ ( k_pattern_length + 1 ) {
#ifdef NEW_KMP
preKmp ( pat_first, pat_last );
#else
init_skip_table ( pat_first, pat_last );
#endif
#ifdef BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_DEBUG
detail::PrintTable ( skip_.begin (), skip_.end ());
#endif
}
~knuth_morris_pratt () {}
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
BOOST_STATIC_ASSERT (( boost::is_same<
typename std::iterator_traits<patIter>::value_type,
typename std::iterator_traits<corpusIter>::value_type>::value ));
if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it!
if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
// If the pattern is larger than the corpus, we can't find it!
if ( k_corpus_length < k_pattern_length )
return corpus_last;
return do_search ( corpus_first, corpus_last, k_corpus_length );
}
private:
/// \cond DOXYGEN_HIDE
patIter pat_first, pat_last;
const difference_type k_pattern_length;
std::vector <difference_type> skip_;
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
/// \brief Searches the corpus for the pattern that was passed into the constructor
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param p A predicate used for the search comparisons.
///
template <typename corpusIter>
corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last,
difference_type k_corpus_length ) const {
difference_type match_start = 0; // position in the corpus that we're matching
#ifdef NEW_KMP
int patternIdx = 0;
while ( match_start < k_corpus_length ) {
while ( patternIdx > -1 && pat_first[patternIdx] != corpus_first [match_start] )
patternIdx = skip_ [patternIdx]; //<--- Shifting the pattern on mismatch
patternIdx++;
match_start++; //<--- corpus is always increased by 1
if ( patternIdx >= (int) k_pattern_length )
return corpus_first + match_start - patternIdx;
}
#else
// At this point, we know:
// k_pattern_length <= k_corpus_length
// for all elements of skip, it holds -1 .. k_pattern_length
//
// In the loop, we have the following invariants
// idx is in the range 0 .. k_pattern_length
// match_start is in the range 0 .. k_corpus_length - k_pattern_length + 1
const difference_type last_match = k_corpus_length - k_pattern_length;
difference_type idx = 0; // position in the pattern we're comparing
while ( match_start <= last_match ) {
while ( pat_first [ idx ] == corpus_first [ match_start + idx ] ) {
if ( ++idx == k_pattern_length )
return corpus_first + match_start;
}
// Figure out where to start searching again
// assert ( idx - skip_ [ idx ] > 0 ); // we're always moving forward
match_start += idx - skip_ [ idx ];
idx = skip_ [ idx ] >= 0 ? skip_ [ idx ] : 0;
// assert ( idx >= 0 && idx < k_pattern_length );
}
#endif
// We didn't find anything
return corpus_last;
}
void preKmp ( patIter first, patIter last ) {
const /*std::size_t*/ int count = std::distance ( first, last );
int i, j;
i = 0;
j = skip_[0] = -1;
while (i < count) {
while (j > -1 && first[i] != first[j])
j = skip_[j];
i++;
j++;
if (first[i] == first[j])
skip_[i] = skip_[j];
else
skip_[i] = j;
}
}
void init_skip_table ( patIter first, patIter last ) {
const difference_type count = std::distance ( first, last );
int j;
skip_ [ 0 ] = -1;
for ( int i = 1; i <= count; ++i ) {
j = skip_ [ i - 1 ];
while ( j >= 0 ) {
if ( first [ j ] == first [ i - 1 ] )
break;
j = skip_ [ j ];
}
skip_ [ i ] = j + 1;
}
}
// \endcond
};
/// \fn knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern.
///
/// \param corpus_first The start of the data to search (Random Access Iterator)
/// \param corpus_last One past the end of the data to search
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
/// \param pat_last One past the end of the data to search for
///
template <typename patIter, typename corpusIter>
corpusIter knuth_morris_pratt_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last ) {
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
return kmp ( corpus_first, corpus_last );
}
}}
#endif // BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP

View File

@ -15,6 +15,8 @@
#include <locale>
#include <functional>
#include <boost/type_traits/make_unsigned.hpp>
namespace boost {
namespace algorithm {
namespace detail {
@ -31,19 +33,19 @@ namespace boost {
struct to_lowerF : public std::unary_function<CharT, CharT>
{
// Constructor
to_lowerF( const std::locale& Loc ) : m_Loc( Loc ) {}
to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::tolower( Ch);
return std::tolower( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
#else
return std::tolower<CharT>( Ch, m_Loc );
return std::tolower<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale& m_Loc;
const std::locale* m_Loc;
};
// a toupper functor
@ -51,19 +53,19 @@ namespace boost {
struct to_upperF : public std::unary_function<CharT, CharT>
{
// Constructor
to_upperF( const std::locale& Loc ) : m_Loc( Loc ) {}
to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper( Ch);
return std::toupper( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch ));
#else
return std::toupper<CharT>( Ch, m_Loc );
return std::toupper<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale& m_Loc;
const std::locale* m_Loc;
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)

View File

@ -32,8 +32,8 @@ namespace boost {
struct is_classifiedF :
public predicate_facade<is_classifiedF>
{
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor from a locale
is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
@ -72,8 +72,8 @@ namespace boost {
typedef typename ::boost::remove_const<CharT>::type set_value_type;
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
template<typename RangeT>
@ -126,7 +126,7 @@ namespace boost {
}
// Use fixed storage
::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
}
// Destructor
@ -206,7 +206,7 @@ namespace boost {
}
// Copy the data
::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
return *this;
}
@ -253,8 +253,8 @@ namespace boost {
struct is_from_rangeF :
public predicate_facade< is_from_rangeF<CharT> >
{
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
@ -278,8 +278,8 @@ namespace boost {
{
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_andF( Pred1T Pred1, Pred2T Pred2 ) :
@ -303,8 +303,8 @@ namespace boost {
public predicate_facade< pred_orF<Pred1T,Pred2T> >
{
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_orF( Pred1T Pred1, Pred2T Pred2 ) :
@ -328,8 +328,8 @@ namespace boost {
public predicate_facade< pred_notF<PredT> >
{
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_notF( PredT Pred ) : m_Pred(Pred) {}

View File

@ -49,17 +49,17 @@ namespace boost {
if ( !M )
{
// Match not found - return original sequence
std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
Output = std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
return Output;
}
// Copy the beginning of the sequence
std::copy( ::boost::begin(Input), ::boost::begin(M), Output );
Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output );
// Format find result
// Copy formated result
std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
// Copy the rest of the sequence
std::copy( M.end(), ::boost::end(Input), Output );
Output = std::copy( M.end(), ::boost::end(Input), Output );
return Output;
}
@ -74,13 +74,17 @@ namespace boost {
const InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult )
{
return ::boost::algorithm::detail::find_format_copy_impl2(
Output,
Input,
Formatter,
FindResult,
Formatter(FindResult) );
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_copy_impl2(
Output,
Input,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
}
}
@ -132,11 +136,15 @@ namespace boost {
FormatterT Formatter,
const FindResultT& FindResult)
{
return ::boost::algorithm::detail::find_format_copy_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_copy_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return Input;
}
}
// replace implementation ----------------------------------------------------//
@ -180,11 +188,13 @@ namespace boost {
FormatterT Formatter,
const FindResultT& FindResult)
{
::boost::algorithm::detail::find_format_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
::boost::algorithm::detail::find_format_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
}
}
} // namespace detail

View File

@ -57,9 +57,9 @@ namespace boost {
while( M )
{
// Copy the beginning of the sequence
std::copy( LastMatch, M.begin(), Output );
Output = std::copy( LastMatch, M.begin(), Output );
// Copy formated result
std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
// Proceed to the next match
LastMatch=M.end();
@ -67,7 +67,7 @@ namespace boost {
}
// Copy the rest of the sequence
std::copy( LastMatch, ::boost::end(Input), Output );
Output = std::copy( LastMatch, ::boost::end(Input), Output );
return Output;
}
@ -84,14 +84,18 @@ namespace boost {
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult )
{
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Output,
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Output,
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
}
}
// find_format_all_copy implementation ----------------------------------------------//
@ -156,12 +160,16 @@ namespace boost {
FormatterT Formatter,
const FindResultT& FindResult)
{
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return Input;
}
}
// find_format_all implementation ------------------------------------------------//
@ -248,12 +256,14 @@ namespace boost {
FormatterT Formatter,
FindResultT FindResult)
{
::boost::algorithm::detail::find_format_all_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
::boost::algorithm::detail::find_format_all_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
}
}
} // namespace detail

View File

@ -52,7 +52,9 @@ namespace boost {
find_format_store& operator=( FindResultT FindResult )
{
iterator_range<ForwardIteratorT>::operator=(FindResult);
m_FormatResult=m_Formatter(FindResult);
if( !this->empty() ) {
m_FormatResult=m_Formatter(FindResult);
}
return *this;
}
@ -68,6 +70,15 @@ namespace boost {
const formatter_type& m_Formatter;
};
template<typename InputT, typename FindResultT>
bool check_find_result(InputT&, FindResultT& FindResult)
{
typedef BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type input_iterator_type;
iterator_range<input_iterator_type> ResultRange(FindResult);
return !ResultRange.empty();
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif

View File

@ -87,6 +87,31 @@ namespace boost {
}
};
// dissect format functor ----------------------------------------------------//
// dissect format functor
template<typename FinderT>
struct dissect_formatF
{
public:
// Construction
dissect_formatF(FinderT Finder) :
m_Finder(Finder) {}
// Operation
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
operator()(const RangeT& Replace) const
{
return m_Finder(::boost::begin(Replace), ::boost::end(Replace));
}
private:
FinderT m_Finder;
};
} // namespace detail
} // namespace algorithm
} // namespace boost

View File

@ -752,7 +752,7 @@ namespace boost {
\param Output An output iterator to which the result will be copied
\param Input An input string
\param N Length of the head.
\param N Length of the tail.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\return An output iterator pointing just after the last inserted character or
@ -797,7 +797,7 @@ namespace boost {
considered to be the tail. The input sequence is modified in-place.
\param Input An input string
\param N Length of the head
\param N Length of the tail
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
*/

View File

@ -257,7 +257,7 @@ namespace boost {
//! Find tail algorithm
/*!
Get the head of the input. Head is a suffix of the string of the
Get the tail of the input. Tail 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.

View File

@ -240,7 +240,7 @@ namespace boost {
m_Match(Other.m_Match),
m_Next(Other.m_Next),
m_End(Other.m_End),
m_bEof(false)
m_bEof(Other.m_bEof)
{}
//! Constructor
@ -259,7 +259,11 @@ namespace boost {
m_End(End),
m_bEof(false)
{
increment();
// force the correct behavior for empty sequences and yield at least one token
if(Begin!=End)
{
increment();
}
}
//! Constructor
/*!
@ -278,7 +282,11 @@ namespace boost {
m_Next=::boost::begin(lit_col);
m_End=::boost::end(lit_col);
increment();
// force the correct behavior for empty sequences and yield at least one token
if(m_Next!=m_End)
{
increment();
}
}

View File

@ -36,7 +36,7 @@ namespace boost {
//! Constant formatter
/*!
Construct the \c const_formatter. Const formatter always returns
Constructs a \c const_formatter. Const formatter always returns
the same value, regardless of the parameter.
\param Format A predefined value used as a result for formating
@ -55,7 +55,7 @@ namespace boost {
//! Identity formatter
/*!
Construct the \c identity_formatter. Identity formatter always returns
Constructs an \c identity_formatter. Identity formatter always returns
the parameter.
\return An instance of the \c identity_formatter object.
@ -73,7 +73,7 @@ namespace boost {
//! Empty formatter
/*!
Construct the \c empty_formatter. Empty formatter always returns an empty
Constructs an \c empty_formatter. Empty formatter always returns an empty
sequence.
\param Input container used to select a correct value_type for the
@ -89,6 +89,22 @@ namespace boost {
BOOST_STRING_TYPENAME range_value<RangeT>::type>();
}
//! Empty formatter
/*!
Constructs a \c dissect_formatter. Dissect formatter uses a specified finder
to extract a portion of the formatted sequence. The first finder's match is returned
as a result
\param Finder a finder used to select a portion of the formated sequence
\return An instance of the \c dissect_formatter object.
*/
template<typename FinderT>
inline detail::dissect_formatF< FinderT >
dissect_formatter(const FinderT& Finder)
{
return detail::dissect_formatF<FinderT>(Finder);
}
} // namespace algorithm
@ -96,6 +112,7 @@ namespace boost {
using algorithm::const_formatter;
using algorithm::identity_formatter;
using algorithm::empty_formatter;
using algorithm::dissect_formatter;
} // namespace boost

View File

@ -0,0 +1,217 @@
// Boost string_algo library trim.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under 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_TRIM_ALL_HPP
#define BOOST_STRING_TRIM_ALL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <locale>
/*! \file
Defines trim_all algorithms.
Just like \c trim, \c trim_all removes all trailing and leading spaces from a
sequence (string). In addition, spaces in the middle of the sequence are truncated
to just one character. Space is recognized using given locales.
\c trim_fill acts as trim_all, but the spaces in the middle are replaces with
a user-define sequence of character.
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
whether a character is a space. Common predicates are provided in classification.hpp header.
*/
namespace boost {
namespace algorithm {
// multi line trim ----------------------------------------------- //
//! Trim All - parametric
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The result is a trimmed copy of the input
\param Input An input sequence
\param IsSpace An unary predicate identifying spaces
\return A trimmed copy of the input
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_all_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
return
::boost::find_format_all_copy(
::boost::trim_copy_if(Input, IsSpace),
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::dissect_formatter(::boost::head_finder(1)));
}
//! Trim All
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The input sequence is modified in-place.
\param Input An input sequence
\param IsSpace An unary predicate identifying spaces
*/
template<typename SequenceT, typename PredicateT>
inline void trim_all_if(SequenceT& Input, PredicateT IsSpace)
{
::boost::trim_if(Input, IsSpace);
::boost::find_format_all(
Input,
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::dissect_formatter(::boost::head_finder(1)));
}
//! Trim All
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
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 of the input
*/
template<typename SequenceT>
inline SequenceT trim_all_copy(const SequenceT& Input, const std::locale& Loc =std::locale())
{
return trim_all_copy_if(Input, ::boost::is_space(Loc));
}
//! Trim All
/*!
Remove all leading and trailing spaces from the input and
compress all other spaces to a single character.
The input sequence is modified in-place.
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT>
inline void trim_all(SequenceT& Input, const std::locale& Loc =std::locale())
{
trim_all_if(Input, ::boost::is_space(Loc));
}
//! Trim Fill - parametric
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The result is a trimmed copy of the input
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param IsSpace An unary predicate identifying spaces
\return A trimmed copy of the input
*/
template<typename SequenceT, typename RangeT, typename PredicateT>
inline SequenceT trim_fill_copy_if(const SequenceT& Input, const RangeT& Fill, PredicateT IsSpace)
{
return
::boost::find_format_all_copy(
::boost::trim_copy_if(Input, IsSpace),
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::const_formatter(::boost::as_literal(Fill)));
}
//! Trim Fill
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The input sequence is modified in-place.
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param IsSpace An unary predicate identifying spaces
*/
template<typename SequenceT, typename RangeT, typename PredicateT>
inline void trim_fill_if(SequenceT& Input, const RangeT& Fill, PredicateT IsSpace)
{
::boost::trim_if(Input, IsSpace);
::boost::find_format_all(
Input,
::boost::token_finder(IsSpace, ::boost::token_compress_on),
::boost::const_formatter(::boost::as_literal(Fill)));
}
//! Trim Fill
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The result is a trimmed copy of the input
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT, typename RangeT>
inline SequenceT trim_fill_copy(const SequenceT& Input, const RangeT& Fill, const std::locale& Loc =std::locale())
{
return trim_fill_copy_if(Input, Fill, ::boost::is_space(Loc));
}
//! Trim Fill
/*!
Remove all leading and trailing spaces from the input and
replace all every block of consecutive spaces with a fill string
defined by user.
The input sequence is modified in-place.
\param Input An input sequence
\param Fill A string used to fill the inner spaces
\param Loc A locale used for 'space' classification
\return A trimmed copy of the input
*/
template<typename SequenceT, typename RangeT>
inline void trim_fill(SequenceT& Input, const RangeT& Fill, const std::locale& Loc =std::locale())
{
trim_fill_if(Input, Fill, ::boost::is_space(Loc));
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::trim_all;
using algorithm::trim_all_if;
using algorithm::trim_all_copy;
using algorithm::trim_all_copy_if;
using algorithm::trim_fill;
using algorithm::trim_fill_if;
using algorithm::trim_fill_copy;
using algorithm::trim_fill_copy_if;
} // namespace boost
#endif // BOOST_STRING_TRIM_ALL_HPP

View File

@ -92,11 +92,11 @@ Synopsis of <tt>&lt;boost/algorithm/minmax.hpp></tt></h3>
namespace boost {
template &lt;class T>
tuple&lt;T const&amp;, T const&amp;> >
tuple&lt;T const&amp;, T const&amp;>
minmax(const T&amp; a, const T&amp; b);
template &lt;class T, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
tuple&lt;T const&amp;, T const&amp;> >
tuple&lt;T const&amp;, T const&amp;>
minmax(const T&amp; a, const T&amp; b, BinaryPredicate comp);
}
@ -338,7 +338,7 @@ most</i> instead of <i>exactly</i> in the odd case.
<b>Rationale:</b></h3>
<a name="two_headers">
<h4><b>Why not a single header <tt>&amp;boost/algorithm/minmax.hpp></tt>?</b></h4>
<h4><b>Why not a single header <tt>&lt;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

View File

@ -12,6 +12,7 @@ toolset.using doxygen ;
boostbook string_algo : string_algo.xml autodoc
:
<xsl:param>boost.root=../../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
@ -42,6 +43,7 @@ doxygen autodoc
[ glob ../../../../boost/algorithm/string/formatter.hpp ]
[ glob ../../../../boost/algorithm/string/regex.hpp ]
[ glob ../../../../boost/algorithm/string/regex_find_format.hpp ]
[ glob ../../../../boost/algorithm/string/trim_all.hpp ]
:
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
<doxygen:param>EXTRACT_PRIVATE=NO

View File

@ -32,7 +32,9 @@
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 >&copy; 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 -->
<br>Use, modification and distribution is subject to the Boost
Software License, Version 1.0. (See accompanying file
<code class="filename">LICENSE_1_0.txt</code> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</br>
</p>
<!-- Copyright Dezide Aps 2003-2004 -->

View File

@ -737,6 +737,20 @@
<functionname>is_xdigit()</functionname>
</entry>
</row>
<row>
<entry>is_any_of</entry>
<entry>Recognize any of a sequence of characters</entry>
<entry>
<functionname>is_any_of()</functionname>
</entry>
</row>
<row>
<entry>is_from_range</entry>
<entry>Recognize characters inside a min..max range</entry>
<entry>
<functionname>is_from_range()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>

View File

@ -33,7 +33,7 @@
<librarypurpose>
A set of generic string-related algorithms and utilities
</librarypurpose>
<librarycategory name="category:algoritms"/>
<librarycategory name="category:algorithms"/>
<librarycategory name="category:string-text"/>
</libraryinfo>

View File

@ -57,7 +57,7 @@
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,
<ulink url="../../libs/range/doc/html/range/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>
<ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>
can be used to package iterators into a structure with a compatible interface.
</para>
</listitem>
@ -169,7 +169,7 @@
<programlisting>
string str1=" hello world! ";
string str2=trim_left_copy(str1); // str2 == "hello world! "
string str3=trim_right_copy(str2); // str3 == " hello world!"
string str3=trim_right_copy(str1); // str3 == " hello world!"
trim(str1); // str1 == "hello world!"
string phone="00423333444";
@ -208,7 +208,7 @@
</programlisting>
<para>
We have used <functionname>find_last()</functionname> to search the <code>text</code> for "ll".
The result is given in the <ulink url="../../libs/range/doc/html/range/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>.
The result is given in the <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.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".
@ -217,7 +217,7 @@
<ulink url="../../libs/range/index.html">Boost.Range</ulink>.
The following lines transform the result. Notice that
<ulink url="../../libs/range/doc/html/range/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink> has familiar
<ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.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>
@ -264,7 +264,7 @@
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/html/range/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>
Dereferencing a find iterator yields an <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>
object, that delimits the current match.
</para>
<para>
@ -339,7 +339,7 @@
typedef vector&lt; string &gt; split_vector_type;
split_vector_type SplitVec; // #2: Search for tokens
split( SplitVec, str1, is_any_of("-*") ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
split( SplitVec, str1, is_any_of("-*"), token_compress_on ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
</programlisting>
<para>
<code>[hello]</code> designates an <code>iterator_range</code> delimiting this substring.

View File

@ -59,5 +59,11 @@ test-suite algorithm/string
:
: regex
]
[ run
find_format_test.cpp
: :
:
: find_format
]
;

View File

@ -0,0 +1,163 @@
// Boost string_algo library find_format_test.cpp file ------------------//
// Copyright (c) 2009 Steven Watanabe
// Distributed under 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 <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/formatter.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <boost/test/test_tools.hpp>
// We're only using const_formatter.
template<class Formatter>
struct formatter_result {
typedef boost::iterator_range<const char*> type;
};
template<class Formatter>
struct checked_formatter {
public:
checked_formatter(const Formatter& formatter) : formatter_(formatter) {}
template< typename T >
typename formatter_result<Formatter>::type operator()( const T & s ) const {
BOOST_CHECK( !s.empty() );
return formatter_(s);
}
private:
Formatter formatter_;
};
template<class Formatter>
checked_formatter<Formatter>
make_checked_formatter(const Formatter& formatter) {
return checked_formatter<Formatter>(formatter);
}
void find_format_test()
{
const std::string source = "$replace $replace";
std::string expected = "ok $replace";
std::string output(80, '\0');
std::string::iterator pos =
boost::find_format_copy(
output.begin(),
source,
boost::first_finder("$replace"),
make_checked_formatter(boost::const_formatter("ok")));
BOOST_CHECK(pos == output.begin() + expected.size());
output.erase(std::remove(output.begin(), output.end(), '\0'), output.end());
BOOST_CHECK_EQUAL(output, expected);
output =
boost::find_format_copy(
source,
boost::first_finder("$replace"),
make_checked_formatter(boost::const_formatter("ok")));
BOOST_CHECK_EQUAL(output, expected);
// now try finding a string that doesn't exist
output.resize(80);
pos =
boost::find_format_copy(
output.begin(),
source,
boost::first_finder("$noreplace"),
make_checked_formatter(boost::const_formatter("bad")));
BOOST_CHECK(pos == output.begin() + source.size());
output.erase(std::remove(output.begin(), output.end(), '\0'), output.end());
BOOST_CHECK_EQUAL(output, source);
output =
boost::find_format_copy(
source,
boost::first_finder("$noreplace"),
make_checked_formatter(boost::const_formatter("bad")));
BOOST_CHECK_EQUAL(output, source);
// in place version
output = source;
boost::find_format(
output,
boost::first_finder("$replace"),
make_checked_formatter(boost::const_formatter("ok")));
BOOST_CHECK_EQUAL(output, expected);
output = source;
boost::find_format(
output,
boost::first_finder("$noreplace"),
make_checked_formatter(boost::const_formatter("bad")));
BOOST_CHECK_EQUAL(output, source);
}
void find_format_all_test()
{
const std::string source = "$replace $replace";
std::string expected = "ok ok";
std::string output(80, '\0');
std::string::iterator pos =
boost::find_format_all_copy(output.begin(),
source,
boost::first_finder("$replace"),
boost::const_formatter("ok"));
BOOST_CHECK(pos == output.begin() + expected.size());
output.erase(std::remove(output.begin(), output.end(), '\0'), output.end());
BOOST_CHECK_EQUAL(output, expected);
output =
boost::find_format_all_copy(
source,
boost::first_finder("$replace"),
make_checked_formatter(boost::const_formatter("ok")));
BOOST_CHECK_EQUAL(output, expected);
// now try finding a string that doesn't exist
output.resize(80);
pos =
boost::find_format_all_copy(
output.begin(),
source,
boost::first_finder("$noreplace"),
make_checked_formatter(boost::const_formatter("bad")));
BOOST_CHECK(pos == output.begin() + source.size());
output.erase(std::remove(output.begin(), output.end(), '\0'), output.end());
BOOST_CHECK_EQUAL(output, source);
output =
boost::find_format_all_copy(
source,
boost::first_finder("$noreplace"),
make_checked_formatter(boost::const_formatter("bad")));
BOOST_CHECK_EQUAL(output, source);
// in place version
output = source;
boost::find_format_all(
output,
boost::first_finder("$replace"),
make_checked_formatter(boost::const_formatter("ok")));
BOOST_CHECK_EQUAL(output, expected);
output = source;
boost::find_format_all(
output,
boost::first_finder("$noreplace"),
make_checked_formatter(boost::const_formatter("bad")));
BOOST_CHECK_EQUAL(output, source);
}
int test_main( int, char*[] )
{
find_format_test();
find_format_all_test();
return 0;
}

View File

@ -11,6 +11,9 @@
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/std/list_traits.hpp>
#include <boost/algorithm/string/std/string_traits.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/classification.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -285,6 +288,23 @@ void collection_comp_test()
}
}
void dissect_format_test()
{
BOOST_CHECK(
find_format_all_copy(
string("aBc123Abc"),
first_finder("abc", is_iequal()),
dissect_formatter(token_finder(is_upper())))=="B123A");
BOOST_CHECK(
find_format_all_copy(
string("abc 123 abc"),
token_finder(is_space(), token_compress_on),
dissect_formatter(head_finder(1)))=="abc 123 abc");
}
// test main
int test_main( int, char*[] )
{
@ -297,6 +317,7 @@ int test_main( int, char*[] )
replace_tail_test();
replace_range_test();
collection_comp_test();
dissect_format_test();
return 0;
}

View File

@ -40,6 +40,7 @@ void iterator_test()
string str1("xx-abc--xx-abb");
string str2("Xx-abc--xX-abb-xx");
string str3("xx");
string strempty("");
const char* pch1="xx-abc--xx-abb";
vector<string> tokens;
vector< vector<int> > vtokens;
@ -123,6 +124,25 @@ void iterator_test()
BOOST_CHECK( tokens[3]==string("xx") );
BOOST_CHECK( tokens[4]==string("abb") );
split(
tokens,
str3,
is_any_of(","),
token_compress_off);
BOOST_REQUIRE( tokens.size()==1 );
BOOST_CHECK( tokens[0]==string("xx") );
split(
tokens,
strempty,
is_punct(),
token_compress_off);
BOOST_REQUIRE( tokens.size()==1 );
BOOST_CHECK( tokens[0]==string("") );
find_iterator<string::iterator> fiter=make_find_iterator(str1, first_finder("xx"));
BOOST_CHECK(equals(*fiter, "xx"));
++fiter;
@ -139,6 +159,7 @@ void iterator_test()
++siter;
BOOST_CHECK(equals(*siter, "abb"));
++siter;
BOOST_CHECK(siter==split_iterator<string::iterator>(siter));
BOOST_CHECK(siter==split_iterator<string::iterator>());
}

View File

@ -8,6 +8,7 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/trim_all.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -109,10 +110,95 @@ void trim_test()
BOOST_CHECK( trim_copy_if( string("<>abc<>"), is_any_of( "<<>>" ) )=="abc" );
}
void trim_all_test()
{
string str1(" 1x x x x1 ");
string str2("+---...2x+--x--+x-+-x2...---+");
string str3(" ");
// *** value passing tests *** //
// general string test
BOOST_CHECK( trim_all_copy( str1 )=="1x x x x1" ) ;
BOOST_CHECK( trim_all_copy_if( str2, is_punct() )=="2x+x-x-x2" ) ;
// spaces-only string test
BOOST_CHECK( trim_all_copy( str3 )=="" );
// empty string check
BOOST_CHECK( trim_all_copy( string("") )=="" );
// general string test
trim_all( str1 );
BOOST_CHECK( str1=="1x x x x1" ) ;
trim_all_if( str2, is_punct() );
BOOST_CHECK( str2=="2x+x-x-x2" ) ;
// spaces-only string test
str3 = " "; trim_all( str3 );
BOOST_CHECK( str3=="" );
// empty string check
str3 = ""; trim_all( str3 );
BOOST_CHECK( str3=="" );
BOOST_CHECK( str3=="" );
// *** non-standard predicate tests *** //
BOOST_CHECK(
trim_all_copy_if(
string("123abc127deb456"),
is_classified(std::ctype_base::digit) )=="abc1deb" );
BOOST_CHECK( trim_all_copy_if( string("<>abc<>def<>"), is_any_of( "<<>>" ) )=="abc<def" );
}
void trim_fill_test()
{
string str1(" 1x x x x1 ");
string str2("+---...2x+--x--+x-+-x2...---+");
string str3(" ");
// *** value passing tests *** //
// general string test
BOOST_CHECK( trim_fill_copy( str1, "-" )=="1x-x-x-x1" ) ;
BOOST_CHECK( trim_fill_copy_if( str2, " ", is_punct() )=="2x x x x2" ) ;
// spaces-only string test
BOOST_CHECK( trim_fill_copy( str3, " " )=="" );
// empty string check
BOOST_CHECK( trim_fill_copy( string(""), " " )=="" );
// general string test
trim_fill( str1, "-" );
BOOST_CHECK( str1=="1x-x-x-x1" ) ;
trim_fill_if( str2, "", is_punct() );
BOOST_CHECK( str2=="2xxxx2" ) ;
// spaces-only string test
str3 = " "; trim_fill( str3, "" );
BOOST_CHECK( str3=="" );
// empty string check
str3 = ""; trim_fill( str3, "" );
BOOST_CHECK( str3=="" );
BOOST_CHECK( str3=="" );
// *** non-standard predicate tests *** //
BOOST_CHECK(
trim_fill_copy_if(
string("123abc127deb456"),
"+",
is_classified(std::ctype_base::digit) )=="abc+deb" );
BOOST_CHECK( trim_fill_copy_if( string("<>abc<>def<>"), "-", is_any_of( "<<>>" ) )=="abc-def" );
}
// test main
int test_main( int, char*[] )
{
trim_test();
trim_all_test();
trim_fill_test();
return 0;
}

44
test/Jamfile.v2 Executable file
View File

@ -0,0 +1,44 @@
# Boost algorithm library test suite Jamfile ----------------------------
#
# Copyright Marshall Clow 2010-2012. 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:
# Search tests
: [ run empty_search_test.cpp : : : : empty_search_test ]
[ run search_test1.cpp : : : : search_test1 ]
[ run search_test2.cpp : : : : search_test2 ]
[ run search_test3.cpp : : : : search_test3 ]
[ compile-fail search_fail1.cpp : : : : ]
[ compile-fail search_fail2.cpp : : : : ]
[ compile-fail search_fail3.cpp : : : : ]
# Clamp tests
[ run clamp_test.cpp : : : : clamp_test ]
# Cxx11 tests
[ run all_of_test.cpp : : : : all_of_test ]
[ run any_of_test.cpp : : : : any_of_test ]
[ run none_of_test.cpp : : : : none_of_test ]
[ run one_of_test.cpp : : : : one_of_test ]
[ run ordered_test.cpp : : : : ordered_test ]
[ run find_if_not_test1.cpp : : : : find_if_not_test1 ]
[ run copy_n_test1.cpp : : : : copy_n_test1 ]
[ run iota_test1.cpp : : : : iota_test1 ]
[ run is_permutation_test1.cpp : : : : is_permutation_test1 ]
[ run partition_point_test1.cpp : : : : partition_point_test1 ]
[ run is_partitioned_test1.cpp : : : : is_partitioned_test1 ]
[ run partition_copy_test1.cpp : : : : partition_copy_test1 ]
;
}

86
test/all_of_test.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <functional>
#include <vector>
#include <list>
template<typename T>
struct is_ : public std::unary_function<T, bool> {
is_ ( T v ) : val_ ( v ) {}
~is_ () {}
bool operator () ( T comp ) const { return val_ == comp; }
private:
is_ (); // need a value
T val_;
};
namespace ba = boost::algorithm;
void test_all ()
{
// Note: The literal values here are tested against directly, careful if you change them:
int some_numbers[] = { 1, 1, 1, 18, 10 };
std::vector<int> vi(some_numbers, some_numbers + 5);
std::list<int> li(vi.begin(), vi.end ());
int some_letters[] = { 'a', 'q', 'n', 'y', 'n' };
std::vector<char> vc(some_letters, some_letters + 5);
BOOST_CHECK (!ba::all_of_equal ( vi, 1 ));
BOOST_CHECK (!ba::all_of ( vi, is_<int> ( 1 )));
BOOST_CHECK (!ba::all_of_equal ( vi.begin(), vi.end(), 1 ));
BOOST_CHECK (!ba::all_of ( vi.begin(), vi.end(), is_<int> ( 1 )));
BOOST_CHECK (!ba::all_of_equal ( vi, 0 ));
BOOST_CHECK (!ba::all_of ( vi, is_<int> ( 0 )));
BOOST_CHECK (!ba::all_of_equal ( vi.begin(), vi.end(), 0 ));
BOOST_CHECK (!ba::all_of ( vi.begin(), vi.end(), is_<int> ( 0 )));
BOOST_CHECK ( ba::all_of_equal ( vi.end(), vi.end(), 0 ));
BOOST_CHECK ( ba::all_of ( vi.end(), vi.end(), is_<int> ( 0 )));
BOOST_CHECK ( ba::all_of_equal ( vi.begin(), vi.begin () + 3, 1 ));
BOOST_CHECK ( ba::all_of ( vi.begin(), vi.begin () + 3, is_<int> ( 1 )));
BOOST_CHECK ( ba::all_of_equal ( vc.begin() + 1, vc.begin() + 2, 'q' ));
BOOST_CHECK ( ba::all_of ( vc.begin() + 1, vc.begin() + 2, is_<char> ( 'q' )));
BOOST_CHECK (!ba::all_of_equal ( vc, '!' ));
BOOST_CHECK (!ba::all_of ( vc, is_<char> ( '!' )));
BOOST_CHECK ( ba::all_of_equal ( vi.begin(), vi.begin(), 1 ));
BOOST_CHECK ( ba::all_of_equal ( vc.begin(), vc.begin(), 'a' ));
BOOST_CHECK ( ba::all_of ( vi.begin(), vi.begin(), is_<int> ( 1 )));
BOOST_CHECK ( ba::all_of ( vc.begin(), vc.begin(), is_<char> ( 'a' )));
BOOST_CHECK (!ba::all_of_equal ( li, 1 ));
BOOST_CHECK (!ba::all_of ( li, is_<int> ( 1 )));
BOOST_CHECK (!ba::all_of_equal ( li.begin(), li.end(), 1 ));
BOOST_CHECK (!ba::all_of ( li.begin(), li.end(), is_<int> ( 1 )));
std::list<int>::iterator l_iter = li.begin ();
l_iter++; l_iter++; l_iter++;
BOOST_CHECK ( ba::all_of_equal ( li.begin(), l_iter, 1 ));
BOOST_CHECK ( ba::all_of ( li.begin(), l_iter, is_<int> ( 1 )));
}
int test_main( int , char* [] )
{
test_all ();
return 0;
}

105
test/any_of_test.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <functional>
#include <vector>
#include <list>
template<typename T>
struct is_ : public std::unary_function<T, bool> {
is_ ( T v ) : val_ ( v ) {}
~is_ () {}
bool operator () ( T comp ) const { return val_ == comp; }
private:
is_ (); // need a value
T val_;
};
namespace ba = boost::algorithm;
void test_any ()
{
// Note: The literal values here are tested against directly, careful if you change them:
int some_numbers[] = { 1, 5, 0, 18, 10 };
std::vector<int> vi(some_numbers, some_numbers + 5);
std::list<int> li(vi.begin(), vi.end ());
int some_letters[] = { 'a', 'q', 'n', 'y', 'n' };
std::vector<char> vc(some_letters, some_letters + 5);
BOOST_CHECK ( ba::any_of_equal ( vi, 1 ));
BOOST_CHECK ( ba::any_of ( vi, is_<int> ( 1 )));
BOOST_CHECK ( ba::any_of_equal ( vi.begin(), vi.end(), 1 ));
BOOST_CHECK ( ba::any_of ( vi.begin(), vi.end(), is_<int> ( 1 )));
BOOST_CHECK (!ba::any_of_equal ( vi, 9 ));
BOOST_CHECK (!ba::any_of ( vi, is_<int> ( 9 )));
BOOST_CHECK (!ba::any_of_equal ( vi.begin(), vi.end(), 9 ));
BOOST_CHECK (!ba::any_of ( vi.begin(), vi.end(), is_<int> ( 9 )));
BOOST_CHECK ( ba::any_of_equal ( vi, 10 ));
BOOST_CHECK ( ba::any_of ( vi, is_<int> ( 10 )));
BOOST_CHECK (!ba::any_of_equal ( vi, 4 ));
BOOST_CHECK (!ba::any_of ( vi, is_<int> ( 4 )));
BOOST_CHECK (!ba::any_of_equal ( vi.end(), vi.end(), 0 ));
BOOST_CHECK (!ba::any_of ( vi.end(), vi.end(), is_<int> ( 0 )));
// 5 is not in { 0, 18, 10 }, but 10 is
BOOST_CHECK ( ba::any_of_equal ( vi.begin() + 2, vi.end(), 10 ));
BOOST_CHECK ( ba::any_of ( vi.begin() + 2, vi.end(), is_<int> ( 10 )));
BOOST_CHECK (!ba::any_of_equal ( vi.begin() + 2, vi.end(), 5 ));
BOOST_CHECK (!ba::any_of ( vi.begin() + 2, vi.end(), is_<int> ( 5 )));
// 18 is not in { 1, 5, 0 }, but 5 is
BOOST_CHECK ( ba::any_of_equal ( vi.begin(), vi.begin() + 3, 5 ));
BOOST_CHECK ( ba::any_of ( vi.begin(), vi.begin() + 3, is_<int> ( 5 )));
BOOST_CHECK (!ba::any_of_equal ( vi.begin(), vi.begin() + 3, 18 ));
BOOST_CHECK (!ba::any_of ( vi.begin(), vi.begin() + 3, is_<int> ( 18 )));
BOOST_CHECK ( ba::any_of_equal ( vc, 'q' ));
BOOST_CHECK ( ba::any_of ( vc, is_<char> ( 'q' )));
BOOST_CHECK (!ba::any_of_equal ( vc, '!' ));
BOOST_CHECK (!ba::any_of ( vc, is_<char> ( '!' )));
BOOST_CHECK ( ba::any_of_equal ( vc, 'n' ));
BOOST_CHECK ( ba::any_of ( vc, is_<char> ( 'n' )));
BOOST_CHECK (!ba::any_of_equal ( vi.begin(), vi.begin(), 1 ));
BOOST_CHECK (!ba::any_of_equal ( vc.begin(), vc.begin(), 'a' ));
BOOST_CHECK (!ba::any_of ( vi.begin(), vi.begin(), is_<int> ( 1 )));
BOOST_CHECK (!ba::any_of ( vc.begin(), vc.begin(), is_<char> ( 'a' )));
BOOST_CHECK ( ba::any_of_equal ( li, 1 ));
BOOST_CHECK ( ba::any_of ( li, is_<int> ( 1 )));
BOOST_CHECK ( ba::any_of_equal ( li.begin(), li.end(), 1 ));
BOOST_CHECK ( ba::any_of ( li.begin(), li.end(), is_<int> ( 1 )));
std::list<int>::iterator l_iter = li.begin ();
l_iter++; l_iter++; l_iter++;
BOOST_CHECK ( ba::any_of_equal ( li.begin(), l_iter, 5 ));
BOOST_CHECK ( ba::any_of ( li.begin(), l_iter, is_<int> ( 5 )));
BOOST_CHECK (!ba::any_of_equal ( li.begin(), l_iter, 18 ));
BOOST_CHECK (!ba::any_of ( li.begin(), l_iter, is_<int> ( 18 )));
}
int test_main( int , char* [] )
{
test_any ();
return 0;
}

218
test/clamp_test.cpp Executable file
View File

@ -0,0 +1,218 @@
// (C) Copyright Jesse Williamson 2009
// 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 <iostream>
#include <vector>
#include <boost/config.hpp>
#include <boost/algorithm/clamp.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
namespace ba = boost::algorithm;
bool intGreater ( int lhs, int rhs ) { return lhs > rhs; }
bool doubleGreater ( double lhs, double rhs ) { return lhs > rhs; }
class custom {
public:
custom ( int x ) : v(x) {}
custom ( const custom &rhs ) : v(rhs.v) {}
~custom () {}
custom & operator = ( const custom &rhs ) { v = rhs.v; return *this; }
bool operator < ( const custom &rhs ) const { return v < rhs.v; }
bool operator == ( const custom &rhs ) const { return v == rhs.v; } // need this for the test
std::ostream & print ( std::ostream &os ) const { return os << v; }
int v;
};
std::ostream & operator << ( std::ostream & os, const custom &x ) { return x.print ( os ); }
bool customLess ( const custom &lhs, const custom &rhs ) { return lhs.v < rhs.v; }
void test_ints()
{
// Inside the range, equal to the endpoints, and outside the endpoints.
BOOST_CHECK_EQUAL ( 3, ba::clamp ( 3, 1, 10 ));
BOOST_CHECK_EQUAL ( 1, ba::clamp ( 1, 1, 10 ));
BOOST_CHECK_EQUAL ( 1, ba::clamp ( 0, 1, 10 ));
BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, 1, 10 ));
BOOST_CHECK_EQUAL ( 10, ba::clamp ( 11, 1, 10 ));
BOOST_CHECK_EQUAL ( 3, ba::clamp ( 3, 10, 1, intGreater ));
BOOST_CHECK_EQUAL ( 1, ba::clamp ( 1, 10, 1, intGreater ));
BOOST_CHECK_EQUAL ( 1, ba::clamp ( 0, 10, 1, intGreater ));
BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, 10, 1, intGreater ));
BOOST_CHECK_EQUAL ( 10, ba::clamp ( 11, 10, 1, intGreater ));
// Negative numbers
BOOST_CHECK_EQUAL ( -3, ba::clamp ( -3, -10, -1 ));
BOOST_CHECK_EQUAL ( -1, ba::clamp ( -1, -10, -1 ));
BOOST_CHECK_EQUAL ( -1, ba::clamp ( 0, -10, -1 ));
BOOST_CHECK_EQUAL ( -10, ba::clamp ( -10, -10, -1 ));
BOOST_CHECK_EQUAL ( -10, ba::clamp ( -11, -10, -1 ));
// Mixed positive and negative numbers
BOOST_CHECK_EQUAL ( 5, ba::clamp ( 5, -10, 10 ));
BOOST_CHECK_EQUAL ( -10, ba::clamp ( -10, -10, 10 ));
BOOST_CHECK_EQUAL ( -10, ba::clamp ( -15, -10, 10 ));
BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, -10, 10 ));
BOOST_CHECK_EQUAL ( 10, ba::clamp ( 15, -10, 10 ));
// Unsigned
BOOST_CHECK_EQUAL ( 5U, ba::clamp ( 5U, 1U, 10U ));
BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 1U, 1U, 10U ));
BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 0U, 1U, 10U ));
BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1U, 10U ));
BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1U, 10U ));
// Mixed (1)
BOOST_CHECK_EQUAL ( 5U, ba::clamp ( 5U, 1, 10 ));
BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 1U, 1, 10 ));
BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 0U, 1, 10 ));
BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1, 10 ));
BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1, 10 ));
// Mixed (3)
BOOST_CHECK_EQUAL ( 5U, ba::clamp ( 5U, 1, 10. ));
BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 1U, 1, 10. ));
BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 0U, 1, 10. ));
BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1, 10. ));
BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1, 10. ));
short foo = 50;
BOOST_CHECK_EQUAL ( 56, ba::clamp ( foo, 56.9, 129 ));
BOOST_CHECK_EQUAL ( 24910, ba::clamp ( foo, 12345678, 123456999 ));
}
void test_floats()
{
// Inside the range, equal to the endpoints, and outside the endpoints.
BOOST_CHECK_EQUAL ( 3.0, ba::clamp ( 3.0, 1.0, 10.0 ));
BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 1.0, 1.0, 10.0 ));
BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 0.0, 1.0, 10.0 ));
BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 10.0, 1.0, 10.0 ));
BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 11.0, 1.0, 10.0 ));
BOOST_CHECK_EQUAL ( 3.0, ba::clamp ( 3.0, 10.0, 1.0, doubleGreater ));
BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 1.0, 10.0, 1.0, doubleGreater ));
BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 0.0, 10.0, 1.0, doubleGreater ));
BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 10.0, 10.0, 1.0, doubleGreater ));
BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 11.0, 10.0, 1.0, doubleGreater ));
// Negative numbers
BOOST_CHECK_EQUAL ( -3.f, ba::clamp ( -3.f, -10.f, -1.f ));
BOOST_CHECK_EQUAL ( -1.f, ba::clamp ( -1.f, -10.f, -1.f ));
BOOST_CHECK_EQUAL ( -1.f, ba::clamp ( 0.f, -10.f, -1.f ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10.f, -1.f ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -11.f, -10.f, -1.f ));
// Mixed positive and negative numbers
BOOST_CHECK_EQUAL ( 5.f, ba::clamp ( 5.f, -10.f, 10.f ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10.f, 10.f ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10.f, 10.f ));
BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 10.f, -10.f, 10.f ));
BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 15.f, -10.f, 10.f ));
// Mixed (1)
BOOST_CHECK_EQUAL ( 5.f, ba::clamp ( 5.f, -10., 10. ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10., 10. ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10., 10. ));
BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 10.f, -10., 10. ));
BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 15.f, -10., 10. ));
// Mixed (2)
BOOST_CHECK_EQUAL ( 5.f, ba::clamp ( 5.f, -10, 10 ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10, 10 ));
BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10, 10 ));
BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 10.f, -10, 10 ));
BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 15.f, -10, 10 ));
}
void test_custom()
{
// Inside the range, equal to the endpoints, and outside the endpoints.
BOOST_CHECK_EQUAL ( custom( 3), ba::clamp ( custom( 3), custom(1), custom(10)));
BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 1), custom(1), custom(10)));
BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 0), custom(1), custom(10)));
BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(10), custom(1), custom(10)));
BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(11), custom(1), custom(10)));
BOOST_CHECK_EQUAL ( custom( 3), ba::clamp ( custom( 3), custom(1), custom(10), customLess ));
BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 1), custom(1), custom(10), customLess ));
BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 0), custom(1), custom(10), customLess ));
BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(10), custom(1), custom(10), customLess ));
BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(11), custom(1), custom(10), customLess ));
// Fail!!
// BOOST_CHECK_EQUAL ( custom(1), ba::clamp ( custom(11), custom(1), custom(10)));
}
#define elementsof(v) (sizeof (v) / sizeof (v[0]))
#define a_begin(v) (&v[0])
#define a_end(v) (v + elementsof (v))
#define a_range(v) v
#define b_e(v) a_begin(v),a_end(v)
void test_int_range ()
{
int inputs [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 19, 99, 999, -1, -3, -99, 234234 };
int outputs [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, -1, -1, -1, 10 };
std::vector<int> results;
std::vector<int> in_v;
std::copy ( a_begin(inputs), a_end(inputs), std::back_inserter ( in_v ));
ba::clamp_range ( a_begin(inputs), a_end(inputs), std::back_inserter ( results ), -1, 10 );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( in_v.begin (), in_v.end (), std::back_inserter ( results ), -1, 10 );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( a_begin(inputs), a_end(inputs), std::back_inserter ( results ), 10, -1, intGreater );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( in_v.begin (), in_v.end (), std::back_inserter ( results ), 10, -1, intGreater );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( a_range(inputs), std::back_inserter ( results ), -1, 10 );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( in_v, std::back_inserter ( results ), -1, 10 );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( a_range(inputs), std::back_inserter ( results ), 10, -1, intGreater );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
ba::clamp_range ( in_v, std::back_inserter ( results ), 10, -1, intGreater );
BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
results.clear ();
int junk[elementsof(inputs)];
ba::clamp_range ( inputs, junk, 10, -1, intGreater );
BOOST_CHECK ( std::equal ( b_e(junk), outputs ));
}
int test_main( int , char* [] )
{
test_ints ();
test_floats ();
test_custom ();
test_int_range ();
// test_float_range ();
// test_custom_range ();
return 0;
}

85
test/copy_n_test1.cpp Normal file
View File

@ -0,0 +1,85 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/copy_n.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <iostream>
#include <vector>
#include <list>
namespace ba = boost::algorithm;
// namespace ba = boost;
template <typename Container>
void test_sequence ( Container const &c ) {
typedef typename Container::value_type value_type;
std::vector<value_type> v;
// Copy zero elements
v.clear ();
ba::copy_n ( c.begin (), 0, back_inserter ( v ));
BOOST_CHECK ( v.size () == 0 );
ba::copy_n ( c.begin (), 0U, back_inserter ( v ));
BOOST_CHECK ( v.size () == 0 );
if ( c.size () > 0 ) {
// Just one element
v.clear ();
ba::copy_n ( c.begin (), 1, back_inserter ( v ));
BOOST_CHECK ( v.size () == 1 );
BOOST_CHECK ( v[0] == *c.begin ());
v.clear ();
ba::copy_n ( c.begin (), 1U, back_inserter ( v ));
BOOST_CHECK ( v.size () == 1 );
BOOST_CHECK ( v[0] == *c.begin ());
// Half the elements
v.clear ();
ba::copy_n ( c.begin (), c.size () / 2, back_inserter ( v ));
BOOST_CHECK ( v.size () == c.size () / 2);
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
// Half the elements + 1
v.clear ();
ba::copy_n ( c.begin (), c.size () / 2 + 1, back_inserter ( v ));
BOOST_CHECK ( v.size () == c.size () / 2 + 1 );
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
// All the elements
v.clear ();
ba::copy_n ( c.begin (), c.size (), back_inserter ( v ));
BOOST_CHECK ( v.size () == c.size ());
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
}
}
void test_sequence1 () {
std::vector<int> v;
for ( int i = 5; i < 15; ++i )
v.push_back ( i );
test_sequence ( v );
std::list<int> l;
for ( int i = 25; i > 15; --i )
l.push_back ( i );
test_sequence ( l );
}
int test_main( int , char* [] )
{
test_sequence1 ();
return 0;
}

83
test/empty_search_test.cpp Executable file
View File

@ -0,0 +1,83 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <string>
#include <boost/algorithm/searching/boyer_moore.hpp>
#include <boost/algorithm/searching/boyer_moore_horspool.hpp>
#include <boost/algorithm/searching/knuth_morris_pratt.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
int test_main( int argc, char *argv [] )
{
const std::string cs;
std::string estr;
std::string str ( "abc" );
// empty corpus, empty pattern
BOOST_CHECK (
boost::algorithm::boyer_moore_search (
cs.begin (), cs.end (), estr.begin (), estr.end ())
== cs.begin ()
);
BOOST_CHECK (
boost::algorithm::boyer_moore_horspool_search (
cs.begin (), cs.end (), estr.begin (), estr.end ())
== cs.begin ()
);
BOOST_CHECK (
boost::algorithm::knuth_morris_pratt_search (
cs.begin (), cs.end (), estr.begin (), estr.end ())
== cs.begin ()
);
// empty corpus, non-empty pattern
BOOST_CHECK (
boost::algorithm::boyer_moore_search (
estr.begin (), estr.end (), str.begin (), str.end ())
== estr.end ()
);
BOOST_CHECK (
boost::algorithm::boyer_moore_horspool_search (
estr.begin (), estr.end (), str.begin (), str.end ())
== estr.end ()
);
BOOST_CHECK (
boost::algorithm::knuth_morris_pratt_search (
estr.begin (), estr.end (), str.begin (), str.end ())
== estr.end ()
);
// non-empty corpus, empty pattern
BOOST_CHECK (
boost::algorithm::boyer_moore_search (
str.begin (), str.end (), estr.begin (), estr.end ())
== str.begin ()
);
BOOST_CHECK (
boost::algorithm::boyer_moore_horspool_search (
str.begin (), str.end (), estr.begin (), estr.end ())
== str.begin ()
);
BOOST_CHECK (
boost::algorithm::knuth_morris_pratt_search (
str.begin (), str.end (), estr.begin (), estr.end ())
== str.begin ()
);
(void) argv; (void) argc;
return 0;
}

View File

@ -0,0 +1,90 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/find_if_not.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <list>
namespace ba = boost::algorithm;
// namespace ba = boost;
template <typename Container>
typename Container::iterator offset_to_iter ( Container &v, int offset ) {
typename Container::iterator retval;
if ( offset >= 0 ) {
retval = v.begin ();
std::advance ( retval, offset );
}
else {
retval = v.end ();
std::advance ( retval, offset + 1 );
}
return retval;
}
template <typename Container, typename Predicate>
void test_sequence ( Container &v, Predicate comp, int expected ) {
typename Container::iterator res, exp;
res = ba::find_if_not ( v.begin (), v.end (), comp );
exp = offset_to_iter ( v, expected );
std::cout << "Expected(1): " << std::distance ( v.begin (), exp )
<< ", got: " << std::distance ( v.begin (), res ) << std::endl;
BOOST_CHECK ( exp == res );
}
template <typename T>
struct less_than {
public:
less_than ( T foo ) : val ( foo ) {}
less_than ( const less_than &rhs ) : val ( rhs.val ) {}
bool operator () ( const T &v ) const { return v < val; }
private:
less_than ();
less_than operator = ( const less_than &rhs );
T val;
};
void test_sequence1 () {
std::vector<int> v;
v.clear ();
for ( int i = 5; i < 15; ++i )
v.push_back ( i );
test_sequence ( v, less_than<int>(3), 0 ); // no elements
test_sequence ( v, less_than<int>(6), 1 ); // only the first element
test_sequence ( v, less_than<int>(10), 5 );
test_sequence ( v, less_than<int>(99), -1 ); // all elements satisfy
// With bidirectional iterators.
std::list<int> l;
for ( int i = 5; i < 15; ++i )
l.push_back ( i );
test_sequence ( l, less_than<int>(3), 0 ); // no elements
test_sequence ( l, less_than<int>(6), 1 ); // only the first element
test_sequence ( l, less_than<int>(10), 5 );
test_sequence ( l, less_than<int>(99), -1 ); // all elements satisfy
}
int test_main( int , char* [] )
{
test_sequence1 ();
return 0;
}

79
test/iota_test1.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/iota.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <list>
// Test to make sure a sequence is "correctly formed"; i.e, ascending by one
template <typename Iterator, typename T>
bool test_iota_results ( Iterator first, Iterator last, T initial_value ) {
if ( first == last ) return true;
if ( initial_value != *first ) return false;
Iterator prev = first;
while ( ++first != last ) {
if (( *first - *prev ) != 1 )
return false;
prev = first;
}
return true;
}
template <typename Range, typename T>
bool test_iota_results ( const Range &r, T initial_value ) {
return test_iota_results (boost::begin (r), boost::end (r), initial_value );
}
void test_ints () {
std::vector<int> v;
std::list<int> l;
v.clear (); v.reserve ( 10 );
boost::algorithm::iota ( v.begin (), v.end (), 23 );
BOOST_CHECK ( test_iota_results ( v.begin (), v.end (), 23 ));
v.clear (); v.reserve ( 19 );
boost::algorithm::iota ( v, 18 );
BOOST_CHECK ( test_iota_results ( v, 18 ));
v.clear ();
boost::algorithm::iota_n ( std::back_inserter(v), 99, 20 );
BOOST_CHECK ( test_iota_results ( v, 99 ));
/*
l.clear (); l.reserve ( 5 );
boost::algorithm::iota ( l.begin (), l.end (), 123 );
BOOST_CHECK ( test_iota_results ( l.begin (), l.end (), 123 ));
l.clear (); l.reserve ( 9 );
boost::algorithm::iota ( l.begin (), l.end (), 87 );
BOOST_CHECK ( test_iota_results ( l.begin (), l.end (), 87 ));
*/
l.clear ();
boost::algorithm::iota_n ( std::back_inserter(l), 99, 20 );
BOOST_CHECK ( test_iota_results ( l, 99 ));
l.clear ();
boost::algorithm::iota_n ( std::front_inserter(l), 123, 20 );
BOOST_CHECK ( test_iota_results ( l.rbegin (), l.rend (), 123 ));
}
int test_main( int , char* [] )
{
test_ints ();
return 0;
}

View File

@ -0,0 +1,63 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/is_partitioned.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <list>
namespace ba = boost::algorithm;
// namespace ba = boost;
template <typename T>
struct less_than {
public:
less_than ( T foo ) : val ( foo ) {}
less_than ( const less_than &rhs ) : val ( rhs.val ) {}
bool operator () ( const T &v ) const { return v < val; }
private:
less_than ();
less_than operator = ( const less_than &rhs );
T val;
};
void test_sequence1 () {
std::vector<int> v;
v.clear ();
for ( int i = 5; i < 15; ++i )
v.push_back ( i );
BOOST_CHECK ( ba::is_partitioned ( v, less_than<int>(3))); // no elements
BOOST_CHECK ( ba::is_partitioned ( v, less_than<int>(6))); // only the first element
BOOST_CHECK ( ba::is_partitioned ( v, less_than<int>(10))); // in the middle somewhere
BOOST_CHECK ( ba::is_partitioned ( v, less_than<int>(99))); // all elements satisfy
// With bidirectional iterators.
std::list<int> l;
for ( int i = 5; i < 15; ++i )
l.push_back ( i );
BOOST_CHECK ( ba::is_partitioned ( l.begin (), l.end (), less_than<int>(3))); // no elements
BOOST_CHECK ( ba::is_partitioned ( l.begin (), l.end (), less_than<int>(6))); // only the first element
BOOST_CHECK ( ba::is_partitioned ( l.begin (), l.end (), less_than<int>(10))); // in the middle somewhere
BOOST_CHECK ( ba::is_partitioned ( l.begin (), l.end (), less_than<int>(99))); // all elements satisfy
}
int test_main( int , char* [] )
{
test_sequence1 ();
return 0;
}

View File

@ -0,0 +1,49 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/is_permutation.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <list>
namespace ba = boost::algorithm;
// namespace ba = boost;
void test_sequence1 () {
std::vector<int> v, v1;
v.clear ();
for ( std::size_t i = 5; i < 15; ++i )
v.push_back ( i );
v1 = v;
BOOST_CHECK ( ba::is_permutation ( v.begin (), v.end (), v.begin ())); // better be a permutation of itself!
BOOST_CHECK ( ba::is_permutation ( v.begin (), v.end (), v1.begin ()));
// With bidirectional iterators.
std::list<int> l;
std::copy ( v.begin (), v.end (), std::back_inserter ( l ));
BOOST_CHECK ( ba::is_permutation ( l.begin (), l.end (), l.begin ())); // better be a permutation of itself!
BOOST_CHECK ( ba::is_permutation ( l.begin (), l.end (), v1.begin ()));
for ( std::size_t i = 0; i < l.size (); ++i ) {
l.push_back ( *l.begin ()); l.pop_front (); // rotation
BOOST_CHECK ( ba::is_permutation ( l.begin (), l.end (), v1.begin ()));
}
}
int test_main( int , char* [] )
{
test_sequence1 ();
return 0;
}

96
test/none_of_test.cpp Normal file
View File

@ -0,0 +1,96 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/none_of.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <functional>
#include <vector>
#include <list>
template<typename T>
struct is_ : public std::unary_function<T, bool> {
is_ ( T v ) : val_ ( v ) {}
~is_ () {}
bool operator () ( T comp ) const { return val_ == comp; }
private:
is_ (); // need a value
T val_;
};
namespace ba = boost::algorithm;
void test_none()
{
// Note: The literal values here are tested against directly, careful if you change them:
int some_numbers[] = { 1, 5, 0, 18, 1 };
std::vector<int> vi(some_numbers, some_numbers + 5);
std::list<int> li(vi.begin(), vi.end ());
int some_letters[] = { 'a', 'q', 'n', 'y', 'n' };
std::vector<char> vc(some_letters, some_letters + 5);
BOOST_CHECK ( ba::none_of_equal ( vi, 100 ));
BOOST_CHECK ( ba::none_of ( vi, is_<int> ( 100 )));
BOOST_CHECK ( ba::none_of_equal ( vi.begin(), vi.end(), 100 ));
BOOST_CHECK ( ba::none_of ( vi.begin(), vi.end(), is_<int> ( 100 )));
BOOST_CHECK (!ba::none_of_equal ( vi, 1 ));
BOOST_CHECK (!ba::none_of ( vi, is_<int> ( 1 )));
BOOST_CHECK (!ba::none_of_equal ( vi.begin(), vi.end(), 1 ));
BOOST_CHECK (!ba::none_of ( vi.begin(), vi.end(), is_<int> ( 1 )));
BOOST_CHECK ( ba::none_of_equal ( vi.end(), vi.end(), 0 ));
BOOST_CHECK ( ba::none_of ( vi.end(), vi.end(), is_<int> ( 0 )));
// 5 is not in { 0, 18, 1 }, but 1 is
BOOST_CHECK ( ba::none_of_equal ( vi.begin() + 2, vi.end(), 5 ));
BOOST_CHECK ( ba::none_of ( vi.begin() + 2, vi.end(), is_<int> ( 5 )));
BOOST_CHECK (!ba::none_of_equal ( vi.begin() + 2, vi.end(), 1 ));
BOOST_CHECK (!ba::none_of ( vi.begin() + 2, vi.end(), is_<int> ( 1 )));
// 18 is not in { 1, 5, 0 }, but 5 is
BOOST_CHECK ( ba::none_of_equal ( vi.begin(), vi.begin() + 3, 18 ));
BOOST_CHECK ( ba::none_of ( vi.begin(), vi.begin() + 3, is_<int> ( 18 )));
BOOST_CHECK (!ba::none_of_equal ( vi.begin(), vi.begin() + 3, 5 ));
BOOST_CHECK (!ba::none_of ( vi.begin(), vi.begin() + 3, is_<int> ( 5 )));
BOOST_CHECK ( ba::none_of_equal ( vc, 'z' ));
BOOST_CHECK ( ba::none_of ( vc, is_<char> ( 'z' )));
BOOST_CHECK (!ba::none_of_equal ( vc, 'a' ));
BOOST_CHECK (!ba::none_of ( vc, is_<char> ( 'a' )));
BOOST_CHECK (!ba::none_of_equal ( vc, 'n' ));
BOOST_CHECK (!ba::none_of ( vc, is_<char> ( 'n' )));
BOOST_CHECK ( ba::none_of_equal ( vi.begin(), vi.begin(), 1 ));
BOOST_CHECK ( ba::none_of_equal ( vc.begin(), vc.begin(), 'a' ));
BOOST_CHECK ( ba::none_of ( vi.begin(), vi.begin(), is_<int> ( 1 )));
BOOST_CHECK ( ba::none_of ( vc.begin(), vc.begin(), is_<char> ( 'a' )));
BOOST_CHECK ( ba::none_of_equal ( li, 100 ));
BOOST_CHECK ( ba::none_of ( li, is_<int> ( 100 )));
BOOST_CHECK ( ba::none_of_equal ( li.begin(), li.end(), 100 ));
BOOST_CHECK ( ba::none_of ( li.begin(), li.end(), is_<int> ( 100 )));
std::list<int>::iterator l_iter = li.begin ();
l_iter++; l_iter++; l_iter++;
BOOST_CHECK ( ba::none_of_equal ( li.begin(), l_iter, 18 ));
BOOST_CHECK ( ba::none_of ( li.begin(), l_iter, is_<int> ( 18 )));
BOOST_CHECK (!ba::none_of ( li.begin(), l_iter, is_<int> ( 5 )));
}
int test_main( int , char* [] )
{
test_none();
return 0;
}

101
test/one_of_test.cpp Normal file
View File

@ -0,0 +1,101 @@
/*
Copyright (c) Marshall Clow 2008-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/one_of.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <functional>
#include <vector>
#include <list>
template<typename T>
struct is_ : public std::unary_function<T, bool> {
is_ ( T v ) : val_ ( v ) {}
~is_ () {}
bool operator () ( T comp ) const { return val_ == comp; }
private:
is_ (); // need a value
T val_;
};
namespace ba = boost::algorithm;
void test_one ()
{
// Note: The literal values here are tested against directly, careful if you change them:
int some_numbers[] = { 1, 1, 2, 3, 5 };
std::vector<int> vi(some_numbers, some_numbers + 5);
std::list<int> li(vi.begin(), vi.end ());
int some_letters[] = { 'a', 'q', 'n', 'y', 'n' };
std::vector<char> vc(some_letters, some_letters + 5);
BOOST_CHECK (!ba::one_of_equal ( vi, 1 ));
BOOST_CHECK (!ba::one_of ( vi, is_<int> ( 1 )));
BOOST_CHECK (!ba::one_of_equal ( vi.begin(), vi.end(), 1 ));
BOOST_CHECK (!ba::one_of ( vi.begin(), vi.end(), is_<int> ( 1 )));
BOOST_CHECK (!ba::one_of_equal ( vi, 0 ));
BOOST_CHECK (!ba::one_of ( vi, is_<int> ( 0 )));
BOOST_CHECK (!ba::one_of_equal ( vi.begin(), vi.end(), 0 ));
BOOST_CHECK (!ba::one_of ( vi.begin(), vi.end(), is_<int> ( 0 )));
BOOST_CHECK ( ba::one_of_equal ( vi, 2 ));
BOOST_CHECK ( ba::one_of ( vi, is_<int> ( 2 )));
BOOST_CHECK ( ba::one_of_equal ( vi.begin(), vi.end(), 2 ));
BOOST_CHECK ( ba::one_of ( vi.begin(), vi.end(), is_<int> ( 2 )));
// Check for a match at the end
BOOST_CHECK ( ba::one_of_equal ( vi, 5 ));
BOOST_CHECK ( ba::one_of ( vi, is_<int> ( 5 )));
BOOST_CHECK ( ba::one_of_equal ( vi.begin(), vi.end(), 5 ));
BOOST_CHECK ( ba::one_of ( vi.begin(), vi.end(), is_<int> ( 5 )));
BOOST_CHECK ( ba::one_of_equal ( vi.begin() + 1, vi.end(), 1 ));
BOOST_CHECK ( ba::one_of ( vi.begin() + 1, vi.end(), is_<int> ( 1 )));
BOOST_CHECK ( ba::one_of_equal ( vc.begin() + 1, vc.begin() + 2, 'q' ));
BOOST_CHECK ( ba::one_of ( vc.begin() + 1, vc.begin() + 2, is_<char> ( 'q' )));
BOOST_CHECK (!ba::one_of_equal ( vc, '!' ));
BOOST_CHECK (!ba::one_of ( vc, is_<char> ( '!' )));
BOOST_CHECK (!ba::one_of_equal ( vc, 'n' ));
BOOST_CHECK (!ba::one_of ( vc, is_<char> ( 'n' )));
// Empty range check
BOOST_CHECK (!ba::one_of_equal ( vi.begin(), vi.begin(), 1 ));
BOOST_CHECK (!ba::one_of_equal ( vc.begin(), vc.begin(), 'a' ));
BOOST_CHECK (!ba::one_of ( vi.begin(), vi.begin(), is_<int> ( 1 )));
BOOST_CHECK (!ba::one_of ( vc.begin(), vc.begin(), is_<char> ( 'a' )));
BOOST_CHECK (!ba::one_of_equal ( li, 1 ));
BOOST_CHECK (!ba::one_of ( li, is_<int> ( 1 )));
BOOST_CHECK (!ba::one_of_equal ( li.begin(), li.end(), 1 ));
BOOST_CHECK (!ba::one_of ( li.begin(), li.end(), is_<int> ( 1 )));
std::list<int>::iterator l_iter = li.begin ();
l_iter++; l_iter++; l_iter++;
BOOST_CHECK (!ba::one_of_equal ( li.begin(), l_iter, 1 ));
BOOST_CHECK (!ba::one_of ( li.begin(), l_iter, is_<int> ( 1 )));
BOOST_CHECK ( ba::one_of_equal ( li.begin(), l_iter, 2 ));
BOOST_CHECK ( ba::one_of ( li.begin(), l_iter, is_<int> ( 2 )));
BOOST_CHECK (!ba::one_of_equal ( li.begin(), l_iter, 3 ));
BOOST_CHECK (!ba::one_of ( li.begin(), l_iter, is_<int> ( 3 )));
}
int test_main( int , char* [] )
{
test_one ();
return 0;
}

127
test/ordered_test.cpp Normal file
View File

@ -0,0 +1,127 @@
// Copyright (c) 2010 Nuovation System Designs, LLC
// Grant Erickson <gerickson@nuovations.com>
//
// Reworked by Marshall Clow; August 2010
//
// Distributed under 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 latest version.
#include <algorithm>
#include <iostream>
#include <boost/algorithm/cxx11/ordered.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
using namespace boost;
/* Preprocessor Defines */
#define elementsof(v) (sizeof (v) / sizeof (v[0]))
#define a_begin(v) (&v[0])
#define a_end(v) (v + elementsof (v))
#define a_range(v) v
#define b_e(v) a_begin(v),a_end(v)
namespace ba = boost::algorithm;
static void
test_ordered(void)
{
const int strictlyIncreasingValues[] = { 1, 2, 3, 4, 5 };
const int strictlyDecreasingValues[] = { 9, 8, 7, 6, 5 };
const int increasingValues[] = { 1, 2, 2, 2, 5 };
const int decreasingValues[] = { 9, 7, 7, 7, 5 };
const int randomValues[] = { 3, 6, 1, 2, 7 };
const int constantValues[] = { 7, 7, 7, 7, 7 };
int nonConstantArray[] = { 7, 7, 7, 7, 7 };
const int inOrderUntilTheEnd [] = { 0, 1, 2, 3, 4, 5, 6, 7, 6 };
// Test a strictly increasing sequence
BOOST_CHECK ( ba::is_strictly_increasing (b_e(strictlyIncreasingValues)));
BOOST_CHECK ( ba::is_increasing (b_e(strictlyIncreasingValues)));
BOOST_CHECK ( !ba::is_strictly_decreasing (b_e(strictlyIncreasingValues)));
BOOST_CHECK ( !ba::is_decreasing (b_e(strictlyIncreasingValues)));
BOOST_CHECK ( ba::is_strictly_increasing (a_range(strictlyIncreasingValues)));
BOOST_CHECK ( ba::is_increasing (a_range(strictlyIncreasingValues)));
BOOST_CHECK ( !ba::is_strictly_decreasing (a_range(strictlyIncreasingValues)));
BOOST_CHECK ( !ba::is_decreasing (a_range(strictlyIncreasingValues)));
// Test a strictly decreasing sequence
BOOST_CHECK ( !ba::is_strictly_increasing (b_e(strictlyDecreasingValues)));
BOOST_CHECK ( !ba::is_increasing (b_e(strictlyDecreasingValues)));
BOOST_CHECK ( ba::is_strictly_decreasing (b_e(strictlyDecreasingValues)));
BOOST_CHECK ( ba::is_decreasing (b_e(strictlyDecreasingValues)));
// Test an increasing sequence
BOOST_CHECK ( !ba::is_strictly_increasing (b_e(increasingValues)));
BOOST_CHECK ( ba::is_increasing (b_e(increasingValues)));
BOOST_CHECK ( !ba::is_strictly_decreasing (b_e(increasingValues)));
BOOST_CHECK ( !ba::is_decreasing (b_e(increasingValues)));
// Test a decreasing sequence
BOOST_CHECK ( !ba::is_strictly_increasing (b_e(decreasingValues)));
BOOST_CHECK ( !ba::is_increasing (b_e(decreasingValues)));
BOOST_CHECK ( !ba::is_strictly_decreasing (b_e(decreasingValues)));
BOOST_CHECK ( ba::is_decreasing (b_e(decreasingValues)));
// Test a random sequence
BOOST_CHECK ( !ba::is_strictly_increasing (b_e(randomValues)));
BOOST_CHECK ( !ba::is_increasing (b_e(randomValues)));
BOOST_CHECK ( !ba::is_strictly_decreasing (b_e(randomValues)));
BOOST_CHECK ( !ba::is_decreasing (b_e(randomValues)));
// Test a constant sequence
BOOST_CHECK ( !ba::is_strictly_increasing (b_e(constantValues)));
BOOST_CHECK ( ba::is_increasing (b_e(constantValues)));
BOOST_CHECK ( !ba::is_strictly_decreasing (b_e(constantValues)));
BOOST_CHECK ( ba::is_decreasing (b_e(constantValues)));
// Test an empty sequence
BOOST_CHECK ( ba::is_strictly_increasing (strictlyIncreasingValues, strictlyIncreasingValues));
BOOST_CHECK ( ba::is_increasing (strictlyIncreasingValues, strictlyIncreasingValues));
BOOST_CHECK ( ba::is_strictly_decreasing (strictlyIncreasingValues, strictlyIncreasingValues));
BOOST_CHECK ( ba::is_decreasing (strictlyIncreasingValues, strictlyIncreasingValues));
// Test a one-element sequence
BOOST_CHECK ( ba::is_strictly_increasing (strictlyIncreasingValues, strictlyIncreasingValues+1));
BOOST_CHECK ( ba::is_increasing (strictlyIncreasingValues, strictlyIncreasingValues+1));
BOOST_CHECK ( ba::is_strictly_decreasing (strictlyIncreasingValues, strictlyIncreasingValues+1));
BOOST_CHECK ( ba::is_decreasing (strictlyIncreasingValues, strictlyIncreasingValues+1));
// Test a two-element sequence
BOOST_CHECK ( ba::is_strictly_increasing (strictlyIncreasingValues, strictlyIncreasingValues+2));
BOOST_CHECK ( ba::is_increasing (strictlyIncreasingValues, strictlyIncreasingValues+2));
BOOST_CHECK ( !ba::is_strictly_decreasing (strictlyIncreasingValues, strictlyIncreasingValues+2));
BOOST_CHECK ( !ba::is_decreasing (strictlyIncreasingValues, strictlyIncreasingValues+2));
// Test underlying routines
BOOST_CHECK ( ba::is_sorted_until ( b_e(strictlyIncreasingValues), std::less<int>()) == a_end(strictlyIncreasingValues));
BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues), std::less<int>()) == boost::end(strictlyIncreasingValues));
BOOST_CHECK ( ba::is_sorted_until ( b_e(nonConstantArray), std::less<int>()) != a_end(nonConstantArray));
BOOST_CHECK ( ba::is_sorted_until ( a_range(nonConstantArray), std::less<int>()) != boost::end(nonConstantArray));
BOOST_CHECK ( ba::is_sorted_until ( b_e(randomValues), std::less<int>()) == &randomValues[2] );
BOOST_CHECK ( ba::is_sorted_until ( a_range(randomValues), std::less<int>()) == &randomValues[2] );
BOOST_CHECK ( ba::is_sorted_until ( b_e(randomValues), std::less<int>()) == &randomValues[2] );
BOOST_CHECK ( ba::is_sorted_until ( a_range(randomValues), std::less<int>()) == &randomValues[2] );
BOOST_CHECK ( ba::is_sorted_until ( a_range(inOrderUntilTheEnd), std::less<int>()) == &inOrderUntilTheEnd[8] );
// For zero and one element collections, the comparison predicate should never be called
BOOST_CHECK ( ba::is_sorted_until ( a_begin(randomValues), a_begin(randomValues), std::equal_to<int>()) == a_begin(randomValues));
BOOST_CHECK ( ba::is_sorted_until ( a_begin(randomValues), a_begin(randomValues) + 1, std::equal_to<int>()) == a_begin(randomValues) + 1);
}
int test_main( int, char * [] )
{
test_ordered ();
return 0;
}

View File

@ -0,0 +1,87 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/partition_copy.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/algorithm/cxx11/none_of.hpp>
#include <string>
#include <vector>
#include <list>
namespace ba = boost::algorithm;
// namespace ba = boost;
template <typename Container, typename Predicate>
void test_sequence ( const Container &c, Predicate comp ) {
std::vector<typename Container::value_type> v1, v2;
v1.clear (); v2.clear ();
ba::partition_copy ( c.begin (), c.end (),
std::back_inserter (v1), std::back_inserter (v2), comp );
// std::cout << "Sizes(1): " << c.size () << " -> { " << v1.size () << ", " << v2.size () << " }" << std::endl;
BOOST_CHECK ( v1.size () + v2.size () == c.size ());
BOOST_CHECK ( ba::all_of ( v1.begin (), v1.end (), comp ));
BOOST_CHECK ( ba::none_of ( v2.begin (), v2.end (), comp ));
v1.clear (); v2.clear ();
ba::partition_copy ( c, std::back_inserter (v1), std::back_inserter ( v2 ), comp );
// std::cout << "Sizes(2): " << c.size () << " -> { " << v1.size () << ", " << v2.size () << " }" << std::endl;
BOOST_CHECK ( v1.size () + v2.size () == c.size ());
BOOST_CHECK ( ba::all_of ( v1, comp ));
BOOST_CHECK ( ba::none_of ( v2, comp ));
}
template <typename T>
struct less_than {
public:
less_than ( T foo ) : val ( foo ) {}
less_than ( const less_than &rhs ) : val ( rhs.val ) {}
bool operator () ( const T &v ) const { return v < val; }
private:
less_than ();
less_than operator = ( const less_than &rhs );
T val;
};
bool is_even ( int v ) { return v % 2 == 0; }
void test_sequence1 () {
std::vector<int> v;
v.clear ();
for ( int i = 5; i < 15; ++i )
v.push_back ( i );
test_sequence ( v, less_than<int>(3)); // no elements
test_sequence ( v, less_than<int>(6)); // only the first element
test_sequence ( v, less_than<int>(10));
test_sequence ( v, less_than<int>(99)); // all elements satisfy
// With bidirectional iterators.
std::list<int> l;
for ( int i = 5; i < 16; ++i )
l.push_back ( i );
test_sequence ( l, less_than<int>(3)); // no elements
test_sequence ( l, less_than<int>(6)); // only the first element
test_sequence ( l, less_than<int>(10));
test_sequence ( l, less_than<int>(99)); // all elements satisfy
}
int test_main( int , char* [] )
{
test_sequence1 ();
return 0;
}

View File

@ -0,0 +1,98 @@
/*
Copyright (c) Marshall Clow 2011-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <boost/config.hpp>
#include <boost/algorithm/cxx11/partition_point.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <list>
namespace ba = boost::algorithm;
// namespace ba = boost;
template <typename Container>
typename Container::iterator offset_to_iter ( Container &v, int offset ) {
typename Container::iterator retval;
if ( offset >= 0 ) {
retval = v.begin ();
std::advance ( retval, offset );
}
else {
retval = v.end ();
std::advance ( retval, offset + 1 );
}
return retval;
}
template <typename Container, typename Predicate>
void test_sequence ( Container &v, Predicate comp, int expected ) {
typename Container::iterator res, exp;
res = ba::partition_point ( v.begin (), v.end (), comp );
exp = offset_to_iter ( v, expected );
std::cout << "Expected(1): " << std::distance ( v.begin (), exp )
<< ", got: " << std::distance ( v.begin (), res ) << std::endl;
BOOST_CHECK ( exp == res );
// Duplicate the last element; this checks for any even/odd problems
v.push_back ( * v.rbegin ());
res = ba::partition_point ( v.begin (), v.end (), comp );
exp = offset_to_iter ( v, expected );
std::cout << "Expected(2): " << std::distance ( v.begin (), exp )
<< ", got: " << std::distance ( v.begin (), res ) << std::endl;
BOOST_CHECK ( exp == res );
}
template <typename T>
struct less_than {
public:
less_than ( T foo ) : val ( foo ) {}
less_than ( const less_than &rhs ) : val ( rhs.val ) {}
bool operator () ( const T &v ) const { return v < val; }
private:
less_than ();
less_than operator = ( const less_than &rhs );
T val;
};
void test_sequence1 () {
std::vector<int> v;
v.clear ();
for ( int i = 5; i < 15; ++i )
v.push_back ( i );
test_sequence ( v, less_than<int>(3), 0 ); // no elements
test_sequence ( v, less_than<int>(6), 1 ); // only the first element
test_sequence ( v, less_than<int>(10), 5 );
test_sequence ( v, less_than<int>(99), -1 ); // all elements satisfy
// With bidirectional iterators.
std::list<int> l;
for ( int i = 5; i < 15; ++i )
l.push_back ( i );
test_sequence ( l, less_than<int>(3), 0 ); // no elements
test_sequence ( l, less_than<int>(6), 1 ); // only the first element
test_sequence ( l, less_than<int>(10), 5 );
test_sequence ( l, less_than<int>(99), -1 ); // all elements satisfy
}
int test_main( int , char* [] )
{
test_sequence1 ();
return 0;
}

26
test/search_fail1.cpp Normal file
View File

@ -0,0 +1,26 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <vector>
#include <boost/algorithm/searching/boyer_moore.hpp>
int main( int argc, char *argv [] )
{
std::vector<char> cv;
std::vector<int> iv;
// Should fail to compile because the underlying types are different
// They are (almost certainly) different sizes
(void) boost::algorithm::boyer_moore_search (
cv.begin (), cv.end (), iv.begin (), iv.end ());
(void) argv; (void) argc;
return 0;
}

27
test/search_fail2.cpp Normal file
View File

@ -0,0 +1,27 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <vector>
#include <boost/cstdint.hpp>
#include <boost/algorithm/searching/boyer_moore.hpp>
int main( int argc, char *argv [] )
{
std::vector<boost::uint8_t> cv;
std::vector<boost:: int8_t> iv;
// Should fail to compile because the underlying types are different
// They are the same size, but one is signed, and the other is not.
(void) boost::algorithm::boyer_moore_search (
cv.begin (), cv.end (), iv.begin (), iv.end ());
(void) argv; (void) argc;
return 0;
}

20
test/search_fail3.cpp Normal file
View File

@ -0,0 +1,20 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <vector>
#include <boost/algorithm/searching/boyer_moore.hpp>
int main( int argc, char *argv [] )
{
// Should fail to compile because the search objects are not default-constructible
boost::algorithm::boyer_moore<std::vector<char>::iterator> bm;
(void) argv; (void) argc;
return 0;
}

272
test/search_test1.cpp Executable file
View File

@ -0,0 +1,272 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/algorithm/searching/boyer_moore.hpp>
#include <boost/algorithm/searching/boyer_moore_horspool.hpp>
#include <boost/algorithm/searching/knuth_morris_pratt.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace ba = boost::algorithm;
template <typename Iter>
std::string make_str ( Iter first, std::size_t len ) {
std::string retVal ( len + 2, '\'' );
std::copy ( first, first+len, retVal.begin () + 1);
return retVal;
}
namespace {
// Check using iterators
template<typename Container>
void check_one_iter ( const Container &haystack, const std::string &needle, int expected ) {
typedef typename Container::const_iterator iter_type;
typedef std::string::const_iterator pattern_type;
iter_type hBeg = haystack.begin ();
iter_type hEnd = haystack.end ();
pattern_type nBeg = needle.begin ();
pattern_type nEnd = needle.end ();
iter_type it0 = std::search (hBeg, hEnd, nBeg, nEnd);
iter_type it1 = ba::boyer_moore_search (hBeg, hEnd, nBeg, nEnd);
iter_type it1r = ba::boyer_moore_search (haystack, nBeg, nEnd);
iter_type it2 = ba::boyer_moore_horspool_search (hBeg, hEnd, nBeg, nEnd);
iter_type it3 = ba::knuth_morris_pratt_search (hBeg, hEnd, nBeg, nEnd);
const int dist = it1 == hEnd ? -1 : std::distance ( hBeg, it1 );
std::cout << "(Iterators) Pattern is " << needle.length () << ", haysstack is " << haystack.length () << " chars long; " << std::endl;
try {
if ( it0 != it1 ) {
throw std::runtime_error (
std::string ( "results mismatch between std::search and boyer-moore search" ));
}
if ( it1 != it1r ) {
throw std::runtime_error (
std::string ( "results mismatch between iterator and range boyer_moore search" ));
}
if ( it1 != it2 ) {
throw std::runtime_error (
std::string ( "results mismatch between boyer-moore and boyer-moore-horspool search" ));
}
if ( it1 != it3 )
throw std::runtime_error (
std::string ( "results mismatch between boyer-moore and knuth-morris-pratt search" ));
}
catch ( ... ) {
std::cout << "Searching for: " << needle << std::endl;
std::cout << "Expected: " << expected << "\n";
std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n";
std::cout << " bm: " << std::distance ( hBeg, it1 ) << "\n";
std::cout << " bm(r): " << std::distance ( hBeg, it1r ) << "\n";
std::cout << " bmh: " << std::distance ( hBeg, it2 ) << "\n";
std::cout << " kpm: " << std::distance ( hBeg, it3 )<< "\n";
std::cout << std::flush;
throw ;
}
BOOST_CHECK_EQUAL ( dist, expected );
}
// Check using pointers
// We're assuming that the container implements contiguous storage here.
template<typename Container>
void check_one_pointer ( const Container &haystack, const std::string &needle, int expected ) {
typedef const typename Container::value_type *ptr_type;
ptr_type hBeg = haystack.size () == 0 ? NULL : &*haystack.begin ();
ptr_type hEnd = hBeg + haystack.size ();
ptr_type nBeg = needle.size () == 0 ? NULL : &*needle.begin ();
ptr_type nEnd = nBeg + needle.size ();
ptr_type it0 = std::search (hBeg, hEnd, nBeg, nEnd);
ptr_type it1 = ba::boyer_moore_search (hBeg, hEnd, nBeg, nEnd);
ptr_type it2 = ba::boyer_moore_horspool_search (hBeg, hEnd, nBeg, nEnd);
ptr_type it3 = ba::knuth_morris_pratt_search (hBeg, hEnd, nBeg, nEnd);
const int dist = it1 == hEnd ? -1 : std::distance ( hBeg, it1 );
std::cout << "(Pointers) Pattern is " << needle.length () << ", haysstack is " << haystack.length () << " chars long; " << std::endl;
try {
if ( it0 != it1 ) {
throw std::runtime_error (
std::string ( "results mismatch between std::search and boyer-moore search" ));
}
if ( it1 != it2 ) {
throw std::runtime_error (
std::string ( "results mismatch between boyer-moore and boyer-moore-horspool search" ));
}
if ( it1 != it3 )
throw std::runtime_error (
std::string ( "results mismatch between boyer-moore and knuth-morris-pratt search" ));
}
catch ( ... ) {
std::cout << "Searching for: " << needle << std::endl;
std::cout << "Expected: " << expected << "\n";
std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n";
std::cout << " bm: " << std::distance ( hBeg, it1 ) << "\n";
std::cout << " bmh: " << std::distance ( hBeg, it2 ) << "\n";
std::cout << " kpm: " << std::distance ( hBeg, it3 )<< "\n";
std::cout << std::flush;
throw ;
}
BOOST_CHECK_EQUAL ( dist, expected );
}
// Check using objects
template<typename Container>
void check_one_object ( const Container &haystack, const std::string &needle, int expected ) {
typedef typename Container::const_iterator iter_type;
typedef std::string::const_iterator pattern_type;
iter_type hBeg = haystack.begin ();
iter_type hEnd = haystack.end ();
pattern_type nBeg = needle.begin ();
pattern_type nEnd = needle.end ();
ba::boyer_moore<pattern_type> bm_r = ba::make_boyer_moore ( needle );
ba::boyer_moore<pattern_type> bm ( nBeg, nEnd );
ba::boyer_moore_horspool<pattern_type> bmh ( nBeg, nEnd );
ba::knuth_morris_pratt<pattern_type> kmp ( nBeg, nEnd );
iter_type it0 = std::search (hBeg, hEnd, nBeg, nEnd);
iter_type it1 = bm (hBeg, hEnd);
iter_type it1r = bm (haystack);
iter_type rt1 = bm_r (hBeg, hEnd);
iter_type rt1r = bm_r (haystack);
iter_type it2 = bmh (hBeg, hEnd);
iter_type it3 = kmp (hBeg, hEnd);
const int dist = it1 == hEnd ? -1 : std::distance ( hBeg, it1 );
std::cout << "(Objects) Pattern is " << needle.length () << ", haysstack is " << haystack.length () << " chars long; " << std::endl;
try {
if ( it0 != it1 ) {
throw std::runtime_error (
std::string ( "results mismatch between std::search and boyer-moore search" ));
}
if ( it1 != it1r ) {
throw std::runtime_error (
std::string ( "results mismatch between iterator and range boyer_moore search(1)" ));
}
if ( it1 != rt1 ) {
throw std::runtime_error (
std::string ( "results mismatch between iterator and range boyer_moore search(2)" ));
}
if ( rt1 != rt1r ) {
throw std::runtime_error (
std::string ( "results mismatch between iterator and range boyer_moore search(3)" ));
}
if ( it1 != it2 ) {
throw std::runtime_error (
std::string ( "results mismatch between boyer-moore and boyer-moore-horspool search" ));
}
if ( it1 != it3 )
throw std::runtime_error (
std::string ( "results mismatch between boyer-moore and knuth-morris-pratt search" ));
}
catch ( ... ) {
std::cout << "Searching for: " << needle << std::endl;
std::cout << "Expected: " << expected << "\n";
std::cout << " std: " << std::distance ( hBeg, it0 ) << "\n";
std::cout << " bm: " << std::distance ( hBeg, it1 ) << "\n";
std::cout << " bm(r1): " << std::distance ( hBeg, it1r ) << "\n";
std::cout << " bm(r2): " << std::distance ( hBeg, rt1 ) << "\n";
std::cout << " bm(r3): " << std::distance ( hBeg, rt1r ) << "\n";
std::cout << " bmh: " << std::distance ( hBeg, it2 ) << "\n";
std::cout << " kpm: " << std::distance ( hBeg, it3 )<< "\n";
std::cout << std::flush;
throw ;
}
BOOST_CHECK_EQUAL ( dist, expected );
}
template<typename Container>
void check_one ( const Container &haystack, const std::string &needle, int expected ) {
check_one_iter ( haystack, needle, expected );
check_one_pointer ( haystack, needle, expected );
check_one_object ( haystack, needle, expected );
}
}
int test_main( int , char* [] )
{
std::string haystack1 ( "NOW AN FOWE\220ER ANNMAN THE ANPANMANEND" );
std::string needle1 ( "ANPANMAN" );
std::string needle2 ( "MAN THE" );
std::string needle3 ( "WE\220ER" );
std::string needle4 ( "NOW " ); // At the beginning
std::string needle5 ( "NEND" ); // At the end
std::string needle6 ( "NOT FOUND" ); // Nowhere
std::string needle7 ( "NOT FO\340ND" ); // Nowhere
std::string haystack2 ( "ABC ABCDAB ABCDABCDABDE" );
std::string needle11 ( "ABCDABD" );
std::string haystack3 ( "abra abracad abracadabra" );
std::string needle12 ( "abracadabra" );
std::string needle13 ( "" );
std::string haystack4 ( "" );
check_one ( haystack1, needle1, 26 );
check_one ( haystack1, needle2, 18 );
check_one ( haystack1, needle3, 9 );
check_one ( haystack1, needle4, 0 );
check_one ( haystack1, needle5, 33 );
check_one ( haystack1, needle6, -1 );
check_one ( haystack1, needle7, -1 );
check_one ( needle1, haystack1, -1 ); // cant find long pattern in short corpus
check_one ( haystack1, haystack1, 0 ); // find something in itself
check_one ( haystack2, haystack2, 0 ); // find something in itself
check_one ( haystack2, needle11, 15 );
check_one ( haystack3, needle12, 13 );
check_one ( haystack1, needle13, 0 ); // find the empty string
check_one ( haystack4, needle1, -1 ); // can't find in an empty haystack
// Mikhail Levin <svarneticist@gmail.com> found a problem, and this was the test
// that triggered it.
const std::string mikhail_pattern =
"GATACACCTACCTTCACCAGTTACTCTATGCACTAGGTGCGCCAGGCCCATGCACAAGGGCTTGAGTGGATGGGAAGGA"
"TGTGCCCTAGTGATGGCAGCATAAGCTACGCAGAGAAGTTCCAGGGCAGAGTCACCATGACCAGGGACACATCCACGAG"
"CACAGCCTACATGGAGCTGAGCAGCCTGAGATCTGAAGACACGGCCATGTATTACTGTGGGAGAGATGTCTGGAGTGGT"
"TATTATTGCCCCGGTAATATTACTACTACTACTACTACATGGACGTCTGGGGCAAAGGGACCACG"
;
const std::string mikhail_corpus = std::string (8, 'a') + mikhail_pattern;
check_one ( mikhail_corpus, mikhail_pattern, 8 );
return 0;
}

145
test/search_test2.cpp Executable file
View File

@ -0,0 +1,145 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/algorithm/searching/boyer_moore.hpp>
#include <boost/algorithm/searching/boyer_moore_horspool.hpp>
#include <boost/algorithm/searching/knuth_morris_pratt.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <iostream>
#include <algorithm>
#include <vector>
typedef std::vector<char> vec;
#define NUM_TRIES 100
#define runOne(call, refDiff) { \
std::clock_t bTime, eTime; \
bTime = std::clock (); \
for ( i = 0; i < NUM_TRIES; ++i ) { \
res = boost::algorithm::call \
( haystack.begin (), haystack.end (), \
needle.begin (), needle.end ()); \
if ( res != exp ) { \
std::cout << "On run # " << i << " expected " \
<< exp - haystack.begin () << " got " \
<< res - haystack.begin () << std::endl; \
throw std::runtime_error \
( "Unexpected result from " #call ); \
} \
} \
eTime = std::clock (); \
printRes ( #call, eTime - bTime, refDiff ); }
#define runObject(obj, refDiff) { \
std::clock_t bTime, eTime; \
bTime = std::clock (); \
boost::algorithm::obj <vec::const_iterator> \
s_o ( needle.begin (), needle.end ()); \
for ( i = 0; i < NUM_TRIES; ++i ) { \
res = s_o ( haystack.begin (), haystack.end ()); \
if ( res != exp ) { \
std::cout << "On run # " << i << " expected " \
<< exp - haystack.begin () << " got " \
<< res - haystack.begin () << std::endl; \
throw std::runtime_error \
( "Unexpected result from " #obj " object" ); \
} \
} \
eTime = std::clock (); \
printRes ( #obj " object", eTime - bTime, refDiff ); }
namespace {
vec ReadFromFile ( const char *name ) {
std::ifstream in ( name, std::ios_base::binary | std::ios_base::in );
vec retVal;
std::istream_iterator<char, char> begin(in);
std::istream_iterator<char, char> end;
std::copy ( begin, end, std::back_inserter ( retVal ));
return retVal;
}
void printRes ( const char *prompt, unsigned long diff, unsigned long stdDiff ) {
std::cout
<< std::setw(34) << prompt << " "
<< std::setw(6) << ( 1.0 * diff) / CLOCKS_PER_SEC << " seconds\t"
<< std::setw(5) << (100.0 * diff) / stdDiff << "% \t"
<< std::setw(12) << diff;
if ( diff > stdDiff )
std::cout << " !!";
std::cout << std::endl;
}
void check_one ( const vec &haystack, const vec &needle, int expected ) {
std::size_t i;
std::clock_t sTime;
unsigned long stdDiff;
vec::const_iterator res;
vec::const_iterator exp; // the expected result
if ( expected >= 0 )
exp = haystack.begin () + expected;
else if ( expected == -1 )
exp = haystack.end (); // we didn't find it!
else if ( expected == -2 )
exp = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ());
else
throw std::logic_error ( "Expected must be -2, -1, or >= 0" );
std::cout << "Pattern is " << needle.size () << " entries long" << std::endl;
std::cout << "Corpus is " << haystack.size () << " entries long" << std::endl;
// First, the std library search
sTime = std::clock ();
for ( i = 0; i < NUM_TRIES; ++i ) {
res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ());
if ( res != exp ) {
std::cout << "On run # " << i << " expected " << exp - haystack.begin () << " got " << res - haystack.begin () << std::endl;
throw std::runtime_error ( "Unexpected result from std::search" );
}
}
stdDiff = std::clock () - sTime;
printRes ( "std::search", stdDiff, stdDiff );
runOne ( boyer_moore_search, stdDiff );
runObject ( boyer_moore, stdDiff );
runOne ( boyer_moore_horspool_search, stdDiff );
runObject ( boyer_moore_horspool, stdDiff );
runOne ( knuth_morris_pratt_search, stdDiff );
runObject ( knuth_morris_pratt, stdDiff );
}
}
int test_main( int , char* [] )
{
vec c1 = ReadFromFile ( "search_test_data/0001.corpus" );
vec p1b = ReadFromFile ( "search_test_data/0001b.pat" );
vec p1e = ReadFromFile ( "search_test_data/0001e.pat" );
vec p1n = ReadFromFile ( "search_test_data/0001n.pat" );
vec p1f = ReadFromFile ( "search_test_data/0001f.pat" );
std::cout << std::ios::fixed << std::setprecision(4);
// std::cout << "Corpus is " << c1.size () << " entries long\n";
std::cout << "--- Beginning ---" << std::endl;
check_one ( c1, p1b, 0 ); // Find it at position zero
std::cout << "---- Middle -----" << std::endl;
check_one ( c1, p1f, -2 ); // Don't know answer
std::cout << "------ End ------" << std::endl;
check_one ( c1, p1e, c1.size() - p1e.size ());
std::cout << "--- Not found ---" << std::endl;
check_one ( c1, p1n, -1 ); // Not found
return 0;
}

145
test/search_test3.cpp Executable file
View File

@ -0,0 +1,145 @@
/*
Copyright (c) Marshall Clow 2010-2012.
Distributed under 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)
For more information, see http://www.boost.org
*/
#include <boost/algorithm/searching/boyer_moore.hpp>
#include <boost/algorithm/searching/boyer_moore_horspool.hpp>
#include <boost/algorithm/searching/knuth_morris_pratt.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
typedef std::vector<std::string> vec;
#define NUM_TRIES 100
#define runOne(call, refDiff) { \
std::clock_t bTime, eTime; \
bTime = std::clock (); \
for ( i = 0; i < NUM_TRIES; ++i ) { \
res = boost::algorithm::call \
( haystack.begin (), haystack.end (), \
needle.begin (), needle.end ()); \
if ( res != exp ) { \
std::cout << "On run # " << i << " expected " \
<< exp - haystack.begin () << " got " \
<< res - haystack.begin () << std::endl; \
throw std::runtime_error \
( "Unexpected result from " #call ); \
} \
} \
eTime = std::clock (); \
printRes ( #call, eTime - bTime, refDiff ); }
#define runObject(obj, refDiff) { \
std::clock_t bTime, eTime; \
bTime = std::clock (); \
boost::algorithm::obj <vec::const_iterator> \
s_o ( needle.begin (), needle.end ()); \
for ( i = 0; i < NUM_TRIES; ++i ) { \
res = s_o ( haystack.begin (), haystack.end ()); \
if ( res != exp ) { \
std::cout << "On run # " << i << " expected " \
<< exp - haystack.begin () << " got " \
<< res - haystack.begin () << std::endl; \
throw std::runtime_error \
( "Unexpected result from " #obj " object" ); \
} \
} \
eTime = std::clock (); \
printRes ( #obj " object", eTime - bTime, refDiff ); }
namespace {
vec ReadFromFile ( const char *name ) {
std::ifstream in ( name, std::ios_base::binary | std::ios_base::in );
std::string temp;
vec retVal;
while ( std::getline ( in, temp ))
retVal.push_back ( temp );
return retVal;
}
void printRes ( const char *prompt, unsigned long diff, unsigned long stdDiff ) {
std::cout
<< std::setw(34) << prompt << " "
<< std::setw(6) << ( 1.0 * diff) / CLOCKS_PER_SEC << " seconds\t"
<< std::setw(5) << (100.0 * diff) / stdDiff << "% \t"
<< std::setw(12) << diff;
if ( diff > stdDiff )
std::cout << " !!";
std::cout << std::endl;
}
void check_one ( const vec &haystack, const vec &needle, int expected ) {
std::size_t i;
std::clock_t sTime;
unsigned long stdDiff;
vec::const_iterator res;
vec::const_iterator exp; // the expected result
if ( expected >= 0 )
exp = haystack.begin () + expected;
else if ( expected == -1 )
exp = haystack.end (); // we didn't find it1
else if ( expected == -2 )
exp = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ());
else
throw std::logic_error ( "Expected must be -2, -1, or >= 0" );
std::cout << "Pattern is " << needle.size () << " entries long" << std::endl;
std::cout << "Corpus is " << haystack.size () << " entries long" << std::endl;
// First, the std library search
sTime = std::clock ();
for ( i = 0; i < NUM_TRIES; ++i ) {
res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ());
if ( res != exp ) {
std::cout << "On run # " << i << " expected " << exp - haystack.begin () << " got " << res - haystack.begin () << std::endl;
throw std::runtime_error ( "Unexpected result from std::search" );
}
}
stdDiff = std::clock () - sTime;
printRes ( "std::search", stdDiff, stdDiff );
runOne ( boyer_moore_search, stdDiff );
runObject ( boyer_moore, stdDiff );
runOne ( boyer_moore_horspool_search, stdDiff );
runObject ( boyer_moore_horspool, stdDiff );
runOne ( knuth_morris_pratt_search, stdDiff );
runObject ( knuth_morris_pratt, stdDiff );
}
}
int test_main( int , char* [] )
{
vec c1 = ReadFromFile ( "search_test_data/0001.corpus" );
vec p1b = ReadFromFile ( "search_test_data/0002b.pat" );
vec p1e = ReadFromFile ( "search_test_data/0002e.pat" );
vec p1n = ReadFromFile ( "search_test_data/0002n.pat" );
vec p1f = ReadFromFile ( "search_test_data/0002f.pat" );
std::cout << std::ios::fixed << std::setprecision(4);
// std::cout << "Corpus is " << c1.size () << " entries long\n";
std::cout << "--- Beginning ---" << std::endl;
check_one ( c1, p1b, 0 ); // Find it at position zero
std::cout << "---- Middle -----" << std::endl;
check_one ( c1, p1f, -2 ); // Don't know answer
std::cout << "------ End ------" << std::endl;
check_one ( c1, p1e, c1.size() - p1e.size ());
std::cout << "--- Not found ---" << std::endl;
check_one ( c1, p1n, -1 ); // Not found
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
TU0AKgAfhPqScHN4dnZ2e3p5e3h7eXl4dnd1dnV3enp5dnd3dHV1dHNzd3l3eHh5
eXZ4dXd2dHNwcHFwcXBxc3h0dHN1eHVzcXV1dXV2c3h5dHV3eHVwcHF

View File

@ -0,0 +1,2 @@
iBJbmMuLCBhbGwg
cmlnaHRzIHJlc2VydmVkLgAAAAA=

View File

@ -0,0 +1,2 @@
q/y9PZ3uHj5ufo6UJDQ0NFQz8+RUZBQEBAOzo6Ozs4Nz06Ojs4Ojo9PT47Ojk0
Nzc7OjQ6NzU6OjgxMzg1OjY2NjU3NTU1Nzc3NTU1NzU

View File

@ -0,0 +1,2 @@
TIzMjIyMjM0MjM1nTQzNTc3MzY1NDU2NzQ2MjEwMjU1MTQ2NzU0NDI1
NDMyMzQxMzQ0NDU1MjU2NTc5NzU1NDc4ODY1

View File

@ -0,0 +1,170 @@
TU0AKgAfhPqScHN4dnZ2e3p5e3h7eXl4dnd1dnV3enp5dnd3dHV1dHNzd3l3eHh5
eXZ4dXd2dHNwcHFwcXBxc3h0dHN1eHVzcXV1dXV2c3h5dHV3eHVwcHF1d3V0dXJy
cXNzcHBwcHJyc3R0dXl7eHJycnF1dHV2d3h4eHV0cnRycXN1dXN0c3R0c3R0cXJx
cHNxb3B0c29scHFybm9sbGpscXJ1c3NycXN0cHFvb3JzdHBycG9vb29vb29ubXBt
bG9vcW5tbGptb3Fwb3Bwb25vbXFtbGtvbGlrbnBuamxsbW1rbW1vbm1ub3Btamxw
bWpsbG9xcG5ua2tpamhqZ2hnam5saWhsbG1nZmZnZ2lnamtxa2ppZWZmZWlrZ2hp
Z2hraWRmZ2psa2pmZWVkZmplZWZiYF1gZGVlYmJiY2RhY2NiYVxdW1xgXl9iZV9d
X11hXF5gZWJhYF5dXWFmYl9hXl5gXmBhZGFhYV1cYWFiX2FgXFxgYF5iYmNiYWRk
YWFjYGFgXl9jYmVlZGZiYV1cXFtbW1pYV1dVV1VWVlFQT1FRUVBRTkxLSktNTVFP
UU1RUVBSUlBPUlNTUVRWWFpcVldXWldXVVhYVlpbWV1dX1tbW11fYWFdXV5iY2Rg
YFxeYmNmZGJgYFxdYmdjYWFhYGJoZGReXF9gX2BhYWJhXltdXVtaXGJlYV5gYF9f
XVxcX2JiYWJkZmNjZGNhYmFcW15dXmBgX1xdYF5fXF5eX15bWV1dXl9eWlldXGJf
XmFgXVpcXF1dXlpdXl9dXWRlYF5cXFtfYF1eYl1hX1xbXV1ZV1hZWltbW1peW1lb
XlteW1xeXlxbXVpYW11dY19fW1xfX2NhXV5hZWNfX2FjZGJlZmVoaWtlY2FkXl5f
YWJjX19fX15dXWBjYmJeWlteXVlaXmBeXF1fXVxdXFtaW19dXFtfWllZWVxeXlxb
XV9eW1xcXF5cW1paVVdbWVteW1pbWlZeYV1ZV1tYVlVWV1hbWVhcWVhVWlhbWFtX
V1ZWWFtXVlZaVlRVVVdVVldWVlNRU1NTUVNXVVlZWVZVVFNWVlRTU1JVV1ZWVFRU
UVFVWVpZWlZWWFpYWllcXVpYWFdWWFxbWFlYWVhVVVRVV1dZWllYV1lcXVpcWVhY
V1VbW1tVVVdaXFpXVlZZW1leW1lWWFdaXVpXWlZXW1xdXFxgX1xYXVxcXFhaW1tb
WlxcWltdWldXVldXWVZVUVJVWFlcW1tcWVpgXF9hX11aWVpdXFxeXFtbX19aW1lb
W1paWlxdXVpaXVxeX1xdX2JjYV9gYl9cW1xbWFpeXl1gYGBgYFtdY2JhYmBgYGBe
YGJkY2NjYmNjYGNiY2JgX19hYV1gX2BgX19hZWRiZWJjZWVgYmFiZGRmaWdmYWJj
YmJjZGFhY2FhY2RkZmVmY2FhYWVnaWVjZGNhY2RlZWZqZ2doZ2RjZGRmaGVlZmZm
Z2dnaGhoZ2hmY2VmZWZjZWNlaWdlZmVoZ2hpamlra2hram1samtqZWpuc2tpa21u
bmtraWtqYWNmZmZmZGVpZ2p0kMLk8vv+/////////5drcHZ1dnd7fHt6end0c3V1
dnR0d3l3d3Z3fH16dnV2d3h0d3l2d3h4dXZ3d3d3dnBucW5vb3BxdHR3d3Jzd3Vz
dndzc3V6eHVyc3JydXZxc3Z1d3V0eHZ1c3Bvc3V0dnR0dXR0dHd4dnRxc3J0c3d3
dXNycXd1dnVzcHJ0d3h0dHFwcXFzc3N0dXFxcXFwcHFwcnFycHJwcHJzc3Fwc3Nx
cnRyc29ucHJ0cnBwb29ub3Fwc3R0cnJubnBycG1ucHBxcXBuc3FwbGpoamlsb3By
c25qaW1tcW1qbXFua25xb21vcG9tbG5qa2doaW1sbGpqamxsaWpmZ2VlZ2tqZ2Zn
amVoa2tvZ2ttamxpamlmZmdoZ2dnZ2traWZmaGlpa2loaGdmZ2ZoZmRnZ2ZmZ2Vl
ZmJiZWBhYmBhZGBhX2BfXVxfYmJkZF5dY2JjYWNhY2BgXl5gXl5dXl5cXFxgZGVh
Xl5eXlxeXl5iYl9fYF9iYWFhZWRkY2RgX2BhX19gY2VlZWRkZF1gYV9bWV1dWVxX
WldXVlZVU1BQUE5QUU9SUU5NUE9OTk9NT1FRUk5PUVRUUVJSVFVYWVpXVldVVlRV
V1dZXl9bW1pYWVhaXl9gXl5bYGJhYWFhX19jZGZmZGJgYF9eX19fYWRmX2RgYWBe
XmFhYWNhYmBeXV5eW1xdYF5dX2NiX19hX11dYmVoY2RlZWFeYF5fXV5hYGFgYF9i
Y19dXl5dYGNgXFZbXlxZWVxhYl5gYF9cXV1cXFxdX19gYVxZW11dX2NjXF5eXF5e
Xl9eYGJfXl9eW1xcX11ZW1xdW15eW11gXl1dW11cX15dXl1cXF5iX2BgYV9iYmJf
XF1mY2NiamZiYWNiY2JiYmVpbGdkYGBmY2VoY11dXFxcX15iYmFiYmBeW19hX19h
XV5aYlxZWlxcW1xcW2BfW1hZXF5cXVtcXlxbWldYW1xcXVpYWFlYWllbW1paWFpe
XFtYWFdUU1ZVWFhVWFteWFdYW1pYVlhVU1RVWVZXVVdXVVFSU1ZWVFNSVVtSUlJT
UlNUVVVWVVVWVVJWVVVTVldXXFlXVVlbVVNUWVtXWVtVVVZVWltZWltYVVVZWVlY
V1ZXWVVUV1dXWl1dW1tcX1lZWl5cXVtcWVVXXFxZXVxZVVRUWVlcWVZWWFhaWFtd
WV5YVlZZWVxbXFxdXFtbXl5dXVtbWV5dYF9cXl9eXF9iXl5bWlhbWltZWFpgXlpa
W15iXF1jYVtcYGBfXVpbXFxcWlxbXFtZXFxaWllaXl1aW11gXV5fX19fX19hXl5f
YGFgYWBhXmBiXlxfXFtcXmBgYmJkYWJgYmNgYGJiYWBfX19jZWBeYWJgYFxcY2Vj
ZGJfX2JiYWNmY2RjYmFhYWFjYWNpZmNjZ2ZkZGBiYmVmZ2VjYmNlZV9iZWhlZWJi
Y2JmZWdoZWVoZmdrZ2VmZmhmZGRkZ2VmZmVkZmppZmVnaGhqamhiZmZnaWdnamZm
ZmtubGtpZWhna21rZmRpaWVlZ2l0bGtrbG1obmdmamZnaGVkZGNobYekwePx+///
////////l2pzdnh3fHt8enp5fnl2d3Vyc3d5eXd1d3d3eXx+eHp3eHR0d3d6enl1
dHNzc3d1dXNwcHJ0c3Byc3V3eXVycnZ5enl3dnh3dnJxdHZ3dXh8eHl1dXZ3dnZ1
dHV0ent2dXl3dXV1d3h3dnZ3enV0d3d0dXN3dXZ1dnd3d3h6eHZzc3JwcnN0dHJy
cXFub3FycW9vcHBvbGxsbXFzcHF1c3N0dHR0c3Bvc3N1cnFvcW9tbXFzcm5ub3Bw
b21ucXBxcXBvc3Bvbm5sa25sbW1vbnJ0b2trbWpqbGtsbnFxcG9vbm1xbm5tbGpp
amtqbm1rbW9sa21taWhoZmlqaGlramxqaWdraGdqaWluam9ua2psamhkZmxpaWpq
aWVlZWdnaGZjY2RpZmZnZmZmZ2ZnZGFhZWNgZGJhY11dXV5hXF9lZGRiY2JhYV5f
YGZgYF5fYWJgYmBgX15gZF9eYF1gYlxeYV5fYV5eYF5gYWJkX2JhZGNlZGJjYmFh
YWNgY2VhZGZkY2JgYWBjY15fXFtaWllaXFlYVlNRUVNTUU5PUlNSVlRPU09PUVJS
U1FNT1JVUk9RU1NRU1NSVFRWVllWWFtXWFhaWlpeXl1hYV9cXV5fXl9gXmFgYGBh
ZmJjYmJjYV9fX19dYWFiZmRiYWBeX2FcW15fYWBfXmNkX11cXF1cXVxfYl9hYWJd
X2BhY2JjX2BkZGFgYWFfYWFgYF9eX2JiZGVjY19dYF9eXV1eXF9hXmBeXF1fXV9b
XGFhY2FkX11dW1peXl9hYWJgX19jYV5dYGFgYGBdWV5cXV9hYGBcX2BhYF5gZWBb
X19dXWBeXl1eYWNhXl1eYGFhYGFgYWFhZGNiZGZoZWdnZWNgXWFhX2NlY2NjYGBl
Y2NjY11bXl9eXmBiYGFgXF9kYF5iYF9iYl9cW15aWV5fXFtaWVpdW1xfYGBfXV5d
XFtcWlhXVlZWWFhYV1ZWV1daWlhbWlpcXFhaWFdYVldYWFlZWWFYWltYWVhSVFdV
VlpWV1RYV1VTVFRYVVRWU1RUVVhWVVRUVFZXVFVXV1VWV1ZYV1lcbltbWV5ZWlpX
V1VSWFtfW1laXV5bWFpZWlpYWVhYW1hYV1daWVlZV15dWlxgXVpZWV1hXFpbW1dY
WlpZVldXWlpWVlZXWlhaWVlZWVpZW1xbWltcWVhaXVxdWVxZWVtaX2BfXFlaWVte
XV5dXV9eXF9bW1xbXl9hXFdcXlxbWVpbXFpcWF1gXV9gYF9aW11cX15dX19gXFtY
WVtZW1tdXWBiYWBfXV5cXV5dX15eXV1iZWRhYWFiYF9eYmBeXV5dYWBdXWBlY2Fh
YWRfYF9hY2RhZGJjZGZjYmJfYV5fZGJkYWBgYGBjY2RlaGNhY2BjYF9eYWJgY2Vk
Y2JlZWRhYmRlY2FjY2RjY2RjY2NjYWBkY2NjZGVjYWRnaGhramtqZmdnZmhoZ2pn
aGhoZmhpa2lpaGhoZ2hlZmdqaGZsbWhpamlqamppa21qaGhmaGxqZWVra25sbW5p
aWhraWprbW1pZ2ZoZ2hsfKXG4/D7//////////+UbnR5e3t6eHmAfH58eHZ2dHd2
d3x3dHZ2dnl4eHt8fHh4dXVydXR3eXd2dXR4d3Z1dXZ1dnhydHd5d3ZzdHV4dXR2
eX13dnV2dHN1eXh4eHd3dnd2d3Z3dXZ3dXZ3eXh5dnR4eHV2eHt8e3l1d3d1dndz
dXV2d3Z1eHh0dXR2d3V0dnNxcXFvb29yc3FucnJycW9ycnBvbG5ycXF0cnNyc3Nz
cnFydHFvcHFycnNucXJvb3FzcHBxc3NxcG1ucG9wb3NxcXJwa2xtbXFwbnJtbnFv
b25uamtqbG1scHJwa25tbXBycG9tbW5vbnBvb2xtb2xxbmtsbGtpamtrbGtnamlq
a2pnaGhmZmptaGhoaGxqaGhpaGhpaWlpZmVkZWdoZ2lmY2RgYmhmamdlamdhYWNg
X2BgYmNhYV1eYWFmZGRkZF9cXWBgX19fY2NdYWFiYWJhXl5kYWJhXF5eX19hYmZi
Xl1gYmJiYV5iY2FhYmRhX2BlYWFiY2FfYWJhYmRjZGJeYmNmZGBhYmFaWVpaXFtZ
V1ZUU1NSVVVXWVNSUE5NT1JPTk1NT09OUlVOTk1PU1NRU1JTVFRRU1NWV1dXWlhb
W19bX11cX15fXFpeXV1dXV9fX15hYGBhZWJhX2FhYGBeXmFmZmJhYV9fYWFeXl1b
XFxcXWJgYGFgXV5eW1peX2BgYF5iY2RiYV9gYmFhX2BhYmNiYWBhYWJfYWFfYF1f
YWBgY19fXV5kYVlcX2FgYF1eW11gX15dXGBgX11hXltbW1teX2FdX15cW11cXF1e
X2BfYGRmW1tfYFxeYWNiX15dXmBcXF5gX2RfW2BjYmFhY19bWl9hXl9hYmBeYWVk
YmRiYmNjY2NjY2FjZGNgZGJjYmBfX19eYmJeXl1eXF5gXV1dXV1cXFtbW15fXV1e
XlxdW1xeXmBbWVpYVltgYF5dXV1eWVlbW1xZVlZVWFhcXl1aWllWWllbXVxbWFha
WFpbW1lZVldXVVZdV1daW1hYV1hVV1hTV1VUWFlXVVNVVVJSVVVWVlJWVlZWVFRW
U1VVUlVUV1RWUlJYVldXVFdcXVlYV1JQVVlTVVZXV1ZTU1dYV1VUWV5bV1RWV1pY
WFlbWldZWlpaWFdZXVlcXlpcXFlcWltfW1hZWltZXVteWFRSV1hZWlpZWFhXWFla
WFheWVtZV1laW1tcWFlcXF1eXVtYWlpbXF1dX1xbWltcXl5hYVtZWl5ZWVxeXV5d
XltaVlhaWVxcW1pbXV5eXlxdXV9eWllbW1tfXlxeXWBeXGFeXl5gX2BfXlxgY2Ji
YWFhZWJgXWBfYV9dXl1cX2BeXl9eXFtcX19gX15hY2NgY2NnZWFjY2FkZGJjZGJi
Y2BhYmNkY2NhYWJjZWJiYGJkY2BhZWVmYmRkZmVmZGNiX2FkZGNkZGJjZWRlZGJi
YmRjYmhjYGJmaGlmY2NnZWhlaWtramhmZmZqZGhpaGZnZmRnaGloZGhqbW9tamdp
bGtubGlsbmxpbW9wbGtra3ZoZGdpamhnZmhpaGhtbW1ra21qaGt+psnk8Pr+////
/////3ZnbnV6fHh2eHp7fHx6d3h3dXV6eHd5dXNzc3h5eXl1d3d3d3h2dnd0dXR0
d3h5eXh6dnV1cXR1dHV1dHR2d3h3d3p4enp5c3Z3dXV0dXl4dXV4eXt5dnZ0dnp5
eHZ4dnd1dnNzdHJ4fHx8eX16eXh2dnR0dHV2eHV0eXRycnB0cnNwc3dzb3FvcXNv
b3Fyc3Bxc3JwbmxucXJycnRzcXBwdHV1dnVzdHJvcnFycnZxcXFxcXJwb3BvcXRw
bXFvbXBubGpwcXFtbG5ub25xcW9rbG1tbGxta2xrcnRxcm5qaWxra25wb3Byc3Zw
b2xsbWtub21ra2xpam5tbG9ybGxrampramlpbHVza21maGxqaGhnaWxrbHBsa2tp
amhnZ2ZmZWViYGNjZmRjZWRoZ2VhX2JjY2JiYGFhYGBfY2dnY2FiY2BiX19fX2Fh
YWJgY2JjYGFgYV9dXF5fYFxfYWJkYmJeX2BiYmFiYGFkZGJfX19iZGlhYGBkZGJj
YmRlZWRhYWBhYmBcXV1dXVxbW1xbW1ZXVFBXVFNUUFRUUk5RVldQT1FPTkxMT1JR
UFFRUFBRU1NRUFBRU1RRUlRVUlNWWFhaWV1eW1tdX2BgXllYXV1bXWBgZWNgYV9g
X2JfX2JlY2VmZ2RmZWZiYl9fX19hX2BeW15hYF9dW15gYWRiXVlbXF9hYmNjZWBm
YmFdY2RkYWFhXV9gZGFhY2JeY2FeXmFgXl9iYl5dYGFcX15dYF5dXVpZXGBfXl1d
W19gYF9cXF1cXl1bX2JeXl9aW11cXF5fYGBhY2ReYF9dYWFjYmFfXlxcXVtdXlpe
X19lY2NgYWBeYmJdXl1hY2JiYl5fYGBhYmRkZGJjY2JjYmJiYGFiYmBfXV5eXV1g
Y2VgX1xbW1teXVpZW15fXVxeXVteW1lZW1pcXFxfW1tZWmBeWl1eXV1eXlxYWlxc
WlhZWFlYWFdbWltdWVlZXFlaW1xaWFdYXFtaWFhYVVZZWVhYWVdWVVZZWFxXW1lU
WVhVU1dXU1JVVVZYWVlaWllYWVZWVldWV1hWVlhXXllYV1ZYVlZVW1lYWFRUU1RX
VlZYWVlYWFhTWFZYW1xaW1lYWVtZVVZXWVpXWltZXFxaWFpXWV9fWltYVVhdWlla
WltZV1hYWVxbV1hWWFxbWl1cWlddWVlbW11aV1daXFlZW1xbWlpeW1pdW1lXW11e
W1tbXFhaXl1bX19cW1tcXF5cXF1aV15eWlpbWl5cXlxcWltcXFxbWlpcXFxdXV1i
X1tcX11gX2BhYWNhYF1eYmJfXmFnZWBeX2JeX2FfX2FjYWNeX2BfYmRkYWBfXl1f
YmNgX2BiYGFhYmNmZmZlZmRjZGVlZWZkYF9kZGNfXl9gX2BjZWVlYmJhZGJlZGJl
Y2JkZmRjY2ZnZGVkaGZlamJiYGRlZGNhY2hoZGNiaGVpZmtpZmBkZ2plYmRnaWdl
ZWdpZGZnaGdkZGlta2pqaGlnZ2RoamlmZ2pta2lqa2tqbG1sbGtqZmtsamhqbGlr
aGloa2dnbmpwZ2lra3uly+Hv+P7/////////cHR9e3x6d3Z3eX16eXh3d3p6dnh3
e3l0dnVxc3Z3dnd5dHV2eXh1c3N0d3Z4eXl8fXyAenl4c3RzcnJ2enZ2dnV0dnl+
e3d0c3V2dXR4eHh2dnZ1eHZ2dHh4d3V3dXR1dnZ1dHR0dHd3eX97eXl2d3R1dnd2
dnd5c3JzdXJ1c3Z3dXZ2eXRwc3FycHBwbnBvbnB3dXV1c3RwcW9ydXJzcnR3eHZ1
eHR0dXRzb29wc3FwbXBtb21ubWxtcnNxbm1rb3Fubm9ubm5vbmlqbmxpamxvbW1s
bm9vb3FycHJsamtra21rbW1vcG5xb25tbGlpbWttbmxsbGxpa2hoamtrbWxqamxt
bW9ub21rbnBoamdlZ2ppbW5tbW1vbmxqZWdmY2VlZGNjZWZlYmVjZGBiZGBfYmJp
Z2NkZWNgX2NjYmNhX15lZWBdYF5iXVxbYWBgYmJgYF5gX15cX19jY2BeXmBfYGJi
YV9gYmFfYWJjYF5gY2RiX2FdYWJlZGRkZWVmZ2NhX2FhXmNiXVtcXV1dXVxaWFZX
WFVUUlNTU1VTVVNVT05QUFFNTU5MTU9RT1JTUFBRU1BRU1VUVVVTU1NWVFZaW1pY
WlpaX11eX15cXVxdXlteXF5hZF9fX2BiYWFgXmBhYmJiZGVkY2RjYGBfXWBiXVxg
YWJhX19jYF9hYGFfXFpbXWJjYmFgYGFiYmNiY2VhXV9fZmNkYWFiZGNjYF5cXVtb
Xl5eX2RkZF9eXF5dYF5hXlxbXFlYW2FiY2JfYlxZXl5dXV9dXV5gXl1cW1tbWVpd
Yl9fYl9eY2FdXV5eXlxdXFtbXmBgYGJiYmhlX2FeXl5fYF9fX11fYGBiYGFiYWFl
Y2NiYmBiYWJnZ2FfY2NgX2JkYmNlYl9fYFxdXV5fXVxZWlpdXF1cYF9gX19eXlla
XWBiXlxYWFxcXVtdXFpfXmFgW1lbWlpYW1pbW1tZWFtdYF1aWVpZXWFfWFZUVlZX
WVtaWFZWWVZUV1dYWFVUVFZVWFxcXVtaW1hWVlVUU1ZXWVhbWFlWVFhaW1lYVlVU
V1pYVllZWFdaW1pYWFtVVlpcWlRUWFdXWVlWWVtbW15YWVtbXFtXWllWVVdZVlZY
V1hZWFlYV1daVVZZV1tcXF5cW1paWVheXl5dW1xcWVpbWFhXWllYW1hZXlpWXFxc
W15aWVpZWllZW15dWlxbW1lbXVxaXF5cXFpaWlpbXVtcXFxcXl1aWFpcYWNfXFxc
XF1dX2FaWVtaWVpbXVxbVltaWVpfXF1cYWBeYWFeX19dX2FfXmBfX2NqZGFfYGJg
YGBjY2VhYGFmZGFgYWJgYV9eXl5fYmNiYWJiYF9eX15gYGBiYGFjZGNjY2JjZmdj
ZGFhX2JfYGJhY2RjYWRjYmNiZGBkZmZmZWRkZmVmZmVlZGlmZ2lpaGZmZWdkZWRl
aWhjY2FjZmNmaGlnZmtqZ2dkZWdkZWVkZGdkZ2hpamhoZ2ltZmZnZWVlY2dpamtr
a25wbWppbW9vcHFxb2xxbGxva2xoamlpaWprbGprb21mZ2h3gqDN4u/3/f//////
//9ueHx9fnx5eHl8eXp7fnl4eX14e3l5d3l3dHV0dXZ4dHZ1c3N0dXRzdnR3eXd4
dHV6e359eXd4dnZ5d3d3dXZzdHZ0eHh3d3h3dXh1cnB0c3R2d3Zyc3R4enp3eXh4
dnd2d3p7e3x6dXh2eHd2dHd5dHR0dXd5d3V0dXR1dHRzdnZ3eHhzdHd4eHJxbmxu
b29wcnJzdnV0dXBydnNxcHFwcnV2dHd1dHV3dXRycnRzdHFtb3FxcXBubm9wbG9w
b29vbnFycXBsbW1xc3Jtbm9ubW9ubWxtb25wdG9tbm1wcWttbW5sbWtwbnFsamps
bGtoaWtvcW9tbGxsa25vbWtoaWtsa2psa2tpbWxqbGloZ2loaWtsbG5tbGxraWlq
a2lnZWVlY2JiYGJnY2JkZV9hY2JjYmBga2dhYWNkY2ZkYWBfXmBgXlpdYl9bW11h
ZGRhX19fXGFcXWFfX19hXmBhYGBiZGZlY11cXWNkY2ZmYmJgXl9eXmFhZGFjY2Nm
Z2hmZGJjYl9eYGNhXl9eXFpcXVxbXFhWU1FRUlNSUE1OUFFNTE1NTUxPT0xKT1JY
U1JSUE9SVFZTUlJTVVdZWlhZWlhZWVhdXF9hXV9cXVxeYl9dYWBdXV9gYl9fXmBg
ZGNfX2NjY2NkYl9jYGFjY2FfYV5gYV9gY2JhYV9lXWBiXmFjX2BfXV9eXF5dX2Bf
ZWNkZWhmX19dYF9jYmFfY2NhXF1dYV1dXFxdXl9gYGFdXGBeXmFhXFtdXVxcXl5g
YmFeXVtcYGBcXl9dYFxfXl9fXl9eXV1eYWBeXVxdYGNhX2FfYWFgYV9eYGNgYWJj
X19gX11cXl5dXl5hX19hYWFkZGJiZGNiYmJjYWFjY2FfXmFkY2RlZmdhX2BhXmBi
ZGRiY19dXVxZXF1eXV1gYV9eYl5hX19eX2JdWl1cXVxcXmFeXF5eXV5bXmBkXFla
WFtbWltbWllbW1hbWVlZWltZW1hXWFdaWlpZW1tVVldYV1ZXWFRWU1NWV1hYWVpY
V1hWVlRTV1ZXVlVTUVNaVlVUWFdVVVNUWl5bWldYWFpbWlhZV1ZYVldcWltaWVdY
WVdVV1lbW1hXWFpXVVZWVlVUV1dZVVVVVVZVWFpXVlhaWlpYWFtaXWFdWllZWltb
W1pbW1lYWVxZWFhUVlhZXF9bWVtYXFxcW1pdXV5YWFlXWltcWldaWVlbW1pXV1pa
W15hXVxgXVlZW11aW1laW11bXF1ZWmBcXFxdXF9cX15aWlpZXFteWl1gYl9hW1la
Xl1eXV1eXV9dXl1dXV9hYGFhX11dX2BgX2RlZWNlYl9hYWNgX2BfW1tdXV9iZGJg
YF9gYGNiYGFjZ2FgZGFgYWVhY2ZkZWdgYGBmZGFgYWFiYmBfY2RlZWRkZGVkYmVn
Z2RnamdoZ2VjY2ZnZGJiZmplZmVlaGNkZ2ZmZWFiY2ZmZ2trbGtpZ2hqa2xqaGZn

View File

@ -0,0 +1,120 @@
5eXl5uXk5eTl5eXl5eXm5eXl5eXl5ebl5ufl5efl5ebm5+bm5ubm5ebm5ufm5ufm
5uXm5+bl5+bl5ufm5+bm5ebn5ufm5ubn5+bm5+bm6Ofn5+fm6Ofn5+jn5ubn6Ofn
5+fm5+fn5+fn6Ofo5ujo5+fo5+fn6Ofo6Ojn6Ojn5+nn5+fn5+jn5+fo5+fo6Ojn
6Ofn5+np6Ofo5ufo6Ojn6Ojn6Ojn5+no5+bn6Ofn5+fn5ufn5+fo5+fo5+fm6Obn
6Ofn5+jo6Ofo6Ojn6Ojo6Ono6eno6ejo5+jo6Ojo6Ono6Ono5Ofo6Ono6ejo6Orp
6ejp6enp6Ojo6Onq6Onp6ejo6eno6enp6eno6ejp6Onp6enp6unp6eno6Onp6unp
6ejp6enq6ejp6unp6enp6Ono6eno6uno6enp6Orp6enq6uno6unp6enp6erp6Orq
6Onq6eno6unp6unp6urp6urq6enp6urq6uno6urp6erp6erq6urp6urq6erq6uvr
6erq6enq6ejq6urp6uvr6erq6urp6unq6unq6Orp6+nq6unp6err6unp6+rp6urp
6ejq6erp6enp6erp6erp6eno6ujp6unq6+rq6urp6+vq6uvr6urq6urp6+rq6urr
6+nq6unq6urq6uvr6+rq6uvr6+rq6uvq6+rr6urr6uvr6+vr6+vq6+vr6+zr6+vr
6+zr6+rr6uvr6+rr6urq6+vr6uzr6+zs6+zs6+zr6+zs7Ovr7Ozr7O3r7Ozs7Ozs
7e3s7ezr6+3r7Ozs7e3t7O7t7O3t7ezt7u3t7u3t7u3t7+/t7e7u7+7u7+3u7+7v
7u7u7u7v7+/w7u/v7/Dv7+/w7+/v7u/w7+/w8O/w8PDw8PDw8PHy8PHw8PHx8PLx
8fLx8vGVjoV7dW1kYmJYVlRVVFRWVldZW1xdYGJjZmlqbG5wcnZ3en1+gYKFh4qL
jY6OkZKTlJaXmZqdnqGjpqipq6yur7Gxs7S0tLa2uLm5u7u9vr7AwMHCw8PDxsbI
ycrJy8zNz8/S09PU1dfX2dnZ2dja2tra2tvb2tra2tvb29rb3Nzd3d3d3t/e3d/f
3t/f39/f197f39/f3+Df39/e3t7e3t/f3d7d3t7e397e39/e3uDg4ODg4OHh4ODg
4d/f3+De3uDf39/g3d7d3Nza29va2tja2tnZ2NjW1tjX1tbW1tXU1dXV1dXV1dXV
1dXW1dTT09PS0tLS0dHS0NHR09PS09LT0tTU1NPT0tPT09TS09PT0tLR09PT09PT
09TU1NTU1NTU1dXV1dXU1dXV1dXV1dXW1tXX2NfX19fX2djZ2dnZ2drZ2tvb2trb
29vc29vb29vc3Nzd3N7d3d/e3d7e397f3t7e39/f3uDg3t/g4OHg4ODh4d/h4OHh
4OHh4eHh4eHi4uLi4uLj4ePi4+Li4uPj4+Pi4uPj4+Pj4+Ti5OPj4+Xj5eTk5OTk
5OXj5OTk5OTk5OTk5OTj5OPj4+Tk5OTj5uXl5OXl5OTl5eTl5OXl5ebl5ebk5eXl
5ubk5OXn5ubl5eXl5uXl5+Xk5eXl5ebl5ebm5ubl5uXm5ufn5uXn5ubn5ubm5+fm
5ubl5ubn5ufm5ufm5ujn5ubn5+fn5ufm5+jo6Ofn5ubm5+bm5+fn5ufn5+fo6Ofo
5+bn5+jn5ujn5+fn5+fo6Ofo6Ojn6Ofo6Ofn6Ojp5ufo6Ojo6ejn6efn6eno6ejo
6Ojo5+fn6Ojp6Ojo6ejo5+no6Ojo6Ofo5+fo6Onp6Ojn6Obn6Ofm5+fn6Ojn6Ojo
5+jo6Ojo5+jo6Ofo6Onp6Ojo6Ojn6Ojo6Ojo6eno6ejo6enp6Ojp6ejp6unp6Onp
6enp6Onp6Onp6eno6Ono6enp6enp6Ono6enp6OXp6Ojq6ero6unp6unp6enp6unp
6unp6eno6enp6urq6enp6enq6unq6enp6erq6urq6unq6unp6Orp6enp6erq6erp
6erp6urq6urq6enq6+rp6urq6unp6ujp6unq6enq6evq6unq6unq6uvq6unq6urq
6+vp6ujq6unq6urp6unq6unp6+rq6evq6urp6unq6+rq6urq6erp6urr6+nq6urp
6unq6+nq6erp6erq6erq6erp6urq6urq6evq6enp6enp6ero6unq6+nr6urq6+rr
6urq6uvr6urq6+vr6+vq6+zq6+vr6+vq6urr6+rr6+vr6urr6urq6+zr6+rq6+vr
6+vr6uzt6uvr6+vr6+vr7Ovs6+vs6+zs6+vs6+rr6+rr6+vr6+vr6+vr6+zr6+zt
7Ozr7Ovr7Ovr6+zt6+zs7e3t7O3s7O3t7ezt7O3t7ezs7O3u7ezt7O3s7u3t7e3u
7ezu7e3u7e/u7u3u7+3u7u/u7u/v7u/u7+/v8O/v7+/v7+/v8PDv7/Dv7+7v7/Dx
8PDw8PDx8PHv8fHy8PHw8fDx8fHw8fHy8vLy8qOdlpGLhH56dXRycHFxcnR1d3l6
fH+ChIeJi42PkpSWmZyfoaKmqKqrra+vsLK0s7W3uLm6vL2+wMLExcfGyMrKzczN
zs/OztDQ0tLT09TV1tbW1dfY2NfY2dra2trc3Nzd3N7e3t7e39/f39/f4ODg4ODg
4eHg3+Hh4eDg4OHg4ODh4uHh4OHh4uHh4eHj4eHi4OHh4uHi4eDh4eHg4eHh4eHi
4eHg4eHg4eDi4eLg4eLj4+Li4+Li4+Hi4eLg4eHh4uHi4uLh4OHg4eDh4N/e4ODf
4ODf397e3d/f3d7f393e3t/d3t7d3d7d3d3d3d3d3tze3d3c3tzb3d3d3Nzc3N3d
3d3e3d3d3d3d3d3d3t7e3tze3d3e3d3e3dzf3d7e3d7d3t7d3t7e3t7e3t7e3t7f
3eDg3+Df4N/f4ODf4N/g4N/g4ODh4OHh4eHg4eDi4eHi4OHh4uHh4uLh4eLi4uLj
4eLj4uLj4+Lh4uPj5OLj5OLj5OPk4+Tk4uPj4+Tj4+Ti5OPk4+Pj5OTl5OXj5OTj
5OPk4+Tk5OXk5eXl5eXl5ubm5eXl5eXm5uXk5eTl5ubl5eXk5Obl5eTj5OXl5OTl
5uXm5ubl4+bl5uXl5ebk5uXl5eXm5uTm5ubn5ubm5uXn5ubm5ufl5ebm5uXm5+Xm
5ufm5+fm5ebm5ubn5ujn5ubl5ubn5ufn5ufn5+fn6Ojn5+fn5+jn5+fm5ufm5+fo
5+fn5+nn5ufn5+bm6Ofm6Ojn5+jo6ejn6Ofp6Ojo5+jo6ejo6Ojn5+jp6ejo6Ojo
6eno6Ojo6Onp6efn6ejo6Ojo6ejo6enp6Ojo6ejo6eno6ejp6eno6ejo6Ojn6Ono
6Ojp6enp6Ojp5+fo6Ojn6Ojo6ejo6ejo6enp6Ofo6ejo6ejp6Ojo6eno6ejp6erp
6Ono6Ojo6eno6eno6enq6erp6uno6ero6Orp6unp6erp6unq6unq6urp6uno6ero
6Orp5eno6erq6urp6unp6erp6Onr6erp6+nq6unq6enq6+nq6urp6urq6erp6urp
6urq6urq6urq6urq6+rp6+rq6uvq6Orq6unr6urs6urr6urp6unq6urq6urq6+rq
6erp6urp6urq6urq6urq6err6err6+rq6+rr6urq6+rr6urr6urq6+vq6uvq6+zq
6urr6uvr6+vq6+rr6urr6uvq6uvq6uvq6+vr6urq6err6evq6uvr6urr6urp6urq
6+rq6unp6urq6urq6urq6uvq6urq6+vr6+vr6+vr6uvs7Ovr6+rq6+vq6+vq6+vq
6+vq6+vr6urr6+zq6uzr6+zr6uvs6uvs6+zr6+zr6+zs6+vr6uzs7Ozs6+vq6+zr
6+zs6+zr6+zs6+zs7Ovr7Ovs7Ovs7Ozs7Ozs7Ozs7O3s7Ozs7Ozt7O3s7Ozs7u3t
7e3t7O3t7e3t7e3t7u3u7e3u7e3t7e3t7e7t7u7u7u7u7u3v7u3v7+/u7+7u7+7w
7+7u7u/w8O7v7+/w8O/x8PDv8PDw8fHw7/Dv8fHx8fDx8fHx8fHx8fHw8fHx8vLy
8vLxs6+qpqGcmJWRkI6Oj5CQkZOVl5mbnaCipKepq62wsrS2uLu9vsDDxMXGx8jI
yszNzc7P0NDS0tLU1dXY2NjY2dnc3Nvc3Nzc3Nzd3d3d3t7e397e4N/f39/g4eHh
4OLg4eHh4eHi4eLh4uDh4uHi4eLi4uPi4+Hh4ePh4uHi4+Lh4uLj4uLi4uPi4uLj
4uPi4uLi4uLi4+Pi4uPi4uHi4uPj4uLj4uLi4uPh4eLi4uLi4+Li4+Pj4+Li4+Pj
4uLi4uLi4uPi4+Lh4uHi4uLi4uPi4eHi4eDh4eHf4eHh4eLi4OLh4ODg4eDh4eHh
4eDh4eDh4eLf4eHg4N/h4ODi4ODg4OHh4eDg4OHh4eDh4uDg4uHi4eLg4OHh4eDh
4OHg4uHh4eHh4eDg4eHi4eHi4eHi4eLh4uLi4uHi4uLi4uPj4uPj4uHi5OPk4+Pj
4+Pj4uPk5OLi5OPj4+Pk5OTi4+Pj5OPk5OPj5OPk5OPk5OTk5OXk5OTk4+Tl5eTk
5eXk4+Tk5OTk5OXk5OXl5eXk5eXm5eXk5OXk5uXl5ebl5uXl5ubn5eXm5ubl5ubm
5uXl5eXm5uXm5uXl5eXl5eXk5eXm5uXl5ubn5ubl5ubl5+Xm5ubm5ubn5ubn5efm
5+fm5ubn5+fn6Ofn5+fm5ufo5ubn5+bm5+fn5+fn5+fn5+jm6Ofn5ujn5+fn5+fn
6Ojo6Ojn6Ojn5+jo6Ofn6Ofo5+fn5+jo6Ofo5+jn5+jn5+jn5+jn6Ojo5+jo6Ono
5+no6Ofo6Ojo6Ofp6ejn6Ojo6Onn6Onp6enp6eno6efo5+jo6Ono6Ojo6enp6Ojo
6enp6enp6Ojq6Ojo6eno6Onp6ejp6unp6ujq6unq6enp6Ojp6Orp6Onp6enq6enq
6eno6Onp6eno6ejp6eno6Onp6erp6ejq6eno6erp6enp6enq6urp6Onq6unp6urp
6+nq6enp6enq6unp6erp6+nq6enp6unp6enp6erq6unr6uvq6erp6+rp6erp6unq
6urq6urp6urq6err6uvq6urq6urp6+rq6uvr6uvq6+rp6urq6urq6uvp6+nq6urr
6unq6+vq6+rr6urq6urq6uvq6urp6urq6urr6urq6urq6urr6+rr6urq6uvq6urr
6uvq6erq6uvr6+rr6urr7Ovq6uvr6+vr6+vq6+vr6+rq6+rr6+vr6urq6+vr6uvq
6uvq6+vq6+zq6uvr6+rq6uvq6+rq6urr6+vq6urq6+rq6urq6uvr6+vq6+rq6uvr
6+zr6+vr6uvr6+vr6+vs6+vr6+vr7Ozr7Orr7evr6+rr6uvs6+vr6+rq6+zs6+vs
7Ovs7Ozs7Ovs6+zs7Ozs7Ovs6+zs7Ovs7Ovs6+zs7O3s7Ovs7Ozr7Ozr7Ozs7Ozs
7O3s7O3s7e3t7Ozr7Ozs7uzt7ezs7O3t7uzs7e3t7uzt7ezu7e7t7u3u7u7u7e7u
7e7u7u/u7u/v7e/u7+7v7+/v7u/u7u/w7+/v7u/w7vHv7u/v7vDw8PDw8PHx8fHx
8PDw8fDx8PLx8vLx8fDw8fHy8vLy8vLy8/MAEAEAAAMAAAABBJcAAAEBAAMAAAAB
Bt4AAAECAAMAAAABAAgAAAEDAAMAAAABAAEAAAEGAAMAAAABAAEAAAERAAQAAAAQ
AB+FwAESAAMAAAABAAEAAAEVAAMAAAABAAEAAAEWAAMAAAABAG8AAAEXAAQAAAAQ
AB+GAAEaAAUAAAABAB+GQAEbAAUAAAABAB+GSAEcAAMAAAABAAEAAAEoAAMAAAAB
AAIAAAFTAAMAAAABAAEAAIdzAAcAAASkAB+GUAAAAAAAAAAIAAH9gQAD+voABfhz
AAf17AAJ82UAC/DeAA3uVwAP69AAEelJABPmwgAV5DsAF+G0ABnfLQAb3KYAHdof
AAH9eQAB/XkAAf15AAH9eQAB/XkAAf15AAH9eQAB/XkAAf15AAH9eQAB/XkAAf15
AAH9eQAB/XkAAf15AAGq2yWAAAAAIAAAJYAAAAAgAAAAAASkYXBwbAIgAABzY25y
R1JBWVhZWiAH0wAHAAEAAAAAAABhY3NwQVBQTAAAAABub25lAAAAAAAAAAAAAAAA
AAAAAAAA9tYAAQAAAADTLWFwcGyYcjd2/nI/x5EwPxA3BfUzAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAVkZXNjAAAA5AAAAEF3dHB0AAAAwAAAABRrVFJD
AAAA1AAAAA5jcHJ0AAAEYAAAAEFkc2NtAAABKAAAAzZYWVogAAAAAAAA81EAAQAA
AAEWzGN1cnYAAAAAAAAAAQHNAABkZXNjAAAAAAAAABVTY2FubmVyIEdyYXkgUHJv
ZmlsZQAAAAAAAAAAAAAAFVNjYW5uZXIgR3JheSBQcm9maWxlAAAAAG1sdWMAAAAA
AAAADwAAAAxlblVTAAAAKAAAAw5lc0VTAAAAMAAAAYpkYURLAAAAPAAAAjZkZURF
AAAAOgAAAeJmaUZJAAAAMgAAAMRmckZVAAAALgAAATBpdElUAAAALAAAAuJubE5M
AAAAKAAAAnJub05PAAAAKAAAAbpwdEJSAAAALgAAArRzdlNFAAAAOgAAAPZqYUpQ
AAAAGgAAAV5rb0tSAAAAGgAAApp6aFRXAAAAEgAAAXh6aENOAAAAGgAAAhwAUwBr
AGEAbgBuAGUAcgBpAG4AIABIAGEAcgBtAGEAYQAtAHAAcgBvAGYAaQBpAGwAaQBH
AHIA5QBzAGsAYQBsAGUAcAByAG8AZgBpAGwAIABmAPYAcgAgAEIAaQBsAGQAbADk
AHMAYQByAGUAUAByAG8AZgBpAGwAIABHAHIAaQBzACAAZAB1ACAAUwBjAGEAbgBu
AGUAdQByMLkwrTDjMMowsDDsMKQw1zDtMNUwoTCkMOtjg2PPVmhwcJaOgnJfaWPP
j/AAUABlAHIAZgBpAGwAIABHAHIAaQBzACAAcABhAHIAYQAgAEUAcwBjAOEAbgBl
AHIARwByAOUAdABvAG4AZQBzAGsAYQBuAG4AZQByAHAAcgBvAGYAaQBsAEcAcgBh
AHUAcwB0AHUAZgBlAG4ALQBQAHIAbwBmAGkAbAAgAGYA/AByACAAUwBjAGEAbgBu
AGUAcmJrY89O6gAgAEcAcgBhAHkAIGPPj/Blh072AEcAcgDlAHQAbwBuAGUAYgBl
AHMAawByAGkAdgBlAGwAcwBlACAAdABpAGwAIABTAGMAYQBuAG4AZQByAEcAcgBp
AGoAcwBwAHIAbwBmAGkAZQBsACAAUwBjAGEAbgBuAGUAcsKkzpCxCAAgAEcAcgBh
AHkAINUEuFzTDMd8AFAAZQByAGYAaQBsACAAQwBpAG4AegBhACAAZABlACAAUwBj
AGEAbgBuAGUAcgBQAHIAbwBmAGkAbABvACAARwByAGkAZwBpAG8AIABTAGMAYQBu
AG4AZQByAFMAYwBhAG4AbgBlAHIAIABHAHIAYQB5ACAAUAByAG8AZgBpAGwAZQAA
dGV4dAAAAABDb3B5cmlnaHQgMjAwMyBBcHBsZSBDb21wdXRlciBJbmMuLCBhbGwg
cmlnaHRzIHJlc2VydmVkLgAAAAA=

View File

@ -0,0 +1,136 @@
TUxOT1JVUFNUVlVRT1VYWVdXUlJUT1FPU1VPT01PUE9WVlFSUFJRTkxKTU1PTEtJ
R0JDR0RDQEBBQD8/PDs/PD0+Pz44NzY1NjY5ODw5OT08Nzk5ODs8QUNBQj9BQUND
QklLSk5KSU9TXlhLT0xWUlFaVFdMTVdVW1VgWVdWXV9dWFtWUlFSTkVERTk1NTUz
MzUzNjU0ODg1ODY2Nzk6PTo6P0NETE1JR1RSTFBISkpKVVVLSUpUTU5STVZRVFpT
Vk5XXGBYUFhVWFJTV19kXVdVUFdVVlZUW1xbWlhZV1pcWE9TWlRWWVlXUE1MTlJD
PDo8Ozo+P0pOTVhWVFJWW15oYFxbXlpUVlpZXFhYVVdXUFlcYFhUVFdaW1RQXVxc
XltXUVBSTU1RUVRYVVNNSU1RUFFWVFFST05QUk9OSU5QTk1KS1BVSkxLTE5LT1RO
VlRZWlZYVE1FRkVHR0ZLSU9LTlFOXWaJo7CspZ2WlZOJfXFmYmFqdG9eS0E+OTk4
ODtBQTw9Ojg5PD5EQT8/P0BAPDc6OEE+Pzo+QENAPDtBQENDRkNDR0A6QEQ8ODU0
MTQ3NTg3Mzc2NDg0OTs/RUpTS05JT1xYWVlUXFZWVVtdWVlXUE5TUlJQT1BUVlZR
VFVYW1NRTkxMUlZUUEtMTk9PTE1MSERESUpLSkxJRklJSUtLRkRJSEVCRENERUZE
QkNBQ0JEQ0FAPjk6PDo3OTc3ODU2ODY2NTc+Rk9YYmdqaGhna3B3e3x+gYGBgYaH
iYuKi4uKioWCfXdwbmpnaWlsb3eCiIuMjYmJjo6SkJCTl5ORjIaBfnZnVEc/Ojo6
ODo7P0RJSkxPUlVWWVhWVlVSVFFRT05JRkVARD5BPkBCRERDQ0ZGRUdFSUpKSkpK
SklOS0xNTkxOT05MS0tMTk9NT1ZWU1dZWl1eXWJkZ2hqbm91dXV4fH5/gYB/gYOC
hYmGiIiHh4iGh4qLi4qMjY2Li4uLjZKTlpeWlpSPjo+SkZOQkpGRlZiXlpaZmZuZ
mZibl5mZmJiampual5aYnKCpr7KqmImGiJWosbzAvLu5u7i1tbGwsbKzt7a8vcC/
vL29vr6/v7q8vLq8vrq4ube1tLe3t7S0ta2ysrK1tKyginBfXVhTUlBOTVBMTU9M
S0tLSUpLSkhJSkdPT05KSUdNS0lJSE1LSkxKTk9MTUtNSk9OTUxPUU5NUE9OT0xM
Tk5QUVFQUU9QUVJSVFVSUlNTU1JRTlJTUFBSVFRSUlFTT09RUlBSUVNTUU9QUVNV
VVVVUVFSU1FVU1JSUFFSU1hUUVFPUVRQUVJRU1NUVVZYWFZWWlhYVFFVWFhXVlhW
WFhaWltbWF5bV1dYVlhbWFZYWVlaWVlYV1laWVpZV1taWVlaWlpaWVtcXV1cXF1d
YF9dYF5dXV1dYF5bXV1cWlxWV1dYV1ZWWFdYV1ZZXIO9ydPa3uHk5efo6el7enh5
ent8eHd1dnl2dnh6enl4eXdwZ1pMR0VFSkVEQz09Q0hKQ0A/P0I/PEJCQT4+PTpA
RURFQ0RHQ0RBPT5ARkhJSkxMTk1JS05QTklKTk5QUVNUU1FXU1ddWVVRUFFTU1JQ
UlBQT0tRVVVVU1JSUFJNSktPT0tJSUhHREVFQ0dEQkNAPj0+PTw7Ozs6OTw2Nzk4
ODg6PDs5OTg3Nzs4Ojw7Ozw9PURBQkQ/RktGS0tISUpRVU5RTUpTT1lTV1VOVlNc
WV1cWVddY1xdXllPT1JVT0pAODc1MzU5Njc6OTs3Njg2NTc7ODg4OTg+Q0dPUEpH
VVRMUUxRSkpUTklOSVNSTU1KV1RSWlFYVFRVWVdNUFJeVFRVYWFdXVZQUVVYV1VZ
VFdYWVhZXGVhVlRbW1pXUU1LTFBMTkhAOTg6OTk7Q1BSVVldWFpeXmFhY2VjXlNR
U1BXWFVVUVZYWFdWU1NTVVZaV09WWVlaWlNQTUtOUE1OUlhZVFFXUE1NUFBQTlFS
UFJWTU1OS0pRSkVJUFBNSkpNUEtPVFVXV1lXVldXU0hGRUdJSVBJSUhOVE9RWnWU
qauroZiVkYl8c2xmY2VrdWlSQTs6Ozg7OTw8Oz08PDw7Ozw7PTtAPj09Pj1BQUJA
OTo+QUQ9OD1FQUM+RUJCOzY9Q0E4ODU0NDY2NjQ0MzI1Njg4Oz1ESkpISkpTWlhY
W1ZZV1hTVldOUVNOTE5OUlFQVFlYU01XV1dWU09MSktOUlRTUU1PT0xQTklFR0ZL
TU1LS0dHR0dJSkpGRUNGSExHQ0RDREVBQD9APz5AOzs+QD88Pjw4NjY0Njc5Nzg7
QUpTXmRmaGdoaGxwdHp7fXmBh4eHhoyQj5CNjYuJhYJ8dnN1b2xtbGtze4SJjI6M
iImOj5KUlpWVk5GQi4B3a11RRj5APkFAQUFCSEpLTVBQU1hYWFZWV1NRUlBQTkxJ
RkdDQT5AP0NDQkNARERJR0lJRkhHSUtQUE1MS0tNTExNTE1NT1FSUFBVVVVXWF1f
XmNjZGdsbG5zdXZ1dnt9f4CDg4F/goOFhYaGh4uHhoWJi4mKi4mIiouNjIuMkZGR
lpSUj5GQkpKSkpWTkpaXl5OVlpmbmpiYmZmZmJqWlZeYl5iZmp+jqrO5s6aTgXeB
mK64vby7urq9ure0srSztba1t7m9vsDDwr69vb+9uru+wL69vbi3tbSztbq1tLe4
rrOztrW1saylknplXFZUVVNPTU9PTk5NTU1NSkhISkpJR0lKS0lKUEpKS0xPTVBL
TUxKS01KTExMTkpPTktQUE5PT09QTU5NUFBSUlNST1BPT05ST05PUVFTVlJSU1NS
UlRTUVJTUVBRUU5RTlFSU1NQTk5NUFVTUlBSUVBRVFRTU1NSVFJQUlVUVlNUVFFS
UFNVU1JUVVVWVVZXV1VWV1dWVVVYWVhZW1pYWVtdXF5aW1hZWFZZWVhYWlpYV1dY
WFZXW1tZWFlYWVhWWVlZXFxcW11cXltcXltdXlxdX19dXl5bXVtbWFlYV1VXV1ZU
VlVVVVdgfLvJ0dre4eTm5+jp6nl7e3x7eHp6dnh5dnd4dXd4dnZ5cmlgUkhCQEJH
QEM/PkFCRERBQERDQz4/QkU7PD1CPkBBQUFAQEFDR0I9PENCR0dISEdJTklMT01P
UlFNUFBRUlJZVVVWV1ZUU1hSVFZVUlJTUlBRUVNTVFVSUFFOUE5NTExPTUtIREhH
RENDQkJFQj5APkE/Pz87Oj08Oz04Nzc4NzxBODQ1Nzc4Ozo6Ojg2OTs7Ozs+QT9D
SUdISEZGRkpQS01LRElHTEpLVVRaWVhZXFtZVlhgX1xXV1BVblVUSkA5NzQ1NDc1
NTQzNDQ0NDg1Njc2NTg7PD8+PkpJTUZNT0dPS1JNSFBLRkxIS0hLSk1UVFlgVl5X
UVJUVUxRT1ZVUlFZXVpWVFJTVllZV1dUVFtaWltfZl1VWFtcVlZVT0tTUElIR0Q5
NzY3Njk/SVJWWmxlWlxdWWBpYV9kV1JUUVJcWlhTT1NSV1pTVFNTVlVXVlZVWFJU
WlNPS01VVVpaWVVYV1VWUU5QTk5PUFVRTE1LS0xIRU5KSEpOTk1JR01MSVBVWlxT
VFhcWFpZTkdDQEFFS0VISElTUU9WYniWpqiooJeOhn92a2NgYGZwbV5JOzs/QkI7
ODs9OkA+PDw6OT1APj4+SDw6Oz4/QkA7O0A9Pz5CPDs8QTxDQkJJPzpBPzo8Ozg2
NzQ3NjczMjQ2Nzg7PT9HS0RJR01SUldSUE9OT01VWFJWVE5LTlFTUlBSVldSVFhW
VFJWUVBNTEhLTFJUTExNS05OSUZITE1LS0pKT0pGREVGRkdIRklKSUlERURCQ0NC
Q0E+PDk9QD9BPzw6ODo4OTo9Ojg5PUdQW2VqamlrbWttcnd6fH19fYKDiI2Ojo2N
jo6LjIiIhX58eXVzcW9sb3d/hIyOkI+Lio6QkZOYlpSTjYuHgXJkWE1IRD89QEJF
RUZMT0xPUVNUVlhaW1lXVVNSUlJPTUtNS0dDQUJEQkJDRUZGR0hFR0dHQ0dHSEtI
SEtJS05LS0xSUVNQTlFUUlVZWFlcXWFlZ2hsbW9zcnV8fH9+fX+AgYGBg4SEg4KD
hYOCh4eHh4eJi4qKi4uOjI2KjpGSlZWUmZaSkpeWkI6TmJWYmpiXmJiampuXnJmY
lpaZmJqYmZmbnJ2jrLGwsbSwopSDfIeXrLu/vr28urq4s7OzsrK0trW3ubu8v8G/
v7++vr27ur27vLy7ubW2uby7t7e1ube1tbe2tLW0sa+mmIFmWldXUlBRT0xOS0xO
TVJPTUtKR0lKTEpKTUpJSUlLTUxJTE1PUExJS0tNS0xOTU5MS0xLS09PUVFTUE9R
UFNSU1FRVFJNT09OTlBQUlNSUVBRT1JUVFFPUVRUUVNRUE5QUVFSUFFPSk5RUE9P
UVNTVlFRTFBPUVJSUlJRT09SUlBQUE9RUlJTVVVTVFVWV1ZYWFZYV1hVVVRTV1ta
W11bWVxaXV1aWlpcWllZWllaXV5bV1dXWFpZWldXWVpZVlVXWVlbXFxaXF9cX11f
XFxcX15iYWBdXFhaW1pfXFtZV1RWVllXU1NXW2Z9usjT2d/h4+bn6OnpeXp7enl7
d3t7enl6eHp4eHl1dG9rZFtRSkdDQkBAQUY/PEVESUREREM9QUFEQUVBPT9BPT8/
Pz8+QT5BRENHQkNFRkhJS0xNTkxQTE1SU1NQUlNRUlVWVVVZWlZVU1VWU1ZWVFJQ
VlJPUFNXWFZVU1RUUFFPTkxISEdJTEpGREJCQUBAQENHQj07PTo8OzU5Nzc4ODg3
Nzg1ODk4ODc5Ozg6ODk3OTk4PD5FQj5AQEBFREU/QlFPSklIR0dHSkxUU1xZUVVZ
YFhPU2BaV1RYUU9UWFZKQDo3NzI0NTAyNjQ0Ozg4Njc2Nzk5ODw6Ozo+S0ZLRUdF
Q1RMWlVMUU9KT0pPTFVWSlVTVFtTWlNUVlJSTFNOUlRQSlRUWVdaWVVSUldZWlVT
U1dUU1pdXFZXW15VVVVOTldSTUdHRzo2NzU2OTk+TV1eYmJYX11aYGleX2lYTVJR
Vl5gXFhRUVNYXFJSWl1ZVlFWWlJSU1JcVVhTTlhYWFNTU1lYVVhSTU9RUVRTT05F
SEhJRk9NS01OTU9KS1FJTFFRUlNUV1FTV1xdX1lRSERBQkJHRkpJRVJRU1dVYnqW
pKekno+Jg3pybWhkZW1yZ1BEPDw+PTs3PDpEQ0E9Ozs7PDs/PEdCOjk9Oz1AQkA9
QEFEQj06Ojw7PT9ASUhAPEFCPDg4OTczNDM2NDQ1MzU2ODk6PD5FRk1JUE5WXlJU
UkxMTFVVT1BSUFRVVk5ISlNVVVRWWFRUVltYWE9LTUtKSkxJSUhLTU9NSUlMTkxI
TU9NR0NHSElLS0xISkhKRkNBQ0RCREJCQz49PDtAPjw6ODg5PDs5Ozg2OkBLWGNo
am1tbWtubXB1enp7e36Bg4aGiZKRjo2NjY2LiIiFhoKCd3Vua25vdH2DjI6NjIyO
kpGQkpOVko+NiYN4aV5XU01LSUI+PUNHTFFSU05RUlVUWVtcXFZUUlFUU1FPTkxK
R0ZCQUBAQUFEQz5CR0pIR0hESUhHRElKSklLS05MUFJVU1JRU1VaWFxdX19iY2lr
bW9ycnR3enp5e318fX9/gH6Cg4SFgIOFhoeGh4mMiouOjo6PjY+MjY2RlJKSlJuX
lZSUlZaQkpKWl5qTk5aYmpqbm5yampyam5mWl5uenZ+lqK2ytby9tqmcmJiRjJit
uL6/vru6uLKuq62vs7a2t7e6u73BwcHAwcG/vcC9vLm4u7e4t7i4ur29urq4tre6
uLa5trWzs62onohtXFVUVFJRT01NS0tKS05RS0tKS0xPTklJS0pJSUdLTEtJTEpO
S0tHSUpNT05QTk5LS0xQTlBPUFJRTVBRTk9OT05PUlJPUlBQTk9QUFFRT1FRVVNU
VFRTUlFWU1JQU1JRUFNVV1RPT1BRT1FSUVNUU1JOTlBPUFBQU1RSUVBSUVNSUVNR
UVNVVFRTVVRWVFJTVlhXWVdXU1NTWFtbWl5dXFlZWFhZWFxYVlpYWFlbWVpZWVZX
V1dYWVhYWFdXVVRZW1pZWlxdW1peXl1cXGBgX19gYV9fW1pZW1lcW1hWVFVXVVlW
U1NVaoS8ytPa3uLk5+jo6el4eXh1eXh9eHt7e3t4eHZ1eHh0cm5jWEtLTEY/PTs8
P0NGSklGREVBOz0+RD9BRENAPkE/Oj0+P0A9Pz0+Q0NCQkRJSUlKSUtMTEpLTFBU
VlVUVlZSWVteXFpYU1RXWFlVWFlXV1VTVVJPUlZaVldTUVJRUVFOUE1KTE1LSElF
QUVEQkVCRUNERD8/Pjs8QDw6Ojo6Ozw5Nzk5PDc2NDQ4Ojg6OTk4Ojc4PEQ7Oj0/
PUNCRkNBSUtHSERJTEdKR1BLUVlVV1ZiV1BLU1JVVVZWU1RbWVBJQzo9NzY3NzYy
Mjc3ODg0MzU3OTk/Pjo8Oz1ERk9FRkVJSklXUkxWUVBRSlFPV1ZHTU9SXlVdVVdc
VlZMUk1QWVJRUFNZWF5eWU9PU1VWVFRSWFBPVllbWlZYWVdUVFFYXFhTUkxKQTo0
MjQ1OT5DVFhPV1paYFtgX15gX1FPUlRUWltbVlNPUVdWUlhXXVZVVldaVlNWVllZ
VFNPTVNRTVFPUlNUUVVUUlhVU1ZRS0lLRk1LSFFPTVFNTUpLT01LUlRMTVNVU1BU
V1tiWFVQSUNDQEVDSEhHVVJYWlBYXn6Ypqiil4qBfHp4cGttcHNtYFBDOz47Ojo3
OT07ODo7Oz88OjxAREA8Pj07OjxBQTw4PUFEQTxAPTtBRUVGR0U+QEI+ODUzMzc2
Njc4ODQxNDY3OTs8P0RKR0hSTlVfVVtRT09RU1VSUVJTU1JQS05OTVJXVVZUUVNY
VVRSTUxOSUtMSktKTEpJTEpKRkdLTE1NT01NSklJSktOTkpGREdGQUFERUREREI9
Pj4/Ozc5ODo5Njc6OTs5NzpBSlhja21vb3RxcHBucnp9eXl6fH+EhIWGjo2Njo+N
j4+MiYuLhH54cm5tb3BzfYaLjo6MjpKSkpORlJeWkpCHfnNrYVdWVVRMQj0/RE9V
UVJQUVFRVFtcXF1dXFlWVlZXV1FRTk9NS0VDQ0FBQUFAP0FER0dHR0dHSUhKSkxL
TEpJTlJOUFFUVlNWVltcYGBfZGhnaW5wcnR2dXh6eXt8f4GBgoKAg4GBgoODgoSE
iIiHio6Ni4+Sk46KjY6Qk5WVkpGUlJOSlpKSlJWTkpOYmJiYmZial5iZm5mZmpye
nZ+foKGip7Cyt7e5vLyznpKcn5aVorO5wcC/wLm2sa2rrK+zuLa4uL2/v768vMDA
wsG+wL68vra1tLK1tri8vbi6ubi2tre3tra1tbW4trGroY1tW1hUVFNNTk5KSktP
T0tLSkpMSktNTExLS0tLSkxKSUlMTUtLSk5JSE1OTk9MTE9RT0xNUFBRU1BPTU1P
UFBTUlFPUlFOUVNRUFFRUU9OUFFTU1NTUlNUVFJTUU5QUlJUVVRUU1ZST1BPUFFS
UVBOUVJPUFJSUFJRU1NRUFFSVFNSVFNUVFFRU1RXVlVXVFlYWFhZWFhVWFZUWFdX
XV1cWFdYWVdaWFdaVVVaWVlaWVdaWVlYVVdaWVlXWFlbWFdYWVpdW1xcXlpbX2Fj
YmBhYV9fX15cXl9aWFlVUFZWV1lYWVlXU1VvorzJ0tre4eTm5+jq6nl3d3l4d3h6
ent8fHh2dXN1d3NxbGFUSkdGSEM7Pj89QUhJRkZFQ0RFQ0JCQj09PTg8PUE7Oj4+
Qz0/QEFDQkVHR0pJSUxLTU1MTExLT1FSVFNTVVRVWFdXV1ZRUlNWVlVXWFlXWlta
VFZXWlxZV1VTVVBTUU1NTEtNS05MR0pMSEVER0ZISEVERD4+Ozs6Ozs6OTk6Ojc1
NTY5ODY2Njg2NzY4ODk3PDo4Pjw8PD9CRUFBPT5GRkVLTEZLTVFKSkxSW1daV11Z
SlJWVlNSV1pUU1dXVlZQQjo7OTU1NDMyNjc0NTZINzc3OTo8PT07QUJDUkpOS0hN
R1RRTlRQTlFIUFJVVEhSUVJgV1ZSWmFeYFJVTk5VUlJQV1lUVVZQSk5OUVZYVFBP
UFNUWV1XUlRZWFlXVFVcXlpWWFBCOTIyMzc2PUNNV01TWlpbW1paXl1VVFZXVVZZ
V1lcUk1OU1BVXVlaVlNTUVNYVVVbUk9VT05JTE9SUU9QUVZVUlNVWFlUS05LTFFU
V09SUFNSUVRNSkpNUk5OV1FNVFpSTlRcYVxYW1FKQ0JER0NFR0hTTFFUTlVWbYma
paOelImBfXx7dnRxcXBpWkY9Oj1COTQ5Ozs7QTk6Pzw7Ozs/QEJDPDo6PkBFPjtA
QkRFQjk6PUJGREZEQkFCRj04MzQ1ODk1NTM5NzQ0NTk6Oj49P0JFSFRRWFlSXFNS
VlZXVVRTU1ZTUFNNTU5PUFRUV1lRTk5SU09MTU5PUVBKS01MSkhIS0pJR0hDR0tL
TUtFSk1OS0tIR0VHRkhEQ0NGRENBPj89PT87PDs4Ojw4OTo4Njk9QUxZZG1vb3By
cnFzcnR2fH99eHh7gISHjJKJjpGRk5WSkpKOiomIgHx0cm5vcXV+hIeLjo+SlZiY
mJWUlZmSjIJ4cG1jVE5NTkxIQ0ZMVFhXVldUVldYXWBiX19gXFxbWlhXU1FPTk1L

View File

@ -0,0 +1,136 @@
TUxOT1JVUFNUVlVRT1VYWVdXUlJUT1FPU1VPT01PUE9WVlFSUFJRTkxKTU1PTEtJ
R0JDR0RDQEBBQD8/PDs/PD0+Pz44NzY1NjY5ODw5OT08Nzk5ODs8QUNBQj9BQUND
QklLSk5KSU9TXlhLT0xWUlFaVFdMTVdVW1VgWVdWXV9dWFtWUlFSTkVERTk1NTUz
MzUzNjU0ODg1ODY2Nzk6PTo6P0NETE1JR1RSTFBISkpKVVVLSUpUTU5STVZRVFpT
Vk5XXGBYUFhVWFJTV19kXVdVUFdVVlZUW1xbWlhZV1pcWE9TWlRWWVlXUE1MTlJD
PDo8Ozo+P0pOTVhWVFJWW15oYFxbXlpUVlpZXFhYVVdXUFlcYFhUVFdaW1RQXVxc
XltXUVBSTU1RUVRYVVNNSU1RUFFWVFFST05QUk9OSU5QTk1KS1BVSkxLTE5LT1RO
VlRZWlZYVE1FRkVHR0ZLSU9LTlFOXWaJo7CspZ2WlZOJfXFmYmFqdG9eS0E+OTk4
ODtBQTw9Ojg5PD5EQT8/P0BAPDc6OEE+Pzo+QENAPDtBQENDRkNDR0A6QEQ8ODU0
MTQ3NTg3Mzc2NDg0OTs/RUpTS05JT1xYWVlUXFZWVVtdWVlXUE5TUlJQT1BUVlZR
VFVYW1NRTkxMUlZUUEtMTk9PTE1MSERESUpLSkxJRklJSUtLRkRJSEVCRENERUZE
QkNBQ0JEQ0FAPjk6PDo3OTc3ODU2ODY2NTc+Rk9YYmdqaGhna3B3e3x+gYGBgYaH
iYuKi4uKioWCfXdwbmpnaWlsb3eCiIuMjYmJjo6SkJCTl5ORjIaBfnZnVEc/Ojo6
ODo7P0RJSkxPUlVWWVhWVlVSVFFRT05JRkVARD5BPkBCRERDQ0ZGRUdFSUpKSkpK
SklOS0xNTkxOT05MS0tMTk9NT1ZWU1dZWl1eXWJkZ2hqbm91dXV4fH5/gYB/gYOC
hYmGiIiHh4iGh4qLi4qMjY2Li4uLjZKTlpeWlpSPjo+SkZOQkpGRlZiXlpaZmZuZ
mZibl5mZmJiampual5aYnKCpr7KqmImGiJWosbzAvLu5u7i1tbGwsbKzt7a8vcC/
vL29vr6/v7q8vLq8vrq4ube1tLe3t7S0ta2ysrK1tKyginBfXVhTUlBOTVBMTU9M
S0tLSUpLSkhJSkdPT05KSUdNS0lJSE1LSkxKTk9MTUtNSk9OTUxPUU5NUE9OT0xM
Tk5QUVFQUU9QUVJSVFVSUlNTU1JRTlJTUFBSVFRSUlFTT09RUlBSUVNTUU9QUVNV
VVVVUVFSU1FVU1JSUFFSU1hUUVFPUVRQUVJRU1NUVVZYWFZWWlhYVFFVWFhXVlhW
WFhaWltbWF5bV1dYVlhbWFZYWVlaWVlYV1laWVpZV1taWVlaWlpaWVtcXV1cXF1d
YF9dYF5dXV1dYF5bXV1cWlxWV1dYV1ZWWFdYV1ZZXIO9ydPa3uHk5efo6el7enh5
ent8eHd1dnl2dnh6enl4eXdwZ1pMR0VFSkVEQz09Q0hKQ0A/P0I/PEJCQT4+PTpA
RURFQ0RHQ0RBPT5ARkhJSkxMTk1JS05QTklKTk5QUVNUU1FXU1ddWVVRUFFTU1JQ
UlBQT0tRVVVVU1JSUFJNSktPT0tJSUhHREVFQ0dEQkNAPj0+PTw7Ozs6OTw2Nzk4
ODg6PDs5OTg3Nzs4Ojw7Ozw9PURBQkQ/RktGS0tISUpRVU5RTUpTT1lTV1VOVlNc
WV1cWVddY1xdXllPT1JVT0pAODc1MzU5Njc6OTs3Njg2NTc7ODg4OTg+Q0dPUEpH
VVRMUUxRSkpUTklOSVNSTU1KV1RSWlFYVFRVWVdNUFJeVFRVYWFdXVZQUVVYV1VZ
VFdYWVhZXGVhVlRbW1pXUU1LTFBMTkhAOTg6OTk7Q1BSVVldWFpeXmFhY2VjXlNR
U1BXWFVVUVZYWFdWU1NTVVZaV09WWVlaWlNQTUtOUE1OUlhZVFFXUE1NUFBQTlFS
UFJWTU1OS0pRSkVJUFBNSkpNUEtPVFVXV1lXVldXU0hGRUdJSVBJSUhOVE9RWnWU
qauroZiVkYl8c2xmY2VrdWlSQTs6Ozg7OTw8Oz08PDw7Ozw7PTtAPj09Pj1BQUJA
OTo+QUQ9OD1FQUM+RUJCOzY9Q0E4ODU0NDY2NjQ0MzI1Njg4Oz1ESkpISkpTWlhY
W1ZZV1hTVldOUVNOTE5OUlFQVFlYU01XV1dWU09MSktOUlRTUU1PT0xQTklFR0ZL
TU1LS0dHR0dJSkpGRUNGSExHQ0RDREVBQD9APz5AOzs+QD88Pjw4NjY0Njc5Nzg7
QUpTXmRmaGdoaGxwdHp7fXmBh4eHhoyQj5CNjYuJhYJ8dnN1b2xtbGtze4SJjI6M
iImOj5KUlpWVk5GQi4B3a11RRj5APkFAQUFCSEpLTVBQU1hYWFZWV1NRUlBQTkxJ
RkdDQT5AP0NDQkNARERJR0lJRkhHSUtQUE1MS0tNTExNTE1NT1FSUFBVVVVXWF1f
XmNjZGdsbG5zdXZ1dnt9f4CDg4F/goOFhYaGh4uHhoWJi4mKi4mIiouNjIuMkZGR
lpSUj5GQkpKSkpWTkpaXl5OVlpmbmpiYmZmZmJqWlZeYl5iZmp+jqrO5s6aTgXeB
mK64vby7urq9ure0srSztba1t7m9vsDDwr69vb+9uru+wL69vbi3tbSztbq1tLe4
rrOztrW1saylknplXFZUVVNPTU9PTk5NTU1NSkhISkpJR0lKS0lKUEpKS0xPTVBL
TUxKS01KTExMTkpPTktQUE5PT09QTU5NUFBSUlNST1BPT05ST05PUVFTVlJSU1NS
UlRTUVJTUVBRUU5RTlFSU1NQTk5NUFVTUlBSUVBRVFRTU1NSVFJQUlVUVlNUVFFS
UFNVU1JUVVVWVVZXV1VWV1dWVVVYWVhZW1pYWVtdXF5aW1hZWFZZWVhYWlpYV1dY
WFZXW1tZWFlYWVhWWVlZXFxcW11cXltcXltdXlxdX19dXl5bXVtbWFlYV1VXV1ZU
VlVVVVdgfLvJ0dre4eTm5+jp6nl7e3x7eHp6dnh5dnd4dXd4dnZ5cmlgUkhCQEJH
QEM/PkFCRERBQERDQz4/QkU7PD1CPkBBQUFAQEFDR0I9PENCR0dISEdJTklMT01P
UlFNUFBRUlJZVVVWV1ZUU1hSVFZVUlJTUlBRUVNTVFVSUFFOUE5NTExPTUtIREhH
RENDQkJFQj5APkE/Pz87Oj08Oz04Nzc4NzxBODQ1Nzc4Ozo6Ojg2OTs7Ozs+QT9D
SUdISEZGRkpQS01LRElHTEpLVVRaWVhZXFtZVlhgX1xXV1BVblVUSkA5NzQ1NDc1
NTQzNDQ0NDg1Njc2NTg7PD8+PkpJTUZNT0dPS1JNSFBLRkxIS0hLSk1UVFlgVl5X
UVJUVUxRT1ZVUlFZXVpWVFJTVllZV1dUVFtaWltfZl1VWFtcVlZVT0tTUElIR0Q5
NzY3Njk/SVJWWmxlWlxdWWBpYV9kV1JUUVJcWlhTT1NSV1pTVFNTVlVXVlZVWFJU
WlNPS01VVVpaWVVYV1VWUU5QTk5PUFVRTE1LS0xIRU5KSEpOTk1JR01MSVBVWlxT
VFhcWFpZTkdDQEFFS0VISElTUU9WYniWpqiooJeOhn92a2NgYGZwbV5JOzs/QkI7
ODs9OkA+PDw6OT1APj4+SDw6Oz4/QkA7O0A9Pz5CPDs8QTxDQkJJPzpBPzo8Ozg2
NzQ3NjczMjQ2Nzg7PT9HS0RJR01SUldSUE9OT01VWFJWVE5LTlFTUlBSVldSVFhW
VFJWUVBNTEhLTFJUTExNS05OSUZITE1LS0pKT0pGREVGRkdIRklKSUlERURCQ0NC
Q0E+PDk9QD9BPzw6ODo4OTo9Ojg5PUdQW2VqamlrbWttcnd6fH19fYKDiI2Ojo2N
jo6LjIiIhX58eXVzcW9sb3d/hIyOkI+Lio6QkZOYlpSTjYuHgXJkWE1IRD89QEJF
RUZMT0xPUVNUVlhaW1lXVVNSUlJPTUtNS0dDQUJEQkJDRUZGR0hFR0dHQ0dHSEtI
SEtJS05LS0xSUVNQTlFUUlVZWFlcXWFlZ2hsbW9zcnV8fH9+fX+AgYGBg4SEg4KD
hYOCh4eHh4eJi4qKi4uOjI2KjpGSlZWUmZaSkpeWkI6TmJWYmpiXmJiampuXnJmY
lpaZmJqYmZmbnJ2jrLGwsbSwopSDfIeXrLu/vr28urq4s7OzsrK0trW3ubu8v8G/
v7++vr27ur27vLy7ubW2uby7t7e1ube1tbe2tLW0sa+mmIFmWldXUlBRT0xOS0xO
TVJPTUtKR0lKTEpKTUpJSUlLTUxJTE1PUExJS0tNS0xOTU5MS0xLS09PUVFTUE9R
UFNSU1FRVFJNT09OTlBQUlNSUVBRT1JUVFFPUVRUUVNRUE5QUVFSUFFPSk5RUE9P
UVNTVlFRTFBPUVJSUlJRT09SUlBQUE9RUlJTVVVTVFVWV1ZYWFZYV1hVVVRTV1ta
W11bWVxaXV1aWlpcWllZWllaXV5bV1dXWFpZWldXWVpZVlVXWVlbXFxaXF9cX11f
XFxcX15iYWBdXFhaW1pfXFtZV1RWVllXU1NXW2Z9usjT2d/h4+bn6OnpeXp7enl7
d3t7enl6eHp4eHl1dG9rZFtRSkdDQkBAQUY/PEVESUREREM9QUFEQUVBPT9BPT8/
Pz8+QT5BRENHQkNFRkhJS0xNTkxQTE1SU1NQUlNRUlVWVVVZWlZVU1VWU1ZWVFJQ
VlJPUFNXWFZVU1RUUFFPTkxISEdJTEpGREJCQUBAQENHQj07PTo8OzU5Nzc4ODg3
Nzg1ODk4ODc5Ozg6ODk3OTk4PD5FQj5AQEBFREU/QlFPSklIR0dHSkxUU1xZUVVZ
YFhPU2BaV1RYUU9UWFZKQDo3NzI0NTAyNjQ0Ozg4Njc2Nzk5ODw6Ozo+S0ZLRUdF
Q1RMWlVMUU9KT0pPTFVWSlVTVFtTWlNUVlJSTFNOUlRQSlRUWVdaWVVSUldZWlVT
U1dUU1pdXFZXW15VVVVOTldSTUdHRzo2NzU2OTk+TV1eYmJYX11aYGleX2lYTVJR
Vl5gXFhRUVNYXFJSWl1ZVlFWWlJSU1JcVVhTTlhYWFNTU1lYVVhSTU9RUVRTT05F
SEhJRk9NS01OTU9KS1FJTFFRUlNUV1FTV1xdX1lRSERBQkJHRkpJRVJRU1dVYnqW
pKekno+Jg3pybWhkZW1yZ1BEPDw+PTs3PDpEQ0E9Ozs7PDs/PEdCOjk9Oz1AQkA9
QEFEQj06Ojw7PT9ASUhAPEFCPDg4OTczNDM2NDQ1MzU2ODk6PD5FRk1JUE5WXlJU
UkxMTFVVT1BSUFRVVk5ISlNVVVRWWFRUVltYWE9LTUtKSkxJSUhLTU9NSUlMTkxI
TU9NR0NHSElLS0xISkhKRkNBQ0RCREJCQz49PDtAPjw6ODg5PDs5Ozg2OkBLWGNo
am1tbWtubXB1enp7e36Bg4aGiZKRjo2NjY2LiIiFhoKCd3Vua25vdH2DjI6NjIyO
kpGQkpOVko+NiYN4aV5XU01LSUI+PUNHTFFSU05RUlVUWVtcXFZUUlFUU1FPTkxK
R0ZCQUBAQUFEQz5CR0pIR0hESUhHRElKSklLS05MUFJVU1JRU1VaWFxdX19iY2lr
bW9ycnR3enp5e318fX9/gH6Cg4SFgIOFhoeGh4mMiouOjo6PjY+MjY2RlJKSlJuX
lZSUlZaQkpKWl5qTk5aYmpqbm5yampyam5mWl5uenZ+lqK2ytby9tqmcmJiRjJit
uL6/vru6uLKuq62vs7a2t7e6u73BwcHAwcG/vcC9vLm4u7e4t7i4ur29urq4tre6
uLa5trWzs62onohtXFVUVFJRT01NS0tKS05RS0tKS0xPTklJS0pJSUdLTEtJTEpO
S0tHSUpNT05QTk5LS0xQTlBPUFJRTVBRTk9OT05PUlJPUlBQTk9QUFFRT1FRVVNU
VFRTUlFWU1JQU1JRUFNVV1RPT1BRT1*SUVNUU1JOTlBPUFBQU1RSUVBSUVNSUVNR
UVNVVFRTVVRWVFJTVlhXWVdXU1NTWFtbWl5dXFlZWFhZWFxYVlpYWFlbWVpZWVZX
V1dYWVhYWFdXVVRZW1pZWlxdW1peXl1cXGBgX19gYV9fW1pZW1lcW1hWVFVXVVlW
U1NVaoS8ytPa3uLk5+jo6el4eXh1eXh9eHt7e3t4eHZ1eHh0cm5jWEtLTEY/PTs8
P0NGSklGREVBOz0+RD9BRENAPkE/Oj0+P0A9Pz0+Q0NCQkRJSUlKSUtMTEpLTFBU
VlVUVlZSWVteXFpYU1RXWFlVWFlXV1VTVVJPUlZaVldTUVJRUVFOUE1KTE1LSElF
QUVEQkVCRUNERD8/Pjs8QDw6Ojo6Ozw5Nzk5PDc2NDQ4Ojg6OTk4Ojc4PEQ7Oj0/
PUNCRkNBSUtHSERJTEdKR1BLUVlVV1ZiV1BLU1JVVVZWU1RbWVBJQzo9NzY3NzYy
Mjc3ODg0MzU3OTk/Pjo8Oz1ERk9FRkVJSklXUkxWUVBRSlFPV1ZHTU9SXlVdVVdc
VlZMUk1QWVJRUFNZWF5eWU9PU1VWVFRSWFBPVllbWlZYWVdUVFFYXFhTUkxKQTo0
MjQ1OT5DVFhPV1paYFtgX15gX1FPUlRUWltbVlNPUVdWUlhXXVZVVldaVlNWVllZ
VFNPTVNRTVFPUlNUUVVUUlhVU1ZRS0lLRk1LSFFPTVFNTUpLT01LUlRMTVNVU1BU
V1tiWFVQSUNDQEVDSEhHVVJYWlBYXn6Ypqiil4qBfHp4cGttcHNtYFBDOz47Ojo3
OT07ODo7Oz88OjxAREA8Pj07OjxBQTw4PUFEQTxAPTtBRUVGR0U+QEI+ODUzMzc2
Njc4ODQxNDY3OTs8P0RKR0hSTlVfVVtRT09RU1VSUVJTU1JQS05OTVJXVVZUUVNY
VVRSTUxOSUtMSktKTEpJTEpKRkdLTE1NT01NSklJSktOTkpGREdGQUFERUREREI9
Pj4/Ozc5ODo5Njc6OTs5NzpBSlhja21vb3RxcHBucnp9eXl6fH+EhIWGjo2Njo+N
j4+MiYuLhH54cm5tb3BzfYaLjo6MjpKSkpORlJeWkpCHfnNrYVdWVVRMQj0/RE9V
UVJQUVFRVFtcXF1dXFlWVlZXV1FRTk9NS0VDQ0FBQUFAP0FER0dHR0dHSUhKSkxL
TEpJTlJOUFFUVlNWVltcYGBfZGhnaW5wcnR2dXh6eXt8f4GBgoKAg4GBgoODgoSE
iIiHio6Ni4+Sk46KjY6Qk5WVkpGUlJOSlpKSlJWTkpOYmJiYmZial5iZm5mZmpye
nZ+foKGip7Cyt7e5vLyznpKcn5aVorO5wcC/wLm2sa2rrK+zuLa4uL2/v768vMDA
wsG+wL68vra1tLK1tri8vbi6ubi2tre3tra1tbW4trGroY1tW1hUVFNNTk5KSktP
T0tLSkpMSktNTExLS0tLSkxKSUlMTUtLSk5JSE1OTk9MTE9RT0xNUFBRU1BPTU1P
UFBTUlFPUlFOUVNRUFFRUU9OUFFTU1NTUlNUVFJTUU5QUlJUVVRUU1ZST1BPUFFS
UVBOUVJPUFJSUFJRU1NRUFFSVFNSVFNUVFFRU1RXVlVXVFlYWFhZWFhVWFZUWFdX
XV1cWFdYWVdaWFdaVVVaWVlaWVdaWVlYVVdaWVlXWFlbWFdYWVpdW1xcXlpbX2Fj
YmBhYV9fX15cXl9aWFlVUFZWV1lYWVlXU1V#orzJ0tre4eTm5+jq6nl3d3l4d3h6
ent8fHh2dXN1d3NxbGFUSkdGSEM7Pj89QUhJRkZFQ0RFQ0JCQj09PTg8PUE7Oj4+
Qz0/QEFDQkVHR0pJSUxLTU1MTExLT1FSVFNTVVRVWFdXV1ZRUlNWVlVXWFlXWlta
VFZXWlxZV1VTVVBTUU1NTEtNS05MR0pMSEVER0ZISEVERD4+Ozs6Ozs6OTk6Ojc1
NTY5ODY2Njg2NzY4ODk3PDo4Pjw8PD9CRUFBPT5GRkVLTEZLTVFKSkxSW1daV11Z
SlJWVlNSV1pUU1dXVlZQQjo7OTU1NDMyNjc0NTZINzc3OTo8PT07QUJDUkpOS0hN
R1RRTlRQTlFIUFJVVEhSUVJgV1ZSWmFeYFJVTk5VUlJQV1lUVVZQSk5OUVZYVFBP
UFNUWV1XUlRZWFlXVFVcXlpWWFBCOTIyMzc2PUNNV01TWlpbW1paXl1VVFZXVVZZ
V1lcUk1OU1BVXVlaVlNTUVNYVVVbUk9VT05JTE9SUU9QUVZVUlNVWFlUS05LTFFU
V09SUFNSUVRNSkpNUk5OV1FNVFpSTlRcYVxYW1FKQ0JER0NFR0hTTFFUTlVWbYma
paOelImBfXx7dnRxcXBpWkY9Oj1COTQ5Ozs7QTk6Pzw7Ozs/QEJDPDo6PkBFPjtA
QkRFQjk6PUJGREZEQkFCRj04MzQ1ODk1NTM5NzQ0NTk6Oj49P0JFSFRRWFlSXFNS
VlZXVVRTU1ZTUFNNTU5PUFRUV1lRTk5SU09MTU5PUVBKS01MSkhIS0pJR0hDR0tL
TUtFSk1OS0tIR0VHRkhEQ0NGRENBPj89PT87PDs4Ojw4OTo4Njk9QUxZZG1vb3By
cnFzcnR2fH99eHh7gISHjJKJjpGRk5WSkpKOiomIgHx0cm5vcXV+hIeLjo+SlZiY
mJWUlZmSjIJ4cG1jVE5NTkxIQ0ZMVFhXVldUVldYXWBiX19gXFxbWlhXU1FPTk1L