From d228e914941d5b894baf0b9f915dc5628ca9beed Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sun, 15 Jul 2012 16:28:35 +0000 Subject: [PATCH] Merge Boost.Algorithm changes to release; Fixes #7104 [SVN r79538] --- doc/ordered-hpp.qbk | 4 +- include/boost/algorithm/cxx11/is_sorted.hpp | 16 +- include/boost/algorithm/hex.hpp | 18 +-- .../boost/algorithm/searching/boyer_moore.hpp | 4 +- .../searching/boyer_moore_horspool.hpp | 57 ++++++- .../searching/knuth_morris_pratt.hpp | 57 ++++++- test/Jamfile.v2 | 2 + test/hex_test4.cpp | 145 ++++++++++++++++++ test/ordered_test.cpp | 8 +- test/search_test4.cpp | 116 ++++++++++++++ 10 files changed, 394 insertions(+), 33 deletions(-) create mode 100644 test/hex_test4.cpp create mode 100644 test/search_test4.cpp diff --git a/doc/ordered-hpp.qbk b/doc/ordered-hpp.qbk index a7632ac..687066a 100644 --- a/doc/ordered-hpp.qbk +++ b/doc/ordered-hpp.qbk @@ -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 { diff --git a/include/boost/algorithm/cxx11/is_sorted.hpp b/include/boost/algorithm/cxx11/is_sorted.hpp index 20180b7..b0505d3 100644 --- a/include/boost/algorithm/cxx11/is_sorted.hpp +++ b/include/boost/algorithm/cxx11/is_sorted.hpp @@ -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::value_type value_type; - return boost::algorithm::is_sorted_until ( first, last, std::less_equal()); + return boost::algorithm::is_sorted_until ( first, last, std::less()); } @@ -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::value_type value_type; - return boost::algorithm::is_sorted (first, last, std::less_equal()); + return boost::algorithm::is_sorted (first, last, std::less()); } @@ -206,7 +202,7 @@ namespace detail { bool is_decreasing ( ForwardIterator first, ForwardIterator last ) { typedef typename std::iterator_traits::value_type value_type; - return boost::algorithm::is_sorted (first, last, std::greater_equal()); + return boost::algorithm::is_sorted (first, last, std::greater()); } /// \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::value_type value_type; - return boost::algorithm::is_sorted (first, last, std::less()); + return boost::algorithm::is_sorted (first, last, std::less_equal()); } /// \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::value_type value_type; - return boost::algorithm::is_sorted (first, last, std::greater()); + return boost::algorithm::is_sorted (first, last, std::greater_equal()); } /// \fn is_strictly_decreasing ( const R &range ) diff --git a/include/boost/algorithm/hex.hpp b/include/boost/algorithm/hex.hpp index 9e566eb..b6b1548 100644 --- a/include/boost/algorithm/hex.hpp +++ b/include/boost/algorithm/hex.hpp @@ -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 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 } @@ -227,10 +223,8 @@ OutputIterator unhex ( const T *ptr, OutputIterator out ) { // 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 ); return out; } diff --git a/include/boost/algorithm/searching/boyer_moore.hpp b/include/boost/algorithm/searching/boyer_moore.hpp index ca7b876..958f0b8 100644 --- a/include/boost/algorithm/searching/boyer_moore.hpp +++ b/include/boost/algorithm/searching/boyer_moore.hpp @@ -223,7 +223,7 @@ Requirements: corpusIter boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) { - typedef typename boost::range_iterator pattern_iterator; + typedef typename boost::range_iterator::type pattern_iterator; boyer_moore bm ( boost::begin(pattern), boost::end (pattern)); return bm ( corpus_first, corpus_last ); } @@ -242,7 +242,7 @@ Requirements: typename boost::range_iterator::type boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern ) { - typedef typename boost::range_iterator pattern_iterator; + typedef typename boost::range_iterator::type pattern_iterator; boyer_moore bm ( boost::begin(pattern), boost::end (pattern)); return bm (boost::begin (corpus), boost::end (corpus)); } diff --git a/include/boost/algorithm/searching/boyer_moore_horspool.hpp b/include/boost/algorithm/searching/boyer_moore_horspool.hpp index 63925bf..5e59cf3 100644 --- a/include/boost/algorithm/searching/boyer_moore_horspool.hpp +++ b/include/boost/algorithm/searching/boyer_moore_horspool.hpp @@ -84,6 +84,11 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html return this->do_search ( corpus_first, corpus_last ); } + template + typename boost::range_iterator::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 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 bmh ( pat_first, pat_last ); return bmh ( corpus_first, corpus_last ); + } + + template + corpusIter boyer_moore_horspool_search ( + corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) + { + typedef typename boost::range_iterator::type pattern_iterator; + boyer_moore_horspool bmh ( boost::begin(pattern), boost::end (pattern)); + return bmh ( corpus_first, corpus_last ); + } + + template + typename boost::lazy_disable_if_c< + boost::is_same::value, typename boost::range_iterator > + ::type + boyer_moore_horspool_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last ) + { + boyer_moore_horspool bmh ( pat_first, pat_last ); + return bm (boost::begin (corpus), boost::end (corpus)); + } + + template + typename boost::range_iterator::type + boyer_moore_horspool_search ( CorpusRange &corpus, const PatternRange &pattern ) + { + typedef typename boost::range_iterator::type pattern_iterator; + boyer_moore_horspool 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 + boost::algorithm::boyer_moore_horspool::type> + make_boyer_moore_horspool ( const Range &r ) { + return boost::algorithm::boyer_moore_horspool + ::type> (boost::begin(r), boost::end(r)); + } + + template + boost::algorithm::boyer_moore_horspool::type> + make_boyer_moore_horspool ( Range &r ) { + return boost::algorithm::boyer_moore_horspool + ::type> (boost::begin(r), boost::end(r)); } }} diff --git a/include/boost/algorithm/searching/knuth_morris_pratt.hpp b/include/boost/algorithm/searching/knuth_morris_pratt.hpp index fe970a5..cc83185 100644 --- a/include/boost/algorithm/searching/knuth_morris_pratt.hpp +++ b/include/boost/algorithm/searching/knuth_morris_pratt.hpp @@ -79,6 +79,11 @@ namespace boost { namespace algorithm { return do_search ( corpus_first, corpus_last, k_corpus_length ); } + template + typename boost::range_iterator::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 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 kmp ( pat_first, pat_last ); return kmp ( corpus_first, corpus_last ); + } + + template + corpusIter knuth_morris_pratt_search ( + corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) + { + typedef typename boost::range_iterator::type pattern_iterator; + knuth_morris_pratt kmp ( boost::begin(pattern), boost::end (pattern)); + return kmp ( corpus_first, corpus_last ); + } + + template + typename boost::lazy_disable_if_c< + boost::is_same::value, typename boost::range_iterator > + ::type + knuth_morris_pratt_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last ) + { + knuth_morris_pratt kmp ( pat_first, pat_last ); + return kmp (boost::begin (corpus), boost::end (corpus)); + } + + template + typename boost::range_iterator::type + knuth_morris_pratt_search ( CorpusRange &corpus, const PatternRange &pattern ) + { + typedef typename boost::range_iterator::type pattern_iterator; + knuth_morris_pratt 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 + boost::algorithm::knuth_morris_pratt::type> + make_knuth_morris_pratt ( const Range &r ) { + return boost::algorithm::knuth_morris_pratt + ::type> (boost::begin(r), boost::end(r)); + } + + template + boost::algorithm::knuth_morris_pratt::type> + make_knuth_morris_pratt ( Range &r ) { + return boost::algorithm::knuth_morris_pratt + ::type> (boost::begin(r), boost::end(r)); } }} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7e9292d..b9cfa2a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -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 ] ; } diff --git a/test/hex_test4.cpp b/test/hex_test4.cpp new file mode 100644 index 0000000..7b22b64 --- /dev/null +++ b/test/hex_test4.cpp @@ -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 +#include +#include + +#include +#include + +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 ); + } + +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 (); + } + + +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(ex)); + return; + } + 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(ex)); + return; + } + 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(ex)); + return; + } + 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 ); + } + +// Make sure that the right thing is thrown +void test_nonhex_input5 () { + std::string s; + + try { ba::unhex ( "012", std::back_inserter(s)); } + catch ( const ba::non_hex_input &ex ) { + BOOST_CHECK ( '\000' == *boost::get_error_info(ex)); + return; + } + BOOST_TEST_MESSAGE ( "Failed to catch ba::non_hex_input in test_nonhex_input4" ); + 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 (); + test_nonhex_input5 (); + } + + + +int test_main( int , char* [] ) +{ + test_short_input (); + test_nonhex_input (); + + return 0; +} diff --git a/test/ordered_test.cpp b/test/ordered_test.cpp index 42e1219..8265c5b 100644 --- a/test/ordered_test.cpp +++ b/test/ordered_test.cpp @@ -54,10 +54,10 @@ test_ordered(void) BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues), std::less()) == boost::end(strictlyIncreasingValues)); // Check for const and non-const arrays - BOOST_CHECK ( ba::is_sorted_until ( b_e(constantValues), std::less()) != a_end(constantValues)); - BOOST_CHECK ( ba::is_sorted_until ( a_range(constantValues), std::less()) != boost::end(constantValues)); - BOOST_CHECK ( ba::is_sorted_until ( b_e(nonConstantArray), std::less()) != a_end(nonConstantArray)); - BOOST_CHECK ( ba::is_sorted_until ( a_range(nonConstantArray), std::less()) != boost::end(nonConstantArray)); + BOOST_CHECK ( ba::is_sorted_until ( b_e(constantValues), std::less()) == a_end(constantValues)); + BOOST_CHECK ( ba::is_sorted_until ( a_range(constantValues), std::less()) == boost::end(constantValues)); + BOOST_CHECK ( ba::is_sorted_until ( b_e(nonConstantArray), std::less()) == a_end(nonConstantArray)); + BOOST_CHECK ( ba::is_sorted_until ( a_range(nonConstantArray), std::less()) == boost::end(nonConstantArray)); BOOST_CHECK ( ba::is_sorted_until ( b_e(randomValues), std::less()) == &randomValues[2] ); BOOST_CHECK ( ba::is_sorted_until ( b_e(randomValues)) == &randomValues[2] ); diff --git a/test/search_test4.cpp b/test/search_test4.cpp new file mode 100644 index 0000000..ff82d1c --- /dev/null +++ b/test/search_test4.cpp @@ -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 +#include +#include + +#include + +#include +#include +#include +#include + +typedef std::vector 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 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; + }