mirror of
https://github.com/boostorg/algorithm.git
synced 2025-06-25 12:01:39 +02:00
Compare commits
9 Commits
boost-1.50
...
boost-1.51
Author | SHA1 | Date | |
---|---|---|---|
b613c29c1e | |||
6341cfb1a6 | |||
7f4acd6170 | |||
314f6dcfe0 | |||
167aa6e31c | |||
d228e91494 | |||
9cc573fbd0 | |||
28a7d3eb4b | |||
883cce61a8 |
@ -66,12 +66,12 @@ If you want to catch all the decoding errors, you can catch exceptions of type `
|
||||
Assuming that `out` is an iterator that accepts `char` values, and `wout` accepts `wchar_t` values (and that sizeof ( wchar_t ) == 2)
|
||||
|
||||
``
|
||||
hex ( "abcde", out ) --> "616263646566"
|
||||
hex ( "abcdef", out ) --> "616263646566"
|
||||
hex ( "32", out ) --> "3332"
|
||||
hex ( "abcde", wout ) --> "006100620063006400650066"
|
||||
hex ( "abcdef", wout ) --> "006100620063006400650066"
|
||||
hex ( "32", wout ) --> "00330032"
|
||||
|
||||
unhex ( "616263646566", out ) --> "abcde"
|
||||
unhex ( "616263646566", out ) --> "abcdef"
|
||||
unhex ( "3332", out ) --> "32"
|
||||
unhex ( "616263646566", wout ) --> "\6162\6364\6566" ( i.e, a 3 character string )
|
||||
unhex ( "3332", wout ) --> "\3233" ( U+3332, SQUARE HUARADDO )
|
||||
|
@ -38,7 +38,9 @@ Iterator requirements: The `is_sorted` functions will work on all kinds of itera
|
||||
|
||||
[heading is_sorted_until]
|
||||
|
||||
The function `is_sorted_until(sequence, predicate)` compares each sequential pair of elements in the sequence, checking if they satisfy the predicate. it returns the first element of the sequence that does not satisfy the predicate with its' predecessor. In short, it returns the element in the sequence that is "out of order". If all adjacent pairs satisfy the predicate, then it will return one past the last element of the sequence.
|
||||
If `distance(first, last) < 2`, then `is_sorted ( first, last )` returns `last`. Otherwise, it returns the last iterator i in [first,last] for which the range [first,i) is sorted.
|
||||
|
||||
In short, it returns the element in the sequence that is "out of order". If the entire sequence is sorted (according to the predicate), then it will return `last`.
|
||||
|
||||
``
|
||||
namespace boost { namespace algorithm {
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of iota if it is available
|
||||
// Use the C++11 versions of is_partitioned if it is available
|
||||
using std::is_partitioned; // Section 25.3.13
|
||||
#else
|
||||
/// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
|
||||
|
@ -27,7 +27,7 @@
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of iota if it is available
|
||||
// Use the C++11 versions of is_sorted/is_sorted_until if they are available
|
||||
using std::is_sorted_until; // Section 25.4.1.5
|
||||
using std::is_sorted; // Section 25.4.1.5
|
||||
#else
|
||||
@ -46,7 +46,7 @@ using std::is_sorted; // Section 25.4.1.5
|
||||
ForwardIterator next = first;
|
||||
while ( ++next != last )
|
||||
{
|
||||
if ( !p ( *first, *next ))
|
||||
if ( p ( *next, *first ))
|
||||
return next;
|
||||
first = next;
|
||||
}
|
||||
@ -63,7 +63,7 @@ using std::is_sorted; // Section 25.4.1.5
|
||||
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>());
|
||||
return boost::algorithm::is_sorted_until ( first, last, std::less<value_type>());
|
||||
}
|
||||
|
||||
|
||||
@ -125,10 +125,6 @@ using std::is_sorted; // Section 25.4.1.5
|
||||
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
typedef struct { typedef bool type; } bool_;
|
||||
};
|
||||
|
||||
/// \fn is_sorted ( const R &range, Pred p )
|
||||
/// \return whether or not the entire range R is sorted
|
||||
/// (according to the comparison predicate 'p').
|
||||
@ -173,7 +169,7 @@ namespace detail {
|
||||
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>());
|
||||
return boost::algorithm::is_sorted (first, last, std::less<value_type>());
|
||||
}
|
||||
|
||||
|
||||
@ -206,7 +202,7 @@ namespace detail {
|
||||
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>());
|
||||
return boost::algorithm::is_sorted (first, last, std::greater<value_type>());
|
||||
}
|
||||
|
||||
/// \fn is_decreasing ( const R &range )
|
||||
@ -238,7 +234,7 @@ namespace detail {
|
||||
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>());
|
||||
return boost::algorithm::is_sorted (first, last, std::less_equal<value_type>());
|
||||
}
|
||||
|
||||
/// \fn is_strictly_increasing ( const R &range )
|
||||
@ -269,7 +265,7 @@ namespace detail {
|
||||
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>());
|
||||
return boost::algorithm::is_sorted (first, last, std::greater_equal<value_type>());
|
||||
}
|
||||
|
||||
/// \fn is_strictly_decreasing ( const R &range )
|
||||
|
@ -51,14 +51,10 @@ namespace boost { namespace algorithm {
|
||||
\brief Thrown when the input sequence unexpectedly ends
|
||||
|
||||
*/
|
||||
struct hex_decode_error: virtual boost::exception, virtual std::exception {};
|
||||
struct not_enough_input : public hex_decode_error {};
|
||||
struct non_hex_input : public hex_decode_error {
|
||||
non_hex_input ( char ch ) : bad_char ( ch ) {}
|
||||
char bad_char;
|
||||
private:
|
||||
non_hex_input (); // don't allow creation w/o a char
|
||||
};
|
||||
struct hex_decode_error : virtual boost::exception, virtual std::exception {};
|
||||
struct not_enough_input : virtual hex_decode_error {};
|
||||
struct non_hex_input : virtual hex_decode_error {};
|
||||
typedef boost::error_info<struct bad_char_,char> bad_char;
|
||||
|
||||
namespace detail {
|
||||
/// \cond DOXYGEN_HIDE
|
||||
@ -77,7 +73,7 @@ namespace detail {
|
||||
if ( c >= '0' && c <= '9' ) return c - '0';
|
||||
if ( c >= 'A' && c <= 'F' ) return c - 'A' + 10;
|
||||
if ( c >= 'a' && c <= 'f' ) return c - 'a' + 10;
|
||||
BOOST_THROW_EXCEPTION (non_hex_input (c));
|
||||
BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));
|
||||
return 0; // keep dumb compilers happy
|
||||
}
|
||||
|
||||
@ -114,33 +110,25 @@ namespace detail {
|
||||
typedef T value_type;
|
||||
};
|
||||
|
||||
// Output Iterators have a value type of 'void'. Kinda sucks.
|
||||
// We special case some output iterators, but we can't enumerate them all.
|
||||
// If we can't figure it out, we assume that you want to output chars.
|
||||
// If you don't, pass in an iterator with a real value_type.
|
||||
template <typename T> struct value_type_or_char { typedef T value_type; };
|
||||
template <> struct value_type_or_char<void> { typedef char value_type; };
|
||||
|
||||
// All in one step
|
||||
template <typename Iterator>
|
||||
struct iterator_value_type {
|
||||
// typedef typename value_type_or_char<typename hex_iterator_traits<Iterator>::value_type>::value_type value_type;
|
||||
typedef typename hex_iterator_traits<Iterator>::value_type value_type;
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
bool iter_end ( Iterator current, Iterator last ) { return current == last; }
|
||||
|
||||
template <typename T>
|
||||
bool ptr_end ( const T* ptr, const T* /*end*/ ) { return *ptr == '\0'; }
|
||||
|
||||
// What can we assume here about the inputs?
|
||||
// is std::iterator_traits<InputIterator>::value_type always 'char' ?
|
||||
// Could it be wchar_t, say? Does it matter?
|
||||
// We are assuming ASCII for the values - but what about the storage?
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
typename boost::enable_if<boost::is_integral<typename iterator_value_type<OutputIterator>::value_type>, OutputIterator>::type
|
||||
decode_one ( InputIterator &first, InputIterator last, OutputIterator out ) {
|
||||
typedef typename iterator_value_type<OutputIterator>::value_type T;
|
||||
template <typename InputIterator, typename OutputIterator, typename EndPred>
|
||||
typename boost::enable_if<boost::is_integral<typename hex_iterator_traits<OutputIterator>::value_type>, OutputIterator>::type
|
||||
decode_one ( InputIterator &first, InputIterator last, OutputIterator out, EndPred pred ) {
|
||||
typedef typename hex_iterator_traits<OutputIterator>::value_type T;
|
||||
T res (0);
|
||||
|
||||
// Need to make sure that we get can read that many chars here.
|
||||
for ( std::size_t i = 0; i < 2 * sizeof ( T ); ++i, ++first ) {
|
||||
if ( first == last )
|
||||
if ( pred ( first, last ))
|
||||
BOOST_THROW_EXCEPTION (not_enough_input ());
|
||||
res = ( 16 * res ) + hex_char_to_int (static_cast<char> (*first));
|
||||
}
|
||||
@ -209,7 +197,7 @@ hex ( const Range &r, OutputIterator out ) {
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) {
|
||||
while ( first != last )
|
||||
out = detail::decode_one ( first, last, out );
|
||||
out = detail::decode_one ( first, last, out, detail::iter_end<InputIterator> );
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -223,14 +211,12 @@ OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator o
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename T, typename OutputIterator>
|
||||
OutputIterator unhex ( const T *ptr, OutputIterator out ) {
|
||||
typedef typename detail::iterator_value_type<OutputIterator>::value_type OutputType;
|
||||
typedef typename detail::hex_iterator_traits<OutputIterator>::value_type OutputType;
|
||||
// If we run into the terminator while decoding, we will throw a
|
||||
// malformed input exception. It would be nicer to throw a 'Not enough input'
|
||||
// exception - but how much extra work would that require?
|
||||
// I just make up an "end iterator" which we will never get to -
|
||||
// two Ts per byte of the output type.
|
||||
while ( *ptr )
|
||||
out = detail::decode_one ( ptr, ptr + 2 * sizeof(OutputType), out );
|
||||
out = detail::decode_one ( ptr, (const T *) NULL, out, detail::ptr_end<T> );
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ Requirements:
|
||||
corpusIter boyer_moore_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<PatternRange> pattern_iterator;
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
|
||||
return bm ( corpus_first, corpus_last );
|
||||
}
|
||||
@ -242,7 +242,7 @@ Requirements:
|
||||
typename boost::range_iterator<CorpusRange>::type
|
||||
boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<PatternRange> pattern_iterator;
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
|
||||
return bm (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
@ -84,6 +84,11 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
|
||||
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;
|
||||
@ -119,6 +124,9 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
|
||||
// \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_horspool_search ( corpusIter corpus_first, corpusIter corpus_last,
|
||||
/// patIter pat_first, patIter pat_last )
|
||||
/// \brief Searches the corpus for the pattern.
|
||||
@ -130,10 +138,55 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
|
||||
///
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter boyer_moore_horspool_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last,
|
||||
patIter pat_first, patIter pat_last ) {
|
||||
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 );
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename corpusIter>
|
||||
corpusIter boyer_moore_horspool_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore_horspool<pattern_iterator> bmh ( boost::begin(pattern), boost::end (pattern));
|
||||
return bmh ( 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_horspool_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
|
||||
{
|
||||
boyer_moore_horspool<patIter> bmh ( 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_horspool_search ( CorpusRange &corpus, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore_horspool<pattern_iterator> bmh ( boost::begin(pattern), boost::end (pattern));
|
||||
return bmh (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
|
||||
// Creator functions -- take a pattern range, return an object
|
||||
template <typename Range>
|
||||
boost::algorithm::boyer_moore_horspool<typename boost::range_iterator<const Range>::type>
|
||||
make_boyer_moore_horspool ( const Range &r ) {
|
||||
return boost::algorithm::boyer_moore_horspool
|
||||
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
boost::algorithm::boyer_moore_horspool<typename boost::range_iterator<Range>::type>
|
||||
make_boyer_moore_horspool ( Range &r ) {
|
||||
return boost::algorithm::boyer_moore_horspool
|
||||
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -79,6 +79,11 @@ namespace boost { namespace algorithm {
|
||||
return do_search ( corpus_first, corpus_last, k_corpus_length );
|
||||
}
|
||||
|
||||
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;
|
||||
@ -179,6 +184,9 @@ namespace boost { namespace algorithm {
|
||||
};
|
||||
|
||||
|
||||
/* 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 knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last,
|
||||
/// patIter pat_first, patIter pat_last )
|
||||
/// \brief Searches the corpus for the pattern.
|
||||
@ -190,10 +198,55 @@ namespace boost { namespace algorithm {
|
||||
///
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter knuth_morris_pratt_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last,
|
||||
patIter pat_first, patIter pat_last ) {
|
||||
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 );
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename corpusIter>
|
||||
corpusIter knuth_morris_pratt_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
knuth_morris_pratt<pattern_iterator> kmp ( boost::begin(pattern), boost::end (pattern));
|
||||
return kmp ( 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
|
||||
knuth_morris_pratt_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
|
||||
{
|
||||
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
|
||||
return kmp (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename CorpusRange>
|
||||
typename boost::range_iterator<CorpusRange>::type
|
||||
knuth_morris_pratt_search ( CorpusRange &corpus, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
knuth_morris_pratt<pattern_iterator> kmp ( boost::begin(pattern), boost::end (pattern));
|
||||
return kmp (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
|
||||
// Creator functions -- take a pattern range, return an object
|
||||
template <typename Range>
|
||||
boost::algorithm::knuth_morris_pratt<typename boost::range_iterator<const Range>::type>
|
||||
make_knuth_morris_pratt ( const Range &r ) {
|
||||
return boost::algorithm::knuth_morris_pratt
|
||||
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
boost::algorithm::knuth_morris_pratt<typename boost::range_iterator<Range>::type>
|
||||
make_knuth_morris_pratt ( Range &r ) {
|
||||
return boost::algorithm::knuth_morris_pratt
|
||||
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
}}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace boost {
|
||||
a match).
|
||||
\param Input A container which will be searched.
|
||||
\param Finder A Finder object used for searching
|
||||
\return A reference the result
|
||||
\return A reference to the result
|
||||
|
||||
\note Prior content of the result will be overwritten.
|
||||
*/
|
||||
@ -122,7 +122,7 @@ namespace boost {
|
||||
Each match is used as a separator of segments. These segments are then
|
||||
returned in the result.
|
||||
|
||||
\param Result A 'container container' to container the result of search.
|
||||
\param Result A 'container container' to contain the result of search.
|
||||
Both outer and inner container must have constructor taking a pair
|
||||
of iterators as an argument.
|
||||
Typical type of the result is
|
||||
@ -131,7 +131,7 @@ namespace boost {
|
||||
a match).
|
||||
\param Input A container which will be searched.
|
||||
\param Finder A finder object used for searching
|
||||
\return A reference the result
|
||||
\return A reference to the result
|
||||
|
||||
\note Prior content of the result will be overwritten.
|
||||
*/
|
||||
|
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/html/index.html">doc/html/index.html</a> <hr>
|
||||
<p>© Copyright Marshall Clow, 2012</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
@ -130,7 +130,7 @@
|
||||
string str1("command.com");
|
||||
cout
|
||||
<< str1
|
||||
<< (is_executable("command.com")? "is": "is not")
|
||||
<< (is_executable(str1)? "is": "is not")
|
||||
<< "an executable"
|
||||
<< endl; // prints "command.com is an executable"
|
||||
|
||||
|
@ -16,6 +16,7 @@ import testing ;
|
||||
[ run search_test1.cpp : : : : search_test1 ]
|
||||
[ run search_test2.cpp : : : : search_test2 ]
|
||||
[ run search_test3.cpp : : : : search_test3 ]
|
||||
[ run search_test4.cpp : : : : search_test4 ]
|
||||
[ compile-fail search_fail1.cpp : : : : ]
|
||||
[ compile-fail search_fail2.cpp : : : : ]
|
||||
[ compile-fail search_fail3.cpp : : : : ]
|
||||
@ -43,6 +44,7 @@ import testing ;
|
||||
[ run hex_test1.cpp : : : : hex_test1 ]
|
||||
[ run hex_test2.cpp : : : : hex_test2 ]
|
||||
[ run hex_test3.cpp : : : : hex_test3 ]
|
||||
[ run hex_test4.cpp : : : : hex_test4 ]
|
||||
[ compile-fail hex_fail1.cpp ]
|
||||
;
|
||||
}
|
||||
|
145
test/hex_test4.cpp
Normal file
145
test/hex_test4.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
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
|
||||
|
||||
Try ostream_iterators
|
||||
*/
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/test/included/test_exec_monitor.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace ba = boost::algorithm;
|
||||
|
||||
void test_short_input1 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( std::string ( "A" ), std::back_inserter(s)); }
|
||||
catch ( const std::exception &ex ) { return; }
|
||||
BOOST_TEST_MESSAGE ( "Failed to catch std::exception in test_short_input1" );
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
void test_short_input2 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( std::string ( "A" ), std::back_inserter(s)); }
|
||||
catch ( const ba::hex_decode_error &ex ) { return; }
|
||||
BOOST_TEST_MESSAGE ( "Failed to catch ba::hex_decode_error in test_short_input2" );
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
void test_short_input3 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( std::string ( "A" ), std::back_inserter(s)); }
|
||||
catch ( const ba::not_enough_input &ex ) { return; }
|
||||
BOOST_TEST_MESSAGE ( "Failed to catch ba::not_enough_input in test_short_input3" );
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
// Make sure that the right thing is thrown
|
||||
void test_short_input4 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( std::string ( "A" ), std::back_inserter(s)); }
|
||||
catch ( const ba::non_hex_input &ex ) { BOOST_CHECK ( false ); }
|
||||
catch ( const ba::not_enough_input &ex ) { return; }
|
||||
catch ( ... ) { BOOST_CHECK ( false ); }
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
// Make sure that the right thing is thrown
|
||||
void test_short_input5 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( "A", std::back_inserter(s)); }
|
||||
catch ( const ba::non_hex_input &ex ) { BOOST_CHECK ( false ); }
|
||||
catch ( const ba::not_enough_input &ex ) { return; }
|
||||
catch ( ... ) { BOOST_CHECK ( false ); }
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
|
||||
void test_short_input () {
|
||||
// BOOST_TEST_MESSAGE ( "Short input tests for boost::algorithm::unhex" );
|
||||
test_short_input1 ();
|
||||
test_short_input2 ();
|
||||
test_short_input3 ();
|
||||
test_short_input4 ();
|
||||
test_short_input5 ();
|
||||
}
|
||||
|
||||
|
||||
void test_nonhex_input1 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( "01234FG1234", std::back_inserter(s)); }
|
||||
catch ( const std::exception &ex ) {
|
||||
BOOST_CHECK ( 'G' == *boost::get_error_info<ba::bad_char>(ex));
|
||||
return;
|
||||
}
|
||||
catch ( ... ) {}
|
||||
BOOST_TEST_MESSAGE ( "Failed to catch std::exception in test_nonhex_input1" );
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
void test_nonhex_input2 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( "012Z4FA1234", std::back_inserter(s)); }
|
||||
catch ( const ba::hex_decode_error &ex ) {
|
||||
BOOST_CHECK ( 'Z' == *boost::get_error_info<ba::bad_char>(ex));
|
||||
return;
|
||||
}
|
||||
catch ( ... ) {}
|
||||
BOOST_TEST_MESSAGE ( "Failed to catch ba::hex_decode_error in test_nonhex_input2" );
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
void test_nonhex_input3 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( "01234FA12Q4", std::back_inserter(s)); }
|
||||
catch ( const ba::non_hex_input &ex ) {
|
||||
BOOST_CHECK ( 'Q' == *boost::get_error_info<ba::bad_char>(ex));
|
||||
return;
|
||||
}
|
||||
catch ( ... ) {}
|
||||
BOOST_TEST_MESSAGE ( "Failed to catch ba::non_hex_input in test_nonhex_input3" );
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
// Make sure that the right thing is thrown
|
||||
void test_nonhex_input4 () {
|
||||
std::string s;
|
||||
|
||||
try { ba::unhex ( "P1234FA1234", std::back_inserter(s)); }
|
||||
catch ( const ba::not_enough_input &ex ) { BOOST_CHECK ( false ); }
|
||||
catch ( const ba::non_hex_input &ex ) { return; }
|
||||
catch ( ... ) { BOOST_CHECK ( false ); }
|
||||
BOOST_CHECK ( false );
|
||||
}
|
||||
|
||||
void test_nonhex_input () {
|
||||
// BOOST_TEST_MESSAGE ( "Non hex input tests for for boost::algorithm::unhex" );
|
||||
test_nonhex_input1 ();
|
||||
test_nonhex_input2 ();
|
||||
test_nonhex_input3 ();
|
||||
test_nonhex_input4 ();
|
||||
}
|
||||
|
||||
int test_main( int , char* [] )
|
||||
{
|
||||
test_short_input ();
|
||||
test_nonhex_input ();
|
||||
|
||||
return 0;
|
||||
}
|
@ -54,10 +54,10 @@ test_ordered(void)
|
||||
BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues), std::less<int>()) == boost::end(strictlyIncreasingValues));
|
||||
|
||||
// Check for const and non-const arrays
|
||||
BOOST_CHECK ( ba::is_sorted_until ( b_e(constantValues), std::less<int>()) != a_end(constantValues));
|
||||
BOOST_CHECK ( ba::is_sorted_until ( a_range(constantValues), std::less<int>()) != boost::end(constantValues));
|
||||
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(constantValues), std::less<int>()) == a_end(constantValues));
|
||||
BOOST_CHECK ( ba::is_sorted_until ( a_range(constantValues), std::less<int>()) == boost::end(constantValues));
|
||||
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 ( b_e(randomValues)) == &randomValues[2] );
|
||||
|
116
test/search_test4.cpp
Normal file
116
test/search_test4.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
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
|
||||
|
||||
Testing the range-based interfaces
|
||||
*/
|
||||
|
||||
#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) { \
|
||||
res = boost::algorithm::call ( haystack, needle ); \
|
||||
if ( res != exp ) { \
|
||||
std::cout << "Expected " \
|
||||
<< exp - haystack.begin () << " got " \
|
||||
<< res - haystack.begin () << std::endl; \
|
||||
throw std::runtime_error \
|
||||
( "Unexpected result from " #call ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define runObject(obj, refDiff) { \
|
||||
boost::algorithm::obj <vec::const_iterator> s_o = \
|
||||
boost::algorithm::make_##obj ( needle ); \
|
||||
res = s_o ( haystack ); \
|
||||
if ( res != exp ) { \
|
||||
std::cout << "Expected " \
|
||||
<< exp - haystack.begin () << " got " \
|
||||
<< res - haystack.begin () << std::endl; \
|
||||
throw std::runtime_error \
|
||||
( "Unexpected result from " #obj " object" ); \
|
||||
} \
|
||||
}
|
||||
|
||||
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 check_one ( const vec &haystack, const vec &needle, int expected ) {
|
||||
|
||||
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
|
||||
res = std::search ( haystack.begin (), haystack.end (), needle.begin (), needle.end ());
|
||||
if ( res != exp ) {
|
||||
std::cout << "Expected " << exp - haystack.begin () << " got " << res - haystack.begin () << std::endl;
|
||||
throw std::runtime_error ( "Unexpected result from std::search" );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user