Compare commits

..

67 Commits

Author SHA1 Message Date
351e98bfef Release 1.53.0
[SVN r82734]
2013-02-04 18:11:49 +00:00
6e098b27aa Merge Michael Morin's typo fixes for Boost.Algorithm to release; no functionality change.
[SVN r82240]
2012-12-28 18:19:25 +00:00
60010b4165 Merge bug fix and test to release; Fixes #7784
[SVN r82238]
2012-12-28 17:39:08 +00:00
1660dc9d48 merge bug fix for minmax_element to release; Fixes #7752
[SVN r82049]
2012-12-17 16:02:38 +00:00
5ae4f848b3 Remove tabs from Boost.Algorithm tests.
[SVN r81857]
2012-12-11 16:56:30 +00:00
fe3e0bb9c4 merge K-M-P doc updates to release; Fixes #7656
[SVN r81840]
2012-12-10 21:13:08 +00:00
311e169376 Merge extra tests for Boost.StringAlgo.Split to release
[SVN r81835]
2012-12-10 20:10:12 +00:00
3dddfa1930 Merge from trunk; Fixes #7346
[SVN r81832]
2012-12-10 19:23:54 +00:00
be6d8f9665 Merge URL fix for boyer-moore; Fixes #7781
[SVN r81825]
2012-12-10 15:40:23 +00:00
bced4ed8dd Merge doc fix for minmax; Fixes #7751
[SVN r81823]
2012-12-10 15:28:36 +00:00
1b57e905ab Merge bug fixes to release; Fixes #7339
[SVN r80808]
2012-10-01 15:31:51 +00:00
29bd9f53d9 Merge bug fixes to release; Fixes #7399 Fixes #7400 Fixes #7401
[SVN r80670]
2012-09-23 14:56:41 +00:00
6341cfb1a6 Merge doc typo corrections to release; fixes #6595; fixes #7182
[SVN r80057]
2012-08-16 05:16:42 +00:00
7f4acd6170 Merged typos in comments to release; no functionality; Fixes #7210
[SVN r79929]
2012-08-08 16:30:33 +00:00
314f6dcfe0 Merge changes from [79588] to Release; fixes a unhex bug
[SVN r79604]
2012-07-19 15:12:33 +00:00
167aa6e31c Get rid of tabs in Boost.Algorithm tests
[SVN r79603]
2012-07-19 15:00:27 +00:00
d228e91494 Merge Boost.Algorithm changes to release; Fixes #7104
[SVN r79538]
2012-07-15 16:28:35 +00:00
9cc573fbd0 Fixed errors in the doxygen comments. Fixes #7083.
[SVN r79285]
2012-07-05 15:30:17 +00:00
28a7d3eb4b Merge doc changes to release; fixes #7073
[SVN r79264]
2012-07-04 16:15:35 +00:00
883cce61a8 Merge algorithm's html redirect.
[SVN r78855]
2012-06-07 20:05:17 +00:00
96d4708367 Merge Boost.Algorithm inspection report changes to release. No functionality change
[SVN r78689]
2012-05-27 15:45:18 +00:00
563fe27a59 Merged changes for Boost.Algorithm to release; Fixes #6596; Fixes #6689; Fixes #3215; Fixes #6840
[SVN r78557]
2012-05-23 16:25:48 +00:00
76cd99ed53 Merge Boost.Algorithm to release branch
[SVN r78025]
2012-04-16 18:54:41 +00:00
0f2399fef0 Merge changes to release; fixes #5589
[SVN r76527]
2012-01-15 16:49:25 +00:00
044d667e79 Merge changes to release; fixes #3634
[SVN r76522]
2012-01-15 16:05:55 +00:00
be9da63894 Merge fix for #4937 to release
[SVN r76267]
2012-01-01 21:18:47 +00:00
787c94bc53 Merge Change 68161 to release
[SVN r76266]
2012-01-01 21:17:02 +00:00
e87ce37b34 Merge Change 76213 to release; Fixes #4811
[SVN r76265]
2012-01-01 21:12:58 +00:00
199a89a1e9 merged from trunk
[SVN r72380]
2011-06-03 21:13:37 +00:00
01492a93c6 trunk changes merged
[SVN r67922]
2011-01-10 19:36:38 +00:00
50703b8c97 Merge documentation fixes to release.
[SVN r66285]
2010-10-30 17:34:45 +00:00
0f8d556130 Merge r65004 from trunk
Fix #4551,#4553,#4575 by removing unused parameter.



[SVN r65168]
2010-09-01 16:18:07 +00:00
bbd3220a1e Merging changes from trunk
[SVN r63824]
2010-07-10 20:29:03 +00:00
9068069106 Spirit: merging from trunk upto rev. 61489
[SVN r63640]
2010-07-04 22:38:38 +00:00
a37af3c81e Merge documentation fixes.
* Use `doc/src/*.css` instead of `doc/html/*.css`.
* Remove wiki and people directories.
* Some documentation fixes.
* Left out `minimal.css` changes and boostbook changes because of clashes.


[SVN r63347]
2010-06-26 12:30:09 +00:00
f5885c6fb0 Merge minmax from the trunk
[SVN r62088]
2010-05-18 17:53:36 +00:00
d45bb3545e Merge some link fixes and release notes.
[SVN r61474]
2010-04-21 23:00:35 +00:00
d735b9fa1e rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
62ec675581 Merged changes from trunk
[SVN r56176]
2009-09-13 19:10:55 +00:00
e7cd4da67b Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
6076f5a18e Merge [53520] from the trunk
[SVN r53909]
2009-06-14 22:56:08 +00:00
60cd5a0500 Merge [53062] from the trunk
[SVN r53270]
2009-05-26 01:17:07 +00:00
c33dad924d Fixed almost all tab and min/max issues found by inspect tool
[SVN r53142]
2009-05-20 19:41:20 +00:00
2f2935f07e Merged revisions 45283,48266 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r45283 | danieljames | 2008-05-11 14:49:20 +0100 (Sun, 11 May 2008) | 1 line
  
  Quote href values - our tools don't support unquoted values.
........
  r48266 | danieljames | 2008-08-20 20:32:23 +0100 (Wed, 20 Aug 2008) | 1 line
  
  Fix the link to the limits documentation.
........


[SVN r51902]
2009-03-22 17:30:02 +00:00
3cbaafc27f Merge PDF build changes from Trunk.
[SVN r51417]
2009-02-23 18:39:32 +00:00
c067b348bf Merge [51045] from the trunk
[SVN r51226]
2009-02-12 18:47:06 +00:00
c33935fa1f merge of cmake build files from trunk per beman
[SVN r50756]
2009-01-24 18:57:20 +00:00
98a8b08afb Memory management fixes for is_any_of predicate merged from the trunk
[SVN r49172]
2008-10-07 21:59:57 +00:00
fc0f3dcffc Cummulative merge of updates from the main trunk
[SVN r46505]
2008-06-19 12:07:24 +00:00
822636418b Merged revisions 43211,43214-43219,43222-43225,43227-43238,43242,43244-43245,43249-43250,43257-43259,43261,43263,43265,43267-43268,43270-43271,43273,43275-43279,43284-43289,43291,43295,43297-43298,43304-43305,43307,43313,43315,43324,43326-43327,43331,43333,43339-43343,43345,43348,43350,43352-43353,43355-43356,43358,43360,43366-43367,43369-43370,43372-43376,43378-43389,43394,43396-43398,43400-43401,43403-43404,43406-43408,43413-43415,43417-43418,43420,43422-43423 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r43417 | danieljames | 2008-02-26 22:04:55 +0000 (Tue, 26 Feb 2008) | 2 lines
  
  Fix a link to Boost.Bimap.
........
  r43418 | danieljames | 2008-02-26 22:07:25 +0000 (Tue, 26 Feb 2008) | 2 lines
  
  Change another link that's no longer in the repository to link to the website.
........
  r43422 | danieljames | 2008-02-27 18:51:14 +0000 (Wed, 27 Feb 2008) | 1 line
  
  Fix broken copyright urls. Fixes #1573.
........
  r43423 | danieljames | 2008-02-27 19:22:01 +0000 (Wed, 27 Feb 2008) | 1 line
  
  Fix incorrect links to copyright of the form 'http:#www.boost.org
........


[SVN r43425]
2008-02-27 20:00:24 +00:00
352e16aade Merged revisions 43206,43208-43213 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r43206 | danieljames | 2008-02-10 09:55:03 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix some broken links.
........
  r43209 | danieljames | 2008-02-10 14:56:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Link to people pages on the website, as they've been removed from the download.
........
  r43210 | danieljames | 2008-02-10 15:02:17 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Point links to the pages that used to be in 'more' to the site.
........
  r43212 | danieljames | 2008-02-10 16:10:16 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix links on the home page as well.
........
  r43213 | danieljames | 2008-02-10 16:21:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Generated documentation which is no longer generated.
........


[SVN r43214]
2008-02-10 16:39:38 +00:00
89c76ea1bb Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
2007-11-25 18:38:02 +00:00
50b5726a6f Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
2007-11-25 18:07:19 +00:00
d4b95734dd Starting point for releases
[SVN r39706]
2007-10-05 14:25:06 +00:00
05af96f84c This commit was manufactured by cvs2svn to create tag
'Version_1_34_1'.

[SVN r38286]
2007-07-24 19:28:14 +00:00
5bdbb2b308 Documentation for iter_find/iter_split added
[SVN r37842]
2007-06-01 13:50:51 +00:00
1a02969303 release notes - fix the incorrect functionname spelling
[SVN r37533]
2007-04-29 07:04:58 +00:00
6309379618 release notes for 1.34 added
[SVN r37532]
2007-04-29 07:02:21 +00:00
37581bac55 documentation typo fixed
[SVN r36843]
2007-01-30 07:59:28 +00:00
a71a4ed5b1 Merged copyright and license addition
[SVN r35907]
2006-11-07 19:27:00 +00:00
c509c3fbad Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
d8683f2498 unused parameters removed
[SVN r35753]
2006-10-27 17:37:37 +00:00
7c0101aa51 Copyright added to index.html
unneeded file removed


[SVN r34908]
2006-08-20 20:14:48 +00:00
6f3e85528f License added to the xml documentation files
[SVN r34894]
2006-08-16 07:10:48 +00:00
8af639b7cf missing 'using' directives for join_if and join_if_regex added
missing #include <boost/algorithm/string/join.hpp> added to string_algo.hpp


[SVN r34122]
2006-05-30 19:13:08 +00:00
d9bc7e800b Merged patch from main trunk for borland by Nicola Musatti
[SVN r33723]
2006-04-17 17:16:11 +00:00
b4ed9beb90 This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
63 changed files with 948 additions and 304 deletions

View File

@ -16,8 +16,6 @@ using quickbook ;
using doxygen ; using doxygen ;
using boostbook ; using boostbook ;
local BOOST_ROOT = [ os.environ BOOST_ROOT ] ;
doxygen autodoc doxygen autodoc
: :
[ glob ../../../boost/algorithm/*.hpp ../../../boost/algorithm/searching/*.hpp ] [ glob ../../../boost/algorithm/*.hpp ../../../boost/algorithm/searching/*.hpp ]
@ -29,14 +27,12 @@ doxygen autodoc
xml algorithm : algorithm.qbk ; xml algorithm : algorithm.qbk ;
# path-constant boost-images : $(BOOST_ROOT)/doc/src/images ;
boostbook standalone boostbook standalone
: :
algorithm algorithm
: :
<dependency>autodoc <dependency>autodoc
<xsl:param>boost.root=$(BOOST_ROOT) <xsl:param>boost.root=../../../..
<xsl:param>"boost.doxygen.reftitle=Boost.Algorithms C++ Reference" <xsl:param>"boost.doxygen.reftitle=Boost.Algorithms C++ Reference"
<xsl:param>chapter.autolabel=0 <xsl:param>chapter.autolabel=0
<xsl:param>chunk.section.depth=8 <xsl:param>chunk.section.depth=8

View File

@ -14,7 +14,7 @@ http://www.boost.org/LICENSE_1_0.txt)
[heading Overview] [heading Overview]
The header file 'boyer_moore.hpp' contains an an implementation of the Boyer-Moore algorithm for searching sequences of values. The header file 'boyer_moore.hpp' contains an implementation of the Boyer-Moore algorithm for searching sequences of values.
The BoyerMoore string search algorithm is a particularly efficient string searching algorithm, and it has been the standard benchmark for the practical string search literature. The Boyer-Moore algorithm was invented by Bob Boyer and J. Strother Moore, and published in the October 1977 issue of the Communications of the ACM , and a copy of that article is available at [@http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf]. The BoyerMoore string search algorithm is a particularly efficient string searching algorithm, and it has been the standard benchmark for the practical string search literature. The Boyer-Moore algorithm was invented by Bob Boyer and J. Strother Moore, and published in the October 1977 issue of the Communications of the ACM , and a copy of that article is available at [@http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf].
@ -24,7 +24,9 @@ However, the Boyer-Moore algorithm cannot be used with comparison predicates lik
Nomenclature: I refer to the sequence being searched for as the "pattern", and the sequence being searched in as the "corpus". Nomenclature: I refer to the sequence being searched for as the "pattern", and the sequence being searched in as the "corpus".
For flexibility, the Boyer-Moore algorithm has has two interfaces; an object-based interface and a procedural one. The object-based interface builds the tables in the constructor, and uses operator () to perform the search. The procedural interface builds the table and does the search all in one step. If you are going to be searching for the same pattern in multiple corpora, then you should use the object interface, and only build the tables once. [heading Interface]
For flexibility, the Boyer-Moore algorithm has two interfaces; an object-based interface and a procedural one. The object-based interface builds the tables in the constructor, and uses operator () to perform the search. The procedural interface builds the table and does the search all in one step. If you are going to be searching for the same pattern in multiple corpora, then you should use the object interface, and only build the tables once.
Here is the object interface: Here is the object interface:
`` ``
@ -78,7 +80,7 @@ Both the object-oriented and procedural versions of the Boyer-Moore algorithm ta
The Boyer-Moore object takes a traits template parameter which enables the caller to customize how one of the precomputed tables is stored. This table, called the skip table, contains (logically) one entry for every possible value that the pattern can contain. When searching 8-bit character data, this table contains 256 elements. The traits class defines the table to be used. The Boyer-Moore object takes a traits template parameter which enables the caller to customize how one of the precomputed tables is stored. This table, called the skip table, contains (logically) one entry for every possible value that the pattern can contain. When searching 8-bit character data, this table contains 256 elements. The traits class defines the table to be used.
The default traits class uses a `boost::array` for small 'alphabets' and a `tr1::unordered_map` for larger ones. The array-based skip table gives excellent performance, but could be prohibitively large when the "alphabet" of elements to be searched grows. The unordered_map based version only grows as the number of unique elements in the pattern, but makes many more heap allocations, and gives slower lookup performance. The default traits class uses a `boost::array` for small 'alphabets' and a `tr1::unordered_map` for larger ones. The array-based skip table gives excellent performance, but could be prohibitively large when the 'alphabet' of elements to be searched grows. The unordered_map based version only grows as the number of unique elements in the pattern, but makes many more heap allocations, and gives slower lookup performance.
To use a different skip table, you should define your own skip table object and your own traits class, and use them to instantiate the Boyer-Moore object. The interface to these objects is described TBD. To use a different skip table, you should define your own skip table object and your own traits class, and use them to instantiate the Boyer-Moore object. The interface to these objects is described TBD.

View File

@ -14,7 +14,73 @@ http://www.boost.org/LICENSE_1_0.txt)
[heading Overview] [heading Overview]
The header file 'boyer_moore_horspool.hpp' contains an an implementation of the Boyer-Moore-Horspool algorithm for searching sequences of values. The header file 'boyer_moore_horspool.hpp' contains an implementation of the Boyer-Moore-Horspool algorithm for searching sequences of values.
The Boyer-Moore-Horspool search algorithm was published by Nigel Horspool in 1980. It is a refinement of the Boyer-Moore algorithm that trades space for time. It uses less space for internal tables than Boyer-Moore, and has poorer worst-case performance.
The Boyer-Moore-Horspool algorithm cannot be used with comparison predicates like `std::search`.
[heading Interface]
Nomenclature: I refer to the sequence being searched for as the "pattern", and the sequence being searched in as the "corpus".
For flexibility, the Boyer-Moore-Horspool algorithm has two interfaces; an object-based interface and a procedural one. The object-based interface builds the tables in the constructor, and uses operator () to perform the search. The procedural interface builds the table and does the search all in one step. If you are going to be searching for the same pattern in multiple corpora, then you should use the object interface, and only build the tables once.
Here is the object interface:
``
template <typename patIter>
class boyer_moore_horspool {
public:
boyer_moore_horspool ( patIter first, patIter last );
~boyer_moore_horspool ();
template <typename corpusIter>
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last );
};
``
and here is the corresponding procedural interface:
``
template <typename patIter, typename corpusIter>
corpusIter boyer_moore_horspool_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last );
``
Each of the functions is passed two pairs of iterators. The first two define the corpus and the second two define the pattern. Note that the two pairs need not be of the same type, but they do need to "point" at the same type. In other words, `patIter::value_type` and `curpusIter::value_type` need to be the same type.
The return value of the function is an iterator pointing to the start of the pattern in the corpus. If the pattern is not found, it returns the end of the corpus (`corpus_last`).
[heading Performance]
The execution time of the Boyer-Moore-Horspool algorithm is linear in the size of the string being searched; it can have a significantly lower constant factor than many other search algorithms: it doesn't need to check every character of the string to be searched, but rather skips over some of them. Generally the algorithm gets faster as the pattern being searched for becomes longer. Its efficiency derives from the fact that with each unsuccessful attempt to find a match between the search string and the text it is searching, it uses the information gained from that attempt to rule out as many positions of the text as possible where the string cannot match.
[heading Memory Use]
The algorithm an internal table that has one entry for each member of the "alphabet" in the pattern. For (8-bit) character types, this table contains 256 entries.
[heading Complexity]
The worst-case performance is ['O(m x n)], where ['m] is the length of the pattern and ['n] is the length of the corpus. The average time is ['O(n)]. The best case performance is sub-linear, and is, in fact, identical to Boyer-Moore, but the initialization is quicker and the internal loop is simpler than Boyer-Moore.
[heading Exception Safety]
Both the object-oriented and procedural versions of the Boyer-Moore-Horspool algorithm take their parameters by value and do not use any information other than what is passed in. Therefore, both interfaces provide the strong exception guarantee.
[heading Notes]
* When using the object-based interface, the pattern must remain unchanged for during the searches; i.e, from the time the object is constructed until the final call to operator () returns.
* The Boyer-Moore-Horspool algorithm requires random-access iterators for both the pattern and the corpus.
[heading Customization points]
The Boyer-Moore-Horspool object takes a traits template parameter which enables the caller to customize how the precomputed table is stored. This table, called the skip table, contains (logically) one entry for every possible value that the pattern can contain. When searching 8-bit character data, this table contains 256 elements. The traits class defines the table to be used.
The default traits class uses a `boost::array` for small 'alphabets' and a `tr1::unordered_map` for larger ones. The array-based skip table gives excellent performance, but could be prohibitively large when the 'alphabet' of elements to be searched grows. The unordered_map based version only grows as the number of unique elements in the pattern, but makes many more heap allocations, and gives slower lookup performance.
To use a different skip table, you should define your own skip table object and your own traits class, and use them to instantiate the Boyer-Moore-Horspool object. The interface to these objects is described TBD.
[endsect] [endsect]

View File

@ -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) 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 ( "32", out ) --> "3332"
hex ( "abcde", wout ) --> "006100620063006400650066" hex ( "abcdef", wout ) --> "006100620063006400650066"
hex ( "32", wout ) --> "00330032" hex ( "32", wout ) --> "00330032"
unhex ( "616263646566", out ) --> "abcde" unhex ( "616263646566", out ) --> "abcdef"
unhex ( "3332", out ) --> "32" unhex ( "3332", out ) --> "32"
unhex ( "616263646566", wout ) --> "\6162\6364\6566" ( i.e, a 3 character string ) unhex ( "616263646566", wout ) --> "\6162\6364\6566" ( i.e, a 3 character string )
unhex ( "3332", wout ) --> "\3233" ( U+3332, SQUARE HUARADDO ) unhex ( "3332", wout ) --> "\3233" ( U+3332, SQUARE HUARADDO )

View File

@ -14,8 +14,69 @@ http://www.boost.org/LICENSE_1_0.txt)
[heading Overview] [heading Overview]
The header file 'knuth_morris_pratt.hpp' contains an an implementation of the Knuth-Morris-Pratt algorithm for searching sequences of values. The header file 'knuth_morris_pratt.hpp' contains an implementation of the Knuth-Morris-Pratt algorithm for searching sequences of values.
The basic premise of the Knuth-Morris-Pratt algorithm is that when a mismatch occurs, there is information in the pattern being searched for that can be used to determine where the next match could begin, enabling the skipping of some elements of the corpus that have already been examined.
It does this by building a table from the pattern being searched for, with one entry for each element in the pattern.
The algorithm was conceived in 1974 by Donald Knuth and Vaughan Pratt, and independently by James H. Morris. The three published it jointly in 1977 in the SIAM Journal on Computing [@http://citeseer.ist.psu.edu/context/23820/0]
However, the Knuth-Morris-Pratt algorithm cannot be used with comparison predicates like `std::search`.
[heading Interface]
Nomenclature: I refer to the sequence being searched for as the "pattern", and the sequence being searched in as the "corpus".
For flexibility, the Knuth-Morris-Pratt algorithm has two interfaces; an object-based interface and a procedural one. The object-based interface builds the table in the constructor, and uses operator () to perform the search. The procedural interface builds the table and does the search all in one step. If you are going to be searching for the same pattern in multiple corpora, then you should use the object interface, and only build the tables once.
Here is the object interface:
``
template <typename patIter>
class knuth_morris_pratt {
public:
knuth_morris_pratt ( patIter first, patIter last );
~knuth_morris_pratt ();
template <typename corpusIter>
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last );
};
``
and here is the corresponding procedural interface:
``
template <typename patIter, typename corpusIter>
corpusIter knuth_morris_pratt_search (
corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last );
``
Each of the functions is passed two pairs of iterators. The first two define the corpus and the second two define the pattern. Note that the two pairs need not be of the same type, but they do need to "point" at the same type. In other words, `patIter::value_type` and `curpusIter::value_type` need to be the same type.
The return value of the function is an iterator pointing to the start of the pattern in the corpus. If the pattern is not found, it returns the end of the corpus (`corpus_last`).
[heading Performance]
The execution time of the Knuth-Morris-Pratt algorithm is linear in the size of the string being searched. Generally the algorithm gets faster as the pattern being searched for becomes longer. Its efficiency derives from the fact that with each unsuccessful attempt to find a match between the search string and the text it is searching, it uses the information gained from that attempt to rule out as many positions of the text as possible where the string cannot match.
[heading Memory Use]
The algorithm an that contains one entry for each element the pattern, plus one extra. So, when searching for a 1026 byte string, the table will have 1027 entries.
[heading Complexity]
The worst-case performance is ['O(2n)], where ['n] is the length of the corpus. The average time is ['O(n)]. The best case performance is sub-linear.
[heading Exception Safety]
Both the object-oriented and procedural versions of the Knuth-Morris-Pratt algorithm take their parameters by value and do not use any information other than what is passed in. Therefore, both interfaces provide the strong exception guarantee.
[heading Notes]
* When using the object-based interface, the pattern must remain unchanged for during the searches; i.e, from the time the object is constructed until the final call to operator () returns.
* The Knuth-Morris-Pratt algorithm requires random-access iterators for both the pattern and the corpus. It should be possible to write this to use bidirectional iterators (or possibly even forward ones), but this implementation does not do that.
[endsect] [endsect]

View File

@ -38,7 +38,9 @@ Iterator requirements: The `is_sorted` functions will work on all kinds of itera
[heading is_sorted_until] [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 { namespace boost { namespace algorithm {
@ -71,7 +73,7 @@ Given the sequence `{ 1, 2, 3, 4, 5, 9 }`, `is_sorted_until ( beg, end, std::l
There are also a set of "wrapper functions" for is_ordered which make it easy to see if an entire sequence is ordered. These functions return a boolean indicating success or failure rather than an iterator to where the out of order items were found. There are also a set of "wrapper functions" for is_ordered which make it easy to see if an entire sequence is ordered. These functions return a boolean indicating success or failure rather than an iterator to where the out of order items were found.
To test if a sequence is increasing (each element at least as large as the preceeding one): To test if a sequence is increasing (each element at least as large as the preceding one):
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename Iterator> template <typename Iterator>
@ -82,7 +84,7 @@ namespace boost { namespace algorithm {
}} }}
`` ``
To test if a sequence is decreasing (each element no larger than the preceeding one): To test if a sequence is decreasing (each element no larger than the preceding one):
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
@ -94,7 +96,7 @@ namespace boost { namespace algorithm {
}} }}
`` ``
To test if a sequence is strictly increasing (each element larger than the preceeding one): To test if a sequence is strictly increasing (each element larger than the preceding one):
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename Iterator> template <typename Iterator>
@ -105,7 +107,7 @@ namespace boost { namespace algorithm {
}} }}
`` ``
To test if a sequence is strictly decreasing (each element smaller than the preceeding one): To test if a sequence is strictly decreasing (each element smaller than the preceding one):
`` ``
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
template <typename Iterator> template <typename Iterator>

0
include/boost/algorithm/clamp.hpp Executable file → Normal file
View File

View File

@ -12,6 +12,7 @@
#ifndef BOOST_ALGORITHM_ALL_OF_HPP #ifndef BOOST_ALGORITHM_ALL_OF_HPP
#define BOOST_ALGORITHM_ALL_OF_HPP #define BOOST_ALGORITHM_ALL_OF_HPP
#include <algorithm> // for std::all_of, if available
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>

View File

@ -14,6 +14,7 @@
#ifndef BOOST_ALGORITHM_ANY_OF_HPP #ifndef BOOST_ALGORITHM_ANY_OF_HPP
#define BOOST_ALGORITHM_ANY_OF_HPP #define BOOST_ALGORITHM_ANY_OF_HPP
#include <algorithm> // for std::any_of, if available
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>

View File

@ -12,7 +12,7 @@
#ifndef BOOST_ALGORITHM_COPY_IF_HPP #ifndef BOOST_ALGORITHM_COPY_IF_HPP
#define BOOST_ALGORITHM_COPY_IF_HPP #define BOOST_ALGORITHM_COPY_IF_HPP
#include <algorithm> // for std::copy_if, if available #include <algorithm> // for std::copy_if, if available
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
@ -39,7 +39,7 @@ OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator
{ {
for ( ; first != last; ++first ) for ( ; first != last; ++first )
if (p(*first)) if (p(*first))
*result++ = first; *result++ = *first;
return result; return result;
} }
#endif #endif
@ -75,7 +75,7 @@ OutputIterator copy_while ( InputIterator first, InputIterator last,
OutputIterator result, Predicate p ) OutputIterator result, Predicate p )
{ {
for ( ; first != last && p(*first); ++first ) for ( ; first != last && p(*first); ++first )
*result++ = first; *result++ = *first;
return result; return result;
} }
@ -109,7 +109,7 @@ template<typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) OutputIterator copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
{ {
for ( ; first != last && !p(*first); ++first ) for ( ; first != last && !p(*first); ++first )
*result++ = first; *result++ = *first;
return result; return result;
} }

View File

@ -71,4 +71,4 @@ OutputIterator iota_n ( OutputIterator out, T value, std::size_t n )
}} }}
#endif // BOOST_ALGORITHM_IOTA_HPP #endif // BOOST_ALGORITHM_IOTA_HPP

View File

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

View File

@ -46,7 +46,7 @@ namespace detail {
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p ) /// \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 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
/// ///
/// \param first The start of the input sequence /// \param first The start of the input sequence
/// \param last One past the end of the input sequence /// \param last One past the end of the input sequence
@ -88,7 +88,7 @@ bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
} }
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 ) /// \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 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
/// ///
/// \param first The start of the input sequence /// \param first The start of the input sequence
/// \param last One past the end of the input sequence /// \param last One past the end of the input sequence
@ -108,7 +108,7 @@ bool is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIter
#endif #endif
/// \fn is_permutation ( const Range &r, ForwardIterator first2 ) /// \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 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
/// ///
/// \param r The input range /// \param r The input range
/// \param first2 The start of the second sequence /// \param first2 The start of the second sequence
@ -119,7 +119,7 @@ bool is_permutation ( const Range &r, ForwardIterator first2 )
} }
/// \fn is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred ) /// \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 /// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
/// ///
/// \param r The input range /// \param r The input range
/// \param first2 The start of the second sequence /// \param first2 The start of the second sequence
@ -136,4 +136,4 @@ is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
}} }}
#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP #endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP

View File

@ -27,7 +27,7 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L #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_until; // Section 25.4.1.5
using std::is_sorted; // Section 25.4.1.5 using std::is_sorted; // Section 25.4.1.5
#else #else
@ -46,7 +46,7 @@ using std::is_sorted; // Section 25.4.1.5
ForwardIterator next = first; ForwardIterator next = first;
while ( ++next != last ) while ( ++next != last )
{ {
if ( !p ( *first, *next )) if ( p ( *next, *first ))
return next; return next;
first = next; first = next;
} }
@ -63,7 +63,7 @@ using std::is_sorted; // Section 25.4.1.5
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last ) ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last )
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 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>());
} }
@ -94,7 +94,7 @@ using std::is_sorted; // Section 25.4.1.5
#endif #endif
/// ///
/// -- Range based versions of the C++11 functions /// -- Range based versions of the C++11 functions
/// ///
/// \fn is_sorted_until ( const R &range, Pred p ) /// \fn is_sorted_until ( const R &range, Pred p )
@ -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 )); 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 ) /// \fn is_sorted ( const R &range, Pred p )
/// \return whether or not the entire range R is sorted /// \return whether or not the entire range R is sorted
/// (according to the comparison predicate 'p'). /// (according to the comparison predicate 'p').
@ -157,7 +153,7 @@ namespace detail {
/// ///
/// -- Range based versions of the C++11 functions /// -- Range based versions of the C++11 functions
/// ///
/// \fn is_increasing ( ForwardIterator first, ForwardIterator last ) /// \fn is_increasing ( ForwardIterator first, ForwardIterator last )
@ -173,7 +169,7 @@ namespace detail {
bool is_increasing ( ForwardIterator first, ForwardIterator last ) bool is_increasing ( ForwardIterator first, ForwardIterator last )
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 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 ) bool is_decreasing ( ForwardIterator first, ForwardIterator last )
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 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 ) /// \fn is_decreasing ( const R &range )
@ -238,7 +234,7 @@ namespace detail {
bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last ) bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 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 ) /// \fn is_strictly_increasing ( const R &range )
@ -269,7 +265,7 @@ namespace detail {
bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last ) bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type; 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 ) /// \fn is_strictly_decreasing ( const R &range )

View File

@ -12,6 +12,7 @@
#ifndef BOOST_ALGORITHM_NONE_OF_HPP #ifndef BOOST_ALGORITHM_NONE_OF_HPP
#define BOOST_ALGORITHM_NONE_OF_HPP #define BOOST_ALGORITHM_NONE_OF_HPP
#include <algorithm> // for std::none_of, if available
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>

View File

@ -12,6 +12,7 @@
#ifndef BOOST_ALGORITHM_PARTITION_COPY_HPP #ifndef BOOST_ALGORITHM_PARTITION_COPY_HPP
#define BOOST_ALGORITHM_PARTITION_COPY_HPP #define BOOST_ALGORITHM_PARTITION_COPY_HPP
#include <algorithm> // for std::partition_copy, if available
#include <utility> // for make_pair #include <utility> // for make_pair
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>

View File

@ -12,7 +12,7 @@
#ifndef BOOST_ALGORITHM_PARTITION_POINT_HPP #ifndef BOOST_ALGORITHM_PARTITION_POINT_HPP
#define BOOST_ALGORITHM_PARTITION_POINT_HPP #define BOOST_ALGORITHM_PARTITION_POINT_HPP
#include <algorithm> // for std::partition_point, if available #include <algorithm> // for std::partition_point, if available
#include <boost/range/begin.hpp> #include <boost/range/begin.hpp>
#include <boost/range/end.hpp> #include <boost/range/end.hpp>
@ -20,12 +20,12 @@
namespace boost { namespace algorithm { namespace boost { namespace algorithm {
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
// Use the C++11 versions of iota if it is available // Use the C++11 versions of partition_point if it is available
using std::partition_point; // Section 25.3.13 using std::partition_point; // Section 25.3.13
#else #else
/// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p ) /// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
/// \brief Given a partitioned range, returns the partition point, i.e, the first element /// \brief Given a partitioned range, returns the partition point, i.e, the first element
/// that does not satisfy p /// that does not satisfy p
/// ///
/// \param first The start of the input sequence /// \param first The start of the input sequence
/// \param last One past the end of the input sequence /// \param last One past the end of the input sequence
@ -69,4 +69,4 @@ typename boost::range_iterator<Range> partition_point ( Range &r, Predicate p )
}} }}
#endif // BOOST_ALGORITHM_PARTITION_POINT_HPP #endif // BOOST_ALGORITHM_PARTITION_POINT_HPP

View File

@ -45,20 +45,16 @@ namespace boost { namespace algorithm {
\struct non_hex_input \struct non_hex_input
\brief Thrown when a non-hex value (0-9, A-F) encountered when decoding. \brief Thrown when a non-hex value (0-9, A-F) encountered when decoding.
Contains the offending character Contains the offending character
\struct not_enough_input \struct not_enough_input
\brief Thrown when the input sequence unexpectedly ends \brief Thrown when the input sequence unexpectedly ends
*/ */
struct hex_decode_error: virtual boost::exception, virtual std::exception {}; struct hex_decode_error : virtual boost::exception, virtual std::exception {};
struct not_enough_input : public hex_decode_error {}; struct not_enough_input : virtual hex_decode_error {};
struct non_hex_input : public hex_decode_error { struct non_hex_input : virtual hex_decode_error {};
non_hex_input ( char ch ) : bad_char ( ch ) {} typedef boost::error_info<struct bad_char_,char> bad_char;
char bad_char;
private:
non_hex_input (); // don't allow creation w/o a char
};
namespace detail { namespace detail {
/// \cond DOXYGEN_HIDE /// \cond DOXYGEN_HIDE
@ -73,14 +69,18 @@ namespace detail {
return std::copy ( res, res + num_hex_digits, out ); return std::copy ( res, res + num_hex_digits, out );
} }
// this needs to be in an un-named namespace because it is not a template
// and might get included in several compilation units. This could cause
// multiple definition errors at link time.
namespace {
unsigned hex_char_to_int ( char c ) { unsigned hex_char_to_int ( char c ) {
if ( c >= '0' && c <= '9' ) return c - '0'; 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;
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 return 0; // keep dumb compilers happy
} }
}
// My own iterator_traits class. // My own iterator_traits class.
// It is here so that I can "reach inside" some kinds of output iterators // It is here so that I can "reach inside" some kinds of output iterators
@ -109,38 +109,30 @@ namespace detail {
// The first one is the output type, the second one is the character type of // The first one is the output type, the second one is the character type of
// the underlying stream, the third is the character traits. // the underlying stream, the third is the character traits.
// We only care about the first one. // We only care about the first one.
template<typename T, typename charType, typename traits> template<typename T, typename charType, typename traits>
struct hex_iterator_traits< std::ostream_iterator<T, charType, traits> > { struct hex_iterator_traits< std::ostream_iterator<T, charType, traits> > {
typedef T value_type; 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> template <typename Iterator>
struct iterator_value_type { bool iter_end ( Iterator current, Iterator last ) { return current == last; }
// 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 T>
}; bool ptr_end ( const T* ptr, const T* /*end*/ ) { return *ptr == '\0'; }
// What can we assume here about the inputs? // What can we assume here about the inputs?
// is std::iterator_traits<InputIterator>::value_type always 'char' ? // is std::iterator_traits<InputIterator>::value_type always 'char' ?
// Could it be wchar_t, say? Does it matter? // Could it be wchar_t, say? Does it matter?
// We are assuming ASCII for the values - but what about the storage? // We are assuming ASCII for the values - but what about the storage?
template <typename InputIterator, typename OutputIterator> template <typename InputIterator, typename OutputIterator, typename EndPred>
typename boost::enable_if<boost::is_integral<typename iterator_value_type<OutputIterator>::value_type>, OutputIterator>::type typename boost::enable_if<boost::is_integral<typename hex_iterator_traits<OutputIterator>::value_type>, OutputIterator>::type
decode_one ( InputIterator &first, InputIterator last, OutputIterator out ) { decode_one ( InputIterator &first, InputIterator last, OutputIterator out, EndPred pred ) {
typedef typename iterator_value_type<OutputIterator>::value_type T; typedef typename hex_iterator_traits<OutputIterator>::value_type T;
T res (0); T res (0);
// Need to make sure that we get can read that many chars here. // 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 ) { 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 ()); BOOST_THROW_EXCEPTION (not_enough_input ());
res = ( 16 * res ) + hex_char_to_int (static_cast<char> (*first)); res = ( 16 * res ) + hex_char_to_int (static_cast<char> (*first));
} }
@ -209,7 +201,7 @@ hex ( const Range &r, OutputIterator out ) {
template <typename InputIterator, typename OutputIterator> template <typename InputIterator, typename OutputIterator>
OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) { OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) {
while ( first != last ) while ( first != last )
out = detail::decode_one ( first, last, out ); out = detail::decode_one ( first, last, out, detail::iter_end<InputIterator> );
return out; return out;
} }
@ -223,14 +215,12 @@ OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator o
/// \note Based on the MySQL function of the same name /// \note Based on the MySQL function of the same name
template <typename T, typename OutputIterator> template <typename T, typename OutputIterator>
OutputIterator unhex ( const T *ptr, OutputIterator out ) { 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 // 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' // malformed input exception. It would be nicer to throw a 'Not enough input'
// exception - but how much extra work would that require? // 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 ) 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; return out;
} }

View File

@ -99,8 +99,10 @@ namespace boost {
// if odd number of elements, treat last element // if odd number of elements, treat last element
if (first != last) { // odd number of elements if (first != last) { // odd number of elements
if (comp(first, min_result)) if (comp(first, min_result)) {
min_result = first, potential_min_result = last; min_result = first;
potential_min_result = last;
}
else if (comp(max_result, first)) else if (comp(max_result, first))
max_result = first; max_result = first;
} }

8
include/boost/algorithm/searching/boyer_moore.hpp Executable file → Normal file
View File

@ -33,8 +33,8 @@ References:
http://www.cs.utexas.edu/users/moore/best-ideas/string-searching/ http://www.cs.utexas.edu/users/moore/best-ideas/string-searching/
http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
Explanations: boostinspect:noascii (test tool complains) Explanations:
http://en.wikipedia.org/wiki/BoyerMoore_string_search_algorithm http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
http://www.movsd.com/bm.htm http://www.movsd.com/bm.htm
http://www.cs.ucdavis.edu/~gusfield/cs224f09/bnotes.pdf http://www.cs.ucdavis.edu/~gusfield/cs224f09/bnotes.pdf
@ -223,7 +223,7 @@ Requirements:
corpusIter boyer_moore_search ( corpusIter boyer_moore_search (
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern ) 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)); boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
return bm ( corpus_first, corpus_last ); return bm ( corpus_first, corpus_last );
} }
@ -242,7 +242,7 @@ Requirements:
typename boost::range_iterator<CorpusRange>::type typename boost::range_iterator<CorpusRange>::type
boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern ) 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)); boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
return bm (boost::begin (corpus), boost::end (corpus)); return bm (boost::begin (corpus), boost::end (corpus));
} }

View File

@ -14,6 +14,11 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/static_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/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/bm_traits.hpp> #include <boost/algorithm/searching/detail/bm_traits.hpp>
@ -84,6 +89,11 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
return this->do_search ( corpus_first, corpus_last ); 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: private:
/// \cond DOXYGEN_HIDE /// \cond DOXYGEN_HIDE
patIter pat_first, pat_last; patIter pat_first, pat_last;
@ -119,6 +129,9 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
// \endcond // \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, /// \fn boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last ) /// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern. /// \brief Searches the corpus for the pattern.
@ -130,10 +143,55 @@ http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
/// ///
template <typename patIter, typename corpusIter> template <typename patIter, typename corpusIter>
corpusIter boyer_moore_horspool_search ( corpusIter boyer_moore_horspool_search (
corpusIter corpus_first, corpusIter corpus_last, corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last ) { patIter pat_first, patIter pat_last )
{
boyer_moore_horspool<patIter> bmh ( pat_first, pat_last ); boyer_moore_horspool<patIter> bmh ( pat_first, pat_last );
return bmh ( corpus_first, corpus_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));
} }
}} }}

0
include/boost/algorithm/searching/detail/bm_traits.hpp Executable file → Normal file
View File

0
include/boost/algorithm/searching/detail/debugging.hpp Executable file → Normal file
View File

View File

@ -15,6 +15,11 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/static_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/type_traits/is_same.hpp>
#include <boost/algorithm/searching/detail/debugging.hpp> #include <boost/algorithm/searching/detail/debugging.hpp>
@ -32,7 +37,7 @@ namespace boost { namespace algorithm {
* Random-access iterators * Random-access iterators
* The two iterator types (I1 and I2) must "point to" the same underlying type. * The two iterator types (I1 and I2) must "point to" the same underlying type.
http://en.wikipedia.org/wiki/KnuthMorrisPratt_algorithm http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm
http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm
*/ */
@ -79,6 +84,11 @@ namespace boost { namespace algorithm {
return do_search ( corpus_first, corpus_last, k_corpus_length ); 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: private:
/// \cond DOXYGEN_HIDE /// \cond DOXYGEN_HIDE
patIter pat_first, pat_last; patIter pat_first, pat_last;
@ -179,6 +189,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, /// \fn knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last,
/// patIter pat_first, patIter pat_last ) /// patIter pat_first, patIter pat_last )
/// \brief Searches the corpus for the pattern. /// \brief Searches the corpus for the pattern.
@ -190,10 +203,55 @@ namespace boost { namespace algorithm {
/// ///
template <typename patIter, typename corpusIter> template <typename patIter, typename corpusIter>
corpusIter knuth_morris_pratt_search ( corpusIter knuth_morris_pratt_search (
corpusIter corpus_first, corpusIter corpus_last, corpusIter corpus_first, corpusIter corpus_last,
patIter pat_first, patIter pat_last ) { patIter pat_first, patIter pat_last )
{
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last ); knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
return kmp ( corpus_first, corpus_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));
} }
}} }}

View File

@ -56,7 +56,7 @@ namespace boost {
// Copy the beginning of the sequence // Copy the beginning of the sequence
Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output ); Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output );
// Format find result // Format find result
// Copy formated result // Copy formatted result
Output = 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 // Copy the rest of the sequence
Output = std::copy( M.end(), ::boost::end(Input), Output ); Output = std::copy( M.end(), ::boost::end(Input), Output );
@ -118,11 +118,11 @@ namespace boost {
InputT Output; InputT Output;
// Copy the beginning of the sequence // Copy the beginning of the sequence
insert( Output, ::boost::end(Output), ::boost::begin(Input), M.begin() ); boost::algorithm::detail::insert( Output, ::boost::end(Output), ::boost::begin(Input), M.begin() );
// Copy formated result // Copy formatted result
insert( Output, ::boost::end(Output), M.format_result() ); boost::algorithm::detail::insert( Output, ::boost::end(Output), M.format_result() );
// Copy the rest of the sequence // Copy the rest of the sequence
insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) ); boost::algorithm::detail::insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) );
return Output; return Output;
} }

View File

@ -58,7 +58,7 @@ namespace boost {
{ {
// Copy the beginning of the sequence // Copy the beginning of the sequence
Output = std::copy( LastMatch, M.begin(), Output ); Output = std::copy( LastMatch, M.begin(), Output );
// Copy formated result // Copy formatted result
Output = 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 // Proceed to the next match
@ -134,9 +134,9 @@ namespace boost {
while( M ) while( M )
{ {
// Copy the beginning of the sequence // Copy the beginning of the sequence
insert( Output, ::boost::end(Output), LastMatch, M.begin() ); boost::algorithm::detail::insert( Output, ::boost::end(Output), LastMatch, M.begin() );
// Copy formated result // Copy formatted result
insert( Output, ::boost::end(Output), M.format_result() ); boost::algorithm::detail::insert( Output, ::boost::end(Output), M.format_result() );
// Proceed to the next match // Proceed to the next match
LastMatch=M.end(); LastMatch=M.end();
@ -218,7 +218,7 @@ namespace boost {
// Adjust search iterator // Adjust search iterator
SearchIt=M.end(); SearchIt=M.end();
// Copy formated replace to the storage // Copy formatted replace to the storage
::boost::algorithm::detail::copy_to_storage( Storage, M.format_result() ); ::boost::algorithm::detail::copy_to_storage( Storage, M.format_result() );
// Find range for a next match // Find range for a next match

View File

@ -92,7 +92,7 @@ namespace boost {
// find last functor -----------------------------------------------// // find last functor -----------------------------------------------//
// find the last match a subseqeunce in the sequence ( functor ) // find the last match a subsequence in the sequence ( functor )
/* /*
Returns a pair <begin,end> marking the subsequence in the sequence. Returns a pair <begin,end> marking the subsequence in the sequence.
If the find fails, returns <End,End> If the find fails, returns <End,End>

View File

@ -60,14 +60,14 @@ namespace boost {
return *this; return *this;
} }
// Match result retrival // Match result retrieval
const match_results_type& match_results() const const match_results_type& match_results() const
{ {
return m_MatchResults; return m_MatchResults;
} }
private: private:
// Saved matchresult // Saved match result
match_results_type m_MatchResults; match_results_type m_MatchResults;
}; };

View File

@ -86,7 +86,7 @@ namespace boost {
//! Find first algorithm ( case insensitive ) //! Find first algorithm ( case insensitive )
/*! /*!
Search for the first occurence of the substring in the input. Search for the first occurrence of the substring in the input.
Searching is case insensitive. Searching is case insensitive.
\param Input A string which will be searched. \param Input A string which will be searched.
@ -293,7 +293,7 @@ namespace boost {
If the "token compress mode" is enabled, adjacent tokens are considered to be one match. If the "token compress mode" is enabled, adjacent tokens are considered to be one match.
\param Input A input string. \param Input A input string.
\param Pred An unary predicate to identify a token \param Pred A unary predicate to identify a token
\param eCompress Enable/Disable compressing of adjacent tokens \param eCompress Enable/Disable compressing of adjacent tokens
\return \return
An \c iterator_range delimiting the match. An \c iterator_range delimiting the match.

View File

@ -132,7 +132,10 @@ namespace boost {
// increment // increment
void increment() void increment()
{ {
m_Match=this->do_find(m_Match.end(),m_End); if(m_Match.begin() == m_Match.end())
m_Match=this->do_find(m_Match.end(),m_End);
else
m_Match=this->do_find(m_Match.begin()+1,m_End);
} }
// comparison // comparison

View File

@ -39,7 +39,7 @@ namespace boost {
Constructs a \c const_formatter. Const formatter always returns Constructs a \c const_formatter. Const formatter always returns
the same value, regardless of the parameter. the same value, regardless of the parameter.
\param Format A predefined value used as a result for formating \param Format A predefined value used as a result for formatting
\return An instance of the \c const_formatter object. \return An instance of the \c const_formatter object.
*/ */
template<typename RangeT> template<typename RangeT>
@ -95,7 +95,7 @@ namespace boost {
to extract a portion of the formatted sequence. The first finder's match is returned to extract a portion of the formatted sequence. The first finder's match is returned
as a result as a result
\param Finder a finder used to select a portion of the formated sequence \param Finder a finder used to select a portion of the formatted sequence
\return An instance of the \c dissect_formatter object. \return An instance of the \c dissect_formatter object.
*/ */
template<typename FinderT> template<typename FinderT>

View File

@ -60,7 +60,7 @@ namespace boost {
a match). a match).
\param Input A container which will be searched. \param Input A container which will be searched.
\param Finder A Finder object used for searching \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. \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 Each match is used as a separator of segments. These segments are then
returned in the result. 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 Both outer and inner container must have constructor taking a pair
of iterators as an argument. of iterators as an argument.
Typical type of the result is Typical type of the result is
@ -131,7 +131,7 @@ namespace boost {
a match). a match).
\param Input A container which will be searched. \param Input A container which will be searched.
\param Finder A finder object used for searching \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. \note Prior content of the result will be overwritten.
*/ */

View File

@ -15,7 +15,7 @@
/* /*
\file boost/algorith/string/predicate_facade.hpp \file boost/algorith/string/predicate_facade.hpp
This file containes predicate_facade definition. This template class is used This file contains predicate_facade definition. This template class is used
to identify classification predicates, so they can be combined using to identify classification predicates, so they can be combined using
composition operators. composition operators.
*/ */

View File

@ -32,7 +32,7 @@ namespace boost {
Construct the \c regex_finder. Finder uses the regex engine to search Construct the \c regex_finder. Finder uses the regex engine to search
for a match. for a match.
Result is given in \c regex_search_result. This is an extension Result is given in \c regex_search_result. This is an extension
of the iterator_range. In addition it containes match results of the iterator_range. In addition it contains match results
from the \c regex_search algorithm. from the \c regex_search algorithm.
\param Rx A regular expression \param Rx A regular expression

View File

@ -50,7 +50,7 @@ namespace boost {
\param Output An output iterator to which the result will be copied \param Output An output iterator to which the result will be copied
\param Input An input range \param Input An input range
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
\return \return
An output iterator pointing just after the last inserted character or An output iterator pointing just after the last inserted character or
a copy of the input a copy of the input
@ -118,7 +118,7 @@ namespace boost {
The input sequence is modified in-place. The input sequence is modified in-place.
\param Input An input sequence \param Input An input sequence
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
*/ */
template<typename SequenceT, typename PredicateT> template<typename SequenceT, typename PredicateT>
inline void trim_left_if(SequenceT& Input, PredicateT IsSpace) inline void trim_left_if(SequenceT& Input, PredicateT IsSpace)
@ -158,7 +158,7 @@ namespace boost {
\param Output An output iterator to which the result will be copied \param Output An output iterator to which the result will be copied
\param Input An input range \param Input An input range
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
\return \return
An output iterator pointing just after the last inserted character or An output iterator pointing just after the last inserted character or
a copy of the input a copy of the input
@ -228,7 +228,7 @@ namespace boost {
The input sequence is modified in-place. The input sequence is modified in-place.
\param Input An input sequence \param Input An input sequence
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
*/ */
template<typename SequenceT, typename PredicateT> template<typename SequenceT, typename PredicateT>
inline void trim_right_if(SequenceT& Input, PredicateT IsSpace) inline void trim_right_if(SequenceT& Input, PredicateT IsSpace)
@ -270,7 +270,7 @@ namespace boost {
\param Output An output iterator to which the result will be copied \param Output An output iterator to which the result will be copied
\param Input An input range \param Input An input range
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
\return \return
An output iterator pointing just after the last inserted character or An output iterator pointing just after the last inserted character or
a copy of the input a copy of the input
@ -352,7 +352,7 @@ namespace boost {
The input sequence is modified in-place. The input sequence is modified in-place.
\param Input An input sequence \param Input An input sequence
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
*/ */
template<typename SequenceT, typename PredicateT> template<typename SequenceT, typename PredicateT>
inline void trim_if(SequenceT& Input, PredicateT IsSpace) inline void trim_if(SequenceT& Input, PredicateT IsSpace)

View File

@ -49,7 +49,7 @@ namespace boost {
The result is a trimmed copy of the input The result is a trimmed copy of the input
\param Input An input sequence \param Input An input sequence
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
\return A trimmed copy of the input \return A trimmed copy of the input
*/ */
template<typename SequenceT, typename PredicateT> template<typename SequenceT, typename PredicateT>
@ -70,7 +70,7 @@ namespace boost {
The input sequence is modified in-place. The input sequence is modified in-place.
\param Input An input sequence \param Input An input sequence
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
*/ */
template<typename SequenceT, typename PredicateT> template<typename SequenceT, typename PredicateT>
inline void trim_all_if(SequenceT& Input, PredicateT IsSpace) inline void trim_all_if(SequenceT& Input, PredicateT IsSpace)
@ -126,7 +126,7 @@ namespace boost {
\param Input An input sequence \param Input An input sequence
\param Fill A string used to fill the inner spaces \param Fill A string used to fill the inner spaces
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
\return A trimmed copy of the input \return A trimmed copy of the input
*/ */
template<typename SequenceT, typename RangeT, typename PredicateT> template<typename SequenceT, typename RangeT, typename PredicateT>
@ -149,7 +149,7 @@ namespace boost {
\param Input An input sequence \param Input An input sequence
\param Fill A string used to fill the inner spaces \param Fill A string used to fill the inner spaces
\param IsSpace An unary predicate identifying spaces \param IsSpace A unary predicate identifying spaces
*/ */
template<typename SequenceT, typename RangeT, typename PredicateT> template<typename SequenceT, typename RangeT, typename PredicateT>
inline void trim_fill_if(SequenceT& Input, const RangeT& Fill, PredicateT IsSpace) inline void trim_fill_if(SequenceT& Input, const RangeT& Fill, PredicateT IsSpace)

View File

@ -13,7 +13,7 @@
/*! \file /*! \file
Cumulative include for string_algo library. Cumulative include for string_algo library.
In addtion to string.hpp contains also regex-related stuff. In addition to string.hpp contains also regex-related stuff.
*/ */
#include <boost/regex.hpp> #include <boost/regex.hpp>

13
index.html Normal file
View 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> &nbsp;<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>

View File

@ -350,7 +350,7 @@ separation into two header files.</p>
std::max.</b></h4> std::max.</b></h4>
<p>I am aware of the problems with std::min and <p>I am aware of the problems with std::min and
std::max, and all the debate that has been going on (please consult std::max, and all the debate that has been going on (please consult
<a href="http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/alexandr.htm">Alexandrescu's paper</a> and the links therein). But I don't see the purpose of this <a href="#Alexandrescu">Alexandrescu's paper</a> and the links therein). But I don't see the purpose of this
library as fixing something that is part of the C++ standard. I humbly library as fixing something that is part of the C++ standard. I humbly
think it's beyond the scope of this library. Rather, I am think it's beyond the scope of this library. Rather, I am
following the way of the standard in simply providing one more function following the way of the standard in simply providing one more function
@ -485,7 +485,12 @@ to keep it like this.
<a name="acks"> <a name="acks">
<h3> <h3>
Acknowledgements</h3> Acknowledgements</h3>
My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>)
<a name="Alexandrescu">
<a href="http://www.drdobbs.com/generic-min-and-max-redivivus/184403774">Generic: Min and Max Redivivus, by Andrei Alexandrescu</a>
Dr. Dobbs, April 2001
<p>My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>)
who had <tt>minmax_element</tt> as an assignment helped clarify the issues, who had <tt>minmax_element</tt> as an assignment helped clarify the issues,
and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>. and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>.
The identification of the issue surrounding <tt>max_element</tt> is solely The identification of the issue surrounding <tt>max_element</tt> is solely
@ -516,7 +521,7 @@ Comparable</a></tt>,
<tt><a href="http://www.sgi.com/tech/stl/nth_element.html">nth_element</a></tt> <tt><a href="http://www.sgi.com/tech/stl/nth_element.html">nth_element</a></tt>
. .
<hr SIZE="6"> <hr SIZE="6">
<br>Last modified 2004-07-01 <br>Last modified 2012-12-10
<p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute; <p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute;
Br&ouml;nnimann, Polytechnic University, 2002--2004. Br&ouml;nnimann, Polytechnic University, 2002--2004.
Use, modification, and distribution is subject to the Boost Software Use, modification, and distribution is subject to the Boost Software

View File

@ -162,8 +162,8 @@ boost::iterator_range&lt;std::string&gt; simple_finder(
<para> <para>
Similarly to finders, formatters generalize format operations. When a finder is used to Similarly to finders, formatters generalize format operations. When a finder is used to
select a part of the input, formatter takes this selection and performs some formating select a part of the input, formatter takes this selection and performs some formatting
on it. Algorithms can abstract from formating using a formatter. on it. Algorithms can abstract from formatting using a formatter.
</para> </para>
<para> <para>
<emphasis role="bold">Examples</emphasis> <emphasis role="bold">Examples</emphasis>
@ -171,7 +171,7 @@ boost::iterator_range&lt;std::string&gt; simple_finder(
<para> <para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
Formatter implemented as a class. This Formatter does not perform any formating and Formatter implemented as a class. This Formatter does not perform any formatting and
returns the match, repackaged. <code>operator()</code> returns the match, repackaged. <code>operator()</code>
is templated, so that the Formatter can be used on any Finder type. is templated, so that the Formatter can be used on any Finder type.

View File

@ -36,7 +36,7 @@
New comparison predicates <code>is_less</code>, <code>is_not_greater</code> New comparison predicates <code>is_less</code>, <code>is_not_greater</code>
</listitem> </listitem>
<listitem> <listitem>
Negative indexes support (like Perl) in various algorihtms Negative indexes support (like Perl) in various algorithms
(<code>*_head/tail</code>, <code>*_nth</code>). (<code>*_head/tail</code>, <code>*_nth</code>).
</listitem> </listitem>
</itemizedlist> </itemizedlist>

View File

@ -130,17 +130,17 @@
string str1("command.com"); string str1("command.com");
cout cout
&lt;&lt; str1 &lt;&lt; str1
&lt;&lt; (is_executable("command.com")? "is": "is not") &lt;&lt; (is_executable(str1)? "is": "is not")
&lt;&lt; "an executable" &lt;&lt; "an executable"
&lt;&lt; endl; // prints "command.com is an executable" &lt;&lt; endl; // prints "command.com is an executable"
//.. //..
char text1[]="hello world!"; char text1[]="hello";
cout cout
&lt;&lt; text1 &lt;&lt; text1
&lt;&lt; (all( text1, is_lower() )? "is": "is not") &lt;&lt; (all( text1, is_lower() )? " is": " is not")
&lt;&lt; " written in the lower case" &lt;&lt; " written in the lower case"
&lt;&lt; endl; // prints "hello world! is written in the lower case" &lt;&lt; endl; // prints "hello is written in the lower case"
</programlisting> </programlisting>
<para> <para>
The predicates determine whether if a substring is contained in the input string The predicates determine whether if a substring is contained in the input string
@ -149,6 +149,11 @@
simply contains the substring or if both strings are equal. See the reference for simply contains the substring or if both strings are equal. See the reference for
<headername>boost/algorithm/string/predicate.hpp</headername> for more details. <headername>boost/algorithm/string/predicate.hpp</headername> for more details.
</para> </para>
<para>
Note that if we had used "hello world" as the input to the test, it would have
output "hello world is not written in the lower case" because the space in the
input string is not a lower case letter.
</para>
<para> <para>
In addition the algorithm <functionname>all()</functionname> checks In addition the algorithm <functionname>all()</functionname> checks
all elements of a container to satisfy a condition specified by a predicate. all elements of a container to satisfy a condition specified by a predicate.

View File

@ -33,7 +33,7 @@ int main()
cout << "str1 ends with \"123\": " << cout << "str1 ends with \"123\": " <<
(ends_with( str1, string("123") )?"true":"false") << endl; (ends_with( str1, string("123") )?"true":"false") << endl;
// Check if str1 containes 'xxx' // Check if str1 contains 'xxx'
cout << "str1 contains \"xxx\": " << cout << "str1 contains \"xxx\": " <<
(contains( str1, string("xxx") )?"true":"false") << endl; (contains( str1, string("xxx") )?"true":"false") << endl;

View File

@ -9,6 +9,7 @@
#include <boost/algorithm/string/find.hpp> #include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
// Include unit test framework // Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp> #include <boost/test/included/test_exec_monitor.hpp>
@ -248,6 +249,20 @@ void find_test()
ostringstream osstr; ostringstream osstr;
osstr << find_first( str1, "abc" ); osstr << find_first( str1, "abc" );
BOOST_CHECK( osstr.str()=="abc" ); BOOST_CHECK( osstr.str()=="abc" );
// Empty string test
BOOST_CHECKPOINT( "overlapping" );
std::string overlap_target("aaaa");
std::vector<boost::iterator_range<std::string::iterator> > overlap_results;
boost::algorithm::find_all(overlap_results, overlap_target, string("aaa"));
BOOST_CHECK( overlap_results.size() == 2 );
std::string overlap_target2("aaaabbbbaaaa");
boost::algorithm::find_all(overlap_results, overlap_target2, string("bb"));
BOOST_CHECK( overlap_results.size() == 3 );
boost::algorithm::find_all(overlap_results, overlap_target2, string("aa"));
BOOST_CHECK( overlap_results.size() == 6 );
} }
// test main // test main

View File

@ -114,7 +114,7 @@ static void replace_test()
string fmt2("_xXx_"); string fmt2("_xXx_");
vector<int> vec1( str1.begin(), str1.end() ); vector<int> vec1( str1.begin(), str1.end() );
// inmutable tests // immutable tests
// basic tests // basic tests
BOOST_CHECK( replace_regex_copy( str1, rx1, fmt1 )==string("123_A1C_xxxa23cXXXa456c321") ); BOOST_CHECK( replace_regex_copy( str1, rx1, fmt1 )==string("123_A1C_xxxa23cXXXa456c321") );

View File

@ -144,18 +144,35 @@ void iterator_test()
find_iterator<string::iterator> fiter=make_find_iterator(str1, first_finder("xx")); find_iterator<string::iterator> fiter=make_find_iterator(str1, first_finder("xx"));
find_iterator<string::iterator> fiter2;
BOOST_CHECK(equals(*fiter, "xx")); BOOST_CHECK(equals(*fiter, "xx"));
++fiter; ++fiter;
BOOST_CHECK(equals(*fiter, "xx"));
fiter2 = fiter;
BOOST_CHECK(equals(*fiter, "xx"));
BOOST_CHECK(equals(*fiter2, "xx"));
++fiter; ++fiter;
BOOST_CHECK(fiter==find_iterator<string::iterator>()); BOOST_CHECK(fiter==find_iterator<string::iterator>());
BOOST_CHECK(equals(*fiter2, "xx"));
++fiter2;
BOOST_CHECK(fiter2==find_iterator<string::iterator>());
split_iterator<string::iterator> siter=make_split_iterator(str1, token_finder(is_any_of("-"), token_compress_on)); split_iterator<string::iterator> siter=make_split_iterator(str1, token_finder(is_any_of("-"), token_compress_on));
split_iterator<string::iterator> siter2;
BOOST_CHECK(equals(*siter, "xx")); BOOST_CHECK(equals(*siter, "xx"));
++siter; ++siter;
BOOST_CHECK(equals(*siter, "abc"));
siter2 = siter;
BOOST_CHECK(equals(*siter, "abc"));
BOOST_CHECK(equals(*siter2, "abc"));
++siter; ++siter;
BOOST_CHECK(equals(*siter, "xx")); BOOST_CHECK(equals(*siter, "xx"));
BOOST_CHECK(equals(*siter2, "abc"));
++siter; ++siter;
BOOST_CHECK(equals(*siter, "abb")); BOOST_CHECK(equals(*siter, "abb"));
++siter; ++siter;

3
test/Jamfile.v2 Executable file → Normal file
View File

@ -16,6 +16,7 @@ import testing ;
[ run search_test1.cpp : : : : search_test1 ] [ run search_test1.cpp : : : : search_test1 ]
[ run search_test2.cpp : : : : search_test2 ] [ run search_test2.cpp : : : : search_test2 ]
[ run search_test3.cpp : : : : search_test3 ] [ run search_test3.cpp : : : : search_test3 ]
[ run search_test4.cpp : : : : search_test4 ]
[ compile-fail search_fail1.cpp : : : : ] [ compile-fail search_fail1.cpp : : : : ]
[ compile-fail search_fail2.cpp : : : : ] [ compile-fail search_fail2.cpp : : : : ]
[ compile-fail search_fail3.cpp : : : : ] [ compile-fail search_fail3.cpp : : : : ]
@ -31,6 +32,7 @@ import testing ;
[ run ordered_test.cpp : : : : ordered_test ] [ run ordered_test.cpp : : : : ordered_test ]
[ run find_if_not_test1.cpp : : : : find_if_not_test1 ] [ run find_if_not_test1.cpp : : : : find_if_not_test1 ]
[ run copy_if_test1.cpp : : : : copy_if_test1 ]
[ run copy_n_test1.cpp : : : : copy_n_test1 ] [ run copy_n_test1.cpp : : : : copy_n_test1 ]
[ run iota_test1.cpp : : : : iota_test1 ] [ run iota_test1.cpp : : : : iota_test1 ]
@ -43,6 +45,7 @@ import testing ;
[ run hex_test1.cpp : : : : hex_test1 ] [ run hex_test1.cpp : : : : hex_test1 ]
[ run hex_test2.cpp : : : : hex_test2 ] [ run hex_test2.cpp : : : : hex_test2 ]
[ run hex_test3.cpp : : : : hex_test3 ] [ run hex_test3.cpp : : : : hex_test3 ]
[ run hex_test4.cpp : : : : hex_test4 ]
[ compile-fail hex_fail1.cpp ] [ compile-fail hex_fail1.cpp ]
; ;
} }

0
test/clamp_test.cpp Executable file → Normal file
View File

87
test/copy_if_test1.cpp Normal file
View File

@ -0,0 +1,87 @@
/*
Copyright (c) Marshall Clow 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_if.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
#include <list>
#include <boost/algorithm/cxx11/all_of.hpp>
namespace ba = boost::algorithm;
// namespace ba = boost;
bool is_true ( int v ) { return true; }
bool is_false ( int v ) { return false; }
bool is_even ( int v ) { return v % 2 == 0; }
bool is_odd ( int v ) { return v % 2 == 1; }
template <typename Container>
void test_sequence ( Container const &c ) {
typedef typename Container::value_type value_type;
std::vector<value_type> v;
// None of the elements
v.clear ();
ba::copy_if ( c.begin (), c.end (), back_inserter ( v ), is_false);
BOOST_CHECK ( v.size () == 0 );
v.clear ();
ba::copy_if ( c, back_inserter ( v ), is_false);
BOOST_CHECK ( v.size () == 0 );
// All the elements
v.clear ();
ba::copy_if ( c.begin (), c.end (), back_inserter ( v ), is_true);
BOOST_CHECK ( v.size () == c.size ());
BOOST_CHECK ( std::equal ( c.begin (), c.end (), v.begin ()));
v.clear ();
ba::copy_if ( c, back_inserter ( v ), is_true);
BOOST_CHECK ( v.size () == c.size ());
BOOST_CHECK ( v.size () == c.size ());
BOOST_CHECK ( std::equal ( c.begin (), c.end (), v.begin ()));
// Some of the elements
v.clear ();
ba::copy_if ( c.begin (), c.end (), back_inserter ( v ), is_even );
BOOST_CHECK ( v.size () == std::count_if ( c.begin (), c.end (), is_even ));
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
v.clear ();
ba::copy_if ( c, back_inserter ( v ), is_even );
BOOST_CHECK ( v.size () == std::count_if ( c.begin (), c.end (), is_even ));
BOOST_CHECK ( ba::all_of ( v.begin (), v.end (), is_even ));
}
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;
}

View File

@ -22,60 +22,60 @@ namespace ba = boost::algorithm;
template <typename Container> template <typename Container>
void test_sequence ( Container const &c ) { void test_sequence ( Container const &c ) {
typedef typename Container::value_type value_type; typedef typename Container::value_type value_type;
std::vector<value_type> v; std::vector<value_type> v;
// Copy zero elements // Copy zero elements
v.clear (); v.clear ();
ba::copy_n ( c.begin (), 0, back_inserter ( v )); ba::copy_n ( c.begin (), 0, back_inserter ( v ));
BOOST_CHECK ( v.size () == 0 ); BOOST_CHECK ( v.size () == 0 );
ba::copy_n ( c.begin (), 0U, back_inserter ( v )); ba::copy_n ( c.begin (), 0U, back_inserter ( v ));
BOOST_CHECK ( v.size () == 0 ); BOOST_CHECK ( v.size () == 0 );
if ( c.size () > 0 ) { if ( c.size () > 0 ) {
// Just one element // Just one element
v.clear (); v.clear ();
ba::copy_n ( c.begin (), 1, back_inserter ( v )); ba::copy_n ( c.begin (), 1, back_inserter ( v ));
BOOST_CHECK ( v.size () == 1 ); BOOST_CHECK ( v.size () == 1 );
BOOST_CHECK ( v[0] == *c.begin ()); BOOST_CHECK ( v[0] == *c.begin ());
v.clear (); v.clear ();
ba::copy_n ( c.begin (), 1U, back_inserter ( v )); ba::copy_n ( c.begin (), 1U, back_inserter ( v ));
BOOST_CHECK ( v.size () == 1 ); BOOST_CHECK ( v.size () == 1 );
BOOST_CHECK ( v[0] == *c.begin ()); BOOST_CHECK ( v[0] == *c.begin ());
// Half the elements // Half the elements
v.clear (); v.clear ();
ba::copy_n ( c.begin (), c.size () / 2, back_inserter ( v )); ba::copy_n ( c.begin (), c.size () / 2, back_inserter ( v ));
BOOST_CHECK ( v.size () == c.size () / 2); BOOST_CHECK ( v.size () == c.size () / 2);
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ())); BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
// Half the elements + 1 // Half the elements + 1
v.clear (); v.clear ();
ba::copy_n ( c.begin (), c.size () / 2 + 1, back_inserter ( v )); ba::copy_n ( c.begin (), c.size () / 2 + 1, back_inserter ( v ));
BOOST_CHECK ( v.size () == c.size () / 2 + 1 ); BOOST_CHECK ( v.size () == c.size () / 2 + 1 );
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ())); BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
// All the elements // All the elements
v.clear (); v.clear ();
ba::copy_n ( c.begin (), c.size (), back_inserter ( v )); ba::copy_n ( c.begin (), c.size (), back_inserter ( v ));
BOOST_CHECK ( v.size () == c.size ()); BOOST_CHECK ( v.size () == c.size ());
BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ())); BOOST_CHECK ( std::equal ( v.begin (), v.end (), c.begin ()));
} }
} }
void test_sequence1 () { void test_sequence1 () {
std::vector<int> v; std::vector<int> v;
for ( int i = 5; i < 15; ++i ) for ( int i = 5; i < 15; ++i )
v.push_back ( i ); v.push_back ( i );
test_sequence ( v ); test_sequence ( v );
std::list<int> l; std::list<int> l;
for ( int i = 25; i > 15; --i ) for ( int i = 25; i > 15; --i )
l.push_back ( i ); l.push_back ( i );
test_sequence ( l ); test_sequence ( l );
} }
int test_main( int , char* [] ) int test_main( int , char* [] )

0
test/empty_search_test.cpp Executable file → Normal file
View File

View File

@ -22,18 +22,18 @@ namespace ba = boost::algorithm;
template <typename Container> template <typename Container>
typename Container::iterator offset_to_iter ( Container &v, int offset ) { typename Container::iterator offset_to_iter ( Container &v, int offset ) {
typename Container::iterator retval; typename Container::iterator retval;
if ( offset >= 0 ) { if ( offset >= 0 ) {
retval = v.begin (); retval = v.begin ();
std::advance ( retval, offset ); std::advance ( retval, offset );
} }
else { else {
retval = v.end (); retval = v.end ();
std::advance ( retval, offset + 1 ); std::advance ( retval, offset + 1 );
} }
return retval; return retval;
} }
template <typename Container, typename Predicate> template <typename Container, typename Predicate>
void test_sequence ( Container &v, Predicate comp, int expected ) { void test_sequence ( Container &v, Predicate comp, int expected ) {
@ -71,7 +71,7 @@ void test_sequence1 () {
test_sequence ( v, less_than<int>(10), 5 ); test_sequence ( v, less_than<int>(10), 5 );
test_sequence ( v, less_than<int>(99), -1 ); // all elements satisfy test_sequence ( v, less_than<int>(99), -1 ); // all elements satisfy
// With bidirectional iterators. // With bidirectional iterators.
std::list<int> l; std::list<int> l;
for ( int i = 5; i < 15; ++i ) for ( int i = 5; i < 15; ++i )
l.push_back ( i ); l.push_back ( i );

View File

@ -15,7 +15,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
// should not compile: vector is not an integral type // should not compile: vector is not an integral type
int test_main( int , char* [] ) int test_main( int , char* [] )
{ {
std::vector<float> v; std::vector<float> v;

View File

@ -21,12 +21,12 @@ Try ostream_iterators
template <typename char_type> template <typename char_type>
void test_to_hex ( const char_type ** tests ) { void test_to_hex ( const char_type ** tests ) {
typedef std::basic_string<char_type> String; typedef std::basic_string<char_type> String;
typedef std::basic_ostringstream<char_type> Stream; typedef std::basic_ostringstream<char_type> Stream;
typedef std::ostream_iterator<char_type, char_type> Iter; typedef std::ostream_iterator<char_type, char_type> Iter;
for ( const char_type **p = tests; *p; p++ ) { for ( const char_type **p = tests; *p; p++ ) {
String arg, argh; String arg, argh;
Stream one, two, three; Stream one, two, three;
arg.assign ( *p ); arg.assign ( *p );
boost::algorithm::hex ( *p, Iter ( one )); boost::algorithm::hex ( *p, Iter ( one ));
@ -49,12 +49,12 @@ void test_to_hex ( const char_type ** tests ) {
template <typename char_type> template <typename char_type>
void test_from_hex_success ( const char_type ** tests ) { void test_from_hex_success ( const char_type ** tests ) {
typedef std::basic_string<char_type> String; typedef std::basic_string<char_type> String;
typedef std::basic_ostringstream<char_type> Stream; typedef std::basic_ostringstream<char_type> Stream;
typedef std::ostream_iterator<char_type, char_type> Iter; typedef std::ostream_iterator<char_type, char_type> Iter;
for ( const char_type **p = tests; *p; p++ ) { for ( const char_type **p = tests; *p; p++ ) {
String arg, argh; String arg, argh;
Stream one, two, three; Stream one, two, three;
arg.assign ( *p ); arg.assign ( *p );
boost::algorithm::unhex ( *p, Iter ( one )); boost::algorithm::unhex ( *p, Iter ( one ));

145
test/hex_test4.cpp Normal file
View 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 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;
}

View File

@ -16,60 +16,60 @@
#include <vector> #include <vector>
#include <list> #include <list>
// Test to make sure a sequence is "correctly formed"; i.e, ascending by one // Test to make sure a sequence is "correctly formed"; i.e, ascending by one
template <typename Iterator, typename T> template <typename Iterator, typename T>
bool test_iota_results ( Iterator first, Iterator last, T initial_value ) { bool test_iota_results ( Iterator first, Iterator last, T initial_value ) {
if ( first == last ) return true; if ( first == last ) return true;
if ( initial_value != *first ) return false; if ( initial_value != *first ) return false;
Iterator prev = first; Iterator prev = first;
while ( ++first != last ) { while ( ++first != last ) {
if (( *first - *prev ) != 1 ) if (( *first - *prev ) != 1 )
return false; return false;
prev = first; prev = first;
} }
return true; return true;
} }
template <typename Range, typename T> template <typename Range, typename T>
bool test_iota_results ( const Range &r, T initial_value ) { bool test_iota_results ( const Range &r, T initial_value ) {
return test_iota_results (boost::begin (r), boost::end (r), initial_value ); return test_iota_results (boost::begin (r), boost::end (r), initial_value );
} }
void test_ints () { void test_ints () {
std::vector<int> v; std::vector<int> v;
std::list<int> l; std::list<int> l;
v.clear (); v.reserve ( 10 ); v.clear (); v.reserve ( 10 );
boost::algorithm::iota ( v.begin (), v.end (), 23 ); boost::algorithm::iota ( v.begin (), v.end (), 23 );
BOOST_CHECK ( test_iota_results ( v.begin (), v.end (), 23 )); BOOST_CHECK ( test_iota_results ( v.begin (), v.end (), 23 ));
v.clear (); v.reserve ( 19 ); v.clear (); v.reserve ( 19 );
boost::algorithm::iota ( v, 18 ); boost::algorithm::iota ( v, 18 );
BOOST_CHECK ( test_iota_results ( v, 18 )); BOOST_CHECK ( test_iota_results ( v, 18 ));
v.clear (); v.clear ();
boost::algorithm::iota_n ( std::back_inserter(v), 99, 20 ); boost::algorithm::iota_n ( std::back_inserter(v), 99, 20 );
BOOST_CHECK ( test_iota_results ( v, 99 )); BOOST_CHECK ( test_iota_results ( v, 99 ));
/* /*
l.clear (); l.reserve ( 5 ); l.clear (); l.reserve ( 5 );
boost::algorithm::iota ( l.begin (), l.end (), 123 ); boost::algorithm::iota ( l.begin (), l.end (), 123 );
BOOST_CHECK ( test_iota_results ( l.begin (), l.end (), 123 )); BOOST_CHECK ( test_iota_results ( l.begin (), l.end (), 123 ));
l.clear (); l.reserve ( 9 ); l.clear (); l.reserve ( 9 );
boost::algorithm::iota ( l.begin (), l.end (), 87 ); boost::algorithm::iota ( l.begin (), l.end (), 87 );
BOOST_CHECK ( test_iota_results ( l.begin (), l.end (), 87 )); BOOST_CHECK ( test_iota_results ( l.begin (), l.end (), 87 ));
*/ */
l.clear (); l.clear ();
boost::algorithm::iota_n ( std::back_inserter(l), 99, 20 ); boost::algorithm::iota_n ( std::back_inserter(l), 99, 20 );
BOOST_CHECK ( test_iota_results ( l, 99 )); BOOST_CHECK ( test_iota_results ( l, 99 ));
l.clear (); l.clear ();
boost::algorithm::iota_n ( std::front_inserter(l), 123, 20 ); boost::algorithm::iota_n ( std::front_inserter(l), 123, 20 );
BOOST_CHECK ( test_iota_results ( l.rbegin (), l.rend (), 123 )); BOOST_CHECK ( test_iota_results ( l.rbegin (), l.rend (), 123 ));
} }
int test_main( int , char* [] ) int test_main( int , char* [] )

View File

@ -40,19 +40,19 @@ void test_sequence1 () {
v.clear (); v.clear ();
for ( int i = 5; i < 15; ++i ) for ( int i = 5; i < 15; ++i )
v.push_back ( 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>(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>(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>(10))); // in the middle somewhere
BOOST_CHECK ( ba::is_partitioned ( v, less_than<int>(99))); // all elements satisfy BOOST_CHECK ( ba::is_partitioned ( v, less_than<int>(99))); // all elements satisfy
// With bidirectional iterators. // With bidirectional iterators.
std::list<int> l; std::list<int> l;
for ( int i = 5; i < 15; ++i ) for ( int i = 5; i < 15; ++i )
l.push_back ( 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>(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>(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>(10))); // in the middle somewhere
BOOST_CHECK ( ba::is_partitioned ( l.begin (), l.end (), less_than<int>(99))); // all elements satisfy BOOST_CHECK ( ba::is_partitioned ( l.begin (), l.end (), less_than<int>(99))); // all elements satisfy
} }

View File

@ -36,28 +36,28 @@ test_ordered(void)
int nonConstantArray[] = { 1, 2, 2, 2, 5 }; int nonConstantArray[] = { 1, 2, 2, 2, 5 };
const int inOrderUntilTheEnd [] = { 0, 1, 2, 3, 4, 5, 6, 7, 6 }; const int inOrderUntilTheEnd [] = { 0, 1, 2, 3, 4, 5, 6, 7, 6 };
// Begin/end checks // Begin/end checks
BOOST_CHECK ( ba::is_sorted (b_e(strictlyIncreasingValues))); BOOST_CHECK ( ba::is_sorted (b_e(strictlyIncreasingValues)));
BOOST_CHECK ( !ba::is_sorted (b_e(randomValues))); BOOST_CHECK ( !ba::is_sorted (b_e(randomValues)));
BOOST_CHECK ( ba::is_sorted (b_e(strictlyIncreasingValues), std::less<int>())); BOOST_CHECK ( ba::is_sorted (b_e(strictlyIncreasingValues), std::less<int>()));
BOOST_CHECK ( !ba::is_sorted (b_e(strictlyIncreasingValues), std::greater<int>())); BOOST_CHECK ( !ba::is_sorted (b_e(strictlyIncreasingValues), std::greater<int>()));
// Range checks // Range checks
BOOST_CHECK ( ba::is_sorted (a_range(strictlyIncreasingValues))); BOOST_CHECK ( ba::is_sorted (a_range(strictlyIncreasingValues)));
BOOST_CHECK ( !ba::is_sorted (a_range(randomValues))); BOOST_CHECK ( !ba::is_sorted (a_range(randomValues)));
BOOST_CHECK ( ba::is_sorted (a_range(strictlyIncreasingValues), std::less<int>())); BOOST_CHECK ( ba::is_sorted (a_range(strictlyIncreasingValues), std::less<int>()));
BOOST_CHECK ( !ba::is_sorted (a_range(strictlyIncreasingValues), std::greater<int>())); BOOST_CHECK ( !ba::is_sorted (a_range(strictlyIncreasingValues), std::greater<int>()));
BOOST_CHECK ( ba::is_sorted_until ( b_e(strictlyIncreasingValues)) == a_end(strictlyIncreasingValues)); BOOST_CHECK ( ba::is_sorted_until ( b_e(strictlyIncreasingValues)) == a_end(strictlyIncreasingValues));
BOOST_CHECK ( ba::is_sorted_until ( b_e(strictlyIncreasingValues), std::less<int>()) == a_end(strictlyIncreasingValues)); BOOST_CHECK ( ba::is_sorted_until ( b_e(strictlyIncreasingValues), std::less<int>()) == a_end(strictlyIncreasingValues));
BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues)) == boost::end(strictlyIncreasingValues)); BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues)) == boost::end(strictlyIncreasingValues));
BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues), std::less<int>()) == boost::end(strictlyIncreasingValues)); BOOST_CHECK ( ba::is_sorted_until ( a_range(strictlyIncreasingValues), std::less<int>()) == boost::end(strictlyIncreasingValues));
// Check for const and non-const arrays // 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 ( 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 ( 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 ( 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 ( 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), std::less<int>()) == &randomValues[2] );
BOOST_CHECK ( ba::is_sorted_until ( b_e(randomValues)) == &randomValues[2] ); BOOST_CHECK ( ba::is_sorted_until ( b_e(randomValues)) == &randomValues[2] );
@ -149,6 +149,6 @@ test_increasing_decreasing(void)
int test_main( int, char * [] ) int test_main( int, char * [] )
{ {
test_ordered (); test_ordered ();
test_increasing_decreasing (); test_increasing_decreasing ();
return 0; return 0;
} }

View File

@ -22,18 +22,18 @@ namespace ba = boost::algorithm;
template <typename Container> template <typename Container>
typename Container::iterator offset_to_iter ( Container &v, int offset ) { typename Container::iterator offset_to_iter ( Container &v, int offset ) {
typename Container::iterator retval; typename Container::iterator retval;
if ( offset >= 0 ) { if ( offset >= 0 ) {
retval = v.begin (); retval = v.begin ();
std::advance ( retval, offset ); std::advance ( retval, offset );
} }
else { else {
retval = v.end (); retval = v.end ();
std::advance ( retval, offset + 1 ); std::advance ( retval, offset + 1 );
} }
return retval; return retval;
} }
template <typename Container, typename Predicate> template <typename Container, typename Predicate>
void test_sequence ( Container &v, Predicate comp, int expected ) { void test_sequence ( Container &v, Predicate comp, int expected ) {
@ -79,7 +79,7 @@ void test_sequence1 () {
test_sequence ( v, less_than<int>(10), 5 ); test_sequence ( v, less_than<int>(10), 5 );
test_sequence ( v, less_than<int>(99), -1 ); // all elements satisfy test_sequence ( v, less_than<int>(99), -1 ); // all elements satisfy
// With bidirectional iterators. // With bidirectional iterators.
std::list<int> l; std::list<int> l;
for ( int i = 5; i < 15; ++i ) for ( int i = 5; i < 15; ++i )
l.push_back ( i ); l.push_back ( i );

0
test/search_test1.cpp Executable file → Normal file
View File

0
test/search_test2.cpp Executable file → Normal file
View File

0
test/search_test3.cpp Executable file → Normal file
View File

116
test/search_test4.cpp Normal file
View 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;
}