Compare commits

...

166 Commits

Author SHA1 Message Date
d431a3702b Release 1.47.0
[SVN r73007]
2011-07-11 22:16:03 +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
bd974bb945 - join and lexicographical_compare added to the quickref
- join.hpp added to jambfil


[SVN r33406]
2006-03-20 13:08:13 +00:00
24b55c67f7 added comments about negative indexes in _nth, _tail and _head algorithms
[SVN r33255]
2006-03-07 13:09:36 +00:00
603223fd3d fixed to comparison operator in is_not_grater predicate
[SVN r33236]
2006-03-06 18:05:10 +00:00
131484606f testcases that were offencing vc8.0 fixed
[SVN r33143]
2006-02-27 14:13:27 +00:00
20d22a8fc8 fix the tests to join_it naming
[SVN r33137]
2006-02-27 12:01:08 +00:00
134a106ae9 regex variant of join_if renamed to join_if_regex for compilers that do not support
template ordering.


[SVN r33136]
2006-02-27 11:58:43 +00:00
0bcbe2afc6 fixed the slist include
[SVN r33024]
2006-02-20 14:38:10 +00:00
b7a3fa2c73 Testcase for regex variant of join_if added
[SVN r32919]
2006-02-14 10:11:33 +00:00
a731e950f2 added a regex variant of join_if
[SVN r32918]
2006-02-14 10:10:47 +00:00
66794c89f6 Tests for join algorihtm added
[SVN r32917]
2006-02-14 09:39:03 +00:00
9b62648970 Join algorithm implemented
[SVN r32916]
2006-02-14 09:37:26 +00:00
3766cbbe5c find_head/tail_impl functions reordered to avoid dependancy problems
[SVN r32893]
2006-02-13 13:21:31 +00:00
e2b9172f5d - tabs removed
- find_tail/head_impl functions rearranged to avoid the dependency problem


[SVN r32676]
2006-02-06 18:10:18 +00:00
fa01964a1f tests fo lexicographical_compare added
[SVN r32479]
2006-01-31 15:24:03 +00:00
ff82e5135c - added more character-comparison predicates (is_less, is_not_greater)
- added range version of lexicographical_compare
- Fixed some copyright years


[SVN r32478]
2006-01-31 14:57:15 +00:00
f50dd248cc testcases for negative indexes addes
[SVN r32476]
2006-01-31 12:37:06 +00:00
dd11014682 negative indexes support added to *_nth, *_head and *_tail algorithms
[SVN r32475]
2006-01-31 12:36:32 +00:00
d9ebe5da13 Merged from Version_1_33_1
[SVN r31949]
2005-12-08 03:23:02 +00:00
e2d5feeb06 Link to Alexandrescu's paper
[SVN r31135]
2005-09-27 21:42:58 +00:00
45949a9316 Merged from 1.33.0 release
[SVN r30540]
2005-08-12 13:02:37 +00:00
924368a775 Fix typo
[SVN r30046]
2005-07-13 13:55:32 +00:00
344225bce1 Inspect fixes
[SVN r30045]
2005-07-13 13:35:30 +00:00
a4137bbae6 Boland "using problem" fix
[SVN r29448]
2005-06-06 20:03:18 +00:00
04a40de48d borland issues
- non working patch reverted
- a working one applied


[SVN r28982]
2005-05-17 07:43:40 +00:00
5ecf446070 Another attempt to fix borland problem.
[SVN r28978]
2005-05-16 21:03:04 +00:00
e909726c60 Another attempt to fix borland problems
[SVN r28974]
2005-05-16 17:56:44 +00:00
9878f92a41 An attempt to fix vc7 compilation failure
[SVN r28952]
2005-05-16 12:35:22 +00:00
d72eec3093 Forgotten reference added
[SVN r28934]
2005-05-15 18:06:14 +00:00
bc09128c6e Work-around CW-8.3 failure because it can't decide between by-value or copy constructor for an iterator range.
[SVN r28918]
2005-05-15 02:38:04 +00:00
0f707ed9c9 remaining "collection" occurences replaced by "range"
[SVN r28908]
2005-05-14 19:11:09 +00:00
77307c2823 Some comment fixes
[SVN r28907]
2005-05-14 19:09:13 +00:00
e00fd7f159 bcc32 patch from Russell Hind applied
[SVN r28811]
2005-05-11 09:17:14 +00:00
5419d39b2e Documents updated to reflect collection traits removal
[SVN r28274]
2005-04-15 21:05:00 +00:00
7ad6c08c68 must free storage obtained by new[] with delete[]
[SVN r28251]
2005-04-14 16:14:18 +00:00
b6c5c86d9c conversion from string literal to char* is deprecated (and unnecessary here)
[SVN r28250]
2005-04-14 16:08:58 +00:00
0f4aa23e9c Update Jamfile.v2 for minmax.
[SVN r28201]
2005-04-13 06:18:54 +00:00
b0a2a9d3e0 Naming convetion changed to follow Boost.Range
[SVN r28185]
2005-04-12 16:50:42 +00:00
8fc117aa7e BOOST_STD_EXTENSION_NAMESPACE properly used as a namespace for slist
[SVN r28184]
2005-04-12 16:01:48 +00:00
0f827f89cf fixed problem with an iterator being == end and dereferencing it
[SVN r28142]
2005-04-12 04:37:06 +00:00
2074344846 Regression test changed to take in account the recent fixes
[SVN r28097]
2005-04-11 07:41:01 +00:00
3b889db8d1 Split iterator fixed. Now it returns also last empty match if appropriate
[SVN r28096]
2005-04-11 07:39:34 +00:00
1489b70457 Make sure atoi is available
[SVN r27913]
2005-04-01 22:19:44 +00:00
c475f8559d fixed small cosmetic typo in link
[SVN r27220]
2005-02-07 18:04:15 +00:00
d3d4ffe0e6 Fixing error in the previous commit
[SVN r26789]
2005-01-21 16:53:34 +00:00
2b5de80031 Library adapted to use official version Boost.Range instead of the internal one.
Internal version removed


[SVN r26788]
2005-01-21 16:49:06 +00:00
aea6f39c11 Library adapted to use official Boost.Range instead of the internal version
Internal version removed


[SVN r26787]
2005-01-21 16:45:29 +00:00
54092d7934 Removed one dead file.
Changed legacy referernces to reg_expression to basic_regex


[SVN r26739]
2005-01-19 13:28:57 +00:00
747597c7ef merge RC_1_32_0 fixes
[SVN r26328]
2004-11-28 03:35:12 +00:00
72b4390091 regex_finder and regex_fomatter pulled to the boost namespace
[SVN r25877]
2004-10-26 21:41:00 +00:00
77ae41a18a Invalid include fixed
[SVN r25672]
2004-10-11 18:30:21 +00:00
5d1448f3ac unused parameter warning removal
[SVN r25671]
2004-10-11 18:28:21 +00:00
0a0facd7c7 c++boost.gif -> boost.png replacement
[SVN r25573]
2004-10-05 15:45:52 +00:00
053cc53eea workaround for a problem of GCC 2.95 with local scope using directives
[SVN r25077]
2004-09-14 07:15:51 +00:00
54ac5bebd3 Fix stylesheet link
[SVN r25048]
2004-09-13 15:44:23 +00:00
3542f868a0 Problematic std::distance removed
[SVN r25008]
2004-09-10 13:23:32 +00:00
4d346d43ad Explicit namespace qualification added to std::distance calls
(hoping to resolve vc7 problem)


[SVN r24953]
2004-09-07 10:30:41 +00:00
56862b0bcc merge new MPL version from 'mplbook' branch
[SVN r24874]
2004-09-02 15:41:37 +00:00
108365abe7 Attempt to fix "Empty sequence after erase problem" reported by vc8.0
[SVN r24835]
2004-08-31 07:43:02 +00:00
fa09dddc75 More general fix for vc8.0
[SVN r24765]
2004-08-26 16:03:48 +00:00
6fb58192d7 Fix fix
[SVN r24678]
2004-08-23 18:52:36 +00:00
792b4eae88 Attempt to fix iterator problem detected by VC8.0
[SVN r24677]
2004-08-23 18:46:28 +00:00
a23ae6316f Licence from authors of previous versions changed to BSL (according to blanket-permission.txt)
[SVN r24479]
2004-08-14 23:02:20 +00:00
5063e96367 Work around problems with the CW8 preprocessor by not using BOOST_PP.
[SVN r24326]
2004-08-06 15:50:35 +00:00
5221839b71 tabs removed
[SVN r24272]
2004-08-03 17:28:02 +00:00
ba00033cbf Addtional credits
[SVN r24271]
2004-08-03 17:23:43 +00:00
047a42934d Incorrect examples fixed
[SVN r24270]
2004-08-03 17:09:28 +00:00
747b4e17cc Small fix to make vacpp happy
[SVN r24245]
2004-08-02 10:32:37 +00:00
4c0efd3d1a Small optimization of equal() functions.
[SVN r24185]
2004-07-30 07:46:11 +00:00
67f7273ab3 replace_test() function splitted to smaller chuncks.
[SVN r24184]
2004-07-30 07:44:43 +00:00
ce6a647dd0 Work-around for CW8 problems with static_cast of references to templates.
[SVN r24178]
2004-07-30 04:32:43 +00:00
246794db2a Added copyright notices.
[SVN r24171]
2004-07-29 20:27:38 +00:00
325fa64dc3 Licence fixed
[SVN r24152]
2004-07-29 07:38:27 +00:00
33122fefa7 Fix tabs in file.
[SVN r24039]
2004-07-25 15:09:51 +00:00
4b3118ed2b Added BOOST_EXPLICIT_TEMPLATE_TYPE(Value) to fix MSVC (thanks to Joaquin
Munoz)


[SVN r23998]
2004-07-23 17:17:37 +00:00
85e0e920bf Removed char* name and dependence on iostream, not appropriate for test
suite (relic of example and debugging).


[SVN r23996]
2004-07-23 16:13:43 +00:00
483bc9e231 replaced tuple::get memfun with equivalent global function so as to cover MSVC
[SVN r23956]
2004-07-22 13:43:01 +00:00
643c793f3b added a fix for compilers without PTS
[SVN r23955]
2004-07-22 13:39:25 +00:00
825468bc42 added an #include for Boost.Ref
[SVN r23954]
2004-07-22 13:37:47 +00:00
69339b779c Removed initialization from singular iterator.
[SVN r23910]
2004-07-21 17:23:40 +00:00
7a88ef8658 Now includes minmax_test in the test suite.
[SVN r23909]
2004-07-21 17:15:40 +00:00
2b2086dd8f Why were these committed in the first place???
[SVN r23908]
2004-07-21 16:48:41 +00:00
bfa0f28830 bugfix from Stefan Slapeta <stefan_nospam_@slapeta.com>
[SVN r23887]
2004-07-21 11:18:16 +00:00
f16de45e46 Don't copy default-initialized iterator, which might be singlular.
[SVN r23843]
2004-07-20 13:42:31 +00:00
f6752d3ae1 change test-suite names to match library names
[SVN r23820]
2004-07-20 01:41:00 +00:00
961e8b399e Applying patches from Daniel James
[SVN r23631]
2004-07-16 14:10:08 +00:00
21440d1b17 Appying patch from Danie James
[SVN r23630]
2004-07-16 13:57:40 +00:00
cc72a93094 tabs removed
[SVN r23618]
2004-07-16 09:08:21 +00:00
9fd4119efc Tabs removed
[SVN r23617]
2004-07-16 09:06:39 +00:00
00d09671f5 Library name fixed
[SVN r23613]
2004-07-16 07:51:36 +00:00
4e55a78e2d Small comment typo removed
[SVN r23609]
2004-07-15 22:24:39 +00:00
48e65026d9 Comment fixed
[SVN r23608]
2004-07-15 22:22:25 +00:00
fb182c2566 Fixing documentation grammar and spelling
[SVN r23606]
2004-07-15 21:48:25 +00:00
d97ff92ae4 Fixing grammar and typos
[SVN r23605]
2004-07-15 21:47:22 +00:00
ddd9baba60 Library documentation index added
- Automatic redirection to boost-book generated docs


[SVN r23565]
2004-07-14 23:01:01 +00:00
3786aa8b04 string-text library category added
[SVN r23564]
2004-07-14 22:57:55 +00:00
cc683155c7 Spellchecker applied
[SVN r23562]
2004-07-14 22:24:12 +00:00
dd8d053685 Some spelling errors fixed.
[SVN r23560]
2004-07-14 22:17:10 +00:00
54075a951b Documentation update
[SVN r23559]
2004-07-14 21:46:50 +00:00
8cf6df3ad6 documentation update.
added remarks about the exception safety


[SVN r23558]
2004-07-14 21:28:31 +00:00
caad29f22a Added vacpp workaround for static constants
[SVN r23557]
2004-07-14 21:21:54 +00:00
06474a276d Fixed construction to not restrict usage of iterators, that are not
default constructible


[SVN r23497]
2004-07-13 15:14:35 +00:00
4185e3fb31 Fixed dangling pointer problem
[SVN r23495]
2004-07-13 15:00:36 +00:00
905cbf4a38 find_all char* test case added
[SVN r23494]
2004-07-13 14:59:43 +00:00
ccce29ecf5 Trying to avoid Intel crash
[SVN r23484]
2004-07-13 14:20:06 +00:00
029851b0ce Comments cleanup
[SVN r23447]
2004-07-11 22:07:00 +00:00
22b59d1848 Grouping documentation for overloaded functions
[SVN r23385]
2004-07-06 21:28:01 +00:00
8242b4ba5a -predicate_facade moved to a separate header
-composition operators for classification predicates moved
 to the same namespace as predicate_facade


[SVN r23382]
2004-07-06 19:52:18 +00:00
a568d32ba9 Cleanup Jamfile
[SVN r23341]
2004-07-04 22:24:17 +00:00
9dcf3e6b76 Cleanup html, dates, grammar, synopsis code. --Herve'
[SVN r23339]
2004-07-04 22:08:29 +00:00
113c676eef std::facet requirement added
[SVN r23324]
2004-07-03 10:40:39 +00:00
b108993f89 std::locale requirement added
[SVN r23323]
2004-07-03 10:32:14 +00:00
81044b4233 Metrowerks workaround added
[SVN r23322]
2004-07-03 10:31:01 +00:00
71d18481dd move BOOST_USING_STD_MIN and _MAX and BOOST_PREVENT_MACRO_SUBSTITUTION to the config headers, remove boost/minmax.hpp, update coding guidelines
[SVN r23313]
2004-07-02 01:21:32 +00:00
16f4b20083 Testing minmax_element only.
[SVN r23310]
2004-07-01 20:52:50 +00:00
e0d1f0692d Spearated into two files due to the dependence on the tuple library.
Minor changes to minmax.hpp (again tuple). --Herve'


[SVN r23309]
2004-07-01 20:16:38 +00:00
cf85da14ed Documentation for the minmax library.
Moved from libs/minmax/ to libs/algorithm/minmax
Also changed documentation to reflect use of Boost.tuple
and separation into two header files. --Herve'


[SVN r23308]
2004-07-01 20:15:51 +00:00
ec606bbf14 Change pair<T,T> to tuple<T,T> in return type of minmax()
[SVN r23307]
2004-07-01 19:23:33 +00:00
729bb65a2d Removed minmax.hpp from boost (leave Eric Niebler's former file)
and move it to subdir boost/algorithm/
Also incorporate boost::ref into boost/algorithm/minmax.hpp  to avoid
copy constructors when params passed by reference.


[SVN r23305]
2004-07-01 18:38:02 +00:00
6df2923b40 Remove these files from the libs/directory, and reenter them later in
the libs/algorithm/ subdir. --Herve'


[SVN r23304]
2004-07-01 18:31:21 +00:00
6d7d244051 Attempt to add static link requirement added for cwpro8 and cwpro9.
Should fix the problems on these compilers


[SVN r23291]
2004-06-30 20:13:05 +00:00
1e7aec2dee Finally adding the minmax library. Still allowing overlap with header
minmax.hpp from Eric Niebler, which should be resolved soon. --Herve'


[SVN r23225]
2004-06-28 08:36:43 +00:00
752c65be35 remove std_min and std_max, update minmax coding guidelines
[SVN r23162]
2004-06-23 04:49:48 +00:00
77303abc55 Added V2 Jamfile
[SVN r23070]
2004-06-10 10:02:02 +00:00
d92e09176c Constructors, accepting a collection added
[SVN r23040]
2004-06-07 09:53:19 +00:00
bc420c5acf Jamfile updated to reflect new file naming
[SVN r22752]
2004-05-06 20:46:42 +00:00
d88e251f39 implementation changed to use boost::function instead of own
virtualizer


[SVN r22658]
2004-04-18 18:36:35 +00:00
91 changed files with 8506 additions and 4721 deletions

View File

@ -0,0 +1,47 @@
// (C) Copyright Herve Bronnimann 2004.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/*
Revision history:
1 July 2004
Split the code into two headers to lessen dependence on
Boost.tuple. (Herve)
26 June 2004
Added the code for the boost minmax library. (Herve)
*/
#ifndef BOOST_ALGORITHM_MINMAX_HPP
#define BOOST_ALGORITHM_MINMAX_HPP
/* PROPOSED STANDARD EXTENSIONS:
*
* minmax(a, b)
* Effect: (b<a) ? std::make_pair(b,a) : std::make_pair(a,b);
*
* minmax(a, b, comp)
* Effect: comp(b,a) ? std::make_pair(b,a) : std::make_pair(a,b);
*
*/
#include <boost/tuple/tuple.hpp> // for using pairs with boost::cref
#include <boost/ref.hpp>
namespace boost {
template <typename T>
tuple< T const&, T const& >
minmax(T const& a, T const& b) {
return (b<a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b));
}
template <typename T, class BinaryPredicate>
tuple< T const&, T const& >
minmax(T const& a, T const& b, BinaryPredicate comp) {
return comp(b,a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b));
}
} // namespace boost
#endif // BOOST_ALGORITHM_MINMAX_HPP

View File

@ -0,0 +1,551 @@
// (C) Copyright Herve Bronnimann 2004.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/*
Revision history:
1 July 2004
Split the code into two headers to lessen dependence on
Boost.tuple. (Herve)
26 June 2004
Added the code for the boost minmax library. (Herve)
*/
#ifndef BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
#define BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
/* PROPOSED STANDARD EXTENSIONS:
*
* minmax_element(first, last)
* Effect: std::make_pair( std::min_element(first, last),
* std::max_element(first, last) );
*
* minmax_element(first, last, comp)
* Effect: std::make_pair( std::min_element(first, last, comp),
* std::max_element(first, last, comp) );
*/
#include <utility> // for std::pair and std::make_pair
namespace boost {
namespace detail { // for obtaining a uniform version of minmax_element
// that compiles with VC++ 6.0 -- avoid the iterator_traits by
// having comparison object over iterator, not over dereferenced value
template <typename Iterator>
struct less_over_iter {
bool operator()(Iterator const& it1,
Iterator const& it2) const { return *it1 < *it2; }
};
template <typename Iterator, class BinaryPredicate>
struct binary_pred_over_iter {
explicit binary_pred_over_iter(BinaryPredicate const& p ) : m_p( p ) {}
bool operator()(Iterator const& it1,
Iterator const& it2) const { return m_p(*it1, *it2); }
private:
BinaryPredicate m_p;
};
// common base for the two minmax_element overloads
template <typename ForwardIter, class Compare >
std::pair<ForwardIter,ForwardIter>
basic_minmax_element(ForwardIter first, ForwardIter last, Compare comp)
{
if (first == last)
return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
// if only one element
ForwardIter second = first; ++second;
if (second == last)
return std::make_pair(min_result, max_result);
// treat first pair separately (only one comparison for first two elements)
ForwardIter potential_min_result = last;
if (comp(first, second))
max_result = second;
else {
min_result = second;
potential_min_result = first;
}
// then each element by pairs, with at most 3 comparisons per pair
first = ++second; if (first != last) ++second;
while (second != last) {
if (comp(first, second)) {
if (comp(first, min_result)) {
min_result = first;
potential_min_result = last;
}
if (comp(max_result, second))
max_result = second;
} else {
if (comp(second, min_result)) {
min_result = second;
potential_min_result = first;
}
if (comp(max_result, first))
max_result = first;
}
first = ++second;
if (first != last) ++second;
}
// if odd number of elements, treat last element
if (first != last) { // odd number of elements
if (comp(first, min_result))
min_result = first, potential_min_result = last;
else if (comp(max_result, first))
max_result = first;
}
// resolve min_result being incorrect with one extra comparison
// (in which case potential_min_result is necessarily the correct result)
if (potential_min_result != last
&& !comp(min_result, potential_min_result))
min_result = potential_min_result;
return std::make_pair(min_result,max_result);
}
} // namespace detail
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
minmax_element(ForwardIter first, ForwardIter last)
{
return detail::basic_minmax_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
minmax_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_minmax_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
}
/* PROPOSED BOOST EXTENSIONS
* In the description below, [rfirst,rlast) denotes the reversed range
* of [first,last). Even though the iterator type of first and last may
* be only a Forward Iterator, it is possible to explain the semantics
* by assuming that it is a Bidirectional Iterator. In the sequel,
* reverse(ForwardIterator&) returns the reverse_iterator adaptor.
* This is not how the functions would be implemented!
*
* first_min_element(first, last)
* Effect: std::min_element(first, last);
*
* first_min_element(first, last, comp)
* Effect: std::min_element(first, last, comp);
*
* last_min_element(first, last)
* Effect: reverse( std::min_element(reverse(last), reverse(first)) );
*
* last_min_element(first, last, comp)
* Effect: reverse( std::min_element(reverse(last), reverse(first), comp) );
*
* first_max_element(first, last)
* Effect: std::max_element(first, last);
*
* first_max_element(first, last, comp)
* Effect: max_element(first, last);
*
* last_max_element(first, last)
* Effect: reverse( std::max_element(reverse(last), reverse(first)) );
*
* last_max_element(first, last, comp)
* Effect: reverse( std::max_element(reverse(last), reverse(first), comp) );
*
* first_min_first_max_element(first, last)
* Effect: std::make_pair( first_min_element(first, last),
* first_max_element(first, last) );
*
* first_min_first_max_element(first, last, comp)
* Effect: std::make_pair( first_min_element(first, last, comp),
* first_max_element(first, last, comp) );
*
* first_min_last_max_element(first, last)
* Effect: std::make_pair( first_min_element(first, last),
* last_max_element(first, last) );
*
* first_min_last_max_element(first, last, comp)
* Effect: std::make_pair( first_min_element(first, last, comp),
* last_max_element(first, last, comp) );
*
* last_min_first_max_element(first, last)
* Effect: std::make_pair( last_min_element(first, last),
* first_max_element(first, last) );
*
* last_min_first_max_element(first, last, comp)
* Effect: std::make_pair( last_min_element(first, last, comp),
* first_max_element(first, last, comp) );
*
* last_min_last_max_element(first, last)
* Effect: std::make_pair( last_min_element(first, last),
* last_max_element(first, last) );
*
* last_min_last_max_element(first, last, comp)
* Effect: std::make_pair( last_min_element(first, last, comp),
* last_max_element(first, last, comp) );
*/
namespace boost {
// Min_element and max_element variants
namespace detail { // common base for the overloads
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_first_min_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter min_result = first;
while (++first != last)
if (comp(first, min_result))
min_result = first;
return min_result;
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_last_min_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter min_result = first;
while (++first != last)
if (!comp(min_result, first))
min_result = first;
return min_result;
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter max_result = first;
while (++first != last)
if (comp(max_result, first))
max_result = first;
return max_result;
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
basic_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return last;
ForwardIter max_result = first;
while (++first != last)
if (!comp(first, max_result))
max_result = first;
return max_result;
}
} // namespace detail
template <typename ForwardIter>
ForwardIter
first_min_element(ForwardIter first, ForwardIter last)
{
return detail::basic_first_min_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
first_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_first_min_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
ForwardIter
last_min_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_min_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
last_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_last_min_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
ForwardIter
first_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_first_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
first_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_first_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
ForwardIter
last_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
ForwardIter
last_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp)
{
return detail::basic_last_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
// Minmax_element variants -- comments removed
namespace detail {
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
basic_first_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last)
return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
ForwardIter second = ++first;
if (second == last)
return std::make_pair(min_result, max_result);
if (comp(second, min_result))
min_result = second;
else
max_result = second;
first = ++second; if (first != last) ++second;
while (second != last) {
if (!comp(second, first)) {
if (comp(first, min_result))
min_result = first;
if (!comp(second, max_result))
max_result = second;
} else {
if (comp(second, min_result))
min_result = second;
if (!comp(first, max_result))
max_result = first;
}
first = ++second; if (first != last) ++second;
}
if (first != last) {
if (comp(first, min_result))
min_result = first;
else if (!comp(first, max_result))
max_result = first;
}
return std::make_pair(min_result, max_result);
}
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
basic_last_min_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
ForwardIter second = ++first;
if (second == last)
return std::make_pair(min_result, max_result);
if (comp(max_result, second))
max_result = second;
else
min_result = second;
first = ++second; if (first != last) ++second;
while (second != last) {
if (comp(first, second)) {
if (!comp(min_result, first))
min_result = first;
if (comp(max_result, second))
max_result = second;
} else {
if (!comp(min_result, second))
min_result = second;
if (comp(max_result, first))
max_result = first;
}
first = ++second; if (first != last) ++second;
}
if (first != last) {
if (!comp(min_result, first))
min_result = first;
else if (comp(max_result, first))
max_result = first;
}
return std::make_pair(min_result, max_result);
}
template <typename ForwardIter, class BinaryPredicate>
std::pair<ForwardIter,ForwardIter>
basic_last_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
if (first == last) return std::make_pair(last,last);
ForwardIter min_result = first;
ForwardIter max_result = first;
ForwardIter second = first; ++second;
if (second == last)
return std::make_pair(min_result,max_result);
ForwardIter potential_max_result = last;
if (comp(first, second))
max_result = second;
else {
min_result = second;
potential_max_result = second;
}
first = ++second; if (first != last) ++second;
while (second != last) {
if (comp(first, second)) {
if (!comp(min_result, first))
min_result = first;
if (!comp(second, max_result)) {
max_result = second;
potential_max_result = last;
}
} else {
if (!comp(min_result, second))
min_result = second;
if (!comp(first, max_result)) {
max_result = first;
potential_max_result = second;
}
}
first = ++second;
if (first != last) ++second;
}
if (first != last) {
if (!comp(min_result, first))
min_result = first;
if (!comp(first, max_result)) {
max_result = first;
potential_max_result = last;
}
}
if (potential_max_result != last
&& !comp(potential_max_result, max_result))
max_result = potential_max_result;
return std::make_pair(min_result,max_result);
}
} // namespace detail
template <typename ForwardIter>
inline std::pair<ForwardIter,ForwardIter>
first_min_first_max_element(ForwardIter first, ForwardIter last)
{
return minmax_element(first, last);
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
first_min_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return minmax_element(first, last, comp);
}
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
first_min_last_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_first_min_last_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
first_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return detail::basic_first_min_last_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
last_min_first_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_min_first_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
last_min_first_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return detail::basic_last_min_first_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
template <typename ForwardIter>
std::pair<ForwardIter,ForwardIter>
last_min_last_max_element(ForwardIter first, ForwardIter last)
{
return detail::basic_last_min_last_max_element(first, last,
detail::less_over_iter<ForwardIter>() );
}
template <typename ForwardIter, class BinaryPredicate>
inline std::pair<ForwardIter,ForwardIter>
last_min_last_max_element(ForwardIter first, ForwardIter last,
BinaryPredicate comp)
{
return detail::basic_last_min_last_max_element(first, last,
detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) );
}
} // namespace boost
#endif // BOOST_ALGORITHM_MINMAX_ELEMENT_HPP

View File

@ -1,11 +1,12 @@
// Boost string_algo library string_algo.hpp header file ---------------------------//
// (C) Copyright Pavol Droba 2002-2003. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ALGO_HPP
#define BOOST_STRING_ALGO_HPP
@ -15,12 +16,12 @@
*/
#include <boost/algorithm/string/std_containers_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/classification.hpp>

View File

@ -1,11 +1,12 @@
// Boost string_algo library case_conv.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CASE_CONV_HPP
#define BOOST_STRING_CASE_CONV_HPP
@ -14,7 +15,12 @@
#include <algorithm>
#include <locale>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
#include <boost/algorithm/string/detail/case_conv.hpp>
/*! \file
@ -31,51 +37,46 @@ namespace boost {
//! Convert to lower case
/*!
Each element of the input sequence is converted to lower
case. The result is copied to the given output iterator.
case. The result is a copy of the input converted to lower case.
It is returned as a sequence or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Input An input collection
\param Output An output iterator to which the result will be copied
\param Input An input range
\param Loc A locale used for conversion
\return An output iterator pointing just after last inserted character
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename CollectionT>
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT
to_lower_copy(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
const std::locale& Loc=std::locale())
{
return std::transform(
begin(Input),
end(Input),
Output,
detail::to_lowerF<
typename value_type_of<CollectionT>::type >(Loc));
return ::boost::algorithm::detail::transform_range_copy(
Output,
::boost::as_literal(Input),
::boost::algorithm::detail::to_lowerF<
typename range_value<RangeT>::type >(Loc));
}
//! Convert to lower case
/*!
Each element of the input sequence is converted to lower
case. The result is a copy of the input converted to lower case.
\param Input An input sequence
\param Loc a locale used for conversion
\return A copy of the input converted to lower case
\overload
*/
template<typename SequenceT>
inline SequenceT to_lower_copy(
const SequenceT& Input,
const std::locale& Loc=std::locale())
{
return SequenceT(
make_transform_iterator(
begin(Input),
detail::to_lowerF<
typename value_type_of<SequenceT>::type >(Loc)),
make_transform_iterator(
end(Input),
detail::to_lowerF<
typename value_type_of<SequenceT>::type >(Loc)));
return ::boost::algorithm::detail::transform_range_copy<SequenceT>(
Input,
::boost::algorithm::detail::to_lowerF<
typename range_value<SequenceT>::type >(Loc));
}
//! Convert to lower case
@ -83,20 +84,18 @@ namespace boost {
Each element of the input sequence is converted to lower
case. The input sequence is modified in-place.
\param Input A collection
\param Input A range
\param Loc a locale used for conversion
*/
template<typename MutableCollectionT>
template<typename WritableRangeT>
inline void to_lower(
MutableCollectionT& Input,
WritableRangeT& Input,
const std::locale& Loc=std::locale())
{
std::transform(
begin(Input),
end(Input),
begin(Input),
detail::to_lowerF<
typename value_type_of<MutableCollectionT>::type >(Loc));
::boost::algorithm::detail::transform_range(
::boost::as_literal(Input),
::boost::algorithm::detail::to_lowerF<
typename range_value<WritableRangeT>::type >(Loc));
}
// to_upper -----------------------------------------------//
@ -104,52 +103,45 @@ namespace boost {
//! Convert to upper case
/*!
Each element of the input sequence is converted to upper
case. The result is copied to the given output iterator.
case. The result is a copy of the input converted to upper case.
It is returned as a sequence or copied to the output iterator
\param Output A output iterator to which the result will be copied
\param Input An input collection
\param Loc a locale used for conversion
\return An output iterator pointing just after last inserted character
\param Output An output iterator to which the result will be copied
\param Input An input range
\param Loc A locale used for conversion
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename CollectionT>
template<typename OutputIteratorT, typename RangeT>
inline OutputIteratorT
to_upper_copy(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
const std::locale& Loc=std::locale())
{
return std::transform(
begin(Input),
end(Input),
Output,
detail::to_upperF<
typename value_type_of<CollectionT>::type >(Loc));
return ::boost::algorithm::detail::transform_range_copy(
Output,
::boost::as_literal(Input),
::boost::algorithm::detail::to_upperF<
typename range_value<RangeT>::type >(Loc));
}
//! Convert to upper case
/*!
Each element of the input sequence is converted to upper
case. The result is a copy if the input converted to upper case.
\param Input An input sequence
\param Loc a locale used for conversion
\return A copy of the input converted to upper case
\overload
*/
template<typename SequenceT>
inline SequenceT to_upper_copy(
const SequenceT& Input,
const std::locale& Loc=std::locale())
{
return SequenceT(
make_transform_iterator(
begin(Input),
detail::to_upperF<
typename value_type_of<SequenceT>::type >(Loc)),
make_transform_iterator(
end(Input),
detail::to_upperF<
typename value_type_of<SequenceT>::type >(Loc)));
return ::boost::algorithm::detail::transform_range_copy<SequenceT>(
Input,
::boost::algorithm::detail::to_upperF<
typename range_value<SequenceT>::type >(Loc));
}
//! Convert to upper case
@ -157,20 +149,18 @@ namespace boost {
Each element of the input sequence is converted to upper
case. The input sequence is modified in-place.
\param Input An input collection
\param Input An input range
\param Loc a locale used for conversion
*/
template<typename MutableCollectionT>
template<typename WritableRangeT>
inline void to_upper(
MutableCollectionT& Input,
WritableRangeT& Input,
const std::locale& Loc=std::locale())
{
std::transform(
begin(Input),
end(Input),
begin(Input),
detail::to_upperF<
typename value_type_of<MutableCollectionT>::type >(Loc));
::boost::algorithm::detail::transform_range(
::boost::as_literal(Input),
::boost::algorithm::detail::to_upperF<
typename range_value<WritableRangeT>::type >(Loc));
}
} // namespace algorithm

View File

@ -1,18 +1,23 @@
// Boost string_algo library classification.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CLASSIFICATION_HPP
#define BOOST_STRING_CLASSIFICATION_HPP
#include <algorithm>
#include <locale>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/classification.hpp>
#include <boost/algorithm/string/predicate_facade.hpp>
/*! \file
Classification predicates are included in the library to give
@ -28,7 +33,7 @@ namespace boost {
//! is_classified predicate
/*!
Construct the \c is_classified predicate. This predicate holds, if an input is
Construct the \c is_classified predicate. This predicate holds if the input is
of specified \c std::ctype category.
\param Type A \c std::ctype category
@ -43,7 +48,7 @@ namespace boost {
//! is_space predicate
/*!
Construct the \c is_classified predicate for \c ctype_base::space category.
Construct the \c is_classified predicate for the \c ctype_base::space category.
\param Loc A locale used for classification
\return An instance of the \c is_classified predicate
@ -186,24 +191,24 @@ namespace boost {
//! is_any_of predicate
/*!
Construct the \c is_any_of predicate. The predicate holds, if an input
Construct the \c is_any_of predicate. The predicate holds if the input
is included in the specified set of characters.
\param Set A set of characters to be recognized
\return An instance of the \c is_any_of predicate
*/
template<typename ContainerT>
template<typename RangeT>
inline detail::is_any_ofF<
BOOST_STRING_TYPENAME value_type_of<ContainerT>::type>
is_any_of( const ContainerT& Set )
BOOST_STRING_TYPENAME range_value<RangeT>::type>
is_any_of( const RangeT& Set )
{
return detail::is_any_ofF<
BOOST_STRING_TYPENAME value_type_of<ContainerT>::type>(Set);
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_set(boost::as_literal(Set));
return detail::is_any_ofF<BOOST_STRING_TYPENAME range_value<RangeT>::type>(lit_set);
}
//! is_from_range predicate
/*!
Construct the \c is_from_range predicate. The predicate holds, if an input
Construct the \c is_from_range predicate. The predicate holds if the input
is included in the specified range. (i.e. From <= Ch <= To )
\param From The start of the range
@ -215,6 +220,74 @@ namespace boost {
{
return detail::is_from_rangeF<CharT>(From,To);
}
// predicate combinators ---------------------------------------------------//
//! predicate 'and' composition predicate
/*!
Construct the \c class_and predicate. This predicate can be used
to logically combine two classification predicates. \c class_and holds,
if both predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_and predicate
*/
template<typename Pred1T, typename Pred2T>
inline detail::pred_andF<Pred1T, Pred2T>
operator&&(
const predicate_facade<Pred1T>& Pred1,
const predicate_facade<Pred2T>& Pred2 )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_andF<Pred1T,Pred2T>(
*static_cast<const Pred1T*>(&Pred1),
*static_cast<const Pred2T*>(&Pred2) );
}
//! predicate 'or' composition predicate
/*!
Construct the \c class_or predicate. This predicate can be used
to logically combine two classification predicates. \c class_or holds,
if one of the predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_or predicate
*/
template<typename Pred1T, typename Pred2T>
inline detail::pred_orF<Pred1T, Pred2T>
operator||(
const predicate_facade<Pred1T>& Pred1,
const predicate_facade<Pred2T>& Pred2 )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_orF<Pred1T,Pred2T>(
*static_cast<const Pred1T*>(&Pred1),
*static_cast<const Pred2T*>(&Pred2));
}
//! predicate negation operator
/*!
Construct the \c class_not predicate. This predicate represents a negation.
\c class_or holds if of the predicates return false.
\param Pred The predicate to be negated
\return An instance of the \c class_not predicate
*/
template<typename PredT>
inline detail::pred_notF<PredT>
operator!( const predicate_facade<PredT>& Pred )
{
// Doing the static_cast with the pointer instead of the reference
// is a workaround for some compilers which have problems with
// static_cast's of template references, i.e. CW8. /grafik/
return detail::pred_notF<PredT>(*static_cast<const PredT*>(&Pred));
}
} // namespace algorithm
@ -236,69 +309,4 @@ namespace boost {
} // namespace boost
// predicate combinators ---------------------------------------------------//
/*
* These operators must be declared in the global namespace, otherwise
* they are not resolved correctly. There will not a problem with a name-clash,
* since they are define only for internal types
*/
//! predicate 'and' composition predicate
/*!
Construct the \c class_and predicate. This predicate can be used
to logically combine two classification predicates. \c class_and holds,
if both predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_and predicate
*/
template<typename Pred1T, typename Pred2T>
inline boost::algorithm::detail::pred_andF<Pred1T, Pred2T>
operator&&(
const boost::algorithm::detail::predicate_facade<Pred1T>& Pred1,
const boost::algorithm::detail::predicate_facade<Pred2T>& Pred2 )
{
return boost::algorithm::detail::pred_andF<Pred1T,Pred2T>(
static_cast<const Pred1T&>(Pred1),
static_cast<const Pred2T&>(Pred2) );
}
//! predicate 'or' composition predicate
/*!
Construct the \c class_or predicate. This predicate can be used
to logically combine two classification predicates. \c class_or holds,
if one of the predicates return true.
\param Pred1 The first predicate
\param Pred2 The second predicate
\return An instance of the \c class_or predicate
*/
template<typename Pred1T, typename Pred2T>
inline boost::algorithm::detail::pred_orF<Pred1T, Pred2T>
operator||(
const boost::algorithm::detail::predicate_facade<Pred1T>& Pred1,
const boost::algorithm::detail::predicate_facade<Pred2T>& Pred2 )
{
return boost::algorithm::detail::pred_orF<Pred1T,Pred2T>(
static_cast<const Pred1T&>(Pred1),
static_cast<const Pred2T&>(Pred2));
}
//! predicate negation operator
/*!
Construct the \c class_not predicate. This predicate represents a negation.
\c class_or holds, if of the predicates return false.
\param Pred The predicate to be negated
\return An instance of the \c class_not predicate
*/
template<typename PredT>
inline boost::algorithm::detail::pred_notF<PredT>
operator!( const boost::algorithm::detail::predicate_facade<PredT>& Pred )
{
return boost::algorithm::detail::pred_notF<PredT>(static_cast<const PredT&>(Pred));
}
#endif // BOOST_STRING_PREDICATE_HPP

View File

@ -1,268 +0,0 @@
// Boost string_algo library collection_traits.hpp header file -------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright Thorsten Ottosen 2002-2003. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// Orignal idea of container traits was proposed by Jeremy Siek and
// Thorsten Ottosen. This implemenetation is lightweighted version
// of container_traits adapter for usage with string_algo library
#ifndef BOOST_STRING_COLLECTION_TRAITS_HPP
#define BOOST_STRING_COLLECTION_TRAITS_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/mpl/apply_if.hpp>
// Implementation
#include <boost/algorithm/string/detail/collection_traits.hpp>
/*! \file
Defines collection_traits class and related free-standing functions.
This facility is used to unify the access to different types of collections.
It allows the algorithms in the library to work with STL collections, c-style
array, null-terminated c-strings (and more) using the same interface.
*/
namespace boost {
namespace algorithm {
// collection_traits template class -----------------------------------------//
//! collection_traits class
/*!
Collection traits provides uniform access to different types of
collections. This functionality allows to write generic algorithms
which work with several different kinds of collections.
Currently following collection types are supported:
- containers with STL compatible container interface ( see ContainerConcept )
( i.e. \c std::vector<>, \c std::list<>, \c std::string<> ... )
- c-style array
( \c char[10], \c int[15] ... )
- null-terminated c-strings
( \c char*, \c wchar_T* )
- std::pair of iterators
( i.e \c std::pair<vector<int>::iterator,vector<int>::iterator> )
Collection traits provide a external collection interface operations.
All are accessible using free-standing functions.
Following operations are supported:
- \c size()
- \c empty()
- \c begin()
- \c end()
Container traits have somewhat limited functionality on compilers not
supporting partial template specialization and partial template ordering.
*/
template< typename T >
struct collection_traits
{
private:
typedef BOOST_STRING_TYPENAME ::boost::mpl::apply_if<
::boost::algorithm::detail::is_pair<T>,
detail::pair_container_traits_selector<T>,
BOOST_STRING_TYPENAME ::boost::mpl::apply_if<
::boost::is_array<T>,
detail::array_container_traits_selector<T>,
BOOST_STRING_TYPENAME ::boost::mpl::apply_if<
::boost::is_pointer<T>,
detail::pointer_container_traits_selector<T>,
detail::default_container_traits_selector<T>
>
>
>::type container_helper_type;
public:
//! Function type
typedef container_helper_type function_type;
//! Value type
typedef BOOST_STRING_TYPENAME
container_helper_type::value_type value_type;
//! Size type
typedef BOOST_STRING_TYPENAME
container_helper_type::size_type size_type;
//! Iterator type
typedef BOOST_STRING_TYPENAME
container_helper_type::iterator iterator;
//! Const iterator type
typedef BOOST_STRING_TYPENAME
container_helper_type::const_iterator const_iterator;
//! Result iterator type ( iterator of const_iterator, depending on the constness of the conainer )
typedef BOOST_STRING_TYPENAME
container_helper_type::result_iterator result_iterator;
//! Difference type
typedef BOOST_STRING_TYPENAME
container_helper_type::difference_type difference_type;
}; // 'collection_traits'
// collection_traits metafunctions -----------------------------------------//
//! Container value_type trait
/*!
Extract the type of elements conained in a container
*/
template< typename C >
struct value_type_of
{
typedef BOOST_STRING_TYPENAME collection_traits<C>::value_type type;
};
//! Container difference trait
/*!
Extract the container's difference type
*/
template< typename C >
struct difference_type_of
{
typedef BOOST_STRING_TYPENAME collection_traits<C>::difference_type type;
};
//! Container iterator trait
/*!
Extract the container's iterator type
*/
template< typename C >
struct iterator_of
{
typedef BOOST_STRING_TYPENAME collection_traits<C>::iterator type;
};
//! Container const_iterator trait
/*!
Extract the container's const_iterator type
*/
template< typename C >
struct const_iterator_of
{
typedef BOOST_STRING_TYPENAME collection_traits<C>::const_iterator type;
};
//! Container result_iterator
/*!
Extract the container's result_iterator type. This type maps to \c C::iterator
for mutable container and \c C::const_iterator for const containers.
*/
template< typename C >
struct result_iterator_of
{
typedef BOOST_STRING_TYPENAME collection_traits<C>::result_iterator type;
};
// collection_traits related functions -----------------------------------------//
//! Free-standing size() function
/*!
Get the size of the container. Uses collection_traits.
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::size_type
size( const C& c )
{
return collection_traits<C>::function_type::size( c );
}
//! Free-standing empty() function
/*!
Check whenever the container is empty. Uses container traits.
*/
template< typename C >
inline bool empty( const C& c )
{
return collection_traits<C>::function_type::empty( c );
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//! Free-standing begin() function
/*!
Get the begin iterator of the container. Uses collection_traits.
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::iterator
begin( C& c )
{
return collection_traits<C>::function_type::begin( c );
}
//! Free-standing begin() function
/*!
\overload
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::const_iterator
begin( const C& c )
{
return collection_traits<C>::function_type::begin( c );
}
//! Free-standing end() function
/*!
Get the begin iterator of the container. Uses collection_traits.
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::iterator
end( C& c )
{
return collection_traits<C>::function_type::end( c );
}
//! Free-standing end() function
/*!
\overload
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::const_iterator
end( const C& c )
{
return collection_traits<C>::function_type::end( c );
}
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//! Free-standing begin() function
/*!
\overload
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::result_iterator
begin( C& c )
{
return collection_traits<C>::function_type::begin( c );
}
//! Free-standing end() function
/*!
\overload
*/
template< typename C >
inline BOOST_STRING_TYPENAME collection_traits<C>::result_iterator
end( C& c )
{
return collection_traits<C>::function_type::end( c );
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_COLLECTION_TRAITS_HPP

View File

@ -1,11 +1,12 @@
// Boost string_algo library compare.hpp header file -------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_COMPARE_HPP
#define BOOST_STRING_COMPARE_HPP
@ -14,7 +15,7 @@
#include <locale>
/*! \file
Defines element comparison predicates. Many algorithms in this library can
Defines element comparison predicates. Many algorithms in this library can
take an additional argument with a predicate used to compare elements.
This makes it possible, for instance, to have case insensitive versions
of the algorithms.
@ -22,13 +23,13 @@
namespace boost {
namespace algorithm {
// is_equal functor -----------------------------------------------//
//! is_equal functor
/*!
Standard STL equal_to does handle only comparison between arguments
of the same type. This is less restrictive version which wraps == operator.
Standard STL equal_to only handle comparison between arguments
of the same type. This is a less restrictive version which wraps operator ==.
*/
struct is_equal
{
@ -37,7 +38,7 @@ namespace boost {
Compare two operands for equality
*/
template< typename T1, typename T2 >
bool operator ()( const T1& Arg1, const T2& Arg2 ) const
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1==Arg2;
}
@ -54,28 +55,143 @@ namespace boost {
/*!
\param Loc locales used for comparison
*/
is_iequal( const std::locale& Loc=std::locale() ) :
is_iequal( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator ()( const T1& Arg1, const T2& Arg2 ) const
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return std::toupper(Arg1,m_Loc)==std::toupper(Arg2,m_Loc);
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)==std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)==std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
} // namespace algorithm
// is_less functor -----------------------------------------------//
//! is_less functor
/*!
Convenient version of standard std::less. Operation is templated, therefore it is
not required to specify the exact types upon the construction
*/
struct is_less
{
//! Functor operation
/*!
Compare two operands using > operator
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1<Arg2;
}
};
//! case insensitive version of is_less
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_iless
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_iless( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)<std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)<std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
// is_not_greater functor -----------------------------------------------//
//! is_not_greater functor
/*!
Convenient version of standard std::not_greater_to. Operation is templated, therefore it is
not required to specify the exact types upon the construction
*/
struct is_not_greater
{
//! Functor operation
/*!
Compare two operands using > operator
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
return Arg1<=Arg2;
}
};
//! case insensitive version of is_not_greater
/*!
Case insensitive comparison predicate. Comparison is done using
specified locales.
*/
struct is_not_igreater
{
//! Constructor
/*!
\param Loc locales used for comparison
*/
is_not_igreater( const std::locale& Loc=std::locale() ) :
m_Loc( Loc ) {}
//! Function operator
/*!
Compare two operands. Case is ignored.
*/
template< typename T1, typename T2 >
bool operator()( const T1& Arg1, const T2& Arg2 ) const
{
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper(Arg1)<=std::toupper(Arg2);
#else
return std::toupper<T1>(Arg1,m_Loc)<=std::toupper<T2>(Arg2,m_Loc);
#endif
}
private:
std::locale m_Loc;
};
} // namespace algorithm
// pull names to the boost namespace
using algorithm::is_equal;
using algorithm::is_iequal;
using algorithm::is_less;
using algorithm::is_iless;
using algorithm::is_not_greater;
using algorithm::is_not_igreater;
} // namespace boost

View File

@ -1,18 +1,20 @@
// Boost string_algo library concept.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONCEPT_HPP
#define BOOST_STRING_CONCEPT_HPP
#include <boost/concept_check.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
/*! \file
Defines concepts used in string_algo library
@ -23,8 +25,8 @@ namespace boost {
//! Finder concept
/*!
Defines finder concept. Finder is a functor which selects
an arbitraty part of a container. Search is performed on
Defines the Finder concept. Finder is a functor which selects
an arbitrary part of a string. Search is performed on
the range specified by starting and ending iterators.
Result of the find operation must be convertible to iterator_range.
@ -49,7 +51,7 @@ namespace boost {
//! Formatter concept
/*!
Defines formatter concept. Formatter is a functor, which
Defines the Formatter concept. Formatter is a functor, which
takes a result from a finder operation and transforms it
in a specific way.
@ -63,8 +65,8 @@ namespace boost {
void constraints()
{
// Operation
begin((*pFo)( (*pF)(i,i) ));
end((*pFo)( (*pF)(i,i) ));
::boost::begin((*pFo)( (*pF)(i,i) ));
::boost::end((*pFo)( (*pF)(i,i) ));
}
private:
IteratorT i;

View File

@ -1,25 +1,28 @@
// Boost string_algo library config.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONFIG_HPP
#define BOOST_STRING_CONFIG_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_STRING_DEDUCED_TYPENAME
# error "macro already defined!"
#endif
#ifdef __BORLANDC__
#define BOOST_STRING_TYPENAME
#else
#define BOOST_STRING_TYPENAME BOOST_DEDUCED_TYPENAME
// Metrowerks workaround
#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
#pragma parse_func_templ off
#endif
#endif // BOOST_STRING_CONFIG_HPP

View File

@ -1,11 +1,12 @@
// Boost string_algo library constants.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CONSTANTS_HPP
#define BOOST_STRING_CONSTANTS_HPP

View File

@ -1,11 +1,12 @@
// Boost string_algo library string_funct.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP
#define BOOST_STRING_CASE_CONV_DETAIL_HPP
@ -20,38 +21,98 @@ namespace boost {
// case conversion functors -----------------------------------------------//
// a tolower functor
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
// a tolower functor
template<typename CharT>
struct to_lowerF : public std::unary_function<CharT, CharT>
{
// Constructor
to_lowerF( const std::locale& Loc ) : m_Loc( Loc ) {}
to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
return std::tolower( Ch, m_Loc );
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::tolower( Ch);
#else
return std::tolower<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale& m_Loc;
const std::locale* m_Loc;
};
// a toupper functor
// a toupper functor
template<typename CharT>
struct to_upperF : public std::unary_function<CharT, CharT>
{
// Constructor
to_upperF( const std::locale& Loc ) : m_Loc( Loc ) {}
to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {}
// Operation
CharT operator ()( CharT Ch ) const
{
return std::toupper( Ch, m_Loc );
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL)
return std::toupper( Ch);
#else
return std::toupper<CharT>( Ch, *m_Loc );
#endif
}
private:
const std::locale& m_Loc;
const std::locale* m_Loc;
};
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
// algorithm implementation -------------------------------------------------------------------------
// Transform a range
template<typename OutputIteratorT, typename RangeT, typename FunctorT>
OutputIteratorT transform_range_copy(
OutputIteratorT Output,
const RangeT& Input,
FunctorT Functor)
{
return std::transform(
::boost::begin(Input),
::boost::end(Input),
Output,
Functor);
}
// Transform a range (in-place)
template<typename RangeT, typename FunctorT>
void transform_range(
const RangeT& Input,
FunctorT Functor)
{
std::transform(
::boost::begin(Input),
::boost::end(Input),
::boost::begin(Input),
Functor);
}
template<typename SequenceT, typename RangeT, typename FunctorT>
inline SequenceT transform_range_copy(
const RangeT& Input,
FunctorT Functor)
{
return SequenceT(
::boost::make_transform_iterator(
::boost::begin(Input),
Functor),
::boost::make_transform_iterator(
::boost::end(Input),
Functor));
}
} // namespace detail
} // namespace algorithm
} // namespace boost

View File

@ -1,11 +1,12 @@
// Boost string_algo library classification.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP
#define BOOST_STRING_CLASSIFICATION_DETAIL_HPP
@ -14,38 +15,29 @@
#include <algorithm>
#include <functional>
#include <locale>
#include <set>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/algorithm/string/predicate_facade.hpp>
#include <boost/type_traits/remove_const.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// predicate facade ------------------------------------------------------//
// Predicate facade
/*
This class allows to recognize classification
predicates, so that they can be combined using
composition operators.
*/
template<typename Derived>
struct predicate_facade {};
// classification functors -----------------------------------------------//
// is_classified functor
// is_classified functor
struct is_classifiedF :
public predicate_facade<is_classifiedF>
{
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor from a locale
// Constructor from a locale
is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
m_Type(Type), m_Locale(Loc) {}
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
@ -53,42 +45,207 @@ namespace boost {
return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
}
#if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL)
template<>
bool operator()( char const Ch ) const
{
return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
}
#endif
private:
const std::ctype_base::mask m_Type;
const std::locale m_Locale;
std::ctype_base::mask m_Type;
std::locale m_Locale;
};
// is_any_of functor
/*
// is_any_of functor
/*
returns true if the value is from the specified set
*/
template<typename CharT>
struct is_any_ofF :
public predicate_facade<is_any_ofF<CharT> >
{
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
private:
// set cannot operate on const value-type
typedef typename ::boost::remove_const<CharT>::type set_value_type;
public:
// Boost.ResultOf support
typedef bool result_type;
// Constructor
template<typename RangeT>
is_any_ofF( const RangeT& Range ) : m_Size(0)
{
// Prepare storage
m_Storage.m_dynSet=0;
std::size_t Size=::boost::distance(Range);
m_Size=Size;
set_value_type* Storage=0;
if(use_fixed_storage(m_Size))
{
// Use fixed storage
Storage=&m_Storage.m_fixSet[0];
}
else
{
// Use dynamic storage
m_Storage.m_dynSet=new set_value_type[m_Size];
Storage=m_Storage.m_dynSet;
}
// Use fixed storage
::std::copy(::boost::begin(Range), ::boost::end(Range), Storage);
::std::sort(Storage, Storage+m_Size);
}
// Copy constructor
is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size)
{
// Prepare storage
m_Storage.m_dynSet=0;
const set_value_type* SrcStorage=0;
set_value_type* DestStorage=0;
if(use_fixed_storage(m_Size))
{
// Use fixed storage
DestStorage=&m_Storage.m_fixSet[0];
SrcStorage=&Other.m_Storage.m_fixSet[0];
}
else
{
// Use dynamic storage
m_Storage.m_dynSet=new set_value_type[m_Size];
DestStorage=m_Storage.m_dynSet;
SrcStorage=Other.m_Storage.m_dynSet;
}
// Use fixed storage
::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
}
// Destructor
~is_any_ofF()
{
if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
{
delete [] m_Storage.m_dynSet;
}
}
// Assignment
is_any_ofF& operator=(const is_any_ofF& Other)
{
// Handle self assignment
if(this==&Other) return *this;
// Prepare storage
const set_value_type* SrcStorage;
set_value_type* DestStorage;
if(use_fixed_storage(Other.m_Size))
{
// Use fixed storage
DestStorage=&m_Storage.m_fixSet[0];
SrcStorage=&Other.m_Storage.m_fixSet[0];
// Delete old storage if was present
if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
{
delete [] m_Storage.m_dynSet;
}
// Set new size
m_Size=Other.m_Size;
}
else
{
// Other uses dynamic storage
SrcStorage=Other.m_Storage.m_dynSet;
// Check what kind of storage are we using right now
if(use_fixed_storage(m_Size))
{
// Using fixed storage, allocate new
set_value_type* pTemp=new set_value_type[Other.m_Size];
DestStorage=pTemp;
m_Storage.m_dynSet=pTemp;
m_Size=Other.m_Size;
}
else
{
// Using dynamic storage, check if can reuse
if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2)
{
// Reuse the current storage
DestStorage=m_Storage.m_dynSet;
m_Size=Other.m_Size;
}
else
{
// Allocate the new one
set_value_type* pTemp=new set_value_type[Other.m_Size];
DestStorage=pTemp;
// Delete old storage if necessary
if(m_Storage.m_dynSet!=0)
{
delete [] m_Storage.m_dynSet;
}
// Store the new storage
m_Storage.m_dynSet=pTemp;
// Set new size
m_Size=Other.m_Size;
}
}
}
// Copy the data
::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
return *this;
}
// Constructor
template< typename SeqT >
is_any_ofF( const SeqT& Seq ) :
m_Set( begin(Seq), end(Seq) ) {}
// Operation
template<typename Char2T>
bool operator()( Char2T Ch ) const
{
return m_Set.find(Ch)!=m_Set.end();
const set_value_type* Storage=
(use_fixed_storage(m_Size))
? &m_Storage.m_fixSet[0]
: m_Storage.m_dynSet;
return ::std::binary_search(Storage, Storage+m_Size, Ch);
}
private:
// set cannot operate on const value-type
typedef typename remove_const<CharT>::type set_value_type;
std::set<set_value_type> m_Set;
// check if the size is eligible for fixed storage
static bool use_fixed_storage(std::size_t size)
{
return size<=sizeof(set_value_type*)*2;
}
private:
// storage
// The actual used storage is selected on the type
union
{
set_value_type* m_dynSet;
set_value_type m_fixSet[sizeof(set_value_type*)*2];
}
m_Storage;
// storage size
::std::size_t m_Size;
};
// is_from_range functor
/*
// is_from_range functor
/*
returns true if the value is from the specified range.
(i.e. x>=From && x>=To)
*/
@ -96,19 +253,19 @@ namespace boost {
struct is_from_rangeF :
public predicate_facade< is_from_rangeF<CharT> >
{
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
// Constructor
is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
// Operation
template<typename Char2T>
bool operator()( Char2T Ch ) const
{
return ( m_From <= Ch ) && ( Ch <= m_To );
return ( m_From <= Ch ) && ( Ch <= m_To );
}
private:
CharT m_From;
CharT m_To;
@ -121,8 +278,8 @@ namespace boost {
{
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_andF( Pred1T Pred1, Pred2T Pred2 ) :
@ -130,11 +287,11 @@ namespace boost {
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
bool operator()( CharT Ch ) const
{
return m_Pred1(Ch) && m_Pred2(Ch);
}
private:
Pred1T m_Pred1;
Pred2T m_Pred2;
@ -146,8 +303,8 @@ namespace boost {
public predicate_facade< pred_orF<Pred1T,Pred2T> >
{
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_orF( Pred1T Pred1, Pred2T Pred2 ) :
@ -155,11 +312,11 @@ namespace boost {
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
bool operator()( CharT Ch ) const
{
return m_Pred1(Ch) || m_Pred2(Ch);
}
private:
Pred1T m_Pred1;
Pred2T m_Pred2;
@ -171,19 +328,19 @@ namespace boost {
public predicate_facade< pred_notF<PredT> >
{
public:
// Boost.Lambda support
template <class Args> struct sig { typedef bool type; };
// Boost.ResultOf support
typedef bool result_type;
// Constructor
pred_notF( PredT Pred ) : m_Pred(Pred) {}
// Operation
template<typename CharT>
bool operator()( CharT Ch ) const
bool operator()( CharT Ch ) const
{
return !m_Pred(Ch);
}
private:
PredT m_Pred;
};

View File

@ -1,621 +0,0 @@
// Boost string_algo library collection_traits.hpp header file -----------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_STRING_DETAIL_COLLECTION_TRAITS_HPP
#define BOOST_STRING_DETAIL_COLLECTION_TRAITS_HPP
#include <boost/algorithm/string/config.hpp>
#include <cstddef>
#include <string>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/algorithm/string/yes_no_type.hpp>
// Container traits implementation ---------------------------------------------------------
namespace boost {
namespace algorithm {
namespace detail {
// Default collection traits -----------------------------------------------------------------
// Default collection helper
/*
Wraps std::container compliant containers
*/
template< typename ContainerT >
struct default_container_traits
{
typedef BOOST_STRING_TYPENAME ContainerT::value_type value_type;
typedef BOOST_STRING_TYPENAME ContainerT::iterator iterator;
typedef BOOST_STRING_TYPENAME ContainerT::const_iterator const_iterator;
typedef BOOST_STRING_TYPENAME
::boost::mpl::if_< ::boost::is_const<ContainerT>,
const_iterator,
iterator
>::type result_iterator;
typedef BOOST_STRING_TYPENAME ContainerT::difference_type difference_type;
typedef BOOST_STRING_TYPENAME ContainerT::size_type size_type;
// static operations
template< typename C >
static size_type size( const C& c )
{
return c.size();
}
template< typename C >
static bool empty( const C& c )
{
return c.empty();
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename C >
static iterator begin( C& c )
{
return c.begin();
}
template< typename C >
static const_iterator begin( const C& c )
{
return c.begin();
}
template< typename C >
static iterator end( C& c )
{
return c.end();
}
template< typename C >
static const_iterator end( const C& c )
{
return c.end();
}
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename C >
static result_iterator begin( C& c )
{
return c.begin();
}
template< typename C >
static result_iterator end( C& c )
{
return c.end();
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
};
template<typename T>
struct default_container_traits_selector
{
typedef default_container_traits<T> type;
};
// Pair container traits ---------------------------------------------------------------------
// pair selector
template< typename T, typename U >
yes_type is_pair_impl( const std::pair<T,U>* );
no_type is_pair_impl( ... );
template<typename T> struct is_pair
{
private:
static T* t;
public:
BOOST_STATIC_CONSTANT( bool, value=
sizeof(is_pair_impl(t))==sizeof(yes_type) );
};
// pair helper
template< typename PairT >
struct pair_container_traits
{
typedef BOOST_STRING_TYPENAME PairT::first_type element_type;
typedef BOOST_STRING_TYPENAME ::boost::detail::
iterator_traits<element_type>::value_type value_type;
typedef std::size_t size_type;
typedef BOOST_STRING_TYPENAME ::boost::detail::
iterator_traits<element_type>::difference_type difference_type;
typedef element_type iterator;
typedef element_type const_iterator;
typedef element_type result_iterator;
// static operations
template< typename P >
static size_type size( const P& p )
{
difference_type diff = std::distance( p.first, p.second );
if ( diff < 0 )
return 0;
else
return diff;
}
template< typename P >
static bool empty( const P& p )
{
return p.first==p.second;
}
template< typename P >
static const_iterator begin( const P& p )
{
return p.first;
}
template< typename P >
static const_iterator end( const P& p )
{
return p.second;
}
}; // 'pair_container_helper'
template<typename T>
struct pair_container_traits_selector
{
typedef pair_container_traits<T> type;
};
// Array container traits ---------------------------------------------------------------
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// array traits ( partial specialization )
template< typename T >
struct array_traits;
template< typename T, std::size_t sz >
struct array_traits<T[sz]>
{
// typedef
typedef T* iterator;
typedef const T* const_iterator;
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// size of the array ( static );
BOOST_STATIC_CONSTANT( size_type, array_size = sz );
};
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// array traits ( no partial specialization )
/*
without parial specialization we are able to
provide support only for a limited number of
types. Currently the primitive numeric types
are supported
*/
template< typename T, typename BaseT >
struct array_traits_impl
{
typedef BaseT value_type;
typedef BaseT* iterator;
typedef const BaseT* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// size of the array
BOOST_STATIC_CONSTANT( size_type, array_size = sizeof(T)/sizeof(BaseT) );
};
template< typename T, typename BaseT >
struct array_traits_impl_selector
{
typedef array_traits_impl<T,BaseT> type;
};
struct array_traits_void
{
typedef void type;
};
template< typename T, typename BaseT >
struct array_traits_cv_selector
{
typedef BOOST_STRING_TYPENAME
::boost::mpl::apply_if<
::boost::is_convertible<T,BaseT*>,
array_traits_impl_selector<T,BaseT>,
::boost::mpl::apply_if<
::boost::is_convertible<T,const BaseT*>,
array_traits_impl_selector<T, const BaseT>,
::boost::mpl::apply_if<
::boost::is_convertible<T, volatile BaseT*>,
array_traits_impl_selector<T, volatile BaseT>,
array_traits_impl_selector<T, const volatile BaseT>
>
>
>::type type;
};
template< typename T >
struct array_traits_select
{
template< typename T1, typename T2 >
struct apply
{
typedef BOOST_STRING_TYPENAME
::boost::mpl::apply_if<
::boost::is_convertible<T,const volatile T2*>,
array_traits_cv_selector<T,T2>,
::boost::mpl::identity<T1> >::type type;
};
};
template< typename T >
struct array_traits_selector
{
private:
// supported array base types
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
typedef BOOST_STRING_TYPENAME
::boost::mpl::vector10<
wchar_t,
#else // BOOST_NO_INTRINSIC_WCHAR_T
typedef BOOST_STRING_TYPENAME
::boost::mpl::vector9<
#endif // BOOST_NO_INTRINSIC_WCHAR_T
char,
signed char,
unsigned char,
signed short,
unsigned short,
signed int,
unsigned int,
signed long,
unsigned long
>::type array_base_types;
public:
typedef BOOST_STRING_TYPENAME
::boost::mpl::fold<
array_base_types,
::boost::algorithm::detail::array_traits_void,
::boost::algorithm::detail::array_traits_select<T> >::type type;
};
template< typename T >
struct array_traits
{
typedef BOOST_STRING_TYPENAME
array_traits_selector<T>::type traits_type;
typedef BOOST_STRING_TYPENAME
traits_type::value_type value_type;
typedef BOOST_STRING_TYPENAME
traits_type::iterator iterator;
typedef BOOST_STRING_TYPENAME
traits_type::const_iterator const_iterator;
typedef BOOST_STRING_TYPENAME
traits_type::size_type size_type;
typedef BOOST_STRING_TYPENAME
traits_type::difference_type difference_type;
BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size );
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// array lenght resolving
/*
Lenght of string contained in a static array could
be different from the size of the array.
For string processing we need the lenght without
terminating 0.
Therefore, the lenght is calulated for char and wchar_t
using char_traits, rather then simply returning
the array size.
*/
template< typename T >
struct array_length_selector
{
template< typename TraitsT >
struct array_length
{
typedef BOOST_STRING_TYPENAME
TraitsT::size_type size_type;
BOOST_STATIC_CONSTANT(
size_type,
array_size=TraitsT::array_size );
template< typename A >
static size_type length( const A& )
{
return array_size;
}
template< typename A >
static bool empty( const A& )
{
return array_size==0;
}
};
};
// specialization for char
template<>
struct array_length_selector<char>
{
template< typename TraitsT >
struct array_length
{
typedef BOOST_STRING_TYPENAME
TraitsT::size_type size_type;
template< typename A >
static size_type length( const A& a )
{
if ( a==0 )
return 0;
else
return std::char_traits<char>::length(a);
}
template< typename A >
static bool empty( const A& a )
{
return a==0 || a[0]==0;
}
};
};
// specialization for wchar_t
template<>
struct array_length_selector<wchar_t>
{
template< typename TraitsT >
struct array_length
{
typedef BOOST_STRING_TYPENAME
TraitsT::size_type size_type;
template< typename A >
static size_type length( const A& a )
{
if ( a==0 )
return 0;
else
return std::char_traits<wchar_t>::length(a);
}
template< typename A >
static bool empty( const A& a )
{
return a==0 || a[0]==0;
}
};
};
template< typename T >
struct array_container_traits
{
private:
// resolve array traits
typedef array_traits<T> traits_type;
public:
typedef BOOST_STRING_TYPENAME
traits_type::value_type value_type;
typedef BOOST_STRING_TYPENAME
traits_type::iterator iterator;
typedef BOOST_STRING_TYPENAME
traits_type::const_iterator const_iterator;
typedef BOOST_STRING_TYPENAME
traits_type::size_type size_type;
typedef BOOST_STRING_TYPENAME
traits_type::difference_type difference_type;
typedef BOOST_STRING_TYPENAME
::boost::mpl::if_< ::boost::is_const<T>,
const_iterator,
iterator
>::type result_iterator;
private:
// resolve array size
typedef BOOST_STRING_TYPENAME
::boost::remove_cv<value_type>::type char_type;
typedef BOOST_STRING_TYPENAME
array_length_selector<char_type>::
BOOST_NESTED_TEMPLATE array_length<traits_type> array_length_type;
public:
BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size );
// static operations
template< typename A >
static size_type size( const A& a )
{
return array_length_type::length(a);
}
template< typename A >
static bool empty( const A& a )
{
return array_length_type::empty(a);
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename A >
static iterator begin( A& a )
{
return a;
}
template< typename A >
static const_iterator begin( const A& a )
{
return a;
}
template< typename A >
static iterator end( A& a )
{
return a+array_length_type::length(a);
}
template< typename A >
static const_iterator end( const A& a )
{
return a+array_length_type::length(a);
}
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename A >
static result_iterator begin( A& a )
{
return a;
}
template< typename A >
static result_iterator end( A& a )
{
return a+array_length_type::length(a);
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
};
template<typename T>
struct array_container_traits_selector
{
typedef array_container_traits<T> type;
};
// Pointer container traits ---------------------------------------------------------------
template<typename T>
struct pointer_container_traits
{
typedef BOOST_STRING_TYPENAME
::boost::remove_pointer<T>::type value_type;
typedef BOOST_STRING_TYPENAME
::boost::remove_cv<value_type>::type char_type;
typedef ::std::char_traits<char_type> char_traits;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef BOOST_STRING_TYPENAME
::boost::mpl::if_< ::boost::is_const<T>,
const_iterator,
iterator
>::type result_iterator;
// static operations
template< typename P >
static size_type size( const P& p )
{
if ( p==0 )
return 0;
else
return char_traits::length(p);
}
template< typename P >
static bool empty( const P& p )
{
return p==0 || p[0]==0;
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename P >
static iterator begin( P& p )
{
return p;
}
template< typename P >
static const_iterator begin( const P& p )
{
return p;
}
template< typename P >
static iterator end( P& p )
{
if ( p==0 )
return p;
else
return p+char_traits::length(p);
}
template< typename P >
static const_iterator end( const P& p )
{
if ( p==0 )
return p;
else
return p+char_traits::length(p);
}
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename P >
static result_iterator begin( P& p )
{
return p;
}
template< typename P >
static result_iterator end( P& p )
{
if ( p==0 )
return p;
else
return p+char_traits::length(p);
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
};
template<typename T>
struct pointer_container_traits_selector
{
typedef pointer_container_traits<T> type;
};
} // namespace detail
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_DETAIL_COLLECTION_HPP

View File

@ -1,17 +1,20 @@
// Boost string_algo library find_format.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_DETAIL_HPP
#define BOOST_STRING_FIND_FORMAT_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/iterator.hpp>
#include <boost/algorithm/string/detail/find_format_store.hpp>
#include <boost/algorithm/string/detail/replace_storage.hpp>
@ -21,46 +24,22 @@ namespace boost {
// find_format_copy (iterator variant) implementation -------------------------------//
template<
template<
typename OutputIteratorT,
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline OutputIteratorT find_format_copy_impl(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult )
{
return find_format_copy_impl2(
Output,
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
}
template<
typename OutputIteratorT,
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline OutputIteratorT find_format_copy_impl2(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult )
{
typedef find_format_store<
BOOST_STRING_TYPENAME
const_iterator_of<InputT>::type,
range_const_iterator<InputT>::type,
FormatterT,
FormatResultT > store_type;
@ -70,58 +49,61 @@ namespace boost {
if ( !M )
{
// Match not found - return original sequence
std::copy( begin(Input), end(Input), Output );
Output = std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
return Output;
}
// Copy the beginning of the sequence
std::copy( begin(Input), begin(M), Output );
Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output );
// Format find result
// Copy formated result
std::copy( begin(M.format_result()), end(M.format_result()), Output );
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
// Copy the rest of the sequence
std::copy( M.end(), end(Input), Output );
Output = std::copy( M.end(), ::boost::end(Input), Output );
return Output;
}
// find_format_copy implementation --------------------------------------------------//
template<
typename InputT,
typename FinderT,
typename OutputIteratorT,
typename InputT,
typename FormatterT,
typename FindResultT >
inline InputT find_format_copy_impl(
inline OutputIteratorT find_format_copy_impl(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult)
{
return find_format_copy_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
const FindResultT& FindResult )
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_copy_impl2(
Output,
Input,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
}
}
template<
// find_format_copy implementation --------------------------------------------------//
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline InputT find_format_copy_impl2(
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult)
{
typedef find_format_store<
BOOST_STRING_TYPENAME
const_iterator_of<InputT>::type,
range_const_iterator<InputT>::type,
FormatterT,
FormatResultT > store_type;
@ -136,52 +118,51 @@ namespace boost {
InputT Output;
// Copy the beginning of the sequence
insert( Output, end(Output), begin(Input), M.begin() );
insert( Output, ::boost::end(Output), ::boost::begin(Input), M.begin() );
// Copy formated result
insert( Output, end(Output), M.format_result() );
insert( Output, ::boost::end(Output), M.format_result() );
// Copy the rest of the sequence
insert( Output, end(Output), M.end(), end(Input) );
insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) );
return Output;
}
// replace implementation ----------------------------------------------------//
template<
typename InputT,
typename FinderT,
template<
typename InputT,
typename FormatterT,
typename FindResultT >
inline void find_format_impl(
InputT& Input,
FinderT Finder,
inline InputT find_format_copy_impl(
const InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult)
{
find_format_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_copy_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return Input;
}
}
// replace implementation ----------------------------------------------------//
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT,
typename FormatResultT >
inline void find_format_impl2(
InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult,
const FormatResultT& FormatResult)
{
typedef find_format_store<
BOOST_STRING_TYPENAME
iterator_of<InputT>::type,
range_iterator<InputT>::type,
FormatterT,
FormatResultT > store_type;
@ -195,7 +176,25 @@ namespace boost {
}
// Replace match
replace( Input, M.begin(), M.end(), M.format_result() );
::boost::algorithm::detail::replace( Input, M.begin(), M.end(), M.format_result() );
}
template<
typename InputT,
typename FormatterT,
typename FindResultT >
inline void find_format_impl(
InputT& Input,
FormatterT Formatter,
const FindResultT& FindResult)
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
::boost::algorithm::detail::find_format_impl2(
Input,
Formatter,
FindResult,
Formatter(FindResult) );
}
}
} // namespace detail

View File

@ -1,17 +1,20 @@
// Boost string_algo library find_format_all.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP
#define BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/algorithm/string/detail/find_format_store.hpp>
#include <boost/algorithm/string/detail/replace_storage.hpp>
@ -21,29 +24,7 @@ namespace boost {
// find_format_all_copy (iterator variant) implementation ---------------------------//
template<
typename OutputIteratorT,
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline OutputIteratorT find_format_all_copy_impl(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult )
{
return find_format_all_copy_impl2(
Output,
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
}
template<
template<
typename OutputIteratorT,
typename InputT,
typename FinderT,
@ -59,7 +40,7 @@ namespace boost {
const FormatResultT& FormatResult )
{
typedef BOOST_STRING_TYPENAME
const_iterator_of<InputT>::type input_iterator_type;
range_const_iterator<InputT>::type input_iterator_type;
typedef find_format_store<
input_iterator_type,
@ -70,49 +51,56 @@ namespace boost {
store_type M( FindResult, FormatResult, Formatter );
// Initialize last match
input_iterator_type LastMatch=begin(Input);
input_iterator_type LastMatch=::boost::begin(Input);
// Iterate throug all matches
// Iterate through all matches
while( M )
{
// Copy the beginning of the sequence
std::copy( LastMatch, M.begin(), Output );
Output = std::copy( LastMatch, M.begin(), Output );
// Copy formated result
std::copy( begin(M.format_result()), end(M.format_result()), Output );
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
// Proceed to the next match
LastMatch=M.end();
M=Finder( LastMatch, end(Input) );
M=Finder( LastMatch, ::boost::end(Input) );
}
// Copy the rest of the sequence
std::copy( LastMatch, end(Input), Output );
Output = std::copy( LastMatch, ::boost::end(Input), Output );
return Output;
}
// find_format_all_copy implementation ----------------------------------------------//
template<
typename InputT,
typename OutputIteratorT,
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline InputT find_format_all_copy_impl(
inline OutputIteratorT find_format_all_copy_impl(
OutputIteratorT Output,
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
const FindResultT& FindResult)
{
return find_format_all_copy_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
const FindResultT& FindResult )
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Output,
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return std::copy( ::boost::begin(Input), ::boost::end(Input), Output );
}
}
template<
// find_format_all_copy implementation ----------------------------------------------//
template<
typename InputT,
typename FinderT,
typename FormatterT,
@ -126,7 +114,7 @@ namespace boost {
const FormatResultT& FormatResult)
{
typedef BOOST_STRING_TYPENAME
const_iterator_of<InputT>::type input_iterator_type;
range_const_iterator<InputT>::type input_iterator_type;
typedef find_format_store<
input_iterator_type,
@ -137,51 +125,55 @@ namespace boost {
store_type M( FindResult, FormatResult, Formatter );
// Initialize last match
input_iterator_type LastMatch=begin(Input);
input_iterator_type LastMatch=::boost::begin(Input);
// Output temporary
InputT Output;
// Iterate throug all matches
// Iterate through all matches
while( M )
{
// Copy the beginning of the sequence
insert( Output, end(Output), LastMatch, M.begin() );
insert( Output, ::boost::end(Output), LastMatch, M.begin() );
// Copy formated result
insert( Output, end(Output), M.format_result() );
insert( Output, ::boost::end(Output), M.format_result() );
// Proceed to the next match
LastMatch=M.end();
M=Finder( LastMatch, end(Input) );
M=Finder( LastMatch, ::boost::end(Input) );
}
// Copy the rest of the sequence
insert( Output, end(Output), LastMatch, end(Input) );
::boost::algorithm::detail::insert( Output, ::boost::end(Output), LastMatch, ::boost::end(Input) );
return Output;
}
// find_format_all implementation ------------------------------------------------//
template<
typename InputT,
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline void find_format_all_impl(
InputT& Input,
inline InputT find_format_all_copy_impl(
const InputT& Input,
FinderT Finder,
FormatterT Formatter,
FindResultT FindResult)
const FindResultT& FindResult)
{
find_format_all_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
return ::boost::algorithm::detail::find_format_all_copy_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
} else {
return Input;
}
}
// find_format_all implementation ------------------------------------------------//
template<
typename InputT,
typename FinderT,
@ -196,7 +188,7 @@ namespace boost {
FormatResultT FormatResult)
{
typedef BOOST_STRING_TYPENAME
iterator_of<InputT>::type input_iterator_type;
range_iterator<InputT>::type input_iterator_type;
typedef find_format_store<
input_iterator_type,
FormatterT,
@ -207,11 +199,11 @@ namespace boost {
// Instantiate replacement storage
std::deque<
BOOST_STRING_TYPENAME value_type_of<InputT>::type> Storage;
BOOST_STRING_TYPENAME range_value<InputT>::type> Storage;
// Initialize replacement iterators
input_iterator_type InsertIt=begin(Input);
input_iterator_type SearchIt=begin(Input);
input_iterator_type InsertIt=::boost::begin(Input);
input_iterator_type SearchIt=::boost::begin(Input);
while( M )
{
@ -227,29 +219,50 @@ namespace boost {
SearchIt=M.end();
// Copy formated replace to the storage
copy_to_storage( Storage, M.format_result() );
::boost::algorithm::detail::copy_to_storage( Storage, M.format_result() );
// Find range for a next match
M=Finder( SearchIt, end(Input) );
M=Finder( SearchIt, ::boost::end(Input) );
}
// process the last segment
InsertIt=process_segment(
InsertIt=::boost::algorithm::detail::process_segment(
Storage,
Input,
InsertIt,
SearchIt,
end(Input) );
::boost::end(Input) );
if ( Storage.empty() )
{
// Truncate input
erase( Input, InsertIt, end(Input) );
::boost::algorithm::detail::erase( Input, InsertIt, ::boost::end(Input) );
}
else
{
// Copy remaining data to the end of input
insert( Input, end(Input), Storage.begin(), Storage.end() );
::boost::algorithm::detail::insert( Input, ::boost::end(Input), Storage.begin(), Storage.end() );
}
}
template<
typename InputT,
typename FinderT,
typename FormatterT,
typename FindResultT >
inline void find_format_all_impl(
InputT& Input,
FinderT Finder,
FormatterT Formatter,
FindResultT FindResult)
{
if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) {
::boost::algorithm::detail::find_format_all_impl2(
Input,
Finder,
Formatter,
FindResult,
Formatter(FindResult) );
}
}

View File

@ -1,18 +1,18 @@
// Boost string_algo library find_format_store.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP
#define BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
namespace boost {
namespace algorithm {
@ -20,6 +20,10 @@ namespace boost {
// temporary format and find result storage --------------------------------//
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
template<
typename ForwardIteratorT,
typename FormatterT,
@ -36,7 +40,7 @@ namespace boost {
public:
// Construction
find_format_store(
const base_type FindResult,
const base_type& FindResult,
const format_result_type& FormatResult,
const formatter_type& Formatter ) :
base_type(FindResult),
@ -48,7 +52,9 @@ namespace boost {
find_format_store& operator=( FindResultT FindResult )
{
iterator_range<ForwardIteratorT>::operator=(FindResult);
m_FormatResult=m_Formatter(FindResult);
if( !this->empty() ) {
m_FormatResult=m_Formatter(FindResult);
}
return *this;
}
@ -64,6 +70,18 @@ namespace boost {
const formatter_type& m_Formatter;
};
template<typename InputT, typename FindResultT>
bool check_find_result(InputT&, FindResultT& FindResult)
{
typedef BOOST_STRING_TYPENAME
range_const_iterator<InputT>::type input_iterator_type;
iterator_range<input_iterator_type> ResultRange(FindResult);
return !ResultRange.empty();
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
} // namespace detail
} // namespace algorithm
} // namespace boost

View File

@ -1,79 +1,26 @@
// Boost string_algo library find_iterator.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
#define BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/function.hpp>
namespace boost {
namespace algorithm {
namespace detail {
// finder virtualizer -----------------------------------------------//
template<typename IteratorT>
struct virtual_finder
{
// typedefs
typedef IteratorT input_iterator_type;
typedef iterator_range<IteratorT> match_type;
// virtual destructor
virtual ~virtual_finder() {}
// clone
virtual virtual_finder* clone() const=0;
// operation
virtual match_type do_find(
input_iterator_type Begin,
input_iterator_type End ) const=0;
};
template<typename IteratorT, typename FinderT>
struct virtual_finder_typed : public virtual_finder<IteratorT>
{
// typedefs
typedef virtual_finder<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME
base_type::input_iterator_type input_iterator_type;
typedef BOOST_STRING_TYPENAME
base_type::match_type match_type;
// constuction
virtual_finder_typed( FinderT Finder ) : m_Finder(Finder) {}
// clone
virtual_finder_typed* clone() const
{
return new virtual_finder_typed(m_Finder);
}
// operation
virtual match_type do_find(
input_iterator_type Begin,
input_iterator_type End ) const
{
return m_Finder(Begin,End);
}
private:
// Finder
FinderT m_Finder;
};
// find_iterator base -----------------------------------------------//
// Find iterator base
@ -84,40 +31,36 @@ namespace boost {
// typedefs
typedef IteratorT input_iterator_type;
typedef iterator_range<IteratorT> match_type;
typedef function2<
match_type,
input_iterator_type,
input_iterator_type> finder_type;
protected:
// Protected construction/destruction
// Default constructor
find_iterator_base() : m_pFinder(0) {};
find_iterator_base() {};
// Copy construction
find_iterator_base( const find_iterator_base& Other ) :
m_pFinder(0)
{
if ( Other.m_pFinder )
{
m_pFinder=Other.m_pFinder->clone();
}
}
m_Finder(Other.m_Finder) {}
// Constructor
template<typename FinderT>
find_iterator_base( FinderT Finder, int ) :
m_pFinder( new virtual_finder_typed<IteratorT,FinderT>(Finder) ) {}
m_Finder(Finder) {}
// Destructor
~find_iterator_base()
{
if (m_pFinder) delete m_pFinder;
}
~find_iterator_base() {}
// Find operation
match_type do_find(
input_iterator_type Begin,
input_iterator_type End ) const
{
if (m_pFinder)
if (!m_Finder.empty())
{
return m_pFinder->do_find(Begin,End);
return m_Finder(Begin,End);
}
else
{
@ -128,12 +71,12 @@ namespace boost {
// Check
bool is_null() const
{
return !m_pFinder;
return m_Finder.empty();
}
private:
// Finder
virtual_finder<IteratorT>* m_pFinder;
finder_type m_Finder;
};
} // namespace detail

View File

@ -1,11 +1,12 @@
// Boost string_algo library finder.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FINDER_DETAIL_HPP
#define BOOST_STRING_FINDER_DETAIL_HPP
@ -13,8 +14,12 @@
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/constants.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/as_literal.hpp>
namespace boost {
namespace algorithm {
@ -25,7 +30,7 @@ namespace boost {
// find a subsequence in the sequence ( functor )
/*
Returns a pair <begin,end> marking the subsequence in the sequence.
Returns a pair <begin,end> marking the subsequence in the sequence.
If the find fails, functor returns <End,End>
*/
template<typename SearchIteratorT,typename PredicateT>
@ -35,9 +40,9 @@ namespace boost {
// Construction
template< typename SearchT >
first_finderF( const SearchT& Search, PredicateT Comp ) :
m_Search(begin(Search), end(Search)), m_Comp(Comp) {}
first_finderF(
first_finderF( const SearchT& Search, PredicateT Comp ) :
m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
first_finderF(
search_iterator_type SearchBegin,
search_iterator_type SearchEnd,
PredicateT Comp ) :
@ -46,8 +51,8 @@ namespace boost {
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
@ -58,8 +63,8 @@ namespace boost {
OuterIt!=End;
++OuterIt)
{
// Sanity check
if( empty(m_Search) )
// Sanity check
if( boost::empty(m_Search) )
return result_type( End, End );
input_iterator_type InnerIt=OuterIt;
@ -68,7 +73,7 @@ namespace boost {
InnerIt!=End && SubstrIt!=m_Search.end();
++InnerIt,++SubstrIt)
{
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
break;
}
@ -87,9 +92,9 @@ namespace boost {
// find last functor -----------------------------------------------//
// find the last match a subsequnce in the sequence ( functor )
// find the last match a subseqeunce in the sequence ( functor )
/*
Returns a pair <begin,end> marking the subsequence in the sequence.
Returns a pair <begin,end> marking the subsequence in the sequence.
If the find fails, returns <End,End>
*/
template<typename SearchIteratorT, typename PredicateT>
@ -102,9 +107,9 @@ namespace boost {
// Construction
template< typename SearchT >
last_finderF( const SearchT& Search, PredicateT Comp ) :
m_Search(begin(Search), end(Search)), m_Comp(Comp) {}
last_finderF(
last_finderF( const SearchT& Search, PredicateT Comp ) :
m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
last_finderF(
search_iterator_type SearchBegin,
search_iterator_type SearchEnd,
PredicateT Comp ) :
@ -113,34 +118,34 @@ namespace boost {
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
if( empty(m_Search) )
if( boost::empty(m_Search) )
return result_type( End, End );
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return findit( Begin, End, category() );
}
}
private:
// forward iterator
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::forward_iterator_tag ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
first_finder_type first_finder(
first_finder_type first_finder(
m_Search.begin(), m_Search.end(), m_Comp );
result_type M=first_finder( Begin, End );
@ -149,7 +154,7 @@ namespace boost {
while( M )
{
Last=M;
M=first_finder( end(M), End );
M=first_finder( ::boost::end(M), End );
}
return Last;
@ -158,9 +163,9 @@ namespace boost {
// bidirectional iterator
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::bidirectional_iterator_tag ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
@ -178,7 +183,7 @@ namespace boost {
InnerIt!=End && SubstrIt!=m_Search.end();
++InnerIt,++SubstrIt)
{
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
if( !( m_Comp(*InnerIt,*SubstrIt) ) )
break;
}
@ -194,12 +199,12 @@ namespace boost {
iterator_range<search_iterator_type> m_Search;
PredicateT m_Comp;
};
// find n-th functor -----------------------------------------------//
// find the n-th match of a subsequnce in the sequence ( functor )
// find the n-th match of 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>
*/
template<typename SearchIteratorT, typename PredicateT>
@ -209,53 +214,76 @@ namespace boost {
typedef first_finderF<
search_iterator_type,
PredicateT> first_finder_type;
typedef last_finderF<
search_iterator_type,
PredicateT> last_finder_type;
// Construction
template< typename SearchT >
nth_finderF(
const SearchT& Search,
unsigned int Nth,
PredicateT Comp) :
m_Search(begin(Search), end(Search)),
nth_finderF(
const SearchT& Search,
int Nth,
PredicateT Comp) :
m_Search(::boost::begin(Search), ::boost::end(Search)),
m_Nth(Nth),
m_Comp(Comp) {}
nth_finderF(
nth_finderF(
search_iterator_type SearchBegin,
search_iterator_type SearchEnd,
unsigned int Nth,
int Nth,
PredicateT Comp) :
m_Search(SearchBegin, SearchEnd),
m_Search(SearchBegin, SearchEnd),
m_Nth(Nth),
m_Comp(Comp) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
if(m_Nth>=0)
{
return find_forward(Begin, End, m_Nth);
}
else
{
return find_backward(Begin, End, -m_Nth);
}
}
private:
// Implementation helpers
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_forward(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
// Sanity check
if( empty(m_Search) )
// Sanity check
if( boost::empty(m_Search) )
return result_type( End, End );
// Instantiate find funtor
first_finder_type first_finder(
// Instantiate find functor
first_finder_type first_finder(
m_Search.begin(), m_Search.end(), m_Comp );
result_type M( Begin, Begin );
for( unsigned int n=0; n<=m_Nth; ++n )
for( unsigned int n=0; n<=N; ++n )
{
// find next match
M=first_finder( end(M), End );
// find next match
M=first_finder( ::boost::end(M), End );
if ( !M )
{
// Subsequence not found, return
// Subsequence not found, return
return M;
}
}
@ -263,166 +291,250 @@ namespace boost {
return M;
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_backward(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
// Sanity check
if( boost::empty(m_Search) )
return result_type( End, End );
// Instantiate find functor
last_finder_type last_finder(
m_Search.begin(), m_Search.end(), m_Comp );
result_type M( End, End );
for( unsigned int n=1; n<=N; ++n )
{
// find next match
M=last_finder( Begin, ::boost::begin(M) );
if ( !M )
{
// Subsequence not found, return
return M;
}
}
return M;
}
private:
iterator_range<search_iterator_type> m_Search;
unsigned int m_Nth;
int m_Nth;
PredicateT m_Comp;
};
// find head/tail implementation helpers ---------------------------//
template<typename ForwardIteratorT>
iterator_range<ForwardIteratorT>
find_head_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::forward_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
input_iterator_type It=Begin;
for(
unsigned int Index=0;
Index<N && It!=End; ++Index,++It ) {};
return result_type( Begin, It );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_head_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::random_access_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
return result_type( Begin, End );
return result_type(Begin,Begin+N);
}
// Find head implementation
template<typename ForwardIteratorT>
iterator_range<ForwardIteratorT>
find_head_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::forward_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
unsigned int Index=0;
input_iterator_type It=Begin;
input_iterator_type It2=Begin;
// Advance It2 by N increments
for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
// Advance It, It2 to the end
for(; It2!=End; ++It,++It2 ) {};
return result_type( It, It2 );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::bidirectional_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
input_iterator_type It=End;
for(
unsigned int Index=0;
Index<N && It!=Begin; ++Index,--It ) {};
return result_type( It, End );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N,
std::random_access_iterator_tag )
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
return result_type( Begin, End );
return result_type( End-N, End );
}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
find_tail_impl(
ForwardIteratorT Begin,
ForwardIteratorT End,
unsigned int N )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() );
}
// find head functor -----------------------------------------------//
// find a head in the sequence ( functor )
/*
This functor find a head of the specified range. For
a specified N, the head is a subsequence of N starting
This functor find a head of the specified range. For
a specified N, the head is a subsequence of N starting
elements of the range.
*/
struct head_finderF
{
// Construction
head_finderF( unsigned int N ) : m_N(N) {}
head_finderF( int N ) : m_N(N) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
if(m_N>=0)
{
return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N );
}
else
{
iterator_range<ForwardIteratorT> Res=
::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N );
return findit( Begin, End, category() );
return ::boost::make_iterator_range(Begin, Res.begin());
}
}
private:
// Find operation implementation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::forward_iterator_tag ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
input_iterator_type It=Begin;
for(
unsigned int Index=0;
Index<m_N && It!=End; ++Index,++It ) {};
return result_type( Begin, It );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::random_access_iterator_tag ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < m_N ) )
return result_type( Begin, End );
return result_type(Begin,Begin+m_N);
}
private:
unsigned int m_N;
int m_N;
};
// find tail functor -----------------------------------------------//
// find a tail in the sequence ( functor )
/*
This functor find a tail of the specified range. For
a specified N, the head is a subsequence of N starting
This functor find a tail of the specified range. For
a specified N, the head is a subsequence of N starting
elements of the range.
*/
struct tail_finderF
{
// Construction
tail_finderF( unsigned int N ) : m_N(N) {}
tail_finderF( int N ) : m_N(N) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
if(m_N>=0)
{
return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N );
}
else
{
iterator_range<ForwardIteratorT> Res=
::boost::algorithm::detail::find_head_impl( Begin, End, -m_N );
return findit( Begin, End, category() );
return ::boost::make_iterator_range(Res.end(), End);
}
}
private:
// Find operation implementation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::forward_iterator_tag ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
unsigned int Index=0;
input_iterator_type It=Begin;
input_iterator_type It2=Begin;
// Advance It2 by N incremets
for( Index=0; Index<m_N && It2!=End; ++Index,++It2 ) {};
// Advance It, It2 to the end
for(; It2!=End; ++It,++It2 ) {};
return result_type( It, It2 );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::bidirectional_iterator_tag ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
input_iterator_type It=End;
for(
unsigned int Index=0;
Index<m_N && It!=Begin; ++Index,--It ) {};
return result_type( It, End );
}
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
findit(
ForwardIteratorT Begin,
ForwardIteratorT End,
std::random_access_iterator_tag ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef iterator_range<ForwardIteratorT> result_type;
if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < m_N ) )
return result_type( Begin, End );
return result_type( End-m_N, End );
}
private:
unsigned int m_N;
int m_N;
};
// find token functor -----------------------------------------------//
@ -434,29 +546,29 @@ namespace boost {
with an exception that it return range instead of a single
iterator.
If bCompress is set to true, adjacent matching tokens are
If bCompress is set to true, adjacent matching tokens are
concatenated into one match.
*/
template< typename PredicateT >
struct token_finderF
{
// Construction
token_finderF(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off ) :
token_finderF(
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off ) :
m_Pred(Pred), m_eCompress(eCompress) {}
// Operation
template< typename ForwardIteratorT >
iterator_range<ForwardIteratorT>
operator()(
ForwardIteratorT Begin,
operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef iterator_range<ForwardIteratorT> result_type;
ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
if( It==End )
{
return result_type( End, End );
@ -468,11 +580,11 @@ namespace boost {
if( m_eCompress==token_compress_on )
{
// Find first non-matching character
while( m_Pred(*It2) && It2!=End ) ++It2;
while( It2!=End && m_Pred(*It2) ) ++It2;
}
else
{
// Advance by one possition
// Advance by one position
++It2;
}
@ -499,21 +611,27 @@ namespace boost {
typedef iterator_range<input_iterator_type> result_type;
// Construction
range_finderF(
input_iterator_type Begin,
range_finderF(
input_iterator_type Begin,
input_iterator_type End ) : m_Range(Begin, End) {}
range_finderF(const iterator_range<input_iterator_type>& Range) :
range_finderF(const iterator_range<input_iterator_type>& Range) :
m_Range(Range) {}
// Operation
template< typename ForwardIterator2T >
iterator_range<ForwardIterator2T>
operator()(
ForwardIterator2T,
iterator_range<ForwardIterator2T>
operator()(
ForwardIterator2T,
ForwardIterator2T ) const
{
#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )
return iterator_range<const ForwardIterator2T>(this->m_Range);
#elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
return iterator_range<ForwardIterator2T>(m_Range.begin(), m_Range.end());
#else
return m_Range;
#endif
}
private:

View File

@ -1,19 +1,22 @@
// Boost string_algo library find_regex.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FINDER_REGEX_DETAIL_HPP
#define BOOST_STRING_FINDER_REGEX_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost {
namespace algorithm {
@ -29,7 +32,6 @@ namespace boost {
typedef regex_search_result<IteratorT> type;
typedef iterator_range<IteratorT> base_type;
typedef BOOST_STRING_TYPENAME base_type::value_type value_type;
typedef BOOST_STRING_TYPENAME base_type::reference reference;
typedef BOOST_STRING_TYPENAME base_type::difference_type difference_type;
typedef BOOST_STRING_TYPENAME base_type::const_iterator const_iterator;
typedef BOOST_STRING_TYPENAME base_type::iterator iterator;
@ -96,7 +98,7 @@ namespace boost {
// instantiate match result
match_results<input_iterator_type> result;
// search for a match
if ( regex_search( Begin, End, result, m_Rx, m_MatchFlags ) )
if ( ::boost::regex_search( Begin, End, result, m_Rx, m_MatchFlags ) )
{
// construct a result
return result_type( result );

View File

@ -1,17 +1,22 @@
// Boost string_algo library formatter.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_STRING_FORMATTER_DETAIL_HPP
#define BOOST_STRING_FORMATTER_DETAIL_HPP
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/algorithm/string/detail/util.hpp>
// generic replace functors -----------------------------------------------//
@ -23,22 +28,30 @@ namespace boost {
// const format functor ----------------------------------------------------//
// constant format functor
template<typename CollectionT>
template<typename RangeT>
struct const_formatF
{
private:
typedef BOOST_STRING_TYPENAME
const_iterator_of<CollectionT>::type format_iterator;
range_const_iterator<RangeT>::type format_iterator;
typedef iterator_range<format_iterator> result_type;
public:
// Construction
const_formatF(const CollectionT& Format) :
m_Format(begin(Format), end(Format)) {}
const_formatF(const RangeT& Format) :
m_Format(::boost::begin(Format), ::boost::end(Format)) {}
// Operation
template<typename Collection2T>
const result_type& operator()(const Collection2T&) const
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template<typename Range2T>
result_type& operator()(const Range2T&)
{
return m_Format;
}
#endif
template<typename Range2T>
const result_type& operator()(const Range2T&) const
{
return m_Format;
}
@ -50,14 +63,14 @@ namespace boost {
// identity format functor ----------------------------------------------------//
// identity format functor
template<typename CollectionT>
template<typename RangeT>
struct identity_formatF
{
// Operation
template< typename Collection2T >
const CollectionT& operator()(const Collection2T& Replace) const
template< typename Range2T >
const RangeT& operator()(const Range2T& Replace) const
{
return CollectionT(begin(Replace), end(Replace));
return RangeT(::boost::begin(Replace), ::boost::end(Replace));
}
};
@ -74,6 +87,31 @@ namespace boost {
}
};
// dissect format functor ----------------------------------------------------//
// dissect format functor
template<typename FinderT>
struct dissect_formatF
{
public:
// Construction
dissect_formatF(FinderT Finder) :
m_Finder(Finder) {}
// Operation
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
operator()(const RangeT& Replace) const
{
return m_Finder(::boost::begin(Replace), ::boost::end(Replace));
}
private:
FinderT m_Finder;
};
} // namespace detail
} // namespace algorithm
} // namespace boost

View File

@ -1,11 +1,12 @@
// Boost string_algo library formatter_regex.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP
#define BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP

View File

@ -1,11 +1,12 @@
// Boost string_algo library predicate.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_PREDICATE_DETAIL_HPP
#define BOOST_STRING_PREDICATE_DETAIL_HPP
@ -62,7 +63,7 @@ namespace boost {
iterator_range<ForwardIterator1T> Result
=last_finder(
make_iterator_range(SubBegin, SubEnd),
::boost::make_iterator_range(SubBegin, SubEnd),
Comp)(Begin, End);
return !Result.empty() && Result.end()==End;

View File

@ -1,11 +1,12 @@
// Boost string_algo library replace_storage.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
#define BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
@ -13,9 +14,7 @@
#include <boost/algorithm/string/config.hpp>
#include <algorithm>
#include <boost/mpl/bool.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/sequence_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/detail/sequence.hpp>
namespace boost {
@ -47,7 +46,7 @@ namespace boost {
StorageT& Storage,
const WhatT& What )
{
Storage.insert( Storage.end(), begin(What), end(What) );
Storage.insert( Storage.end(), ::boost::begin(What), ::boost::end(What) );
}
@ -69,7 +68,7 @@ namespace boost {
ForwardIteratorT SegmentEnd )
{
// Copy data from the storage until the beginning of the segment
ForwardIteratorT It=move_from_storage( Storage, InsertIt, SegmentBegin );
ForwardIteratorT It=::boost::algorithm::detail::move_from_storage( Storage, InsertIt, SegmentBegin );
// 3 cases are possible :
// a) Storage is empty, It==SegmentBegin
@ -123,9 +122,10 @@ namespace boost {
ForwardIteratorT InsertIt,
ForwardIteratorT SegmentBegin,
ForwardIteratorT SegmentEnd )
{
// Call replace to do the job
replace( Input, InsertIt, SegmentBegin, Storage );
::boost::algorithm::detail::replace( Input, InsertIt, SegmentBegin, Storage );
// Empty the storage
Storage.clear();
// Iterators were not changed, simply return the end of segment

View File

@ -1,11 +1,12 @@
// Boost string_algo library sequence.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_DETAIL_SEQUENCE_HPP
#define BOOST_STRING_DETAIL_SEQUENCE_HPP
@ -13,7 +14,9 @@
#include <boost/algorithm/string/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
@ -38,7 +41,7 @@ namespace boost {
BOOST_STRING_TYPENAME InputT::iterator At,
const InsertT& Insert )
{
insert( Input, At, begin(Insert), end(Insert) );
::boost::algorithm::detail::insert( Input, At, ::boost::begin(Insert), ::boost::end(Insert) );
}
// erase helper ---------------------------------------------------//
@ -110,7 +113,14 @@ namespace boost {
BOOST_STRING_TYPENAME InputT::iterator At=Input.erase( From, To );
if ( Begin!=End )
{
Input.insert( At, Begin, End );
if(!Input.empty())
{
Input.insert( At, Begin, End );
}
else
{
Input.insert( Input.begin(), Begin, End );
}
}
}
};
@ -172,7 +182,14 @@ namespace boost {
BOOST_STRING_TYPENAME InputT::iterator To,
const InsertT& Insert )
{
replace( Input, From, To, begin(Insert), end(Insert) );
if(From!=To)
{
::boost::algorithm::detail::replace( Input, From, To, ::boost::begin(Insert), ::boost::end(Insert) );
}
else
{
::boost::algorithm::detail::insert( Input, From, ::boost::begin(Insert), ::boost::end(Insert) );
}
}
} // namespace detail

View File

@ -1,11 +1,12 @@
// Boost string_algo library trim.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_TRIM_DETAIL_HPP
#define BOOST_STRING_TRIM_DETAIL_HPP
@ -19,36 +20,6 @@ namespace boost {
// trim iterator helper -----------------------------------------------//
// Search for first non matching character from the beginning of the sequence
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_begin(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace )
{
ForwardIteratorT It=InBegin;
for(; It!=InEnd; ++It )
{
if (!IsSpace(*It))
return It;
}
return It;
}
// Search for first non matching character from the end of the sequence
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_end(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return trim_end_iter_select( InBegin, InEnd, IsSpace, category() );
}
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_end_iter_select(
ForwardIteratorT InBegin,
@ -85,6 +56,36 @@ namespace boost {
return InBegin;
}
// Search for first non matching character from the beginning of the sequence
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_begin(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace )
{
ForwardIteratorT It=InBegin;
for(; It!=InEnd; ++It )
{
if (!IsSpace(*It))
return It;
}
return It;
}
// Search for first non matching character from the end of the sequence
template< typename ForwardIteratorT, typename PredicateT >
inline ForwardIteratorT trim_end(
ForwardIteratorT InBegin,
ForwardIteratorT InEnd,
PredicateT IsSpace )
{
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<ForwardIteratorT>::iterator_category category;
return ::boost::algorithm::detail::trim_end_iter_select( InBegin, InEnd, IsSpace, category() );
}
} // namespace detail
} // namespace algorithm

View File

@ -1,17 +1,19 @@
// Boost string_algo library util.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_UTIL_DETAIL_HPP
#define BOOST_STRING_UTIL_DETAIL_HPP
#include <boost/algorithm/string/config.hpp>
#include <functional>
#include <boost/range/iterator_range.hpp>
namespace boost {
namespace algorithm {
@ -22,7 +24,7 @@ namespace boost {
// empty_container
/*
This class represents always empty container,
containing elemets of type CharT.
containing elements of type CharT.
It is supposed to be used in a const version only
*/
@ -92,7 +94,7 @@ namespace boost {
{
SeqT operator()( const iterator_range<IteratorT>& Range ) const
{
return copy_iterator_range<SeqT>(Range);
return copy_range<SeqT>(Range);
}
};

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,31 @@
// Boost string_algo library find.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_HPP
#define BOOST_STRING_FIND_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/constants.hpp>
/*! \file
Defines a set of find algorithms. The algorithms are searching
for a subsequence of the input. The result is given as an \c iterator_range
for a substring of the input. The result is given as an \c iterator_range
delimiting the substring.
*/
@ -32,264 +38,280 @@ namespace boost {
/*!
Search the input using the given finder.
\param Input A collection which will be searched.
\param Input A string which will be searched.
\param Finder Finder object used for searching.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c CollectionT::iterator or
\c CollectionT::const_iterator, depending on the constness of
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
*/
template<typename CollectionT, typename FinderT>
template<typename RangeT, typename FinderT>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find(
CollectionT& Input,
FinderT Finder)
RangeT& Input,
const FinderT& Finder)
{
return Finder(begin(Input),end(Input));
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return Finder(::boost::begin(lit_input),::boost::end(lit_input));
}
// find_first -----------------------------------------------//
//! Find first algorithm
/*!
Search for a first match of search sequence in the
input collection.
Search for the first occurrence of the substring in the input.
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c CollectionT::iterator or
\c CollectionT::const_iterator, depending on the constness of
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
find_first(
Collection1T& Input,
const Collection2T& Search)
Range1T& Input,
const Range2T& Search)
{
return first_finder(Search)(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::first_finder(Search));
}
//! Find first algorithm ( case insensitive )
/*!
Search for a first match of search sequence in the
input collection. Searching is case insensitive.
Search for the first occurence of the substring in the input.
Searching is case insensitive.
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Loc a locale used for case insensitive comparison
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Collection1T::iterator or
\c Collection1T::const_iterator, depending on the constness of
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
ifind_first(
Collection1T& Input,
const Collection2T& Search,
Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale())
{
return first_finder(Search,is_iequal(Loc))(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::first_finder(Search,is_iequal(Loc)));
}
// find_last -----------------------------------------------//
//! Find last algorithm
/*!
Search for a last match of search sequence in the
input collection.
Search for the last occurrence of the substring in the input.
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Collection1T::iterator or
\c Collection1T::const_iterator, depending on the constness of
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
find_last(
Collection1T& Input,
const Collection2T& Search)
Range1T& Input,
const Range2T& Search)
{
return last_finder(Search)(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::last_finder(Search));
}
//! Find last algorithm ( case insensitive )
/*!
Search for a last match of search sequence in the
input collection. Searching is case insensitive.
Search for the last match a string in the input.
Searching is case insensitive.
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Loc a locale used for case insensitive comparison
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Collection1T::iterator or
\c Collection1T::const_iterator, depending on the constness of
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
ifind_last(
Collection1T& Input,
const Collection2T& Search,
Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale())
{
return last_finder(Search, is_iequal(Loc))(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::last_finder(Search, is_iequal(Loc)));
}
// find_nth ----------------------------------------------------------------------//
//! Find n-th algorithm
/*!
Search for an n-th match of search sequence in the
input collection.
Search for the n-th (zero-indexed) occurrence of the substring in the
input.
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Nth An index of the match to be found.
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Nth An index (zero-indexed) of the match to be found.
For negative N, the matches are counted from the end of string.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Collection1T::iterator or
\c Collection1T::const_iterator, depending on the constness of
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
find_nth(
Collection1T& Input,
const Collection2T& Search,
unsigned int Nth)
Range1T& Input,
const Range2T& Search,
int Nth)
{
return nth_finder(Search,Nth)(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::nth_finder(Search,Nth));
}
//! Find n-th algorithm ( case insensitive ).
/*!
Search for an n-th match of search sequence in the
input collection. Searching is case insensitive.
Search for the n-th (zero-indexed) occurrence of the substring in the
input. Searching is case insensitive.
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Nth An index of the match to be found.
\param Loc a locale used for case insensitive comparison
\param Input A string which will be searched.
\param Search A substring to be searched for.
\param Nth An index (zero-indexed) of the match to be found.
For negative N, the matches are counted from the end of string.
\param Loc A locale used for case insensitive comparison
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Collection1T::iterator or
\c Collection1T::const_iterator, depending on the constness of
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<Collection1T>::type>
BOOST_STRING_TYPENAME range_iterator<Range1T>::type>
ifind_nth(
Collection1T& Input,
const Collection2T& Search,
unsigned int Nth,
Range1T& Input,
const Range2T& Search,
int Nth,
const std::locale& Loc=std::locale())
{
return nth_finder(Search,Nth,is_iequal(Loc))(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::nth_finder(Search,Nth,is_iequal(Loc)));
}
// find_head ----------------------------------------------------------------------//
//! Find head algorithm
/*!
Get the head of the input. Head is a prefix of
a seqence of given size. If the sequence is shorter then required,
whole sequence if considered to be the head.
Get the head of the input. Head is a prefix of the string of the
given size. If the input is shorter then required, whole input if considered
to be the head.
\param Input A container which will be searched.
\param N A length of the head
\param Input An input string
\param N Length of the head
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c Collection1T::iterator or
\c Collection1T::const_iterator, depending on the constness of
Returned iterator is either \c Range1T::iterator or
\c Range1T::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename CollectionT>
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find_head(
CollectionT& Input,
unsigned int N)
RangeT& Input,
int N)
{
return head_finder(N)(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::head_finder(N));
}
// find_tail ----------------------------------------------------------------------//
//! Find tail algorithm
/*!
Get the tail of the input. Head is a suffix of
a seqence of given size. If the sequence is shorter then required,
whole sequence if considered to be the tail.
Get the tail of the input. Tail is a suffix of the string of the
given size. If the input is shorter then required, whole input if considered
to be the tail.
\param Input A container which will be searched.
\param N A length of the tail
\param Input An input string
\param N Length of the tail.
For N>=0, at most N characters are extracted.
For N<0, size(Input)-|N| characters are extracted.
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c CollectionT::iterator or
\c CollectionT::const_iterator, depending on the constness of
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename CollectionT>
template<typename RangeT>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find_tail(
CollectionT& Input,
unsigned int N)
RangeT& Input,
int N)
{
return tail_finder(N)(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::tail_finder(N));
}
// find_token --------------------------------------------------------------------//
//! Find token algorithm
/*!
Look for a given token in the collection. Token is specified by a predicate.
If bCompressed is given, adjacent tokens are considered to be one match.
Look for a given token in the string. Token is a character that matches the
given predicate.
If the "token compress mode" is enabled, adjacent tokens are considered to be one match.
\param Input A container which will be searched.
\param Input A input string.
\param Pred An unary predicate to identify a token
\param eCompress Enable/Disable compressing of adjacent tokens
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c CollectionT::iterator or
\c CollectionT::const_iterator, depending on the constness of
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<typename CollectionT, typename PredicateT>
template<typename RangeT, typename PredicateT>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
find_token(
CollectionT& Input,
RangeT& Input,
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off)
{
return token_finder(Pred, eCompress)(
begin(Input),end(Input));
return ::boost::algorithm::find(Input, ::boost::algorithm::token_finder(Pred, eCompress));
}
} // namespace algorithm

View File

@ -1,26 +1,31 @@
// Boost string_algo library find_format.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_FORMAT_HPP
#define BOOST_STRING_FIND_FORMAT_HPP
#include <deque>
#include <boost/detail/iterator.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/concept.hpp>
#include <boost/algorithm/string/detail/find_format.hpp>
#include <boost/algorithm/string/detail/find_format_all.hpp>
/*! \file
Defines generic replace algorithms. Each algorithm replaces
a part(s) of the input. The part to be replaced is looked up using a Finder object.
part(s) of the input. The part to be replaced is looked up using a Finder object.
Result of finding is then used by a Formatter object to generate the replacement.
*/
@ -33,52 +38,53 @@ namespace boost {
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input.
The resulting sequence is copied to the given output iterator.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Output An output iterator to which the result will be copied
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
\return An output iterator pointing just after last inserted character
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename CollectionT,
typename RangeT,
typename FinderT,
typename FormatterT>
inline OutputIteratorT find_format_copy(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
FinderT Finder,
FormatterT Formatter )
{
// Concept check
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return detail::find_format_copy_impl(
Output,
Input,
Finder,
lit_input,
Formatter,
Finder( begin(Input), end(Input) ) );
Finder( ::boost::begin(lit_input), ::boost::end(lit_input) ) );
}
//! Generic replace algorithm
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input.
The result is the modified copy of the input.
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
\return A modified copy of the input
\overload
*/
template<
typename SequenceT,
@ -90,19 +96,21 @@ namespace boost {
FormatterT Formatter )
{
// Concept check
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
return detail::find_format_copy_impl(
Input,
Finder,
Formatter,
Finder(begin(Input), end(Input)));
Finder(::boost::begin(Input), ::boost::end(Input)));
}
//! Generic replace algorithm
@ -124,19 +132,21 @@ namespace boost {
FormatterT Formatter)
{
// Concept check
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
detail::find_format_impl(
Input,
Finder,
Formatter,
Finder(begin(Input), end(Input)));
Finder(::boost::begin(Input), ::boost::end(Input)));
}
@ -147,53 +157,54 @@ namespace boost {
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input. Repeat this for all matching
substrings.
The resulting sequence is copied to the given output iterator.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Output An output iterator to which the result will be copied
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
\return An output iterator pointing just after last inserted character
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename CollectionT,
typename RangeT,
typename FinderT,
typename FormatterT>
inline OutputIteratorT find_format_all_copy(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
FinderT Finder,
FormatterT Formatter)
{
// Concept check
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME const_iterator_of<CollectionT>::type> >();
FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return detail::find_format_all_copy_impl(
Output,
Input,
lit_input,
Finder,
Formatter,
Finder(begin(Input), end(Input)));
Finder(::boost::begin(lit_input), ::boost::end(lit_input)));
}
//! Generic replace all algorithm
/*!
Use the Finder to search for a substring. Use the Formatter to format
this substring and replace it in the input. Repeat this for all matching
substrings.
The result is the modified copy of the input.
\param Input An input sequence
\param Finder A Finder object used to search for a match to be replaced
\param Formatter A Formatter object used to format a match
\return A modified copy of the input
\overload
*/
template<
typename SequenceT,
@ -205,19 +216,22 @@ namespace boost {
FormatterT Formatter )
{
// Concept check
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
return detail::find_format_all_copy_impl(
Input,
Finder,
Formatter,
Finder( begin(Input), end(Input) ) );
Finder( ::boost::begin(Input), ::boost::end(Input) ) );
}
//! Generic replace all algorithm
@ -240,19 +254,22 @@ namespace boost {
FormatterT Formatter )
{
// Concept check
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
BOOST_CONCEPT_ASSERT((
FormatterConcept<
FormatterT,
FinderT,BOOST_STRING_TYPENAME const_iterator_of<SequenceT>::type> >();
FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type>
));
detail::find_format_all_impl(
Input,
Finder,
Formatter,
Finder(begin(Input), end(Input)));
Finder(::boost::begin(Input), ::boost::end(Input)));
}

View File

@ -1,23 +1,35 @@
// Boost string_algo library find_iterator.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FIND_ITERATOR_HPP
#define BOOST_STRING_FIND_ITERATOR_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/detail/find_iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/find_iterator.hpp>
/*! \file
Defines find iterator classes. Find iterator repeatedly applies a Finder
to the specified input string to search for matches. Dereferencing
the iterator yields the current match or a range between the last and the current
match depending on the iterator used.
*/
namespace boost {
namespace algorithm {
@ -26,10 +38,10 @@ namespace boost {
//! find_iterator
/*!
Find iterator encapsulates a Finder and allows
an incremental searching in the sequence.
for incremental searching in a string.
Each increment moves the iterator to the next match.
Find iterator is readable forward traversal iterator.
Find iterator is a readable forward traversal iterator.
Dereferencing the iterator yields an iterator_range delimiting
the current match.
@ -46,12 +58,6 @@ namespace boost {
// facade support
friend class ::boost::iterator_core_access;
// base type
typedef iterator_facade<
find_iterator<IteratorT>,
const iterator_range<IteratorT>,
forward_traversal_tag> facade_type;
private:
// typedefs
@ -96,6 +102,24 @@ namespace boost {
increment();
}
//! Constructor
/*!
Construct new find_iterator for a given finder
and a range.
*/
template<typename FinderT, typename RangeT>
find_iterator(
RangeT& Col,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col));
m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col));
m_End=::boost::end(lit_col);
increment();
}
private:
// iterator operations
@ -114,14 +138,13 @@ namespace boost {
// comparison
bool equal( const find_iterator& Other ) const
{
return
bool bEof=eof();
bool bOtherEof=Other.eof();
return bEof || bOtherEof ? bEof==bOtherEof :
(
m_Match==Other.m_Match &&
m_End==Other.m_End
)
||
(
eof() && Other.eof()
);
}
@ -130,7 +153,7 @@ namespace boost {
//! Eof check
/*!
Check the eof condition. Eof condition means, that
Check the eof condition. Eof condition means that
there is nothing more to be searched i.e. find_iterator
is after the last match.
*/
@ -152,17 +175,17 @@ namespace boost {
//! find iterator construction helper
/*!
* Construct a find iterator to iterate through the specified collection
* Construct a find iterator to iterate through the specified string
*/
template<typename CollectionT, typename FinderT>
template<typename RangeT, typename FinderT>
inline find_iterator<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
make_find_iterator(
CollectionT& Collection,
RangeT& Collection,
FinderT Finder)
{
return find_iterator<BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>(
Collection.begin(), Collection.end(), Finder);
return find_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>(
Collection, Finder);
}
// split iterator -----------------------------------------------//
@ -170,11 +193,11 @@ namespace boost {
//! split_iterator
/*!
Split iterator encapsulates a Finder and allows
an incremental searching in the sequence.
for incremental searching in a string.
Unlike the find iterator, split iterator iterates
through gasps between matches.
through gaps between matches.
Find iterator is readable forward traversal iterator.
Find iterator is a readable forward traversal iterator.
Dereferencing the iterator yields an iterator_range delimiting
the current match.
@ -191,12 +214,6 @@ namespace boost {
// facade support
friend class ::boost::iterator_core_access;
// base type
typedef iterator_facade<
find_iterator<IteratorT>,
iterator_range<IteratorT>,
forward_traversal_tag> facade_type;
private:
// typedefs
@ -216,17 +233,19 @@ namespace boost {
split_iterator() {}
//! Copy constructor
/*!
Construct a copy of the find_iterator
Construct a copy of the split_iterator
*/
split_iterator( const split_iterator& Other ) :
base_type(Other),
m_Match(Other.m_Match),
m_Next(Other.m_Next),
m_End(Other.m_End) {}
m_End(Other.m_End),
m_bEof(Other.m_bEof)
{}
//! Constructor
/*!
Construct new find_iterator for a given finder
Construct new split_iterator for a given finder
and a range.
*/
template<typename FinderT>
@ -237,10 +256,39 @@ namespace boost {
detail::find_iterator_base<IteratorT>(Finder,0),
m_Match(Begin,Begin),
m_Next(Begin),
m_End(End)
m_End(End),
m_bEof(false)
{
increment();
// force the correct behavior for empty sequences and yield at least one token
if(Begin!=End)
{
increment();
}
}
//! Constructor
/*!
Construct new split_iterator for a given finder
and a collection.
*/
template<typename FinderT, typename RangeT>
split_iterator(
RangeT& Col,
FinderT Finder ) :
detail::find_iterator_base<IteratorT>(Finder,0),
m_bEof(false)
{
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col));
m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col));
m_Next=::boost::begin(lit_col);
m_End=::boost::end(lit_col);
// force the correct behavior for empty sequences and yield at least one token
if(m_Next!=m_End)
{
increment();
}
}
private:
// iterator operations
@ -255,6 +303,16 @@ namespace boost {
void increment()
{
match_type FindMatch=this->do_find( m_Next, m_End );
if(FindMatch.begin()==m_End && FindMatch.end()==m_End)
{
if(m_Match.end()==m_End)
{
// Mark iterator as eof
m_bEof=true;
}
}
m_Match=match_type( m_Next, FindMatch.begin() );
m_Next=FindMatch.end();
}
@ -262,15 +320,14 @@ namespace boost {
// comparison
bool equal( const split_iterator& Other ) const
{
return
bool bEof=eof();
bool bOtherEof=Other.eof();
return bEof || bOtherEof ? bEof==bOtherEof :
(
m_Match==Other.m_Match &&
m_Next==Other.m_Next &&
m_End==Other.m_End
)
||
(
eof() && Other.eof()
m_End==Other.m_End
);
}
@ -279,18 +336,13 @@ namespace boost {
//! Eof check
/*!
Check the eof condition. Eof condition means, that
Check the eof condition. Eof condition means that
there is nothing more to be searched i.e. find_iterator
is after the last match.
*/
bool eof() const
{
return
this->is_null() ||
(
m_Match.begin() == m_End &&
m_Match.end() == m_End
);
return this->is_null() || m_bEof;
}
private:
@ -298,21 +350,22 @@ namespace boost {
match_type m_Match;
input_iterator_type m_Next;
input_iterator_type m_End;
bool m_bEof;
};
//! split iterator construction helper
/*!
* Construct a split iterator to iterate through the specified collection
*/
template<typename CollectionT, typename FinderT>
template<typename RangeT, typename FinderT>
inline split_iterator<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
make_split_iterator(
CollectionT& Collection,
RangeT& Collection,
FinderT Finder)
{
return split_iterator<BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type>(
Collection.begin(), Collection.end(), Finder);
return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>(
Collection, Finder);
}

View File

@ -1,26 +1,31 @@
// Boost string_algo library finder.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FINDER_HPP
#define BOOST_STRING_FINDER_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/algorithm/string/constants.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/detail/finder.hpp>
#include <boost/algorithm/string/compare.hpp>
/*! \file
Defines Finder generators. Finder object is a functor which is able to
find a subsequence matching a specific criterium in an input
sequence.
find a substring matching a specific criteria in the input.
Finders are used as a pluggable components for replace, find
and split facilities. This header contains generator functions
for finders provided in this library.
@ -34,163 +39,141 @@ namespace boost {
//! "First" finder
/*!
Construct the \c first_finder. The finder searches for the first
occurrence of the search sequence in a given input.
The result is given as a \c iterator_range delimiting the match.
occurrence of the string in a given input.
The result is given as an \c iterator_range delimiting the match.
\param Search A sequence to be searched for.
\param Search A substring to be searched for.
\param Comp An element comparison predicate
\return An instance of the \c first_finder object
*/
template<typename ContainerT>
template<typename RangeT>
inline detail::first_finderF<
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
is_equal>
first_finder( const ContainerT& Search )
first_finder( const RangeT& Search )
{
return
detail::first_finderF<
BOOST_STRING_TYPENAME
const_iterator_of<ContainerT>::type,
is_equal>( Search, is_equal() ) ;
range_const_iterator<RangeT>::type,
is_equal>( ::boost::as_literal(Search), is_equal() ) ;
}
//! "First" finder
/*!
Construct the \c first_finder. The finder searches for the first
occurrence of the search sequence in a given input.
The result is given as a \c iterator_range delimiting the match.
Elements are compared using the given predicate.
\param Search A sequence to be searched for.
\param Comp An element comparison predicate
\return An instance of the \c first_finder object
\overload
*/
template<typename ContainerT,typename PredicateT>
template<typename RangeT,typename PredicateT>
inline detail::first_finderF<
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
PredicateT>
first_finder(
const ContainerT& Search, PredicateT Comp )
const RangeT& Search, PredicateT Comp )
{
return
detail::first_finderF<
BOOST_STRING_TYPENAME
const_iterator_of<ContainerT>::type,
PredicateT>( Search, Comp );
range_const_iterator<RangeT>::type,
PredicateT>( ::boost::as_literal(Search), Comp );
}
//! "Last" finder
/*!
Construct the \c last_finder. The finder searches for the last
occurrence of the search sequence in a given input.
The result is given as a \c iterator_range delimiting the match.
occurrence of the string in a given input.
The result is given as an \c iterator_range delimiting the match.
\param Search A sequence to be searched for.
\return An instance of the \c last_finder object
*/
template<typename ContainerT>
inline detail::last_finderF<
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
is_equal>
last_finder( const ContainerT& Search )
{
return
detail::last_finderF<
BOOST_STRING_TYPENAME
const_iterator_of<ContainerT>::type,
is_equal>( Search, is_equal() );
}
//! "Last" finder
/*!
Construct the \c last_finder. The finder searches for the last
occurrence of the search sequence in a given input.
The result is given as a \c iterator_range delimiting the match.
Elements are compared using the given predicate.
\param Search A sequence to be searched for.
\param Search A substring to be searched for.
\param Comp An element comparison predicate
\return An instance of the \c last_finder object
*/
template<typename ContainerT, typename PredicateT>
template<typename RangeT>
inline detail::last_finderF<
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
PredicateT>
last_finder( const ContainerT& Search, PredicateT Comp )
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
is_equal>
last_finder( const RangeT& Search )
{
return
detail::last_finderF<
BOOST_STRING_TYPENAME
const_iterator_of<ContainerT>::type,
PredicateT>( Search, Comp ) ;
range_const_iterator<RangeT>::type,
is_equal>( ::boost::as_literal(Search), is_equal() );
}
//! "Last" finder
/*!
\overload
*/
template<typename RangeT, typename PredicateT>
inline detail::last_finderF<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
PredicateT>
last_finder( const RangeT& Search, PredicateT Comp )
{
return
detail::last_finderF<
BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type,
PredicateT>( ::boost::as_literal(Search), Comp ) ;
}
//! "Nth" finder
/*!
Construct the \c nth_finder. The finder searches for the n-th
occurrence of the search sequence in a given input.
The result is given as a \c iterator_range delimiting the match.
Construct the \c nth_finder. The finder searches for the n-th (zero-indexed)
occurrence of the string in a given input.
The result is given as an \c iterator_range delimiting the match.
\param Search A sequence to be searched for.
\param Search A substring to be searched for.
\param Nth An index of the match to be find
\param Comp An element comparison predicate
\return An instance of the \c nth_finder object
*/
template<typename ContainerT>
template<typename RangeT>
inline detail::nth_finderF<
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
is_equal>
nth_finder(
const ContainerT& Search,
unsigned int Nth)
const RangeT& Search,
int Nth)
{
return
detail::nth_finderF<
BOOST_STRING_TYPENAME
const_iterator_of<ContainerT>::type,
is_equal>( Search, Nth, is_equal() ) ;
range_const_iterator<RangeT>::type,
is_equal>( ::boost::as_literal(Search), Nth, is_equal() ) ;
}
//! "Nth" finder
/*!
Construct the \c nth_finder. The finder searches for the n-th
occurrence of the search sequence in a given input.
The result is given as a \c iterator_range delimiting the match.
Elements are compared using the given predicate.
\param Search A sequence to be searched for.
\param Nth An index of the match to be find
\param Comp An element comparison predicate
\return An instance of the \c nth_finder object
\overload
*/
template<typename ContainerT, typename PredicateT>
template<typename RangeT, typename PredicateT>
inline detail::nth_finderF<
BOOST_STRING_TYPENAME const_iterator_of<ContainerT>::type,
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type,
PredicateT>
nth_finder(
const ContainerT& Search,
unsigned int Nth,
const RangeT& Search,
int Nth,
PredicateT Comp )
{
return
detail::nth_finderF<
BOOST_STRING_TYPENAME
const_iterator_of<ContainerT>::type,
PredicateT>( Search, Nth, Comp );
range_const_iterator<RangeT>::type,
PredicateT>( ::boost::as_literal(Search), Nth, Comp );
}
//! "Head" finder
/*!
Construct the \c head_finder. The finder returns a head of a given
input. Head is a prefix of a sequence up to n elements in
input. The head is a prefix of a string up to n elements in
size. If an input has less then n elements, whole input is
considered a head.
The result is given as a \c iterator_range delimiting the match.
The result is given as an \c iterator_range delimiting the match.
\param N The size of the head
\return An instance of the \c head_finder object
*/
inline detail::head_finderF
head_finder( unsigned int N )
head_finder( int N )
{
return detail::head_finderF(N);
}
@ -198,16 +181,16 @@ namespace boost {
//! "Tail" finder
/*!
Construct the \c tail_finder. The finder returns a tail of a given
input. Tail is a suffix of the sequence up to n elements in
input. The tail is a suffix of a string up to n elements in
size. If an input has less then n elements, whole input is
considered a head.
The result is given as a \c iterator_range delimiting the match.
The result is given as an \c iterator_range delimiting the match.
\param N The size of the head
\return An instance of the \c tail_finder object
*/
inline detail::tail_finderF
tail_finder( unsigned int N )
tail_finder( int N )
{
return detail::tail_finderF(N);
}
@ -219,12 +202,12 @@ namespace boost {
algorithm, with an exception that it return a range of
instead of a single iterator.
If bCompress is set to true, adjacent matching tokens are
If "compress token mode" is enabled, adjacent matching tokens are
concatenated into one match. Thus the finder can be used to
search for continuous segments of elements satisfying the
search for continuous segments of characters satisfying the
given predicate.
The result is given as a \c iterator_range delimiting the match.
The result is given as an \c iterator_range delimiting the match.
\param Pred An element selection predicate
\param eCompress Compress flag
@ -247,6 +230,7 @@ namespace boost {
\param Begin Beginning of the range
\param End End of the range
\param Range The range.
\return An instance of the \c range_finger object
*/
template< typename ForwardIteratorT >
@ -259,9 +243,7 @@ namespace boost {
}
//! "Range" finder
/*!
\param Range The range.
/*!
\overload
*/
template< typename ForwardIteratorT >

View File

@ -1,81 +1,108 @@
// Boost string_algo library formatter.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_FORMATTER_HPP
#define BOOST_STRING_FORMATTER_HPP
#include <boost/detail/iterator.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/detail/formatter.hpp>
/*! \file
Defines formatter generators. Formatter is a functor which formats
a string according to give parameters. A Formatter works
Defines Formatter generators. Formatter is a functor which formats
a string according to given parameters. A Formatter works
in conjunction with a Finder. A Finder can provide additional information
for a specific Formatter. An example of such a cooperation is reger_finder
for a specific Formatter. An example of such a cooperation is regex_finder
and regex_formatter.
Formatters are used by as a pluggable components for replace facilities.
Formatters are used as pluggable components for replace facilities.
This header contains generator functions for the Formatters provided in this library.
*/
namespace boost {
namespace algorithm {
// generic formaters ---------------------------------------------------------------//
// generic formatters ---------------------------------------------------------------//
//! Constant formatter
/*!
Construct the \c const_formatter. Const formatter always returns
Constructs a \c const_formatter. Const formatter always returns
the same value, regardless of the parameter.
\param Format A predefined value used as a result for formating
\return An instance of the \c const_formatter object.
*/
template<typename CollectionT>
inline detail::const_formatF<CollectionT>
const_formatter(const CollectionT& Format)
template<typename RangeT>
inline detail::const_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >
const_formatter(const RangeT& Format)
{
return detail::const_formatF<CollectionT>(Format);
return detail::const_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >(::boost::as_literal(Format));
}
//! Identity formatter
/*!
Construct the \c identity_formatter. Identity formatter always returns
Constructs an \c identity_formatter. Identity formatter always returns
the parameter.
\return An instance of the \c identity_formatter object.
*/
template<typename CollectionT>
inline detail::identity_formatF<CollectionT>
template<typename RangeT>
inline detail::identity_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >
identity_formatter()
{
return detail::identity_formatF<CollectionT>();
return detail::identity_formatF<
iterator_range<
BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >();
}
//! Empty formatter
/*!
Construct the \c empty_formatter. Empty formater always returns an empty
Constructs an \c empty_formatter. Empty formatter always returns an empty
sequence.
\param Input container used to select a correct value_type for the
resulting empty_container<>.
\return An instance of the \c empty_formatter object.
*/
template<typename CollectionT>
template<typename RangeT>
inline detail::empty_formatF<
BOOST_STRING_TYPENAME value_type_of<CollectionT>::type>
empty_formatter(const CollectionT& Input)
BOOST_STRING_TYPENAME range_value<RangeT>::type>
empty_formatter(const RangeT&)
{
return detail::empty_formatF<
BOOST_STRING_TYPENAME value_type_of<CollectionT>::type>();
BOOST_STRING_TYPENAME range_value<RangeT>::type>();
}
//! Empty formatter
/*!
Constructs a \c dissect_formatter. Dissect formatter uses a specified finder
to extract a portion of the formatted sequence. The first finder's match is returned
as a result
\param Finder a finder used to select a portion of the formated sequence
\return An instance of the \c dissect_formatter object.
*/
template<typename FinderT>
inline detail::dissect_formatF< FinderT >
dissect_formatter(const FinderT& Finder)
{
return detail::dissect_formatF<FinderT>(Finder);
}
@ -85,6 +112,7 @@ namespace boost {
using algorithm::const_formatter;
using algorithm::identity_formatter;
using algorithm::empty_formatter;
using algorithm::dissect_formatter;
} // namespace boost

View File

@ -1,11 +1,12 @@
// Boost string_algo library iter_find.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ITER_FIND_HPP
#define BOOST_STRING_ITER_FIND_HPP
@ -14,8 +15,14 @@
#include <algorithm>
#include <iterator>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/concept.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
#include <boost/algorithm/string/detail/util.hpp>
@ -23,12 +30,12 @@
/*! \file
Defines generic split algorithms. Split algorithms can be
used to divide a sequence into several part according
to a given criterium. Result is given as a 'container
to a given criteria. Result is given as a 'container
of containers' where elements are copies or references
to extracted parts.
There are two algorithms provided. One iterates over matching
substrings, the other one over the gasps between these matches.
substrings, the other one over the gaps between these matches.
*/
namespace boost {
@ -55,40 +62,51 @@ namespace boost {
\param Finder A Finder object used for searching
\return A reference the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
*/
template<
typename SequenceSequenceT,
typename CollectionT,
typename RangeT,
typename FinderT >
inline SequenceSequenceT&
iter_find(
SequenceSequenceT& Result,
CollectionT& Input,
RangeT& Input,
FinderT Finder )
{
function_requires<
FinderConcept<FinderT,
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type> >();
BOOST_CONCEPT_ASSERT((
FinderConcept<
FinderT,
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
typedef BOOST_STRING_TYPENAME
result_iterator_of<CollectionT>::type input_iterator_type;
range_iterator<RangeT>::type input_iterator_type;
typedef find_iterator<input_iterator_type> find_iterator_type;
typedef detail::copy_iterator_rangeF<
BOOST_STRING_TYPENAME
value_type_of<SequenceSequenceT>::type,
range_value<SequenceSequenceT>::type,
input_iterator_type> copy_range_type;
input_iterator_type InputEnd=end(Input);
input_iterator_type InputEnd=::boost::end(lit_input);
SequenceSequenceT Tmp(
make_transform_iterator(
find_iterator_type( begin(Input), InputEnd, Finder ),
copy_range_type() ),
make_transform_iterator(
typedef transform_iterator<copy_range_type, find_iterator_type>
transform_iter_type;
transform_iter_type itBegin=
::boost::make_transform_iterator(
find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
copy_range_type());
transform_iter_type itEnd=
::boost::make_transform_iterator(
find_iterator_type(),
copy_range_type() ) );
copy_range_type());
SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;
}
@ -115,40 +133,50 @@ namespace boost {
\param Finder A finder object used for searching
\return A reference the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
*/
template<
typename SequenceSequenceT,
typename CollectionT,
typename RangeT,
typename FinderT >
inline SequenceSequenceT&
iter_split(
SequenceSequenceT& Result,
CollectionT& Input,
RangeT& Input,
FinderT Finder )
{
function_requires<
BOOST_CONCEPT_ASSERT((
FinderConcept<FinderT,
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type> >();
BOOST_STRING_TYPENAME range_iterator<RangeT>::type>
));
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
typedef BOOST_STRING_TYPENAME
result_iterator_of<CollectionT>::type input_iterator_type;
range_iterator<RangeT>::type input_iterator_type;
typedef split_iterator<input_iterator_type> find_iterator_type;
typedef detail::copy_iterator_rangeF<
BOOST_STRING_TYPENAME
value_type_of<SequenceSequenceT>::type,
range_value<SequenceSequenceT>::type,
input_iterator_type> copy_range_type;
input_iterator_type InputEnd=end(Input);
input_iterator_type InputEnd=::boost::end(lit_input);
SequenceSequenceT Tmp(
make_transform_iterator(
find_iterator_type( begin(Input), InputEnd, Finder ),
copy_range_type() ),
make_transform_iterator(
typedef transform_iterator<copy_range_type, find_iterator_type>
transform_iter_type;
transform_iter_type itBegin=
::boost::make_transform_iterator(
find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
copy_range_type() );
transform_iter_type itEnd=
::boost::make_transform_iterator(
find_iterator_type(),
copy_range_type() ) );
copy_range_type() );
SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;
}

View File

@ -1,295 +0,0 @@
// Boost string_algo library iterator_range.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#ifndef BOOST_STRING_ITERATOR_RANGE_HPP
#define BOOST_STRING_ITERATOR_RANGE_HPP
#include <boost/algorithm/string/config.hpp>
#include <utility>
#include <iterator>
#include <algorithm>
#include <ostream>
#include <boost/detail/iterator.hpp>
/*! \file
Defines the \c iterator_class and related functions.
\c iterator_range is a simple wrapper of iterator pair idiom. It provides
a rich subset of Container interface.
*/
namespace boost {
namespace algorithm {
// iterator range template class -----------------------------------------//
//! iterator_range class
/*!
An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
An iterator_range can be passed to an algorithm which requires a sequence as an input.
For example, the \c toupper() function may be used most frequently on strings,
but can also be used on iterator_ranges:
\code
boost::tolower( find( s, "UPPERCASE STRING" ) );
\endcode
Many algorithms working with sequences take a pair of iterators,
delimiting a working range, as an arguments. The \c iterator_range class is an
encapsulation of a range identified by a pair of iterators.
It provides a collection interface,
so it is possible to pass an instance to an algorithm requiring a collection as an input.
*/
template<typename IteratorT>
class iterator_range
{
public:
//! this type
typedef iterator_range<IteratorT> type;
//! Encapsulated value type
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<IteratorT>::value_type value_type;
//! Reference type
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<IteratorT>::reference reference;
//! Difference type
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<IteratorT>::difference_type difference_type;
//! Size type
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<IteratorT>::difference_type size_type;
//! const_iterator type
/*!
There is no distinction between const_iterator and iterator.
These typedefs are provides to fulfill container interface
*/
typedef IteratorT const_iterator;
//! iterator type
typedef IteratorT iterator;
//! Default constructor
iterator_range() {}
//! Constructor from a pair of iterators
iterator_range( iterator Begin, iterator End ) :
m_Begin(Begin), m_End(End) {}
//! Constructor from a std::pair
iterator_range( const std::pair<IteratorT,IteratorT>& Range ) :
m_Begin(Range.first), m_End(Range.second) {}
//! Copy constructor
iterator_range( const iterator_range& Other ) :
m_Begin(Other.begin()), m_End(Other.end()) {}
//! Templated copy constructor
/*!
This constructor is provided to allow conversion between
const and mutable iterator instances of this class template
*/
template< typename OtherItT >
iterator_range( const iterator_range<OtherItT>& Other ) :
m_Begin(Other.begin()), m_End(Other.end()) {}
//! Assignment operator
iterator_range& operator=( const iterator_range& Other )
{
m_Begin=Other.begin(); m_End=Other.end();
return *this;
}
//! Assignment operator ( templated version )
template< typename OtherItT >
iterator_range& operator=( const iterator_range<OtherItT>& Other )
{
m_Begin=Other.begin(); m_End=Other.end();
return *this;
}
//! Comparison operator ( equal )
/*!
Compare operands for equality
*/
template< typename OtherItT >
bool operator==( const iterator_range<OtherItT>& Other ) const
{
return m_Begin==Other.begin() && m_End==Other.end();
}
//! Comparison operator ( not-equal )
/*!
Compare operands for non-equality
*/
template< typename OtherItT >
bool operator!=( const iterator_range<OtherItT>& Other ) const
{
return m_Begin!=Other.begin() || m_End!=Other.end();
}
//! begin access
/*!
Retrieve the begin iterator
*/
IteratorT begin() const
{
return m_Begin;
}
//! end access
/*!
Retrieve the end iterator
*/
IteratorT end() const
{
return m_End;
}
//! Empty container test
/*!
Test whenever the range is empty
*/
bool empty() const
{
return m_Begin==m_End;
}
//! Size of the range
/*!
Retrieve the size of the range
*/
difference_type size() const
{
return std::distance( m_Begin, m_End );
}
//! Swap
/*!
Swap two ranges
*/
void swap( iterator_range& Other )
{
std::swap( m_Begin, Other.begin() );
std::swap( m_End, Other.end() );
}
//! Safe bool conversion
/*!
Check whenever the range is empty.
Allows to use construction like this:
\code
iterator_range r;
if (!r)
{
...
}
\endcode
*/
typedef iterator (iterator_range::*unspecified_bool_type) () const;
operator unspecified_bool_type() const
{
return empty()? 0: &iterator_range::end;
}
private:
// begin and end iterators
IteratorT m_Begin;
IteratorT m_End;
};
// iterator range free-standing operators ---------------------------//
//! iterator_range output operator
/*!
Output the range to an ostream. Elements are outputed
in a sequence without separators.
*/
template< typename IteratorT, typename Elem, typename Traits >
std::basic_ostream<Elem,Traits>& operator<<(
std::basic_ostream<Elem, Traits>& Os,
const iterator_range<IteratorT>& Range )
{
std::copy(Range.begin(), Range.end(), std::ostream_iterator<Elem>(Os));
return Os;
}
// iterator range utilities -----------------------------------------//
//! iterator_range construct helper
/*!
Construct an \c iterator_range from a pair of iterators
\param Begin A begin iterator
\param End An end iterator
\return iterator_range object
*/
template< typename IteratorT >
inline iterator_range< IteratorT > make_iterator_range( IteratorT Begin, IteratorT End )
{
return iterator_range<IteratorT>( Begin, End );
}
//! iterator_range construct helper
/*!
Construct an \c iterator_range from a \c std::pair<> containing the begin
and end iterators.
\param Pair A \c std::pair<> with begin and end iterators
\return \c iterator_range object
*/
template< typename IteratorT >
inline iterator_range< IteratorT > make_iterator_range( const std::pair<IteratorT,IteratorT>& Pair )
{
return iterator_range<IteratorT>( Pair.first, Pair.second );
}
//! copy a range into a sequence
/*!
Construct a new sequence of the specified type from the elements
in the given range
\param Range An input range
\return New sequence
*/
template< typename SeqT, typename IteratorT >
inline SeqT copy_iterator_range( const iterator_range<IteratorT>& Range )
{
return SeqT( Range.begin(), Range.end() );
}
//! transform a range into a sequence
/*!
Create a new sequence from the elements in the range, transformed
by a function
\param Range An input range
\param Func Transformation function
\return New sequence
*/
template< typename SeqT, typename IteratorT, typename FuncT >
inline SeqT transform_iterator_range( const iterator_range<IteratorT>& Range, FuncT Func )
{
SeqT Seq;
std::transform( Range.begin(), Range.end(), std::back_inserter(Seq), Func );
return Seq;
}
} // namespace algorithm
// pull names to the namespace boost
using algorithm::iterator_range;
using algorithm::make_iterator_range;
using algorithm::copy_iterator_range;
using algorithm::transform_iterator_range;
} // namespace boost
#endif // BOOST_STRING_ITERATOR_RANGE_HPP

View File

@ -0,0 +1,145 @@
// Boost string_algo library join.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_JOIN_HPP
#define BOOST_STRING_JOIN_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/detail/sequence.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/as_literal.hpp>
/*! \file
Defines join algorithm.
Join algorithm is a counterpart to split algorithms.
It joins strings from a 'list' by adding user defined separator.
Additionally there is a version that allows simple filtering
by providing a predicate.
*/
namespace boost {
namespace algorithm {
// join --------------------------------------------------------------//
//! Join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Range1T>
inline typename range_value<SequenceSequenceT>::type
join(
const SequenceSequenceT& Input,
const Range1T& Separator)
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Append first element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
return Result;
}
// join_if ----------------------------------------------------------//
//! Conditional join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator. Only segments that
satisfy the predicate will be added to the result.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\param Pred A segment selection predicate
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Range1T, typename PredicateT>
inline typename range_value<SequenceSequenceT>::type
join_if(
const SequenceSequenceT& Input,
const Range1T& Separator,
PredicateT Pred)
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Roll to the first element that will be added
while(itBegin!=itEnd && !Pred(*itBegin)) ++itBegin;
// Add this element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
if(Pred(*itBegin))
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
}
return Result;
}
} // namespace algorithm
// pull names to the boost namespace
using algorithm::join;
using algorithm::join_if;
} // namespace boost
#endif // BOOST_STRING_JOIN_HPP

View File

@ -1,28 +1,37 @@
// Boost string_algo library predicate.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_PREDICATE_HPP
#define BOOST_STRING_PREDICATE_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/detail/predicate.hpp>
/*! \file boost/algorithm/string/predicate.hpp
Defines string-related predicates.
The predicates are resolving if a substring is contained in the input string
under various conditions. If a string starts with the substring, ends with the
The predicates determine whether a substring is contained in the input string
under various conditions: a string starts with the substring, ends with the
substring, simply contains the substring or if both strings are equal.
In addition the algorithm \c all() checks all elements of a container to satisfy a
Additionaly the algorithm \c all() checks all elements of a container to satisfy a
condition.
All predicates provide the strong exception guarantee.
*/
namespace boost {
@ -32,30 +41,37 @@ namespace boost {
//! 'Starts with' predicate
/*!
This predicate holds when the test collection is a prefix of the Input.
In other word, if the input starts with the test.
This predicate holds when the test string is a prefix of the Input.
In other words, if the input starts with the test.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return A result of the test
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T, typename PredicateT>
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool starts_with(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
typedef BOOST_STRING_TYPENAME
const_iterator_of<Collection1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME
const_iterator_of<Collection2T>::type Iterator2T;
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
Iterator1T InputEnd=end(Input);
Iterator2T TestEnd=end(Test);
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range2T>::type Iterator2T;
Iterator1T it=begin(Input);
Iterator2T pit=begin(Test);
Iterator1T InputEnd=::boost::end(lit_input);
Iterator2T TestEnd=::boost::end(lit_test);
Iterator1T it=::boost::begin(lit_input);
Iterator2T pit=::boost::begin(lit_test);
for(;
it!=InputEnd && pit!=TestEnd;
++it,++pit)
@ -69,39 +85,36 @@ namespace boost {
//! 'Starts with' predicate
/*!
This predicate holds when the test container is a prefix of the Input.
In other words, if the input starts with the test.
\param Input An input sequence
\param Test A test sequence
\return A result of the test
\overload
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool starts_with(
const Collection1T& Input,
const Collection2T& Test)
const Range1T& Input,
const Range2T& Test)
{
return starts_with(Input, Test, is_equal());
return ::boost::algorithm::starts_with(Input, Test, is_equal());
}
//! 'Starts with' predicate ( case insensitive )
/*!
This predicate holds when the test container is a prefix of the Input.
In other word, if the input starts with the test.
This predicate holds when the test string is a prefix of the Input.
In other words, if the input starts with the test.
Elements are compared case insensitively.
\param Input An input sequence
\param Test A test sequence
\param Loc a locale used for case insensitive comparison
\return A result of the test
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool istarts_with(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return starts_with(Input, Test, is_iequal(Loc));
return ::boost::algorithm::starts_with(Input, Test, is_iequal(Loc));
}
@ -109,31 +122,39 @@ namespace boost {
//! 'Ends with' predicate
/*!
This predicate holds when the test container is a suffix of the Input.
In other word, if the input ends with the test.
This predicate holds when the test string is a suffix of the Input.
In other words, if the input ends with the test.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return A result of the test
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T, typename PredicateT>
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool ends_with(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
typedef BOOST_STRING_TYPENAME
const_iterator_of<Collection1T>::type Iterator1T;
range_const_iterator<Range1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME boost::detail::
iterator_traits<Iterator1T>::iterator_category category;
return detail::
ends_with_iter_select(
begin(Input),
end(Input),
begin(Test),
end(Test),
::boost::begin(lit_input),
::boost::end(lit_input),
::boost::begin(lit_test),
::boost::end(lit_test),
Comp,
category());
}
@ -141,39 +162,36 @@ namespace boost {
//! 'Ends with' predicate
/*!
This predicate holds when the test container is a suffix of the Input.
In other word, if the input ends with the test.
\param Input An input sequence
\param Test A test sequence
\return A result of the test
\overload
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool ends_with(
const Collection1T& Input,
const Collection2T& Test)
const Range1T& Input,
const Range2T& Test)
{
return ends_with(Input, Test, is_equal());
return ::boost::algorithm::ends_with(Input, Test, is_equal());
}
//! 'Ends with' predicate ( case insensitive )
/*!
This predicate holds when the test container is a suffix of the Input.
In other word, if the input ends with the test.
In other words, if the input ends with the test.
Elements are compared case insensitively.
\param Input An input sequence
\param Test A test sequence
\param Loc a locale used for case insensitive comparison
\return A result of the test
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool iends_with(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return ends_with(Input, Test, is_iequal(Loc));
return ::boost::algorithm::ends_with(Input, Test, is_iequal(Loc));
}
// contains predicate -----------------------------------------------//
@ -181,41 +199,46 @@ namespace boost {
//! 'Contains' predicate
/*!
This predicate holds when the test container is contained in the Input.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return A result of the test
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T, typename PredicateT>
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool contains(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
if (empty(Test))
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
if (::boost::empty(lit_test))
{
// Empty range is contained always
return true;
}
return (first_finder(Test,Comp)(begin(Input), end(Input)));
// Use the temporary variable to make VACPP happy
bool bResult=(::boost::algorithm::first_finder(lit_test,Comp)(::boost::begin(lit_input), ::boost::end(lit_input)));
return bResult;
}
//! 'Contains' predicate
/*!
This predicate holds when the test container is contained in the Input.
\param Input An input sequence
\param Test A test sequence
\return A result of the test
\overload
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool contains(
const Collection1T& Input,
const Collection2T& Test)
const Range1T& Input,
const Range2T& Test)
{
return contains(Input, Test, is_equal());
return ::boost::algorithm::contains(Input, Test, is_equal());
}
//! 'Contains' predicate ( case insensitive )
@ -225,16 +248,18 @@ namespace boost {
\param Input An input sequence
\param Test A test sequence
\param Loc a locale used for case insensitive comparison
\return A result of the test
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool icontains(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return contains(Input, Test, is_iequal(Loc));
return ::boost::algorithm::contains(Input, Test, is_iequal(Loc));
}
// equals predicate -----------------------------------------------//
@ -243,28 +268,37 @@ namespace boost {
/*!
This predicate holds when the test container is equal to the
input container i.e. all elements in both containers are same.
When the optional predicate is specified, it is used for character-wise
comparison.
\param Input An input sequence
\param Test A test sequence
\param Comp An element comparison predicate
\return A result of the test
\return The result of the test
\note This is a two-way version of \c std::equal algorithm
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T, typename PredicateT>
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool equals(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
PredicateT Comp)
{
typedef BOOST_STRING_TYPENAME
const_iterator_of<Collection1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME
const_iterator_of<Collection2T>::type Iterator2T;
Iterator1T InputEnd=end(Input);
Iterator2T TestEnd=end(Test);
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test));
Iterator1T it=begin(Input);
Iterator2T pit=begin(Test);
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range1T>::type Iterator1T;
typedef BOOST_STRING_TYPENAME
range_const_iterator<Range2T>::type Iterator2T;
Iterator1T InputEnd=::boost::end(lit_input);
Iterator2T TestEnd=::boost::end(lit_test);
Iterator1T it=::boost::begin(lit_input);
Iterator2T pit=::boost::begin(lit_test);
for(;
it!=InputEnd && pit!=TestEnd;
++it,++pit)
@ -278,24 +312,17 @@ namespace boost {
//! 'Equals' predicate
/*!
This predicate holds when the test container is equal to the
input container i.e. all elements in both containers are same.
\param Input An input sequence
\param Test A test sequence
\return A result of the test
\note This is two-way version of \c std::equal algorithm
\overload
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool equals(
const Collection1T& Input,
const Collection2T& Test)
const Range1T& Input,
const Range2T& Test)
{
return equals(Input, Test, is_equal());
return ::boost::algorithm::equals(Input, Test, is_equal());
}
//! 'Equals' predicate ( casa insensitive )
//! 'Equals' predicate ( case insensitive )
/*!
This predicate holds when the test container is equal to the
input container i.e. all elements in both containers are same.
@ -303,20 +330,97 @@ namespace boost {
\param Input An input sequence
\param Test A test sequence
\param Loc a locale used for case insensitive comparison
\return A result of the test
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This is two-way version of \c std::equal algorithm
\note This is a two-way version of \c std::equal algorithm
\note This function provides the strong exception-safety guarantee
*/
template<typename Collection1T, typename Collection2T>
template<typename Range1T, typename Range2T>
inline bool iequals(
const Collection1T& Input,
const Collection2T& Test,
const Range1T& Input,
const Range2T& Test,
const std::locale& Loc=std::locale())
{
return equals(Input, Test, is_iequal(Loc));
return ::boost::algorithm::equals(Input, Test, is_iequal(Loc));
}
// lexicographical_compare predicate -----------------------------//
//! Lexicographical compare predicate
/*!
This predicate is an overload of std::lexicographical_compare
for range arguments
It check whether the first argument is lexicographically less
then the second one.
If the optional predicate is specified, it is used for character-wise
comparison
\param Arg1 First argument
\param Arg2 Second argument
\param Pred Comparison predicate
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T, typename PredicateT>
inline bool lexicographical_compare(
const Range1T& Arg1,
const Range2T& Arg2,
PredicateT Pred)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_arg1(::boost::as_literal(Arg1));
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_arg2(::boost::as_literal(Arg2));
return std::lexicographical_compare(
::boost::begin(lit_arg1),
::boost::end(lit_arg1),
::boost::begin(lit_arg2),
::boost::end(lit_arg2),
Pred);
}
//! Lexicographical compare predicate
/*!
\overload
*/
template<typename Range1T, typename Range2T>
inline bool lexicographical_compare(
const Range1T& Arg1,
const Range2T& Arg2)
{
return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_less());
}
//! Lexicographical compare predicate (case-insensitive)
/*!
This predicate is an overload of std::lexicographical_compare
for range arguments.
It check whether the first argument is lexicographically less
then the second one.
Elements are compared case insensitively
\param Arg1 First argument
\param Arg2 Second argument
\param Loc A locale used for case insensitive comparison
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename Range1T, typename Range2T>
inline bool ilexicographical_compare(
const Range1T& Arg1,
const Range2T& Arg2,
const std::locale& Loc=std::locale())
{
return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_iless(Loc));
}
// all predicate -----------------------------------------------//
//! 'All' predicate
@ -326,18 +430,22 @@ namespace boost {
\param Input An input sequence
\param Pred A predicate
\return A result of the test
\return The result of the test
\note This function provides the strong exception-safety guarantee
*/
template<typename CollectionT, typename PredicateT>
template<typename RangeT, typename PredicateT>
inline bool all(
const CollectionT& Input,
const RangeT& Input,
PredicateT Pred)
{
typedef BOOST_STRING_TYPENAME
const_iterator_of<CollectionT>::type Iterator1T;
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
Iterator1T InputEnd=end(Input);
for( Iterator1T It=begin(Input); It!=InputEnd; ++It)
typedef BOOST_STRING_TYPENAME
range_const_iterator<RangeT>::type Iterator1T;
Iterator1T InputEnd=::boost::end(lit_input);
for( Iterator1T It=::boost::begin(lit_input); It!=InputEnd; ++It)
{
if (!Pred(*It))
return false;
@ -358,6 +466,8 @@ namespace boost {
using algorithm::equals;
using algorithm::iequals;
using algorithm::all;
using algorithm::lexicographical_compare;
using algorithm::ilexicographical_compare;
} // namespace boost

View File

@ -0,0 +1,42 @@
// Boost string_algo library predicate_facade.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_PREDICATE_FACADE_HPP
#define BOOST_STRING_PREDICATE_FACADE_HPP
#include <boost/algorithm/string/config.hpp>
/*
\file boost/algorith/string/predicate_facade.hpp
This file containes predicate_facade definition. This template class is used
to identify classification predicates, so they can be combined using
composition operators.
*/
namespace boost {
namespace algorithm {
// predicate facade ------------------------------------------------------//
//! Predicate facade
/*!
This class allows to recognize classification
predicates, so that they can be combined using
composition operators.
Every classification predicate must be derived from this class.
*/
template<typename Derived>
struct predicate_facade {};
} // namespace algorithm
} // namespace boost
#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP

View File

@ -1,26 +1,32 @@
// Boost string_algo library regex.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REGEX_HPP
#define BOOST_STRING_REGEX_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/regex_find_format.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/iter_find.hpp>
/*! \file
Defines regex variant of the algorithms.
Defines regex variants of the algorithms.
*/
namespace boost {
@ -30,100 +36,102 @@ namespace boost {
//! Find regex algorithm
/*!
Search for a subsequence matching the given regex in the input.
Search for a substring matching the given regex in the input.
\param Input A container which will be searched.
\param Rx A regular expression
\param Flags Regex options
\return
An \c iterator_range delimiting the match.
Returned iterator is either \c InputContainerT::iterator or
\c InputContainerT::const_iterator, depending on the constness of
Returned iterator is either \c RangeT::iterator or
\c RangeT::const_iterator, depending on the constness of
the input parameter.
\note This function provides the strong exception-safety guarantee
*/
template<
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT>
typename RegexTraitsT>
inline iterator_range<
BOOST_STRING_TYPENAME result_iterator_of<CollectionT>::type >
BOOST_STRING_TYPENAME range_iterator<RangeT>::type >
find_regex(
CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return regex_finder(Rx,Flags)(
begin(Input), end(Input) );
iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
return ::boost::algorithm::regex_finder(Rx,Flags)(
::boost::begin(lit_input), ::boost::end(lit_input) );
}
// replace_regex --------------------------------------------------------------------//
//! Replace regex algorithm
/*!
Search for a subsequence matching given regex and format it with
the specified format. The result is copied to the given output iterator.
Search for a substring matching given regex and format it with
the specified format.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Input An input sequence
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\return An output iterator pointing just after last inserted character
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline OutputIteratorT replace_regex_copy(
OutputIteratorT Output,
const CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return find_format_copy(
return ::boost::algorithm::find_format_copy(
Output,
Input,
regex_finder( Rx, Flags ),
regex_formatter( Format, Flags ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace regex algorithm
/*!
Search for a subsequence matching given regex and format it with
the specified format. The result is a modified copy of the input.
\param Input An input sequence
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\return A modified copy of the input
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline SequenceT replace_regex_copy(
const SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return find_format_copy(
return ::boost::algorithm::find_format_copy(
Input,
regex_finder( Rx, Flags ),
regex_formatter( Format, Flags ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace regex algorithm
/*!
Search for a subsequence matching given regex and format it with
the specified format. The input sequence is modified in-place.
Search for a substring matching given regex and format it with
the specified format. The input string is modified in-place.
\param Input An input sequence
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
@ -131,267 +139,261 @@ namespace boost {
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline void replace_regex(
SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
find_format(
::boost::algorithm::find_format(
Input,
regex_finder( Rx, Flags ),
regex_formatter( Format, Flags ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
// replace_all_regex --------------------------------------------------------------------//
//! Replace all regex algorithm
/*!
Format all subsequences, matching given regex, with the specified format.
The result is copied to the given output iterator.
Format all substrings, matching given regex, with the specified format.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Input An input sequence
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\return An output iterator pointing just after last inserted character
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline OutputIteratorT replace_all_regex_copy(
OutputIteratorT Output,
const CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return find_format_all_copy(
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
regex_finder( Rx, Flags ),
regex_formatter( Format, Flags ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace all regex algorithm
/*!
Format all subsequences, mathing given regex, with the specified format.
The result is a modified copy of the input.
\param Input An input sequence
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\return A modified copy of the input
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline SequenceT replace_all_regex_copy(
const SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
return find_format_all_copy(
return ::boost::algorithm::find_format_all_copy(
Input,
regex_finder( Rx, Flags ),
regex_formatter( Format, Flags ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
//! Replace all regex algorithm
/*!
Format all subsequences, matching given regex, with the specified format.
The input sequence is modified in-place.
Format all substrings, matching given regex, with the specified format.
The input string is modified in-place.
\param Input An input sequence
\param Input An input string
\param Rx A regular expression
\param Format Regex format definition
\param Flags Regex options
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT,
typename RegexTraitsT,
typename FormatStringTraitsT, typename FormatStringAllocatorT >
inline void replace_all_regex(
SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format,
match_flag_type Flags=match_default | format_default )
{
find_format_all(
::boost::algorithm::find_format_all(
Input,
regex_finder( Rx, Flags ),
regex_formatter( Format, Flags ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::regex_formatter( Format, Flags ) );
}
// erase_regex --------------------------------------------------------------------//
//! Erase regex algorithm
/*!
Remove a subsequence matching given regex from the input.
The result is copied to the given output iterator.
Remove a substring matching given regex from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Input An input sequence
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
\return An output iterator pointing just after last inserted character
*/
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline OutputIteratorT erase_regex_copy(
OutputIteratorT Output,
const CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return find_format_copy(
return ::boost::algorithm::find_format_copy(
Output,
Input,
regex_finder( Rx, Flags ),
empty_formatter( Input ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase regex algorithm
/*!
Remove a subsequence matching given regex from the input.
The result is a modified copy of the input.
\param Input An input sequence
\param Rx A regular expression
\param Flags Regex options
\return A modified copy of the input
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline SequenceT erase_regex_copy(
const SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return find_format_copy(
return ::boost::algorithm::find_format_copy(
Input,
regex_finder( Rx, Flags ),
empty_formatter( Input ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase regex algorithm
/*!
Remove a subsequence matching given regex from the input.
The input sequence is modified in-place.
Remove a substring matching given regex from the input.
The input string is modified in-place.
\param Input An input sequence
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline void erase_regex(
SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
find_format(
::boost::algorithm::find_format(
Input,
regex_finder( Rx, Flags ),
empty_formatter( Input ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
// erase_all_regex --------------------------------------------------------------------//
//! Erase all regex algorithm
/*!
Erase all subsequences, matching given regex, from the input.
The result is copied to the given output iterator.
Erase all substrings, matching given regex, from the input.
The result is a modified copy of the input. It is returned as a sequence
or copied to the output iterator.
\param Output A output iterator to which the result will be copied
\param Input An input sequence
\param Output An output iterator to which the result will be copied
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
\return An output iterator pointing just after last inserted character
\return An output iterator pointing just after the last inserted character or
a modified copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<
typename OutputIteratorT,
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline OutputIteratorT erase_all_regex_copy(
OutputIteratorT Output,
const CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return find_format_all_copy(
return ::boost::algorithm::find_format_all_copy(
Output,
Input,
regex_finder( Rx, Flags ),
empty_formatter( Input ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase all regex algorithm
/*!
Erase all subsequences, matching given regex, from the input.
The result is a modified copy of the input.
\param Input An input sequence
\param Rx A regular expression
\param Flags Regex options
\return A modified copy of the input
\overload
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline SequenceT erase_all_regex_copy(
const SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return find_format_all_copy(
return ::boost::algorithm::find_format_all_copy(
Input,
regex_finder( Rx, Flags ),
empty_formatter( Input ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
//! Erase all regex algorithm
/*!
Erase all subsequences, matching given regex, from the input.
The input sequence is modified in-place.
Erase all substrings, matching given regex, from the input.
The input string is modified in-place.
\param Input An input sequence
\param Input An input string
\param Rx A regular expression
\param Flags Regex options
*/
template<
typename SequenceT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT>
typename RegexTraitsT>
inline void erase_all_regex(
SequenceT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
find_format_all(
::boost::algorithm::find_format_all(
Input,
regex_finder( Rx, Flags ),
empty_formatter( Input ) );
::boost::algorithm::regex_finder( Rx, Flags ),
::boost::algorithm::empty_formatter( Input ) );
}
// find_all_regex ------------------------------------------------------------------//
@ -399,80 +401,224 @@ namespace boost {
//! Find all regex algorithm
/*!
This algorithm finds all substrings matching the give regex
in the input. The result is given as a 'container of containers'.
Each match of the search sequence is represented by one
element in the result.
in the input.
Each part is copied and added as a new element to the output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A 'container container' to container the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
\c std::vector<boost::iterator_range<iterator>>.
(each element of such a vector will container a range delimiting
a match).
\param Result A container that can hold copies of references to the substrings.
\param Input A container which will be searched.
\param Rx A regular expression
\param Flags Regex options
\return A reference to the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline SequenceSequenceT& find_all_regex(
SequenceSequenceT& Result,
const CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return iter_find(
return ::boost::algorithm::iter_find(
Result,
Input,
regex_finder(Rx,Flags) );
::boost::algorithm::regex_finder(Rx,Flags) );
}
// split_regex ------------------------------------------------------------------//
//! Split regex algorithm
/*!
Tokenize expression. This function is equivalent of C strtok. Input
Tokenize expression. This function is equivalent to C strtok. Input
sequence is split into tokens, separated by separators. Separator
is an every match of the given regex.
\param Result A 'container container' to container the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
'c std::vector<boost::iterator_range<iterator>>.
(each element of such a vector will container a range delimiting
a match).
Each part is copied and added as a new element to the output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A container that can hold copies of references to the substrings.
\param Input A container which will be searched.
\param Rx A regular expression
\param Flags Regex options
\return A reference to the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename CollectionT,
typename RangeT,
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT >
typename RegexTraitsT >
inline SequenceSequenceT& split_regex(
SequenceSequenceT& Result,
const CollectionT& Input,
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const RangeT& Input,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
return iter_split(
return ::boost::algorithm::iter_split(
Result,
Input,
regex_finder(Rx,Flags) );
::boost::algorithm::regex_finder(Rx,Flags) );
}
// join_if ------------------------------------------------------------------//
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//! Conditional join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator. Only segments that
match the given regular expression will be added to the result
This is a specialization of join_if algorithm.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\param Rx A regular expression
\param Flags Regex options
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename Range1T,
typename CharT,
typename RegexTraitsT >
inline typename range_value<SequenceSequenceT>::type
join_if(
const SequenceSequenceT& Input,
const Range1T& Separator,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Roll to the first element that will be added
while(
itBegin!=itEnd &&
!::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin;
// Add this element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
if(::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags))
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
}
return Result;
}
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
//! Conditional join algorithm
/*!
This algorithm joins all strings in a 'list' into one long string.
Segments are concatenated by given separator. Only segments that
match the given regular expression will be added to the result
This is a specialization of join_if algorithm.
\param Input A container that holds the input strings. It must be a container-of-containers.
\param Separator A string that will separate the joined segments.
\param Rx A regular expression
\param Flags Regex options
\return Concatenated string.
\note This function provides the strong exception-safety guarantee
*/
template<
typename SequenceSequenceT,
typename Range1T,
typename CharT,
typename RegexTraitsT >
inline typename range_value<SequenceSequenceT>::type
join_if_regex(
const SequenceSequenceT& Input,
const Range1T& Separator,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type Flags=match_default )
{
// Define working types
typedef typename range_value<SequenceSequenceT>::type ResultT;
typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT;
// Parse input
InputIteratorT itBegin=::boost::begin(Input);
InputIteratorT itEnd=::boost::end(Input);
// Construct container to hold the result
ResultT Result;
// Roll to the first element that will be added
while(
itBegin!=itEnd &&
!::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin;
// Add this element
if(itBegin!=itEnd)
{
detail::insert(Result, ::boost::end(Result), *itBegin);
++itBegin;
}
for(;itBegin!=itEnd; ++itBegin)
{
if(::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags))
{
// Add separator
detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator));
// Add element
detail::insert(Result, ::boost::end(Result), *itBegin);
}
}
return Result;
}
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
} // namespace algorithm
// pull names into the boost namespace
@ -488,6 +634,12 @@ namespace boost {
using algorithm::find_all_regex;
using algorithm::split_regex;
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
using algorithm::join_if;
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
using algorithm::join_if_regex;
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
} // namespace boost

View File

@ -1,11 +1,12 @@
// Boost string_algo library regex_find_format.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_REGEX_FIND_FORMAT_HPP
#define BOOST_STRING_REGEX_FIND_FORMAT_HPP
@ -16,9 +17,9 @@
#include <boost/algorithm/string/detail/formatter_regex.hpp>
/*! \file
Defines the \c refex_finder and \c regex_formatter generators. These two functors
Defines the \c regex_finder and \c regex_formatter generators. These two functors
are designed to work together. \c regex_formatter uses additional information
about a match contained in the reger_finder search result.
about a match contained in the regex_finder search result.
*/
namespace boost {
@ -28,7 +29,7 @@ namespace boost {
//! "Regex" finder
/*!
Construct the \c regex_finder. Finder uses regex engine to search
Construct the \c regex_finder. Finder uses the regex engine to search
for a match.
Result is given in \c regex_search_result. This is an extension
of the iterator_range. In addition it containes match results
@ -40,22 +41,22 @@ namespace boost {
*/
template<
typename CharT,
typename RegexTraitsT, typename RegexAllocatorT>
inline detail::find_regexF< reg_expression<CharT, RegexTraitsT, RegexAllocatorT> >
typename RegexTraitsT>
inline detail::find_regexF< basic_regex<CharT, RegexTraitsT> >
regex_finder(
const reg_expression<CharT, RegexTraitsT, RegexAllocatorT>& Rx,
const basic_regex<CharT, RegexTraitsT>& Rx,
match_flag_type MatchFlags=match_default )
{
return detail::
find_regexF<
reg_expression<CharT, RegexTraitsT, RegexAllocatorT> >( Rx, MatchFlags );
basic_regex<CharT, RegexTraitsT> >( Rx, MatchFlags );
}
// regex_formater ---------------------------------------------//
//! Regex formatter
/*!
Construct the \c regex_formatter. Regex formatter uses regex engine to
Construct the \c regex_formatter. Regex formatter uses the regex engine to
format a match found by the \c regex_finder.
This formatted it designed to closely cooperate with \c regex_finder.
@ -78,6 +79,11 @@ namespace boost {
}
} // namespace algorithm
// pull the names to the boost namespace
using algorithm::regex_finder;
using algorithm::regex_formatter;
} // namespace boost

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
// Boost string_algo library sequence_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_SEQUENCE_TRAITS_HPP
#define BOOST_STRING_SEQUENCE_TRAITS_HPP
@ -22,12 +23,12 @@
For lacking compilers, it is possible of define an override for a specific tester
function.
Due to language restriction, it is not currently possible to define specialization for
stl containers without including the coresponding header. To decrease the overhead
needed by this inclusion, user can selectively include specialization
Due to a language restriction, it is not currently possible to define specializations for
stl containers without including the corresponding header. To decrease the overhead
needed by this inclusion, user can selectively include a specialization
header for a specific container. They are located in boost/algorithm/string/stl
directory. Alternatively she can include boost/algorithm/string/std_collection_traits.hpp
header which contains specialization for all stl containers.
header which contains specializations for all stl containers.
*/
namespace boost {
@ -39,7 +40,7 @@ namespace boost {
//! Native replace tester
/*!
Declare an override of this tester function with return
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the container has basic_string like native replace
@ -49,31 +50,31 @@ namespace boost {
//! Stable iterators tester
/*!
Declare an override of this tester function with return
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the seqeunce's insert/replace/erase methods do not invalidate
\return yes_type if the sequence's insert/replace/erase methods do not invalidate
existing iterators.
*/
no_type has_stable_iterators_tester(...);
no_type has_stable_iterators_tester(...);
//! const time insert tester
/*!
Declare an override of this tester function with return
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the sequence's insert method is working in constant time
*/
no_type has_const_time_insert_tester(...);
no_type has_const_time_insert_tester(...);
//! const time erase tester
/*!
Declare an override of this tester function with return
Declare an override of this tester function with return
type boost::string_algo::yes_type for a sequence with this property.
\return yes_type if the sequence's erase method is working in constant time
*/
no_type has_const_time_erase_tester(...);
no_type has_const_time_erase_tester(...);
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
@ -89,21 +90,25 @@ namespace boost {
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_native_replace_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public:
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<value> type;
typedef mpl::bool_<has_native_replace<T>::value> type;
};
//! Stable iterators trait
/*!
This trait specifies that the sequence has stable iterators. It means,
This trait specifies that the sequence has stable iterators. It means
that operations like insert/erase/replace do not invalidate iterators.
*/
template< typename T >
@ -113,20 +118,24 @@ namespace boost {
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_stable_iterators_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public:
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<value> type;
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
//! Const time insert trait
/*!
This trait specifies that the sequence's insert method has
This trait specifies that the sequence's insert method has
constant time complexity.
*/
template< typename T >
@ -136,20 +145,24 @@ namespace boost {
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_const_time_insert_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public:
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<value> type;
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
//! Const time erase trait
/*!
This trait specifies that the sequence's erase method has
This trait specifies that the sequence's erase method has
constant time complexity.
*/
template< typename T >
@ -159,14 +172,18 @@ namespace boost {
private:
static T* t;
public:
BOOST_STATIC_CONSTANT(bool, value=(
BOOST_STATIC_CONSTANT(bool, value=(
sizeof(has_const_time_erase_tester(t))==sizeof(yes_type) ) );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
public:
public:
# if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = false };
# else
BOOST_STATIC_CONSTANT(bool, value=false);
# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
typedef mpl::bool_<value> type;
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
} // namespace algorithm

View File

@ -1,30 +1,34 @@
// Boost string_algo library find.hpp header file ---------------------------//
// Boost string_algo library split.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2006.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_SPLIT_HPP
#define BOOST_STRING_SPLIT_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/iter_find.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/compare.hpp>
/*! \file
Defines basic split algorithms.
Split algorithms can be used to divide a sequence
into several parts according to a given criterium.
Result is given as a 'container of containers' where
elements are copies or references to extracted parts.
This file contains some common specializations of generic
algorithms contained in the file split2.hpp
Split algorithms can be used to divide a string
into several parts according to given criteria.
Each part is copied and added as a new element to the
output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
*/
namespace boost {
@ -34,68 +38,72 @@ namespace boost {
//! Find all algorithm
/*!
This algorithm finds all occurrences of the search sequence
in the input. A result is given as a 'container of containers'.
Each match of the search sequence is represented by one
element in the result.
This algorithm finds all occurrences of the search string
in the input.
Each part is copied and added as a new element to the
output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A 'container container' to container the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
\c std::vector<boost::iterator_range<iterator>).
(each element of such a vector will container a range delimiting
a match).
\param Result A container that can hold copies of references to the substrings
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Search A substring to be searched for.
\return A reference the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Collection1T, typename Collection2T >
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
inline SequenceSequenceT& find_all(
SequenceSequenceT& Result,
Collection1T& Input,
const Collection2T& Search)
Range1T& Input,
const Range2T& Search)
{
return iter_find(
return ::boost::algorithm::iter_find(
Result,
Input,
first_finder(Search) );
::boost::algorithm::first_finder(Search) );
}
//! Find all algorithm ( case insensitive )
/*!
This algorithm finds all occurrences of the search sequence
in the input. A result is given as a 'container of containers'.
Each match of the search sequence is represented by one
element in the result. Searching is case insensitive.
This algorithm finds all occurrences of the search string
in the input.
Each part is copied and added as a new element to the
output container. Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A 'container container' to container the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
\c std::vector<boost::iterator_range<iterator>>.
(each element of such a vector will container a range delimiting
a match).
Searching is case insensitive.
\param Result A container that can hold copies of references to the substrings
\param Input A container which will be searched.
\param Search A string to be searched for.
\param Loc a locale used for case insensitive comparison
\param Search A substring to be searched for.
\param Loc A locale used for case insensitive comparison
\return A reference the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename Collection1T, typename Collection2T >
template< typename SequenceSequenceT, typename Range1T, typename Range2T >
inline SequenceSequenceT& ifind_all(
SequenceSequenceT& Result,
Collection1T& Input,
const Collection2T& Search,
Range1T& Input,
const Range2T& Search,
const std::locale& Loc=std::locale() )
{
return iter_find(
return ::boost::algorithm::iter_find(
Result,
Input,
first_finder(Search, is_iequal(Loc) ) );
::boost::algorithm::first_finder(Search, is_iequal(Loc) ) );
}
@ -103,18 +111,19 @@ namespace boost {
//! Split algorithm
/*!
Tokenize expression. This function is equivalent of C strtok. Input
Tokenize expression. This function is equivalent to C strtok. Input
sequence is split into tokens, separated by separators. Separators
are given in the mean of predicate.
\param Result A 'container container' to container the result of search.
Both outer and inner container must have constructor taking a pair
of iterators as an argument.
Typical type of the result is
\c std::vector<boost::iterator_range<iterator>>.
(each element of such a vector will container a range delimiting
a match).
are given by means of the predicate.
Each part is copied and added as a new element to the
output container.
Thus the result container must be able to hold copies
of the matches (in a compatible structure like std::string) or
a reference to it (e.g. using the iterator range class).
Examples of such a container are \c std::vector<std::string>
or \c std::list<boost::iterator_range<std::string::iterator>>
\param Result A container that can hold copies of references to the substrings
\param Input A container which will be searched.
\param Pred A predicate to identify separators. This predicate is
supposed to return true if a given element is a separator.
@ -123,19 +132,21 @@ namespace boost {
delimit a token.
\return A reference the result
\note Prior content of the result will be overridden.
\note Prior content of the result will be overwritten.
\note This function provides the strong exception-safety guarantee
*/
template< typename SequenceSequenceT, typename CollectionT, typename PredicateT >
template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
inline SequenceSequenceT& split(
SequenceSequenceT& Result,
CollectionT& Input,
RangeT& Input,
PredicateT Pred,
token_compress_mode_type eCompress=token_compress_off )
{
return iter_split(
return ::boost::algorithm::iter_split(
Result,
Input,
token_finder( Pred, eCompress ) );
::boost::algorithm::token_finder( Pred, eCompress ) );
}
} // namespace algorithm

View File

@ -1,11 +1,12 @@
// Boost string_algo library list_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_LIST_TRAITS_HPP
#define BOOST_STRING_STD_LIST_TRAITS_HPP
@ -33,38 +34,50 @@ namespace boost {
template<typename T, typename AllocT>
yes_type has_const_time_erase_tester( const ::std::list<T,AllocT>* );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// stable iterators trait
// stable iterators trait
template<typename T, typename AllocT>
class has_stable_iterators< ::std::list<T,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
// const time insert trait
// const time insert trait
template<typename T, typename AllocT>
class has_const_time_insert< ::std::list<T,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
// const time erase trait
// const time erase trait
template<typename T, typename AllocT>
class has_const_time_erase< ::std::list<T,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
#endif
} // namespace algorithm
} // namespace boost

View File

@ -1,11 +1,12 @@
// Boost string_algo library string_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_ROPE_TRAITS_HPP
#define BOOST_STRING_STD_ROPE_TRAITS_HPP
@ -43,8 +44,12 @@ namespace boost {
template<typename T, typename TraitsT, typename AllocT>
class has_native_replace< std::rope<T,TraitsT,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
@ -52,8 +57,12 @@ namespace boost {
template<typename T, typename TraitsT, typename AllocT>
class has_stable_iterators< std::rope<T,TraitsT,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
@ -61,8 +70,12 @@ namespace boost {
template<typename T, typename TraitsT, typename AllocT>
class has_const_time_insert< std::rope<T,TraitsT,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
@ -70,8 +83,12 @@ namespace boost {
template<typename T, typename TraitsT, typename AllocT>
class has_const_time_erase< std::rope<T,TraitsT,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<value> type;
};
#endif

View File

@ -1,17 +1,19 @@
// Boost string_algo library slist_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_SLIST_TRAITS_HPP
#define BOOST_STRING_STD_SLIST_TRAITS_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/yes_no_type.hpp>
#include <slist>
#include BOOST_SLIST_HEADER
#include <boost/algorithm/string/sequence_traits.hpp>
namespace boost {
@ -23,43 +25,55 @@ namespace boost {
// stable iterators tester
template<typename T, typename AllocT>
yes_type has_stable_iterators_tester( const std::slist<T,AllocT>* );
yes_type has_stable_iterators_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
// const time insert tester
template<typename T, typename AllocT>
yes_type has_const_time_insert_tester( const std::slist<T,AllocT>* );
yes_type has_const_time_insert_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
// const time erase tester
template<typename T, typename AllocT>
yes_type has_const_time_erase_tester( const std::slist<T,AllocT>* );
yes_type has_const_time_erase_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT>* );
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// stable iterators trait
template<typename T, typename AllocT>
class has_stable_iterators< std::slist<T,AllocT> >
class has_stable_iterators< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_stable_iterators<T>::value> type;
};
// const time insert trait
template<typename T, typename AllocT>
class has_const_time_insert< std::slist<T,AllocT> >
class has_const_time_insert< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_insert<T>::value> type;
};
// const time erase trait
template<typename T, typename AllocT>
class has_const_time_erase< std::slist<T,AllocT> >
class has_const_time_erase< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true };
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_const_time_erase<T>::value> type;
};
#endif

View File

@ -1,11 +1,12 @@
// Boost string_algo library string_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_STRING_TRAITS_HPP
#define BOOST_STRING_STD_STRING_TRAITS_HPP
@ -31,9 +32,14 @@ namespace boost {
template<typename T, typename TraitsT, typename AllocT>
class has_native_replace< std::basic_string<T, TraitsT, AllocT> >
{
public:
public:
#if BOOST_WORKAROUND( __IBMCPP__, <= 600 )
enum { value = true } ;
#else
BOOST_STATIC_CONSTANT(bool, value=true);
typedef mpl::bool_<value> type;
#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 )
typedef mpl::bool_<has_native_replace<T>::value> type;
};

View File

@ -1,11 +1,12 @@
// Boost string_algo library std_containers_traits.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_STD_CONTAINERS_TRAITS_HPP
#define BOOST_STRING_STD_CONTAINERS_TRAITS_HPP

View File

@ -1,17 +1,24 @@
// Boost string_algo library trim.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_TRIM_HPP
#define BOOST_STRING_TRIM_HPP
#include <boost/algorithm/string/config.hpp>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/as_literal.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/algorithm/string/detail/trim.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <locale>
@ -21,10 +28,10 @@
Trim algorithms are used to remove trailing and leading spaces from a
sequence (string). Space is recognized using given locales.
Parametric (\c _if) variants use predicate (functor) to select which characters
Parametric (\c _if) variants use a predicate (functor) to select which characters
are to be trimmed..
Functions take a selection predicate as a parameter, which is used to determine
if a character is a space. Common predicates are provided in classification.hpp header.
whether a character is a space. Common predicates are provided in classification.hpp header.
*/
@ -36,27 +43,34 @@ namespace boost {
//! Left trim - parametric
/*!
Remove all leading spaces from the input. Supplied predicate
is used to determine which character is a space.
The result is copied to the given output iterator.
Remove all leading spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The result is a trimmed copy of the input. It is returned as a sequence
or copied to the output iterator
\param Output A output iterator to which the result will be copied
\param Input An input collection
\param Output An output iterator to which the result will be copied
\param Input An input range
\param IsSpace An unary predicate identifying spaces
\return An output iterator pointing just after last inserted character
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename CollectionT, typename PredicateT>
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
inline OutputIteratorT trim_left_copy_if(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
PredicateT IsSpace)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input));
std::copy(
detail::trim_begin(
begin(Input),
end(Input),
::boost::algorithm::detail::trim_begin(
::boost::begin(lit_range),
::boost::end(lit_range),
IsSpace ),
end(Input),
::boost::end(lit_range),
Output);
return Output;
@ -64,47 +78,43 @@ namespace boost {
//! Left trim - parametric
/*!
Remove all leading spaces from the input. Supplied predicate
is used to determine which character is a space.
The result is a trimmed copy if the input
\param Input An input sequence
\param IsSpace An unary predicate identifying spaces
\return A trimmed copy if the input
\overload
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_left_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
return SequenceT(
detail::trim_begin(
begin(Input),
end(Input),
::boost::algorithm::detail::trim_begin(
::boost::begin(Input),
::boost::end(Input),
IsSpace ),
end(Input));
::boost::end(Input));
}
//! Left trim - parametric
/*!
Remove all leading spaces from the input.
The result is a trimmed copy if the input
The result is a trimmed copy of the input.
\param Input An input sequence
\param Loc a locale used for 'space' classification
\return A trimmed copy if the input
\return A trimmed copy of the input
\note This function provides the strong exception-safety guarantee
*/
template<typename SequenceT>
inline SequenceT trim_left_copy(const SequenceT& Input, const std::locale& Loc=std::locale())
{
return
trim_left_copy_if(
::boost::algorithm::trim_left_copy_if(
Input,
is_space(Loc));
}
//! Left trim
/*!
Remove all leading spaces from the input. Supplied predicate
is used to determine which character is a space.
Remove all leading spaces from the input. The supplied predicate is
used to determine which characters are considered spaces.
The input sequence is modified in-place.
\param Input An input sequence
@ -114,10 +124,10 @@ namespace boost {
inline void trim_left_if(SequenceT& Input, PredicateT IsSpace)
{
Input.erase(
begin(Input),
detail::trim_begin(
begin(Input),
end(Input),
::boost::begin(Input),
::boost::algorithm::detail::trim_begin(
::boost::begin(Input),
::boost::end(Input),
IsSpace));
}
@ -132,7 +142,7 @@ namespace boost {
template<typename SequenceT>
inline void trim_left(SequenceT& Input, const std::locale& Loc=std::locale())
{
trim_left_if(
::boost::algorithm::trim_left_if(
Input,
is_space(Loc));
}
@ -141,26 +151,33 @@ namespace boost {
//! Right trim - parametric
/*!
Remove all trailing spaces from the input. Supplied predicate
is used to determine which character is a space.
The result is copied to the given output iterator.
Remove all trailing spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The result is a trimmed copy of the input. It is returned as a sequence
or copied to the output iterator
\param Output A output iterator to which the result will be copied
\param Input An input collection
\param Output An output iterator to which the result will be copied
\param Input An input range
\param IsSpace An unary predicate identifying spaces
\return An output iterator pointing just after last inserted character
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename CollectionT, typename PredicateT>
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
inline OutputIteratorT trim_right_copy_if(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
PredicateT IsSpace )
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input));
std::copy(
begin(Input),
detail::trim_end(
begin(Input),
end(Input),
::boost::begin(lit_range),
::boost::algorithm::detail::trim_end(
::boost::begin(lit_range),
::boost::end(lit_range),
IsSpace ),
Output );
@ -169,22 +186,16 @@ namespace boost {
//! Right trim - parametric
/*!
Remove all trailing spaces from the input. Supplied predicate
is used to determine which character is a space.
The result is a trimmed copy if the input
\param Input An input Sequence
\param IsSpace An unary predicate identifying spaces
\return A trimmed copy if the input
*/
\overload
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_right_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
return SequenceT(
begin(Input),
detail::trim_end(
begin(Input),
end(Input),
::boost::begin(Input),
::boost::algorithm::detail::trim_end(
::boost::begin(Input),
::boost::end(Input),
IsSpace)
);
}
@ -192,17 +203,19 @@ namespace boost {
//! Right trim
/*!
Remove all trailing spaces from the input.
The result is a trimmed copy if the input
The result is a trimmed copy of the input
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy if the input
*/
\return A trimmed copy of the input
\note This function provides the strong exception-safety guarantee
*/
template<typename SequenceT>
inline SequenceT trim_right_copy(const SequenceT& Input, const std::locale& Loc=std::locale())
{
return
trim_right_copy_if(
::boost::algorithm::trim_right_copy_if(
Input,
is_space(Loc));
}
@ -210,8 +223,8 @@ namespace boost {
//! Right trim - parametric
/*!
Remove all trailing spaces from the input. Supplied predicate
is used to determine which character is a space.
Remove all trailing spaces from the input.
The supplied predicate is used to determine which characters are considered spaces.
The input sequence is modified in-place.
\param Input An input sequence
@ -221,11 +234,11 @@ namespace boost {
inline void trim_right_if(SequenceT& Input, PredicateT IsSpace)
{
Input.erase(
detail::trim_end(
begin(Input),
end(Input),
::boost::algorithm::detail::trim_end(
::boost::begin(Input),
::boost::end(Input),
IsSpace ),
end(Input)
::boost::end(Input)
);
}
@ -241,7 +254,7 @@ namespace boost {
template<typename SequenceT>
inline void trim_right(SequenceT& Input, const std::locale& Loc=std::locale())
{
trim_right_if(
::boost::algorithm::trim_right_if(
Input,
is_space(Loc) );
}
@ -251,30 +264,37 @@ namespace boost {
//! Trim - parametric
/*!
Remove all trailing and leading spaces from the input.
Supplied predicate is used to determine which character is a space.
The result is copied to the given output iterator.
The supplied predicate is used to determine which characters are considered spaces.
The result is a trimmed copy of the input. It is returned as a sequence
or copied to the output iterator
\param Output A output iterator to which the result will be copied
\param Input An input collection
\param Output An output iterator to which the result will be copied
\param Input An input range
\param IsSpace An unary predicate identifying spaces
\return An output iterator pointing just after last inserted character
\return
An output iterator pointing just after the last inserted character or
a copy of the input
\note The second variant of this function provides the strong exception-safety guarantee
*/
template<typename OutputIteratorT, typename CollectionT, typename PredicateT>
template<typename OutputIteratorT, typename RangeT, typename PredicateT>
inline OutputIteratorT trim_copy_if(
OutputIteratorT Output,
const CollectionT& Input,
const RangeT& Input,
PredicateT IsSpace)
{
iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input));
BOOST_STRING_TYPENAME
const_iterator_of<CollectionT>::type TrimEnd=
detail::trim_end(
begin(Input),
end(Input),
range_const_iterator<RangeT>::type TrimEnd=
::boost::algorithm::detail::trim_end(
::boost::begin(lit_range),
::boost::end(lit_range),
IsSpace);
std::copy(
detail::trim_begin(
begin(Input), TrimEnd, IsSpace),
::boost::begin(lit_range), TrimEnd, IsSpace),
TrimEnd,
Output
);
@ -284,27 +304,21 @@ namespace boost {
//! Trim - parametric
/*!
Remove all leading and trailing spaces from the input.
Supplied predicate is used to determine which character is a space.
The result is a trimmed copy if the input
\param Input An input sequence
\param IsSpace An unary predicate identifying spaces
\return A trimmed copy if the input
*/
\overload
*/
template<typename SequenceT, typename PredicateT>
inline SequenceT trim_copy_if(const SequenceT& Input, PredicateT IsSpace)
{
BOOST_STRING_TYPENAME
const_iterator_of<SequenceT>::type TrimEnd=
detail::trim_end(
begin(Input),
end(Input),
range_const_iterator<SequenceT>::type TrimEnd=
::boost::algorithm::detail::trim_end(
::boost::begin(Input),
::boost::end(Input),
IsSpace);
return SequenceT(
detail::trim_begin(
begin(Input),
::boost::begin(Input),
TrimEnd,
IsSpace),
TrimEnd
@ -314,17 +328,19 @@ namespace boost {
//! Trim
/*!
Remove all leading and trailing spaces from the input.
The result is a trimmed copy if the input
The result is a trimmed copy of the input
\param Input An input sequence
\param Loc A locale used for 'space' classification
\return A trimmed copy if the input
\return A trimmed copy of the input
\note This function provides the strong exception-safety guarantee
*/
template<typename SequenceT>
inline SequenceT trim_copy( const SequenceT& Input, const std::locale& Loc=std::locale() )
{
return
trim_copy_if(
::boost::algorithm::trim_copy_if(
Input,
is_space(Loc) );
}
@ -332,7 +348,7 @@ namespace boost {
//! Trim
/*!
Remove all leading and trailing spaces from the input.
Supplied predicate is used to determine which character is a space.
The supplied predicate is used to determine which characters are considered spaces.
The input sequence is modified in-place.
\param Input An input sequence
@ -341,8 +357,8 @@ namespace boost {
template<typename SequenceT, typename PredicateT>
inline void trim_if(SequenceT& Input, PredicateT IsSpace)
{
trim_right_if( Input, IsSpace );
trim_left_if( Input, IsSpace );
::boost::algorithm::trim_right_if( Input, IsSpace );
::boost::algorithm::trim_left_if( Input, IsSpace );
}
//! Trim
@ -356,7 +372,7 @@ namespace boost {
template<typename SequenceT>
inline void trim(SequenceT& Input, const std::locale& Loc=std::locale())
{
trim_if(
::boost::algorithm::trim_if(
Input,
is_space( Loc ) );
}

View File

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

View File

@ -1,11 +1,12 @@
// Boost string_algo library yes_no_type.hpp header file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Pavol Droba 2002-2003.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_YES_NO_TYPE_DETAIL_HPP
#define BOOST_STRING_YES_NO_TYPE_DETAIL_HPP
@ -14,7 +15,7 @@ namespace boost {
namespace algorithm {
// taken from boost mailing-list
// when yes_no_type will become officialy
// when yes_no_type will become officially
// a part of boost distribution, this header
// will be deprecated
template<int I> struct size_descriptor

View File

@ -1,22 +1,23 @@
// Boost string_algo library string_algo.hpp header file ---------------------------//
// Boost string_algo library string_regex.hpp header file ---------------------------//
// (C) Copyright Pavol Droba 2002-2003. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// Copyright Pavol Droba 2002-2004.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// See http://www.boost.org/ for updates, documentation, and revision history.
#ifndef BOOST_STRING_ALGO_REGEX_HPP
#define BOOST_STRING_ALGO_REGEX_HPP
/*! \file
Cumulative include for string_algo library.
In addtion to string_algo.hpp, it contains also regex-related stuff.
In addtion to string.hpp contains also regex-related stuff.
*/
#include <boost/regex.hpp>
#include <boost/string_algo.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#endif // BOOST_STRING_ALGO_REGEX_HPP

View File

@ -1,52 +0,0 @@
// (C) Copyright Eric Niebler 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/*
Revision history:
25 February 2004
Initial version.
*/
#ifndef BOOST_MINMAX_HPP
#define BOOST_MINMAX_HPP
#include <algorithm> // for std::min and std::max
#include <boost/config.hpp>
namespace boost
{
template< typename T >
inline T const & std_min( T const & a, T const & b )
{
using std::min;
return min BOOST_PREVENT_MACRO_SUBSTITUTION ( a, b );
}
template< typename T >
inline T const & std_max( T const & a, T const & b )
{
using std::max;
return max BOOST_PREVENT_MACRO_SUBSTITUTION ( a, b );
}
// Overloads for unsigned long to work around a bug in the Borland headers
#ifdef __BORLANDC__
inline unsigned long const & std_min( unsigned long const & a, unsigned long const & b )
{
return a < b ? a : b;
}
inline unsigned long const & std_max( unsigned long const & a, unsigned long const & b )
{
return a > b ? a : b;
}
#endif
}
#endif // BOOST_MINMAX_HPP

View File

@ -0,0 +1,524 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
<meta name="Author" content="Herve Bronnimann">
<meta name="Description" content="Small library to propose minmax_element algorithm.">
<title>Boost minmax library</title>
</head>
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
<center>
<h1>
Minmax_element Performance</h1></center>
<h3>
<a NAME="Performance"></a><b>About performance</b></h3>
Of course, there are many factors that affect the performance of an algorithm.
The number of comparison is only one, but also branch prediction, pipelining,
locality of reference (affects cache efficiency), etc. In practice,
we observe that when the iterator type is a pointer,
<tt>boost::minmax_element</tt>
is only a tad slower than
<tt>std::min_element</tt>, and is even faster
than
<tt>boost::first_min_last_max_element</tt>! This is even more true
for slower iterators (<tt>list&lt;>::iterator</tt> or
<tt>map&lt;>iterator</tt>
for instance). The following experiments were conducted on a Pentium III
500 Mhz running Linux and compiled with g++, version 2.95.2, flags -O3.
In the tables, we use different distributions: <i>Identical</i> means that
all the elements are identical, <i>2-valued</i> means that we replace the
second half of the identical elements by a distinct element, <i>increasing</i>
means that all the elements are distinct and in increasing order, <i>decrea</i>sing
is the reverse, and <i>random</i> is produced by random_shuffle.
<br>
The program that created these tables is included in the distribution,
under <a href="../example/minmax_timer.cpp">minmax_timer.cpp</a>
<br>
<center><table BORDER NOSAVE >
<tr NOSAVE>
<td NOSAVE><b>vector&lt;int>::iterator</b></td>
<td>Identical</td>
<td>2-valued</td>
<td>Increasing</td>
<td>Decreasing</td>
<td>Random</td>
</tr>
<tr>
<td>std::min_element</td>
<td>23.26M/s</td>
<td>23.26M/s</td>
<td>23.15M/s</td>
<td>22.94M/s</td>
<td>22.94M/s</td>
</tr>
<tr>
<td>std::max_element</td>
<td>23.26M/s</td>
<td>23.26M/s</td>
<td>23.15M/s</td>
<td>22.94M/s</td>
<td>22.62M/s</td>
</tr>
<tr>
<td>boost::first_min_element</td>
<td>23.15M/s</td>
<td>23.04M/s</td>
<td>23.04M/s</td>
<td>22.94M/s</td>
<td>22.83M/s</td>
</tr>
<tr>
<td>boost::last_min_element</td>
<td>23.26M/s</td>
<td>23.26M/s</td>
<td>23.26M/s</td>
<td>22.83M/s</td>
<td>16.23M/s</td>
</tr>
<tr>
<td>boost::first_max_element</td>
<td>23.15M/s</td>
<td>23.26M/s</td>
<td>23.15M/s</td>
<td>23.04M/s</td>
<td>22.93M/s</td>
</tr>
<tr>
<td>boost::last_max_element</td>
<td>23.26M/s</td>
<td>23.15M/s</td>
<td>23.15M/s</td>
<td>22.94M/s</td>
<td>16.18M/s</td>
</tr>
<tr>
<td>boost::minmax_element</td>
<td>21.83M/s</td>
<td>21.83M/s</td>
<td>21.83M/s</td>
<td>21.55M/s</td>
<td>17.79M/s</td>
</tr>
<tr>
<td>boost::first_min_last_max_element</td>
<td>18.52M/s</td>
<td>18.38M/s</td>
<td>18.38M/s</td>
<td>18.94M/s</td>
<td>16.29M/s</td>
</tr>
<tr>
<td>boost::last_min_first_max_element</td>
<td>20.08M/s</td>
<td>20.83M/s</td>
<td>20.75M/s</td>
<td>19.76M/s</td>
<td>15.87M/s</td>
</tr>
<tr>
<td>boost::last_min_last_max_element</td>
<td>18.66M/s</td>
<td>19.69M/s</td>
<td>19.69M/s</td>
<td>19.23M/s</td>
<td>15.77M/s</td>
</tr>
<caption ALIGN=BOTTOM>Number of elements per second for standard vector
container iterators</caption>
</table></center>
<center><table BORDER NOSAVE >
<tr NOSAVE>
<td NOSAVE><b>list&lt;int>::iterator</b></td>
<td>Identical</td>
<td>2-valued</td>
<td>Increasing</td>
<td>Decreasing</td>
<td>Random</td>
</tr>
<tr>
<td>std::min_element</td>
<td>5.8M/s</td>
<td>5.8M/s</td>
<td>5.80M/s</td>
<td>5.73M/s</td>
<td>5.73M/s</td>
</tr>
<tr>
<td>std::max_element</td>
<td>5.81M/s</td>
<td>5.81M/s</td>
<td>5.78M/s</td>
<td>5.73M/s</td>
<td>5.75M/s</td>
</tr>
<tr>
<td>boost::first_min_element</td>
<td>5.81M/s</td>
<td>5.81M/s</td>
<td>5.79M/s</td>
<td>5.75M/s</td>
<td>5.73M/s</td>
</tr>
<tr>
<td>boost::last_min_element</td>
<td>5.81M/s</td>
<td>5.80M/s</td>
<td>5.79M/s</td>
<td>5.73M/s</td>
<td>5.03M/s</td>
</tr>
<tr>
<td>boost::first_max_element</td>
<td>5.81M/s</td>
<td>5.80M/s</td>
<td>5.78M/s</td>
<td>5.74M/s</td>
<td>5.73M/s</td>
</tr>
<tr>
<td>boost::last_max_element</td>
<td>5.81M/s</td>
<td>5.80M/s</td>
<td>5.79M/s</td>
<td>5.73M/s</td>
<td>5.07M/s</td>
</tr>
<tr>
<td>boost::minmax_element</td>
<td>5.68M/s</td>
<td>5.80M/s</td>
<td>5.66M/s</td>
<td>5.74M/s</td>
<td>5.30M/s</td>
</tr>
<tr>
<td>boost::first_min_last_max_element</td>
<td>5.79M/s</td>
<td>5.81M/s</td>
<td>5.78M/s</td>
<td>5.73M/s</td>
<td>5.04M/s</td>
</tr>
<tr>
<td>boost::last_min_first_max_element</td>
<td>5.69M/s</td>
<td>5.79M/s</td>
<td>5.69M/s</td>
<td>5.73M/s</td>
<td>4.84M/s</td>
</tr>
<tr>
<td>boost::last_min_last_max_element</td>
<td>5.61M/s</td>
<td>5.79M/s</td>
<td>5.64M/s</td>
<td>5.74M/s</td>
<td>4.75M/s</td>
</tr>
<caption ALIGN=BOTTOM>Runtimes for standard list container iterators</caption>
</table></center>
<center><table BORDER NOSAVE >
<tr NOSAVE>
<td NOSAVE><b>multiset&lt;int>::iterator</b></td>
<td>Identical</td>
<td>2-valued</td>
<td>Increasing</td>
<td>Decreasing</td>
<td>Random</td>
</tr>
<tr>
<td>std::min_element</td>
<td>4.03M/s</td>
<td>4.04M/s</td>
<td>4.02M/s</td>
<td>4.04M/s</td>
<td>2.97M/s</td>
</tr>
<tr>
<td>std::max_element3.007M</td>
<td>4.02M/s</td>
<td>4.02M/s</td>
<td>4.01M/s</td>
<td>4.02M/s</td>
<td>2.96M/s</td>
</tr>
<tr>
<td>boost::first_min_element</td>
<td>4.01M/s</td>
<td>4.04M/s</td>
<td>4.03M/s</td>
<td>4.04M/s</td>
<td>3.01M/s</td>
</tr>
<tr>
<td>boost::last_min_element</td>
<td>4.03M/s</td>
<td>4.04M/s</td>
<td>4.04M/s</td>
<td>4.04M/s</td>
<td>3.00M/s</td>
</tr>
<tr>
<td>boost::first_max_element</td>
<td>4.04M/s</td>
<td>4.04M/s</td>
<td>4.04M/s</td>
<td>4.06M/s</td>
<td>3.01M/s</td>
</tr>
<tr>
<td>boost::last_max_element</td>
<td>4.04M/s</td>
<td>4.04M/s</td>
<td>4.03M/s</td>
<td>4.04M/s</td>
<td>3.00M/s</td>
</tr>
<tr>
<td>boost::minmax_element</td>
<td>3.98M/s</td>
<td>3.99M/s</td>
<td>3.98M/s</td>
<td>3.99M/s</td>
<td>3.00M/s</td>
</tr>
<tr>
<td>boost::first_min_last_max_element</td>
<td>3.99M/s</td>
<td>3.98M/s</td>
<td>3.97M/s</td>
<td>3.99M/s</td>
<td>2.99M/s</td>
</tr>
<tr>
<td>boost::last_min_first_max_element</td>
<td>3.97M/s</td>
<td>3.98M/s</td>
<td>3.96M/s</td>
<td>3.98M/s</td>
<td>3.00M/s</td>
</tr>
<tr>
<td>boost::last_min_last_max_element</td>
<td>4.00M/s</td>
<td>4.00M/s</td>
<td>4.00M/s</td>
<td>4.02M/s</td>
<td>2.97M/s</td>
</tr>
<caption ALIGN=BOTTOM>Runtimes for standard set/multiset container iterators</caption>
</table></center>
<hr SIZE="6">
<br>Last modified 2004-06-28
<p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute;
Br&ouml;nnimann, Polytechnic University, 2002--2004.
Use, modification, and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
</font></font>
</body>
</html>

View File

@ -0,0 +1,127 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
<meta name="Author" content="Herve Bronnimann">
<meta name="Description" content="Small library to propose minmax_element algorithm.">
<title>Boost minmax library synopsis</title>
</head>
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
<center>
<h1>
Minmax_element complete synopsis</h1></center>
<h3>
Synopsis of <tt>&lt;boost/algorithm/minmax.hpp></tt></h3>
<pre>#include &lt;boost/tuple/tuple.hpp>
namespace boost {
template &lt;class T>
tuple&lt;T const&amp;, T const&amp;> >
minmax(const T&amp; a, const T&amp; b);
template &lt;class T, class <a href="http://www.sgi.com/tech/stl/ BinaryPredicate.html">BinaryPredicate</a>>
tuple&lt;T const&amp;, T const&amp;> >
minmax(const T&amp; a, const T&amp; b, BinaryPredicate comp);
}
</pre>
<h3>
Synopsis of <tt>&lt;boost/algorithm/minmax_element.hpp></tt></h3>
<pre>#include &lt;utility> //for std::pair
namespace boost {
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
minmax_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
minmax_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
// Variants
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
ForwardIterator first_min_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
ForwardIterator last_min_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
ForwardIterator first_max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
ForwardIterator last_max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
first_min_first_max_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
first_min_first_max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
first_min_last_max_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
first_min_last_max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
last_min_first_max_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
last_min_first_max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
last_min_last_max_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
last_min_last_max_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
}</pre>
<hr SIZE="6">
<br>Last modified 2002-07-01
<p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute;
Br&ouml;nnimann, Polytechnic University, 2002--2004.
Use, modification, and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
</font></font>
</body>
</html>

12
minmax/example/Jamfile Normal file
View File

@ -0,0 +1,12 @@
# Boost.Minmax Library Example Jamfile
#
# Copyright (C) 2002--2004, Herve Bronnimann
#
# Use, modification, and distribution is subject to the Boost Software
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
exe minmax_ex : minmax_ex.cpp ;
exe minmax_timer : minmax_timer.cpp ;

View File

@ -0,0 +1,36 @@
// (C) Copyright Herve Bronnimann 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <list>
#include <algorithm>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <boost/algorithm/minmax.hpp>
#include <boost/algorithm/minmax_element.hpp>
int main()
{
using namespace std;
// Demonstrating minmax()
boost::tuple<int const&, int const&> result1 = boost::minmax(1, 0);
assert( result1.get<0>() == 0 );
assert( result1.get<1>() == 1 );
// Demonstrating minmax_element()
list<int> L;
typedef list<int>::const_iterator iterator;
generate_n(front_inserter(L), 1000, rand);
pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end());
cout << "The smallest element is " << *(result2.first) << endl;
cout << "The largest element is " << *(result2.second) << endl;
assert( result2.first == std::min_element(L.begin(), L.end()) );
assert( result2.second == std::max_element(L.begin(), L.end()) );
}

View File

@ -0,0 +1,212 @@
// (C) Copyright Herve Bronnimann 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <utility>
#include <functional>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <vector>
#include <list>
#include <set>
#include <iostream>
// What's the proper BOOST_ flag for <iomanip.h> vs <ios>
#include <iomanip>
#include <boost/timer.hpp>
#include <boost/algorithm/minmax.hpp>
template <class T1, class T2>
void tie(std::pair<T1, T2> p, T1& min, T2& max)
{
min = p.first; max = p.second;
}
template <class Value>
struct less_count : std::less<Value> {
less_count(less_count<Value> const& lc) : _M_counter(lc._M_counter) {}
less_count(int& counter) : _M_counter(counter) {}
bool operator()(Value const& a, Value const& b) const {
++_M_counter;
return std::less<Value>::operator()(a,b);
}
void reset() {
_M_counter = 0;
}
private:
int& _M_counter;
};
inline int opt_min_count(int n) {
return (n==0) ? 0 : n-1;
}
inline int opt_minmax_count(int n) {
if (n < 2) return 0;
if (n == 2) return 1;
return (n%2 == 0) ? 3*(n/2)-1 : 3*(n/2)+1;
}
inline int opt_boost_minmax_count(int n) {
if (n < 2) return 0;
if (n == 2) return 1;
return (n%2 == 0) ? 3*(n/2)-2 : 3*(n/2);
}
int repeats = 10;
#define TIMER( n, cmd , cmdname ) \
t.restart(); \
for (int i=0; i<repeats; ++i) { cmd ; } \
std::cout << " " << std::setprecision(4) \
<< (double)n*repeats/t.elapsed()/1.0E6 \
<< "M items/sec " << cmdname << "\n"
#define CTIMER( n, cmd , cmdname, count, opt ) \
t.restart(); lc.reset(); \
for (int i=0; i<repeats; ++i) { cmd ; } \
std::cout << " " << std::setprecision(4) \
<< (double)n*repeats/t.elapsed()/1.0E6 \
<< "M items/sec " << cmdname \
<< " ("<< (count)/repeats << " vs " << opt << ")\n"
template <class CIterator>
void test_minmax_element(CIterator first, CIterator last, int n, char* name)
{
typedef typename std::iterator_traits<CIterator>::value_type vtype;
boost::timer t;
std::cout << " ON " << name << " WITH OPERATOR<()\n";
TIMER( n, std::min_element(first, last),
"std::min_element" << name << "");
TIMER( n, std::max_element(first, last),
"std::max_element" << name << "");
TIMER( n, boost::first_min_element(first, last),
"boost::first_min_element" << name << "");
TIMER( n, boost::last_min_element(first, last),
"boost::last_min_element" << name << " ");
TIMER( n, boost::first_max_element(first, last),
"boost::first_max_element" << name << "");
TIMER( n, boost::last_max_element(first, last),
"boost::last_max_element" << name << " ");
TIMER( n, boost::minmax_element(first, last),
"boost::minmax_element" << name << " ");
TIMER( n, boost::first_min_last_max_element(first, last),
"boost::first_min_last_max_element" << name << "");
TIMER( n, boost::last_min_first_max_element(first, last),
"boost::last_min_first_max_element" << name << "");
TIMER( n, boost::last_min_last_max_element(first, last),
"boost::last_min_last_max_element" << name << " ");
#define pred std::bind2nd( std::greater<vtype>(), vtype(10) )
TIMER( n, boost::min_element_if(first, last, pred),
"boost::min_element_if" << name << "");
TIMER( n, boost::max_element_if(first, last, pred),
"boost::max_element_if" << name << "");
TIMER( n, std::min_element(boost::make_filter_iterator(first, last, pred),
boost::make_filter_iterator(last, last, pred)),
"std::min_element_with_filter_iterator" << name << "");
TIMER( n, std::max_element(boost::make_filter_iterator(first, last, pred),
boost::make_filter_iterator(last, last, pred)),
"std::max_element_if_with_filter_iterator" << name << "");
#undef pred
int counter = 0;
less_count<vtype> lc(counter);
std::cout << " ON " << name << " WITH LESS<> AND COUNTING COMPARISONS\n";
CTIMER( n, std::min_element(first, last, lc),
"std::min_element" << name << " ",
counter, opt_min_count(n) );
CTIMER( n, std::max_element(first, last, lc),
"std::max_element" << name << " ",
counter, opt_min_count(n) );
CTIMER( n, boost::first_min_element(first, last, lc),
"boost::first_min_element" << name << "",
counter, opt_min_count(n) );
CTIMER( n, boost::last_min_element(first, last, lc),
"boost::last_max_element" << name << " ",
counter, opt_min_count(n) );
CTIMER( n, boost::first_max_element(first, last, lc),
"boost::first_min_element" << name << "",
counter, opt_min_count(n) );
CTIMER( n, boost::last_max_element(first, last, lc),
"boost::last_max_element" << name << " ",
counter, opt_min_count(n) );
CTIMER( n, boost::minmax_element(first, last, lc),
"boost::minmax_element" << name << " ",
counter, opt_minmax_count(n) );
CTIMER( n, boost::first_min_last_max_element(first, last, lc),
"boost::first_min_last_max_element" << name << "",
counter, opt_boost_minmax_count(n) );
CTIMER( n, boost::last_min_first_max_element(first, last, lc),
"boost::last_min_first_max_element" << name << "",
counter, opt_boost_minmax_count(n) );
CTIMER( n, boost::last_min_last_max_element(first, last, lc),
"boost::last_min_last_max_element" << name << " ",
counter, opt_minmax_count(n) );
}
template <class Container, class Iterator, class Value>
void test_container(Iterator first, Iterator last, int n, char* name)
{
Container c(first, last);
typename Container::iterator fit(c.begin()), lit(c.end());
test_minmax_element(fit, lit, n, name);
}
template <class Iterator>
void test_range(Iterator first, Iterator last, int n)
{
typedef typename std::iterator_traits<Iterator>::value_type Value;
// Test various containers with these values
test_container< std::vector<Value>, Iterator, Value >(first, last, n, "<vector>");
#ifndef ONLY_VECTOR
test_container< std::list<Value>, Iterator, Value >(first, last, n, "<list> ");
test_container< std::multiset<Value>, Iterator, Value >(first, last, n, "<set> ");
#endif
}
template <class Value>
void test(int n)
{
// Populate test vector with identical values
std::cout << "IDENTICAL VALUES... \n";
std::vector<Value> test_vector(n, Value(1));
typename std::vector<Value>::iterator first( test_vector.begin() );
typename std::vector<Value>::iterator last( test_vector.end() );
test_range(first, last, n);
// Populate test vector with two values
std::cout << "TWO DISTINCT VALUES...\n";
typename std::vector<Value>::iterator middle( first + n/2 );
std::fill(middle, last, Value(2));
test_range(first, last, n);
// Populate test vector with increasing values
std::cout << "INCREASING VALUES... \n";
std::fill(first, last, Value(1));
std::accumulate(first, last, Value(0));
test_range(first, last, n);
// Populate test vector with decreasing values
std::cout << "DECREASING VALUES... \n";
std::reverse(first, last);
test_range(first, last, n);
// Populate test vector with random values
std::cout << "RANDOM VALUES... \n";
std::random_shuffle(first, last);
test_range(first, last, n);
}
int
main(char argc, char** argv)
{
int n = 100;
if (argc > 1) n = atoi(argv[1]);
if (argc > 2) repeats = atoi(argv[2]);
test<int>(n);
return 0;
}

527
minmax/index.html Normal file
View File

@ -0,0 +1,527 @@
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
<HTML>
<HEAD>
<LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css">
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<META name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
<META name="Author" content="Herve Bronnimann">
<META name="Description" content="Small library to propose minmax_element algorithm.">
<title>Boost Minmax library</title>
</HEAD>
<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
<h2><img src="../../../boost.png" WIDTH="276" HEIGHT="86">Header &lt;<A
HREF="../../../boost/algorithm/minmax.hpp">boost/algorithm/minmax.hpp</A>&gt; </H2>
<quote>
<b>
<a href="#minmax_element">Motivation</a><br>
<a href="#synopsis">Synopsis</a><br>
<a href="#description">Function templates description</a><br>
<a href="#definition">Definition</a><br>
<a href="#reqs">Requirements on types</a><br>
<a href="#precond">Preconditions</a><br>
<a href="#postcond">Postconditions</a><br>
<a href="#complexity">Complexity</a><br>
<a href="#example">Example</a><br>
<a href="#notes">Notes</a><br>
<a href="#rationale">Rationale</a><br>
<a href="#perf">Note about performance</a><br>
<a href="#acks">Acknowledgements</a>
</b>
</quote>
<a name="minmax_element">
<h3>
Motivation</h3>
<p>The minmax library is composed of two headers, <a
href="../../../boost/algorithm/minmax.hpp">&lt;boost/algorithm/minmax.hpp></a>
and <a
href="../../../boost/algorithm/minmax_element.hpp">&lt;boost/algorithm/minmax_element.hpp></a>.
(See <a href="#two_headers">rationale</a>.)
The problem solved by this library is that simultaneous min and max
computation requires
only one comparison, but using <tt>std::min</tt> and <tt>std::max</tt>
forces two comparisons. Worse, to compute the minimum and
maximum elements of a range of <tt>n</tt> elements requires only
<tt>3n/2+1</tt> comparisons, instead of the <tt>2n</tt> (in two passes)
forced by <tt>std::min_element</tt> and <tt>std::max_element</tt>.
I always thought it is a waste to have to call two functions to compute the
extent of a range, performing two passes over the input, when one should
be enough. The present library solves both problems.</p>
<p>The first file implements the function templates
<tt>minmax</tt>
as straightforward extensions of the C++
standard. As it returns a pair of <tt>const&amp;</tt>, we must use the <a
href="../../tuple/index.html">Boost.tuple</a> library to construct such
pairs. (Please note: the intent is not to fix the known defaults of
<tt>std::min</tt>
and <tt>std::max</tt>, but to add one more algorithms that combines both; see the
<a href="#no-fix">rationale</a>.)</p>
<p>The second file implements the function templates
<tt>minmax_element</tt>. In a
second part, it also proposes variants that can usually not be computed by
the minmax algorithm, and which are more flexible in case some elements are equal.
Those variants could have been also provided with policy-based design,
but I ruled against that (see <a href="#no-policy">rationale</a>).
</p>
<p>If you are interested about
<a href="doc/minmax_benchs.html">performance</a>,
you will see that <tt>minmax_element</tt> is just slightly less efficient
than a single <tt>min_element</tt> or <tt>max_element</tt>, and thus
twice as efficient as two separate calls to <tt>min_element</tt> and
<tt>max_element</tt>. From a
theoretical standpoint,
all the <tt>minmax_element</tt> functions perform at most
<tt>3n/2+1</tt>
comparisons and exactly n increments of the
<tt>ForwardIterator</tt>.</p>
</a>
<a name="synopsis">
<h3>
Synopsis of <tt>&lt;boost/algorithm/minmax.hpp></tt></h3>
<pre>#include &lt;boost/tuple/tuple.hpp>
namespace boost {
template &lt;class T>
tuple&lt;T const&amp;, T const&amp;>
minmax(const T&amp; a, const T&amp; b);
template &lt;class T, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
tuple&lt;T const&amp;, T const&amp;>
minmax(const T&amp; a, const T&amp; b, BinaryPredicate comp);
}
</pre>
<h3>
Synopsis of <tt>&lt;boost/algorithm/minmax_element.hpp></tt></h3>
<pre>#include &lt;utility> // for std::pair
namespace boost {
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
minmax_element(ForwardIterator first, ForwardIterator last);
template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
std::pair&lt;ForwardIterator,ForwardIterator>
minmax_element(ForwardIterator first, ForwardIterator last,
BinaryPredicate comp);
}
</pre>
In addition, there are a bunch of extensions which specify
which element(s) you want to pick in case of equal elements. They are:
<ul>
<li><tt>first_min_element</tt> and <tt>last_min_element</tt></li>
<li><tt>first_max_element</tt> and <tt>last_max_element</tt></li>
<li><tt>first_min_first_max_element</tt>,
<tt>first_min_last_max_element</tt>,
<tt>last_min_first_max_element</tt>, and
<tt>last_min_last_max_element</tt></li>
</ul>
I won't bore you with the complete synopsis, they have exactly the same
declaration as their corresponding <tt>_element</tt> function. Still,
you can find the complete synopsis <a href="doc/minmax_synopsis.html">here</a>.
</a>
<a name="description">
<h3>
Function templates description</h3>
The <tt>minmax</tt> algorithm returns a pair <tt>p</tt> containing either
<i>(a,b)</i>
or <i>(b,a)</i>, such that <tt>p.first&lt;p.second</tt> in the first version,
or <tt>comp(p.first,p.second)</tt> in the second version. If the elements
are equivalent, the pair <i>(a,b) </i>is returned. <a href="#Note1">[1]</a>
<p>The <tt>minmax_element </tt>is semantically equivalent to <tt>first_min_first_max_element</tt>.
<p><tt>First_min_element</tt> and <tt>first_max_element</tt> find the smallest
and largest elements in the range <tt>[first, last)</tt>. If there are
several instance of these elements, the first one is returned. They are
identical to
<tt>std::min_element</tt> and <tt>std::max_element</tt>and
are only included in this library for symmetry.
<p><tt>Last_min_element</tt> and <tt>last_max_element</tt> find the smallest
and largest elements in the range <tt>[first, last)</tt>. They are almost
identical to
<tt>std::min_element</tt> and <tt>std::max_element</tt>, except
that they return the last instance of the largest element (and not the
first, as <tt>first_min_element</tt> and <tt>last_max_element</tt> would).
<p>The family of algorithms comprising <tt>first_min_first_max_element</tt>,
<tt>first_min_last_max_element</tt>,
<tt>last_min_first_max_element</tt>,
and <tt>last_min_last_max_element</tt> can be described generically as
follows (using <i><tt>which</tt></i> and
<i><tt>what</tt></i> for <tt>first</tt>
or <tt>last</tt>): <tt><i>which</i>_min_<i>what</i>_max_element</tt> finds
the (first or last, according to <i><tt>which</tt></i>) smallest element
and the (first or last, according to <i><tt>what</tt></i>) largest element
in the range
<tt>[first, last)</tt>. The first version is semantically
equivalent to:
<pre><tt> std::make_pair(boost::<i>which</i>_min_element(first,last),
boost::<i>what</i>_max_element(first,last))</tt>,</pre>
and the second version to:
<pre><tt> std::make_pair(boost::<i>which</i>_min_element(first,last,comp),
boost::<i>what</i>_max_element(first,last,comp))</tt>.</pre>
<p><br><b><i>Note</i></b>: the <tt>first_min_last_max_element</tt> can also be described
as finding the first and last elements in the range if it were stably sorted.
</a>
<a name="definition">
<h3>
Definition</h3>
Defined in <a href="../../../boost/algorithm/minmax.hpp">minmax.hpp</a>
and
in <a href="../../../boost/algorithm/minmax_element.hpp">minmax_element.hpp</a>.
</a>
<a name="reqs">
<h3>
Requirements on types</h3>
For minmax, <tt>T</tt> must be a model of <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
Comparable</a>.
<p>For all the other function templates, versions with two template parameters:
<ul>
<li>
<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
Iterator</a>.</li>
<li>
<tt>ForwardIterator</tt>'s value type is <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
Comparable</a>.</li>
</ul>
For the versions with three template parameters:
<ul>
<li>
<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
Iterator</a>.</li>
<li>
<tt>BinaryPredicate</tt> is a model of <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary
Predicate</a>.</li>
<li>
<tt>ForwardIterator</tt>'s value type is convertible to <tt>BinaryPredicate</tt>'s
first argument type and second argument type.</li>
</ul>
</a>
<a name="precond">
<h3>
Preconditions</h3>
<ul>
<li>
<tt>[first, last)</tt> is a valid range.</li>
</ul>
</a>
<a name="postcond">
<h3>
Postconditions</h3>
In addition to the semantic description above. for <tt>minmax_element</tt>
and all the <tt><i>which</i>_min_<i>what</i>_max_element</tt>
variants, the return value is
<tt>last</tt> or <tt>std::make_pair(last,last)</tt>
if and only if <tt>[first, last)</tt> is an empty range. Otherwise, the
return value or both members of the resulting pair are iterators in the
range
<tt>[first, last)</tt>.
</a>
<a name="complexity">
<h3>
Complexity</h3>
Minmax performs a single comparison and is otherwise of constant complexity.
The use of <tt>boost::tuple&lt;T const&amp;></tt> prevents copy
constructors in case the arguments are passed by reference.
<p>The complexity of all the other algorithms is linear. They all perform
exactly n increment operations, and zero comparisons if <tt>[first,last)</tt>
is empty, otherwise :
<ul>
<li>
all the <tt>min_element</tt> and <tt>max_element</tt> variants perform
exactly<tt>(n-1)</tt> comparisons,</li>
<li>
<tt>minmax_element</tt> , <tt>first_min_first_max_element</tt>, and <tt>last_min_last_max_element</tt>
perform at most <tt>3(n/2)-1</tt> comparisons if <tt>n</tt> is even and
non-zero, and at most <tt>3(n/2)+1</tt> if <tt>n</tt> is odd,
<a href="#Note2">[2]</a></li>
<li>
<tt>first_min_last_max_element</tt>, and <tt>last_min_first_max_element</tt>
perform exactly <tt>3n/2-2</tt> comparisons if n is even and non-zero,
and at most <tt>3(n/2)</tt> if <tt>n</tt> is odd,
<a href="#Note1">[3]</a></li>
</ul>
where <tt>n</tt> is the number of elements in <tt>[first,last)</tt>.
</a>
<a name="example">
<h3>
Example</h3>
This example is included in the distribution in the examples section of
the library under
<a href="example/minmax_ex.cpp">minmax_ex.cpp</a>.
<pre>int main()
{
using namespace std;
boost::tuple&lt;int const&amp;, int const&amp;> result1 = boost::minmax(1, 0);
assert( result1.get<0>() == 0 );
assert( result1.get<1>() == 1 );
<a href="http://www.sgi.com/tech/stl/List.html">list</a>&lt;int> L;
<a href="http://www.sgi.com/tech/stl/generate_n.html">generate_n</a>(<a href="http://www.sgi.com/tech/stl/front_insert_iterator.html">front_inserter</a>(L), 1000, rand);
typedef list&lt;int>::const_iterator iterator;
pair&lt; iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end());
cout &lt;&lt; "The smallest element is " &lt;&lt; *(result2.first) &lt;&lt; endl;
cout &lt;&lt; "The largest element is " &lt;&lt; *(result2.second) &lt;&lt; endl;
assert( result2.first == std::min_element(L.begin(), L.end());
assert( result2.second == std::max_element(L.begin(), L.end());
}</pre>
</a>
<a name="notes">
<h3>
Notes</h3>
<a NAME="Note1"></a><a href="#Note1">[1]</a> We do not support
idioms such as <tt><a href="../../tuple/doc/tuple_users_guide.html#tiers">tie</a>(a,b)=minmax(a,b)</tt>
to order two elements <tt>a</tt>, <tt>b</tt>, although this would have
the desired effect if we returned a reference instead of a constant
reference. The reason is that two unnecessary assignments are
performed if a and b are in order. It is better to stick to <tt>if (b&lt;a)
swap(a,b)</tt> to achieve that effect.
<p><a NAME="Note2"></a><a href="#Note2">[2]</a> These algorithms always
perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
the number of comparisons in any case (Cormen, Leiserson, Rivest: "Introduction
to Algorithms", section 9.1, Exercise 9.1-). The algorithms essentially compare
the elements in pairs, performing 1 comparison for the first two elements,
then 3 comparisons for each remaining pair of elements (one to order the
elements and one for updating each the minimum and and the maximum). When
the number of elements is odd, the last one needs to be compared to the
current minimum and also to the current maximum. In addition, for <tt>minmax</tt>,
in cases where equality of the two members in the pair could occur, and
the update stores the second, we save the first to check at the end if
the update should have stored the first (in case of equality). It's hard
to predict if the last comparison is performed or not, hence the at most
in both cases.
<p><a NAME="Note3"></a><a href="#Note3">[3]</a> These algorithms always
perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
the number of comparisons in any case. The method is the same as in note
<a href="#Note2">[2]</a>
above, and like above, when the number of elements is odd, the last one
needs to be compared to the current minimum and also to the current maximum.
We can avoid the latter comparison if the former is successful, hence the
<i>at
most</i> instead of <i>exactly</i> in the odd case.
</a>
<a name="rationale">
<h3>
<b>Rationale:</b></h3>
<a name="two_headers">
<h4><b>Why not a single header <tt>&amp;boost/algorithm/minmax.hpp></tt>?</b></h4>
<p>This was the design originally proposed and approved in the formal
review. As the need for Boost.tuple became clear (due to the limitations
of <tt>std::pair</tt>), it became also annoying to require another
library for <tt>minmax_element</tt> which does not need it. Hence the
separation into two header files.</p>
<a name="no-fix">
<h4><b>Your minmax suffers from the same problems as std::min and
std::max.</b></h4>
<p>I am aware of the problems with std::min and
std::max, and all the debate that has been going on (please consult
<a href="http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/alexandr.htm">Alexandrescu's paper</a> and the links therein). But I don't see the purpose of this
library as fixing something that is part of the C++ standard. I humbly
think it's beyond the scope of this library. Rather, I am
following the way of the standard in simply providing one more function
of the same family. If someone else wants to fix std::min, their fix
would probably apply to boost::minmax as well.</p>
</a>
<h4><b>Why no <tt>min/max_element_if</tt>?</b></h4>
<p>In a first version of the library, I proposed <tt>_if</tt> versions of
all the algorithms (well, not all, because that would be too much).
However, there is simply no reason to do so, and all the versions I had
were just as fast implemented using the excellent
<tt>&lt;boost/iterator_adaptors.hpp></tt> library. Namely, a call to
<tt>min_element_if(first, last, pred)</tt> would be just as well
implemented by:
<pre>
// equivalent to min_element_if(first, last, pred)
min_element(boost::make_filter_iterator(first, last, pred),
boost::make_filter_iterator(last, last, pred));
</pre>
Arguably, the <tt>min_element_if</tt> version is somewhat shorter, but
the overhead of iterator adaptors is not large, and they get rid of a
lot of code (think of all the combinations between first/last and
doubling them with _if variants!).</p>
<h4><b>Discussion: about std::max_element</b></h4>
<p>This rationale is somewhat historical, but explains why there are all
these <tt>first/last_min/max_element</tt> functions.</p>
<p>The C++ standard mandates that <tt>std::min_element</tt> and <tt>std::max_element</tt>
return the first instance of the smallest and largest elements (as opposed
to, say, the last). This arbitrary choice has some consistency: In the
case of v of type vector&lt;int>, for instance, it is true that <tt>std::min_element(v.begin(),v.end(),std::less&lt;int>())
== std::max_element(v.begin(),v.end(),std::greater&lt;int>())</tt>.
<p>There is of course nothing wrong with this: it's simply a matter of
choice. Yet another way to specify min_element and max_element is to define
them as the first and the last elements if the range was stably sorted.
(The <i>stable</i> sort is necessary to disambiguate between iterators
that have the same value.) In that case, min should return the first instance
and max should return the last. Then, both functions are related by
<tt>reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less&lt;int>()))
==
std::last_max_element(v.rbegin(),v.rend(),std::greater&lt;int>())</tt>.
This definition is subtly different from the previous one.</p>
<p>The definition problem surfaces when one tries to design a minmax_element,
using the procedure proposed in (Cormen, Leiserson, Rivest: "Introduction
to Algorithms", section 9.1). It <i>should</i> be possible to derive an
algorithm using only <tt>3n/2</tt> comparisons if <tt>[first,last) </tt>has
<tt>n</tt>
elements, but if one tries to write a function called <tt>first_min_first_max_element()</tt>
which returns both <tt>std::min_element</tt> and <tt>std::max_element</tt>
in a pair, the trivial implementation does not work. The problem, rather
subtly, is about equal elements: I had to think for a while to find a
way to perform only three
comparisons per pair and return the first min and first max elements.
For a long time, it seemed any
attempts at doing so would consume four comparisons per pair in the worst
case. This implementation achieves three.</p>
<p>It is not possible (or even desirable) to change the meaning of
<tt>max_element</tt>,
but it is still beneficial to provide a function called <tt>minmax_element</tt>,
which returns a pair of <tt>min_element</tt> and <tt>max_element</tt>.
Although it is easy enough to call <tt>min_element</tt> and <tt>max_element</tt>,
this performs
<tt>2(n-1)</tt> comparisons, and necessitates <b>two</b>
passes over the input. In contrast,
<tt>minmax_element</tt> will perform
the fewer comparisons and perform a <b>single</b> pass over the input.
The savings can be significant when the iterator type is not a raw pointer,
or even is just a model of the InputIterator concept (although in that
case the interface would have to be
changed, as the return type could not be copied, so one could e.g.
return a value).</p>
<p>In order to benefit from all the variants of the algorithm, I propose
to introduce both <tt>first_min_element</tt> and <tt>last_min_element</tt>,
and their counterparts <tt>first_max_element</tt> and <tt>last_max_element</tt>.
Then I also propose all the variants algorithms: <tt>first_min_last_max_element</tt>
and <tt>last_min_first_max_element</tt>, which perform only at most <tt>3n/2</tt>
comparisons, and only a single pass on the input. In fact, it can be proven
that computing minmax requires at least <tt>3(n/2)-2</tt> comparisons in
any instance of the problem (Cormen, Leiserson, Rivest, 2nd edition, section
9.1). The implementation I give does not perform unnecessary comparisons
(whose result could have been computed by transitivity from previous
comparisons).</p>
<p>It appears that <tt>first_min_last_max_element</tt> may be just a tad
slower than
<tt>first_min_element</tt> alone, still much less than <tt>first_min_element</tt>
and
<tt>last_max_element</tt> called separately. <a href="#Note2">[2]</a>
<h4><b>Why algorithms and not accumulators?</b></h4>
<p>The minmax algorithms are useful in computing the extent of a range.
In computer graphics, we need a bounding box of a set of objects.
In that case the need for a single pass is even more stringent
as all three directions must be done at once. Food for thoughts: there
is matter for a nice generic programming library with stackable <tt>update_min</tt>
and <tt>update_max</tt> function objects which store a reference to the
<tt>min_result</tt>and
<tt>max_result</tt> variables, in conjunction with the <tt>for_each</tt>
algorithm).</p>
<p>I believe many standard sequential algorithms could be reformulated
with accumulators (and many others, such as in statistics, expectation /
variance / etc.). It seems that there is room for another library, but I
do not see it competing with minmax, rather extending several algorithms
(including minmax) to the accumulator framework. However, I felt it is
beyond the scope of this library to provide such accumulators.</p>
<a NAME="no-policy">
<h4><b>This first/last is a perfect application for a policy-based
design.</b></h4>
<p>True, and I could have gone that way, with the default policy for
<tt>min_element</tt> and <tt>max_element</tt> to pick the first
occurence of the result. This would have thinned the number of
combinations of the minmax_element variants. But it would also have
meant to change the interface of <tt>boost::minmax_element</tt>.
One of the goals of the <tt>minmax_element</tt> algorithm is its
eventual addition to the C++ standard, in connection with
<tt>std::min_element</tt> and <tt>std::max_element</tt>
(and I feel that it would be quite natural
given the shortness of the implementation, and the not quite trivial
detail which is needed to get it right). So changing the interface by
adding policies would have meant unfortunately to depart from the
standard and created an obstacle towards that goal. Besides, the code
remains rather readable and simple without policies. So I am quite happy
to keep it like this.
</p></a>
</a>
<a name="perf">
<a href="doc/minmax_benchs.html"><h3><b>About performance</b></h3></a>
</a>
<a name="acks">
<h3>
Acknowledgements</h3>
My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>)
who had <tt>minmax_element</tt> as an assignment helped clarify the issues,
and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>.
The identification of the issue surrounding <tt>max_element</tt> is solely
my own.
<p>One <tt>minmax_element</tt> implementation, which performs <tt>3(n/2)+O(log
n)</tt> comparisons on the average when the elements are <tt>random_shuffle</tt>d,
was suggested by my student Marc Glisse. The current one, which performs
<tt>3(n/2)+1</tt>
comparisons in the worst case, was suggested by John Iacono.<p>
<p>Finally, Matthew Wilson and Jeremy Siek contributed pre-review
comments, while Gennadiy Rozental, John Maddock, Craig Henderson, Gary
Powell participated in the review of the library, managed by Thomas
Witt. In particular, Gennadiy suggested a factorization of the code;
while I haven't followed it all the way, his suggestions do make the
code more readable and still work with older compilers.
Late after the review, as I finally scrounged to add the library for a
release, Eric Niebler noted the bad behavior of <tt>std::pair</tt> for
<tt>minmax</tt> and suggested to use Boost.tuple instead.
All my thanks for the excellent advice and reviews from all.
<h3>
See also</h3>
<tt><a href="http://www.sgi.com/tech/stl/min.html">min</a></tt>, <tt><a href="http://www.sgi.com/tech/stl/max.html">max</a></tt>,
<tt><a href="http://www.sgi.com/tech/stl/min_element.html">min_element</a></tt>,
<tt><a href="http://www.sgi.com/tech/stl/max_element.html">max_element</a></tt>,
<tt><a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
Comparable</a></tt>,
<tt><a href="http://www.sgi.com/tech/stl/sort.html">sort</a></tt>,
<tt><a href="http://www.sgi.com/tech/stl/nth_element.html">nth_element</a></tt>
.
<hr SIZE="6">
<br>Last modified 2004-07-01
<p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute;
Br&ouml;nnimann, Polytechnic University, 2002--2004.
Use, modification, and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
</font></font>
</body>
</html>

20
minmax/test/Jamfile.v2 Normal file
View File

@ -0,0 +1,20 @@
# Boost.Minmax Library test Jamfile
#
# Copyright (C) 2002--2004, Herve Bronnimann
#
# Use, modification, and distribution is subject to the Boost Software
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
import testing ;
{
test-suite algorithm/minmax:
: [ run minmax_element_test.cpp
: : : : minmax_element ]
[ run minmax_test.cpp
: : : : minmax ]
;
}

View File

@ -0,0 +1,241 @@
// (C) Copyright Herve Bronnimann 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <utility>
#include <functional>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <vector>
#include <list>
#include <set>
#include <cstdlib>
#include <boost/config.hpp> /* prevents some nasty warns in MSVC */
#include <boost/algorithm/minmax_element.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
#include <boost/iterator/reverse_iterator.hpp>
class custom {
int m_x;
friend bool operator<(custom const& x, custom const& y);
public:
explicit custom(int x = 0) : m_x(x) {}
custom(custom const& y) : m_x(y.m_x) {}
custom operator+(custom const& y) const { return custom(m_x+y.m_x); }
custom& operator+=(custom const& y) { m_x += y.m_x; return *this; }
};
bool operator< (custom const& x, custom const& y)
{
return x.m_x < y.m_x;
}
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(custom)
namespace std {
template <>
struct iterator_traits<int*> {
typedef random_access_iterator_tag iterator_category;
typedef int value_type;
typedef ptrdiff_t difference_type;
typedef value_type* pointer;
typedef value_type& reference;
};
template <>
struct iterator_traits<custom*> {
typedef random_access_iterator_tag iterator_category;
typedef custom value_type;
typedef ptrdiff_t difference_type;
typedef value_type* pointer;
typedef value_type& reference;
};
}
template <class T1, class T2, class T3, class T4>
void tie(std::pair<T1, T2> p, T3& first, T4& second)
{
first = T3(p.first); second = T4(p.second);
}
template <class Value>
struct less_count : std::less<Value> {
typedef std::less<Value> Base;
less_count(less_count<Value> const& lc) : m_counter(lc.m_counter) {}
less_count(int& counter) : m_counter(counter) {}
bool operator()(Value const& a, Value const& b) const {
++m_counter;
return Base::operator()(a,b);
}
void reset() {
m_counter = 0;
}
private:
int& m_counter;
};
inline int opt_min_count(int n) {
return (n==0) ? 0 : n-1;
}
inline int opt_minmax_count(int n) {
if (n < 2) return 0;
if (n == 2) return 2;
return (n%2 == 0) ? 3*(n/2)-1 : 3*(n/2)+1;
}
inline int opt_boost_minmax_count(int n) {
if (n < 2) return 0;
if (n == 2) return 1;
return (n%2 == 0) ? 3*(n/2)-2 : 3*(n/2);
}
#define CHECK_EQUAL_ITERATORS( left, right, first ) \
BOOST_CHECK_EQUAL( std::distance( first, left ), std::distance( first, right ) )
template <class CIterator>
void test_minmax(CIterator first, CIterator last, int n)
{
using namespace boost;
typedef typename std::iterator_traits<CIterator>::value_type Value;
typedef boost::reverse_iterator<CIterator> RCIterator;
// assume that CIterator is BidirectionalIter
CIterator min, max;
RCIterator rfirst(last), rlast(first), rmin, rmax;
int counter = 0;
less_count<Value> lc(counter);
// standard extensions
// first version, operator<
tie( boost::minmax_element(first, last), min, max );
CHECK_EQUAL_ITERATORS( min, std::min_element(first, last), first );
CHECK_EQUAL_ITERATORS( max, std::max_element(first, last), first );
// second version, comp function object (keeps a counter!)
lc.reset();
tie( boost::minmax_element(first, last, lc), min, max );
BOOST_CHECK( counter <= opt_minmax_count(n) );
CHECK_EQUAL_ITERATORS( min, std::min_element(first, last, lc), first );
CHECK_EQUAL_ITERATORS( max, std::max_element(first, last, lc), first );
// boost extensions
// first version, operator<
CHECK_EQUAL_ITERATORS( boost::first_min_element(first, last), std::min_element(first, last), first );
rmin = RCIterator(boost::last_min_element(first, last));
rmin = (rmin == rfirst) ? rlast : --rmin;
CHECK_EQUAL_ITERATORS( rmin, std::min_element(rfirst, rlast), rfirst );
CHECK_EQUAL_ITERATORS( boost::first_max_element(first, last), std::max_element(first, last), first );
rmax = RCIterator(boost::last_max_element(first, last));
rmax = (rmax == rfirst) ? rlast : --rmax;
CHECK_EQUAL_ITERATORS( rmax, std::max_element(rfirst, rlast), rfirst );
tie( boost::first_min_last_max_element(first, last), min, max );
CHECK_EQUAL_ITERATORS( min, boost::first_min_element(first, last), first );
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last), first );
tie( boost::last_min_first_max_element(first, last), min, max );
CHECK_EQUAL_ITERATORS( min, boost::last_min_element(first, last), first );
CHECK_EQUAL_ITERATORS( max, boost::first_max_element(first, last), first );
tie( boost::last_min_last_max_element(first, last), min, max );
CHECK_EQUAL_ITERATORS( min, boost::last_min_element(first, last), first );
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last), first );
// second version, comp function object (keeps a counter!)
lc.reset();
min = boost::first_min_element(first, last, lc);
BOOST_CHECK( counter <= opt_min_count(n) );
CHECK_EQUAL_ITERATORS( min, std::min_element(first, last, lc), first );
lc.reset();
rmin = RCIterator(boost::last_min_element(first, last, lc));
rmin = (rmin == rfirst) ? rlast : --rmin;
BOOST_CHECK( counter <= opt_min_count(n) );
CHECK_EQUAL_ITERATORS( rmin, std::min_element(rfirst, rlast, lc), rfirst );
lc.reset();
max = boost::first_max_element(first, last, lc);
BOOST_CHECK( counter <= opt_min_count(n) );
CHECK_EQUAL_ITERATORS( max, std::max_element(first, last, lc), first );
lc.reset();
rmax = RCIterator(boost::last_max_element(first, last, lc));
rmax = (rmax == rfirst) ? rlast : --rmax;
BOOST_CHECK( counter <= opt_min_count(n) );
CHECK_EQUAL_ITERATORS( rmax, std::max_element(rfirst, rlast, lc), rfirst );
lc.reset();
tie( boost::first_min_last_max_element(first, last, lc), min, max );
BOOST_CHECK( counter <= opt_boost_minmax_count(n) );
CHECK_EQUAL_ITERATORS( min, boost::first_min_element(first, last, lc), first );
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last, lc), first );
lc.reset();
tie( boost::last_min_first_max_element(first, last, lc), min, max );
BOOST_CHECK( counter <= opt_boost_minmax_count(n) );
BOOST_CHECK( min == boost::last_min_element(first, last, lc) );
CHECK_EQUAL_ITERATORS( max, boost::first_max_element(first, last, lc), first );
lc.reset();
tie( boost::last_min_last_max_element(first, last, lc), min, max );
BOOST_CHECK( counter <= opt_minmax_count(n) );
CHECK_EQUAL_ITERATORS( min, boost::last_min_element(first, last, lc), first );
CHECK_EQUAL_ITERATORS( max, boost::last_max_element(first, last, lc), first );
}
template <class Container, class Iterator, class Value>
void test_container(Iterator first, Iterator last, int n,
Container* dummy = 0
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Value) )
{
Container c(first, last);
test_minmax(c.begin(), c.end(), n);
}
template <class Iterator>
void test_range(Iterator first, Iterator last, int n)
{
typedef typename std::iterator_traits<Iterator>::value_type Value;
// Test various containers with these values
test_container< std::vector<Value>, Iterator, Value >(first, last, n);
test_container< std::list<Value>, Iterator, Value >(first, last, n);
test_container< std::set<Value>, Iterator, Value >(first, last, n);
}
template <class Value>
void test(int n BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Value))
{
// Populate test vector with identical values
std::vector<Value> test_vector(n, Value(1));
typename std::vector<Value>::iterator first( test_vector.begin() );
typename std::vector<Value>::iterator last( test_vector.end() );
test_range(first, last, n);
// Populate test vector with two values
typename std::vector<Value>::iterator middle( first + n/2 );
std::fill(middle, last, Value(2));
test_range(first, last, n);
// Populate test vector with increasing values
std::accumulate(first, last, Value(0));
test_range(first, last, n);
// Populate test vector with decreasing values
std::reverse(first, last);
test_range(first, last, n);
// Populate test vector with random values
std::random_shuffle(first, last);
test_range(first, last, n);
}
int test_main( int argc, char* argv[] )
{
#ifndef BOOST_NO_STDC_NAMESPACE
using std::atoi;
#endif
int n = 100;
if (argc > 1) n = atoi(argv[1]);
test<int>(n);
test<custom>(n);
return 0;
}

View File

@ -0,0 +1,85 @@
// (C) Copyright Herve Bronnimann 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <utility>
#include <functional>
#include <boost/config.hpp>
#include <boost/algorithm/minmax.hpp>
#include <boost/test/included/test_exec_monitor.hpp>
class custom {
int m_x;
friend std::ostream& operator<<(std::ostream& str, custom const& x);
public:
explicit custom(int x = 0) : m_x(x) {}
custom(custom const& y) : m_x(y.m_x) {}
bool operator==(custom const& y) const { return m_x == y.m_x; }
bool operator<(custom const& y) const { return m_x < y.m_x; }
custom operator+(custom const& y) const { return custom(m_x+y.m_x); }
custom& operator+=(custom const& y) { m_x += y.m_x; return *this; }
};
std::ostream&
operator<<(std::ostream& str, custom const& x)
{
return str << x.m_x;
}
template <class Value>
struct less_count : std::less<Value> {
typedef std::less<Value> Base;
less_count(less_count<Value> const& lc) : m_counter(lc.m_counter) {}
less_count(int& counter) : m_counter(counter) {}
bool operator()(Value const& a, Value const& b) const {
++m_counter;
return Base::operator()(a,b);
}
void reset() {
m_counter = 0;
}
private:
int& m_counter;
};
using namespace boost;
template <class Value>
void test(BOOST_EXPLICIT_TEMPLATE_TYPE(Value))
{
Value zero(0), one(1);
int counter = 0;
less_count<Value> lc(counter);
// Test functionality
tuple<Value const&, Value const&> result1 = boost::minmax(zero, one);
BOOST_CHECK_EQUAL( get<0>(result1), zero );
BOOST_CHECK_EQUAL( get<1>(result1), one );
tuple<Value const&, Value const&> result2 = boost::minmax(one, zero);
BOOST_CHECK_EQUAL( get<0>(result2), zero );
BOOST_CHECK_EQUAL( get<1>(result2), one );
// Test functionality and number of comparisons
lc.reset();
tuple<Value const&, Value const&> result3 = boost::minmax(zero, one, lc );
BOOST_CHECK_EQUAL( get<0>(result3), zero );
BOOST_CHECK_EQUAL( get<1>(result3), one );
BOOST_CHECK_EQUAL( counter, 1 );
lc.reset();
tuple<Value const&, Value const&> result4 = boost::minmax(one, zero, lc );
BOOST_CHECK_EQUAL( get<0>(result4), zero );
BOOST_CHECK_EQUAL( get<1>(result4), one );
BOOST_CHECK_EQUAL( counter, 1);
}
int test_main( int , char* [] )
{
test<int>(); // ("builtin");
test<custom>(); // ("custom ");
return 0;
}

View File

@ -3,45 +3,46 @@
# Copyright Pavol Droba 2002-2003. Use, modification and
# distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# htt../..//www.boost.org/LICENSE_1_0.txt)
# http://www.boost.org/LICENSE_1_0.txt)
#
# See htt../..//www.boost.org for updates, documentation, and revision history.
# See http://www.boost.org for updates, documentation, and revision history.
project boost/libs/algorithm/string/doc ;
import toolset ;
toolset.using doxygen ;
doxygen reference
boostbook string_algo : string_algo.xml autodoc
:
<xsl:param>boost.root=../../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
doxygen autodoc
:
../../../../boost/algorithm/string.hpp
../../../../boost/algorithm/string_regex.hpp
[ glob ../../../../boost/algorithm/string.hpp ]
[ glob ../../../../boost/algorithm/string_regex.hpp ]
../../../../boost/algorithm/string/classification.hpp
../../../../boost/algorithm/string/iterator_range.hpp
../../../../boost/algorithm/string/sequence_traits.hpp
../../../../boost/algorithm/string/std_containers_traits.hpp
../../../../boost/algorithm/string/container_traits.hpp
../../../../boost/algorithm/string/concept.hpp
../../../../boost/algorithm/string/compare.hpp
../../../../boost/algorithm/string/constants.hpp
../../../../boost/algorithm/string/case_conv.hpp
../../../../boost/algorithm/string/find.hpp
../../../../boost/algorithm/string/finder.hpp
../../../../boost/algorithm/string/find_iterator.hpp
../../../../boost/algorithm/string/trim.hpp
../../../../boost/algorithm/string/predicate.hpp
../../../../boost/algorithm/string/split.hpp
../../../../boost/algorithm/string/iter_find.hpp
../../../../boost/algorithm/string/erase.hpp
../../../../boost/algorithm/string/replace.hpp
../../../../boost/algorithm/string/find_format.hpp
../../../../boost/algorithm/string/formatter.hpp
../../../../boost/algorithm/string/regex.hpp
../../../../boost/algorithm/string/regex_find_format.hpp
[ glob ../../../../boost/algorithm/string/classification.hpp ]
[ glob ../../../../boost/algorithm/string/iterator_range.hpp ]
[ glob ../../../../boost/algorithm/string/sequence_traits.hpp ]
[ glob ../../../../boost/algorithm/string/std_containers_traits.hpp ]
[ glob ../../../../boost/algorithm/string/concept.hpp ]
[ glob ../../../../boost/algorithm/string/compare.hpp ]
[ glob ../../../../boost/algorithm/string/constants.hpp ]
[ glob ../../../../boost/algorithm/string/case_conv.hpp ]
[ glob ../../../../boost/algorithm/string/find.hpp ]
[ glob ../../../../boost/algorithm/string/finder.hpp ]
[ glob ../../../../boost/algorithm/string/find_iterator.hpp ]
[ glob ../../../../boost/algorithm/string/trim.hpp ]
[ glob ../../../../boost/algorithm/string/predicate.hpp ]
[ glob ../../../../boost/algorithm/string/split.hpp ]
[ glob ../../../../boost/algorithm/string/iter_find.hpp ]
[ glob ../../../../boost/algorithm/string/erase.hpp ]
[ glob ../../../../boost/algorithm/string/join.hpp ]
[ glob ../../../../boost/algorithm/string/replace.hpp ]
[ glob ../../../../boost/algorithm/string/find_format.hpp ]
[ glob ../../../../boost/algorithm/string/formatter.hpp ]
[ glob ../../../../boost/algorithm/string/regex.hpp ]
[ glob ../../../../boost/algorithm/string/regex_find_format.hpp ]
:
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
<doxygen:param>EXTRACT_PRIVATE=NO
@ -52,10 +53,6 @@ doxygen reference
<doxygen:param>PREDEFINED="BOOST_STRING_TYPENAME=typename \"BOOST_STATIC_CONSTANT(type,var)=static const type var;\""
;
boostbook string_algo
:
string_algo.xml
;

View File

@ -1,11 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.concept" last-revision="$Date$">
<title>Concepts</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<using-namespace name="boost::algorithm"/>
<section>
<title>Definitions</title>
@ -75,9 +81,9 @@
</table>
<para>
Various algorithms need to perform a searching in a container and a Finder is a generalization of such
Various algorithms need to perform a search in a container and a Finder is a generalization of such
search operations that allows algorithms to abstract from searching. For instance, generic replace
algorithms can replace any part of the input, and the finder is used to select the desired one.
algorithms can replace any part of the input, and the Finder is used to select the desired one.
</para>
<para>
Note, that it is only required that the finder works with a particular iterator type. However,
@ -96,7 +102,7 @@
struct simple_finder
{
template&lt;typename ForwardIteratorT&gt;
boost::iterator_range&lt;ForwardIterator&gt; operator()(
boost::iterator_range&lt;ForwardIteratorT&gt; operator()(
ForwardIteratorT Begin,
ForwardIteratorT End )
{
@ -106,7 +112,7 @@ struct simple_finder
</programlisting>
</listitem>
<listitem>
Function Finder. Finder can be any function object. That means, an ordinary function with the
Function Finder. Finder can be any function object. That is, any ordinary function with the
required signature can be used as well. However, such a function can be used only for
a specific iterator type.
@ -166,7 +172,7 @@ boost::iterator_range&lt;std::string&gt; simple_finder(
<itemizedlist>
<listitem>
Formatter implemented as a class. This Formatter does not perform any formating and
returns repackaged match. <code>operator()</code>
returns the match, repackaged. <code>operator()</code>
is templated, so that the Formatter can be used on any Finder type.
<programlisting>

View File

@ -1,13 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.credits" last-revision="$Date$">
<title>Credits</title>
<section id="string_algo.ack">
<title>Acknowledgments</title>
<para>
Thanks for everybody who gave suggestions and comments. Especially to Thorsten Ottosen, Jeff Garland
and the other boost members who participated.
The author would like to thank everybody who gave suggestions and comments. Especially valuable
were the contributions of Thorsten Ottosen, Jeff Garland and the other boost members who participated
in the review process, namely David Abrahams, Daniel Frey, Beman Dawes, John Maddock, David B.Held, Pavel Vozenilek
and many other.
</para>
<para>
Additional thanks go to Stefan Slapeta and Toon Knapen, who have been very resourceful in solving various
portability issues.
</para>
</section>
</section>

View File

@ -1,175 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.design" last-revision="$Date$">
<title>Design Topics</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<section id="string_algo.iterator_range">
<title><code>iterator_range</code> class</title>
<using-namespace name="boost::algorithm"/>
<section id="string_algo.string">
<title>String Representation</title>
<para>
An <classname>iterator_range</classname> is an encapsulation of a pair of iterators that
delimit a sequence (or, a range). This concept is widely used by
sequence manipulating algorithms. Although being so useful, there no direct support
for it in the standard library (The closest thing is that some algorithms return a pair of iterators).
Instead all STL algorithms have two distinct parameters for beginning and end of a range. This design
is natural for implementation of generic algorithms, but it forbids to work with a range as a single value.
</para>
<para>
It is possible to encapsulate a range in <code>std::pair&lt;&gt;</code>, but
the <code>std::pair&lt;&gt;</code> is a too generic encapsulation, so it is not best match for a range.
For instance, it does not enforce that begin and end iterators are of the same type.
As the name suggest, this library works mainly with strings. However, in the context of this library,
a string is not restricted to any particular implementation (like <code>std::basic_string</code>),
rather it is a concept. This allows the algorithms in this library to be reused for any string type,
that satisfies the given requirements.
</para>
<para>
Naturally the range concept is heavily used also in this library. During the development of
the library, it was discovered, that there is a need for a reasonable encapsulation for it.
A core part of the library deals with substring searching algorithms. Any such an algorithm,
returns a range delimiting the result of the search. <code>std::pair&lt;&gt;</code> was considered as
unsuitable. Therefore the <code>iterator_range</code> was defined.
<emphasis role="bold">Definition:</emphasis> A string is a
<ulink url="../../libs/range/index.html">range</ulink> of characters accessible in sequential
ordered fashion. Character is any value type with "cheap" copying and assignment.
</para>
<para>
The intention of the <code>iterator_range</code> class is to manage a range as a single value and provide
a basic interface for common operations. Its interface is similar to that of container.
In addition of <code>begin()</code>
and <code>end()</code> accessors, it has member functions for checking if the range is empty,
or to determine the size of the range. It has also a set of member typedefs that extract
type information from the encapsulated iterators. As such, the interface is compatible with
the <link linkend="string_algo.container_traits">container traits</link> requirements so
it is possible to use this class as a parameter to many algorithms in this library.
First requirement of string-type is that it must accessible using
<ulink url="../../libs/range/index.html">Boost.Range</ulink>. This facility allows to access
the elements inside the string in a uniform iterator-based fashion.
This is sufficient for our library
</para>
<para>
Second requirement defines the way in which the characters are stored in the string. Algorithms in
this library work with an assumption that copying a character is cheaper then allocating extra
storage to cache results. This is a natural assumption for common character types. Algorithms will
work even if this requirement is not satisfied, however at the cost of performance degradation.
<para>
</para>
In addition some algorithms have additional requirements on the string-type. Particularly, it is required
that an algorithm can create a new string of the given type. In this case, it is required that
the type satisfies the sequence (Std &sect;23.1.1) requirements.
</para>
<para>
In the reference and also in the code, requirement on the string type is designated by the name of
template argument. <code>RangeT</code> means that the basic range requirements must hold.
<code>SequenceT</code> designates extended sequence requirements.
</para>
</section>
<section id="string_algo.container_traits">
<title>Container Traits</title>
<para>
Container traits provide uniform access to different types of containers.
This functionality allows to write generic algorithms which work with several
different kinds of containers. For this library it means, that, for instance,
many algorithms work with <code>std::string</code> as well as with <code>char[]</code>.
</para>
<para>
The following container types are supported:
<itemizedlist>
<listitem>
Standard containers
</listitem>
<listitem>
Built-in arrays (like int[])
</listitem>
<listitem>
Null terminated strings (this includes char[],wchar_t[],char*, and wchar_t*)
</listitem>
<listitem>
std::pair&lt;iterator,iterator&gt;
</listitem>
</itemizedlist>
</para>
<para>
Container traits support a subset of container concept (Std &sect;23.1). This subset
can be described as an input container concept, e.g. a container with an immutable content.
Its definition can be found in the header <headername>boost/string_algo/container_traits.hpp</headername>.
</para>
<para>
In the table C denotes a container and c is an object of C.
</para>
<table>
<title>Container Traits</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Name</entry>
<entry>Standard container equivalent</entry>
<entry>Description</entry>
</row>Maeterlinck
</thead>
<tbody>
<row>
<entry><classname>container_value_type&lt;C&gt;</classname>::type</entry>
<entry><code>C::value_type</code></entry>
<entry>Type of contained values</entry>
</row>
<row>
<entry><classname>container_difference_type&lt;C&gt;</classname>::type</entry>
<entry><code>C::difference_type</code></entry>
<entry>difference type of the container</entry>
</row>
<row>
<entry><classname>container_iterator&lt;C&gt;</classname>::type</entry>
<entry><code>C::iterator</code></entry>
<entry>iterator type of the container</entry>
</row>
<row>
<entry><classname>container_const_iterator&lt;C&gt;</classname>::type</entry>
<entry><code>C::const_iterator</code></entry>
<entry>const_iterator type of the container</entry>
</row>
<row>
<entry><classname>container_result_iterator&lt;C&gt;</classname>::type</entry>
<entry></entry>
<entry>
result_iterator type of the container. This type maps to <code>C::iterator</code>
for mutable container and <code>C::const_iterator</code> for const containers.
</entry>
</row>
<row>
<entry><functionname>begin(c)</functionname></entry>
<entry><code>c.begin()</code></entry>
<entry>
Gets the iterator pointing to the start of the container.
</entry>
</row>
<row>
<entry><functionname>end(c)</functionname></entry>
<entry><code>c.end()</code></entry>
<entry>
Gets the iterator pointing to the end of the container.
</entry>
</row>
<row>
<entry><functionname>size(c)</functionname></entry>
<entry><code>c.size()</code></entry>
<entry>
Gets the size of the container.
</entry>
</row>
<row>
<entry><functionname>empty(c)</functionname></entry>
<entry><code>c.empty()</code></entry>
<entry>
Checks if the container is empty.
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
The container traits are only a temporary part of this library. There is a plan for a separate submission
of a container_traits library to Boost. Once it gets accepted, String Algorithm Library will be adopted to
use it and the internal implementation will be deprecated.
</para>
</section>
<section id="string_algo.sequence_traits">
<title>Sequence Traits</title>
<para>
Major difference between <code>std::list</code> and <code>std::vector</code> is not in the interfaces
they provide, rather in the inner details of the class and the way how it performs
various operation. The problem is that it is not possible to infer this difference from the
The major difference between <code>std::list</code> and <code>std::vector</code> is not in the interfaces
they provide, but rather in the inner details of the class and the way how it performs
various operations. The problem is that it is not possible to infer this difference from the
definitions of classes without some special mechanism.
However some algorithms can run significantly faster with the knowledge of the properties
However, some algorithms can run significantly faster with the knowledge of the properties
of a particular container.
</para>
<para>
Sequence traits allows one to specify additional properties of a sequence container (see Std.&sect;32.2).
Sequence traits allow one to specify additional properties of a sequence container (see Std.&sect;32.2).
These properties are then used by algorithms to select optimized handling for some operations.
The sequence traits are declared in the header
<headername>boost/string_algo/sequence_traits.hpp</headername>.
<headername>boost/algorithm/string/sequence_traits.hpp</headername>.
</para>
<para>
@ -186,11 +84,11 @@
</thead>
<tbody>
<row>
<entry><classname>sequence_has_native_replace&lt;C&gt;</classname>::value</entry>
<entry><classname>has_native_replace&lt;C&gt;</classname>::value</entry>
<entry>Specifies that the sequence has std::string like replace method</entry>
</row>
<row>
<entry><classname>sequence_has_stable_iterators&lt;C&gt;</classname>::value</entry>
<entry><classname>has_stable_iterators&lt;C&gt;</classname>::value</entry>
<entry>
Specifies that the sequence has stable iterators. It means,
that operations like <code>insert</code>/<code>erase</code>/<code>replace</code>
@ -198,14 +96,14 @@
</entry>
</row>
<row>
<entry><classname>sequence_has_const_time_insert&lt;C&gt;</classname>::value</entry>
<entry><classname>has_const_time_insert&lt;C&gt;</classname>::value</entry>
<entry>
Specifies that the insert method of the sequence has
constant time complexity.
</entry>
</row>
<row>
<entry><classname>sequence_has_const_time_erase&lt;C&gt;</classname>::value</entry>
<entry><classname>has_const_time_erase&lt;C&gt;</classname>::value</entry>
<entry>
Specifies that the erase method of the sequence has constant time complexity
</entry>
@ -243,7 +141,7 @@
Currently the library contains only naive implementation of find algorithms with complexity
O(n * m) where n is the size of the input sequence and m is the size of the search sequence.
There are algorithms with complexity O(n), but for smaller sequence a constant overhead is
rather big. For small m &lt;&lt; n (m magnitued smaller than n) the current implementation
rather big. For small m &lt;&lt; n (m by magnitude smaller than n) the current implementation
provides acceptable efficiency.
Even the C++ standard defines the required complexity for search algorithm as O(n * m).
It is possible that a future version of library will also contain algorithms with linear
@ -263,19 +161,63 @@
</para>
<para>
As usual, the implementation of the lower layer is designed to work with a generic sequence while
taking an advantage of specific features if possible
taking advantage of specific features if possible
(by using <link linkend="string_algo.sequence_traits">Sequence traits</link>)
</para>
</section>
<section id="string_algo.split">
<title>Split Algorithms</title>
<title>Find Iterators &amp; Split Algorithms</title>
<para>
Split algorithms are a logical extension of <link linkend="string_algo.find">find facility</link>.
Instead of searching for one match, the whole input is searched. The result of the search is then used
to partition the input. It depends on the algorithms which parts are returned as the result of
split operations. It can be the matching parts (<functionname>find_all()</functionname>) of the parts in
between (<functionname>split()</functionname>).
Find iterators are a logical extension of the <link linkend="string_algo.find">find facility</link>.
Instead of searching for one match, the whole input can be iteratively searched for multiple matches.
The result of the search is then used to partition the input. It depends on the algorithms which parts
are returned as the result. They can be the matching parts (<classname>find_iterator</classname>) of the parts in
between (<classname>split_iterator</classname>).
</para>
<para>
In addition the split algorithms like <functionname>find_all()</functionname> and <functionname>split()</functionname>
can simplify the common operations. They use a find iterator to search the whole input and copy the
matches they found into the supplied container.
</para>
</section>
<section id="string_algo.exception">
<title>Exception Safety</title>
<para>
The library requires that all operations on types used as template
or function arguments provide the <emphasis>basic exception-safety guarantee</emphasis>.
In turn, all functions and algorithms in this library, except where stated
otherwise, will provide the <emphasis>basic exception-safety guarantee</emphasis>.
In other words:
The library maintains its invariants and does not leak resources in
the face of exceptions. Some library operations give stronger
guarantees, which are documented on an individual basis.
</para>
<para>
Some functions can provide the <emphasis>strong exception-safety guarantee</emphasis>.
That means that following statements are true:
<itemizedlist>
<listitem>
If an exception is thrown, there are no effects other than those
of the function
</listitem>
<listitem>
If an exception is thrown other than by the function, there are no effects
</listitem>
</itemizedlist>
This guarantee can be provided under the condition that the operations
on the types used for arguments for these functions either
provide the strong exception guarantee or do not alter the global state .
</para>
<para>
In the reference, under the term <emphasis>strong exception-safety guarantee</emphasis>, we mean the
guarantee as defined above.
</para>
<para>
For more information about the exception safety topics, follow this
<ulink url="http://www.boost.org/more/generic_exception_safety.html">link</ulink>
</para>
</section>
</section>

View File

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.env" last-revision="$Date$">
<title>Environment</title>
<section>
@ -8,8 +14,8 @@
<para>
The whole library is provided in headers. Regex variants of some algorithms,
however, are dependent on the <libraryname>Boost.Regex</libraryname> library. All such algorithms are
separated in <headername>boost/string_algo/regex.hpp</headername>.
If this header is used, an application must be linked with the <libraryname>Boost.Regex</libraryname>
separated in <headername>boost/algorithm/string_regex.hpp</headername>.
If this header is used, the application must be linked with the <libraryname>Boost.Regex</libraryname>
library.
</para>
</section>
@ -17,7 +23,7 @@
<section>
<title>Examples</title>
<para>
Examples showing the basic usage of the library can be found in the libs/string_algo/example
Examples showing the basic usage of the library can be found in the libs/algorithm/string/example
directory. There is a separate file for the each part of the library. Please follow the boost
build guidelines to build examples using the bjam. To successfully build regex examples
the <libraryname>Boost.Regex</libraryname> library is required.
@ -27,7 +33,7 @@
<section>
<title>Tests</title>
<para>
A full set of test cases for the library is located in the libs/string_algo/test directory.
A full set of test cases for the library is located in the libs/algorithm/string/test directory.
The test cases can be executed using the boost build system. For the tests of regular
expression variants of algorithms, the <libraryname>Boost.Regex</libraryname> library is required.
</para>
@ -44,12 +50,16 @@
<listitem>GCC 3.2</listitem>
<listitem>GCC 3.3.1</listitem>
</itemizedlist>
See <ulink url="http://boost.sourceforge.net/regression-logs/">Boost regression tables</ulink>
for additional info for a particular compiler.
</para>
<para>
There are known limitation on platforms not supporting partial template specialization.
Library depends on correctly implemented std::iterator_traits class. If a standard library provided
with compiler is broken, the String Algorithm Library cannot function properly. Usually it implies
that primitive pointer iterators are not working with the library functions.
Library depends on correctly implemented <code>std::iterator_traits</code> class.
If a standard library provided with compiler is broken, the String Algorithm Library
cannot function properly. Usually it implies that primitive pointer iterators are not
working with the library functions.
</para>
</section>
</section>

View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title> Concepts and External Concepts </title><meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1"></head> <body><table ><tr ><td ><img src="../../../../boost.png" width="100%" border="0"></td><td ><h1 >Concepts and External Concepts</h1></td></tr></table><p >Generic programming in C++ is characterized by the use of function and class templates where
the template parameter(s) must satisfy certain requirements.Often these
requirements are so important that we give them a name: we call
such a set of type requirements a <b>concept</b>. We say that a type <i>
conforms to a concept</i> or that it <i>is a model of a concept</i> if it
satisfies all of those requirements. The concept can be specified as a set
of member functions with well-defined semantics
and a set of nested typedefs with well-defined properties.</p><p >Often it much more flexible to provide free-standing functions and typedefs
which provides the exact same semantics (but a different syntax) as
specified
by the concept. This allows generic code to treat different types <i> as if
</i> they fulfilled the concept. In this case we say that the concept has
been <b> externalized </b> or that the new requirements constitutes an <b>external
concept </b>. We say that a type <i> conforms to an external concept </i>
or that it <i> is a model of an external concept </i>. A concept may exist
without a corresponding external concept and conversely.</p><p >Whenever a concept specifies a member function, the corresponding external
concept
must specify a free-standing function of the same name, same return type and
the same argument list except there is an extra first argument which must
be of the type (or a reference to that type) that is to fulfill the external
concept. If the corresonding member function has any cv-qulifiers, the
first argument must have the same cv-qualifiers. Whenever a concept
specifies a nested typedef, the corresponding external concept
specifies a <b>type-generator</b>, that is, a type with a nested typedef
named <code>type</code>. The type-generator has the name as the nested typedef with
<code>_of</code> appended.
The converse relationship of an external concept and its corresponding concept
also holds.</p><p ><b ><i >Example:</i></b></p><p >A type <code>T</code> fulfills the FooConcept if it
has the follwing public members:</p><code> void T::foo( int ) const; <br>
int T::bar(); <br>
typedef <i>implementation defined </i> foo_type;</code><p >The corresponding external concept is the ExternalFooConcept.</p><p >A type <code>T</code> fullfills the ExternalFooConcept if these
free-standing functions and type-generators exists:</p><code>void foo( const T&, int ); <br>
int bar( T& ); <br>
foo_type_of< T >::type;</code> <br> <br><hr size="1" ><h3 >Literature</h3><ul ><li > <a href="http://www.boost.org/more/generic_programming.html#type_generator" target="_self" >Type Generators</a> </li><li > <a href="http://www.boost.org/more/generic_programming.html#concept" target="_self" >Concepts</a> </li><li > <a href="http://www.sgi.com/tech/stl/stl_introduction.html" target="_self" >Concepts and SGI STL</a> </li></ul><hr size="1" ><p >&copy; Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk).
<br>Use, modification and distribution is subject to the Boost
Software License, Version 1.0. (See accompanying file
<code class="filename">LICENSE_1_0.txt</code> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</br>
</p>
<!-- Copyright Dezide Aps 2003-2004 -->

View File

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.intro" last-revision="$Date$">
<title>Introduction</title>
@ -13,28 +20,30 @@
</para>
<para>
The implementation is not restricted to work with a particular container
(like a <code>std::basic_string</code>), rather it is as generic as
(like <code>std::basic_string</code>), rather it is as generic as
possible. This generalization is not compromising the performance since
algorithms are using container specific features when it means a performance
gain.
</para>
<para>
<emphasis role="bold">
Important note: In this documentation we use term <emphasis>string</emphasis> to
designate a sequence of <emphasis>characters</emphasis> stored in an arbitrary container.
A <emphasis>string</emphasis> is not restricted to <code>std::basic_string</code> and
<emphasis>character</emphasis> does not have to be <code>char</code> or <code>wchar_t</code>,
although these are most common candidates.
</emphasis>
Consult the <link linkend="string_algo.design">design chapter</link> to see precise specification of
supported string types.
</para>
<para>
The library has layered structure to simplify the usage without sacrificing the
generalization.
The easy-to-use interface, defined in the namespace <code>boost</code>, represents the first layer.
Algorithms and classes defined here do not offer a lot of customization opportunities
rather they are provided in more different variants, so a user can chose the
one that suits her needs.
The second layer, defined in the namespace <code>boost::string_algo</code>, on the
other hand, is generic. Basically it contains the same set of algorithms as the first layer,
but the interface is more flexible and allows more customization, but it is harder to use.
The first layer is implemented as set of wrappers around the second layer.
The library interface functions and classes are defined in namespace <code>boost::algorithm</code>, and
they are lifted into namespace <code>boost</code> via using declaration.
</para>
<para>
The documentation is divided into several sections. For a quick start read the
<link linkend="string_algo.usage">Usage</link> section.
<link linkend="string_algo.usage">Usage</link> section followed by
<link linkend="string_algo.quickref">Quick Reference</link>.
<link linkend="string_algo.design">The Design Topics</link>,
<link linkend="string_algo.concept">Concepts</link> and <link linkend="string_algo.rationale">Rationale</link>
provide some explanation about the library design and structure an explain how it should be used.

744
string/doc/quickref.xml Normal file
View File

@ -0,0 +1,744 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.quickref" last-revision="$Date$">
<title>Quick Reference</title>
<using-namespace name="boost"/>
<using-namespace name="boost::algorithm"/>
<section>
<title>Algorithms</title>
<table>
<title>Case Conversion</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>to_upper</code></entry>
<entry>Convert a string to upper case</entry>
<entry>
<functionname>to_upper_copy()</functionname>
<sbr/>
<functionname>to_upper()</functionname>
</entry>
</row>
<row>
<entry><code>to_lower</code></entry>
<entry>Convert a string to lower case</entry>
<entry>
<functionname>to_lower_copy()</functionname>
<sbr/>
<functionname>to_lower()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Trimming</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>trim_left</code></entry>
<entry>Remove leading spaces from a string</entry>
<entry>
<functionname>trim_left_copy_if()</functionname>
<sbr/>
<functionname>trim_left_if()</functionname>
<sbr/>
<functionname>trim_left_copy()</functionname>
<sbr/>
<functionname>trim_left()</functionname>
</entry>
</row>
<row>
<entry><code>trim_right</code></entry>
<entry>Remove trailing spaces from a string</entry>
<entry>
<functionname>trim_right_copy_if()</functionname>
<sbr/>
<functionname>trim_right_if()</functionname>
<sbr/>
<functionname>trim_right_copy()</functionname>
<sbr/>
<functionname>trim_right()</functionname>
</entry>
</row>
<row>
<entry><code>trim</code></entry>
<entry>Remove leading and trailing spaces from a string</entry>
<entry>
<functionname>trim_copy_if()</functionname>
<sbr/>
<functionname>trim_if()</functionname>
<sbr/>
<functionname>trim_copy()</functionname>
<sbr/>
<functionname>trim()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Predicates</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>starts_with</code></entry>
<entry>Check if a string is a prefix of the other one</entry>
<entry>
<functionname>starts_with()</functionname>
<sbr/>
<functionname>istarts_with()</functionname>
</entry>
</row>
<row>
<entry><code>ends_with</code></entry>
<entry>Check if a string is a suffix of the other one</entry>
<entry>
<functionname>ends_with()</functionname>
<sbr/>
<functionname>iends_with()</functionname>
</entry>
</row>
<row>
<entry><code>contains</code></entry>
<entry>Check if a string is contained of the other one</entry>
<entry>
<functionname>contains()</functionname>
<sbr/>
<functionname>icontains()</functionname>
</entry>
</row>
<row>
<entry><code>equals</code></entry>
<entry>Check if two strings are equal</entry>
<entry>
<functionname>equals()</functionname>
<sbr/>
<functionname>iequals()</functionname>
</entry>
</row>
<row>
<entry><code>lexicographical_compare</code></entry>
<entry>Check if a string is lexicographically less then another one</entry>
<entry>
<functionname>lexicographical_compare()</functionname>
<sbr/>
<functionname>ilexicographical_compare()</functionname>
</entry>
</row>
<row>
<entry><code>all</code></entry>
<entry>Check if all elements of a string satisfy the given predicate</entry>
<entry>
<functionname>all()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Find algorithms</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry>find_first</entry>
<entry>Find the first occurrence of a string in the input</entry>
<entry>
<functionname>find_first()</functionname>
<sbr/>
<functionname>ifind_first()</functionname>
</entry>
</row>
<row>
<entry>find_last</entry>
<entry>Find the last occurrence of a string in the input</entry>
<entry>
<functionname>find_last()</functionname>
<sbr/>
<functionname>ifind_last()</functionname>
</entry>
</row>
<row>
<entry>find_nth</entry>
<entry>Find the nth (zero-indexed) occurrence of a string in the input</entry>
<entry>
<functionname>find_nth()</functionname>
<sbr/>
<functionname>ifind_nth()</functionname>
</entry>
</row>
<row>
<entry>find_head</entry>
<entry>Retrieve the head of a string</entry>
<entry>
<functionname>find_head()</functionname>
</entry>
</row>
<row>
<entry>find_tail</entry>
<entry>Retrieve the tail of a string</entry>
<entry>
<functionname>find_tail()</functionname>
</entry>
</row>
<row>
<entry>find_token</entry>
<entry>Find first matching token in the string</entry>
<entry>
<functionname>find_token()</functionname>
</entry>
</row>
<row>
<entry>find_regex</entry>
<entry>Use the regular expression to search the string</entry>
<entry>
<functionname>find_regex()</functionname>
</entry>
</row>
<row>
<entry>find</entry>
<entry>Generic find algorithm</entry>
<entry>
<functionname>find()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Erase/Replace</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry>replace/erase_first</entry>
<entry>Replace/Erase the first occurrence of a string in the input</entry>
<entry>
<functionname>replace_first()</functionname>
<sbr/>
<functionname>replace_first_copy()</functionname>
<sbr/>
<functionname>ireplace_first()</functionname>
<sbr/>
<functionname>ireplace_first_copy()</functionname>
<sbr/>
<functionname>erase_first()</functionname>
<sbr/>
<functionname>erase_first_copy()</functionname>
<sbr/>
<functionname>ierase_first()</functionname>
<sbr/>
<functionname>ierase_first_copy()</functionname>
</entry>
</row>
<row>
<entry>replace/erase_last</entry>
<entry>Replace/Erase the last occurrence of a string in the input</entry>
<entry>
<functionname>replace_last()</functionname>
<sbr/>
<functionname>replace_last_copy()</functionname>
<sbr/>
<functionname>ireplace_last()</functionname>
<sbr/>
<functionname>ireplace_last_copy()</functionname>
<sbr/>
<functionname>erase_last()</functionname>
<sbr/>
<functionname>erase_last_copy()</functionname>
<sbr/>
<functionname>ierase_last()</functionname>
<sbr/>
<functionname>ierase_last_copy()</functionname>
</entry>
</row>
<row>
<entry>replace/erase_nth</entry>
<entry>Replace/Erase the nth (zero-indexed) occurrence of a string in the input</entry>
<entry>
<functionname>replace_nth()</functionname>
<sbr/>
<functionname>replace_nth_copy()</functionname>
<sbr/>
<functionname>ireplace_nth()</functionname>
<sbr/>
<functionname>ireplace_nth_copy()</functionname>
<sbr/>
<functionname>erase_nth()</functionname>
<sbr/>
<functionname>erase_nth_copy()</functionname>
<sbr/>
<functionname>ierase_nth()</functionname>
<sbr/>
<functionname>ierase_nth_copy()</functionname>
</entry>
</row>
<row>
<entry>replace/erase_all</entry>
<entry>Replace/Erase the all occurrences of a string in the input</entry>
<entry>
<functionname>replace_all()</functionname>
<sbr/>
<functionname>replace_all_copy()</functionname>
<sbr/>
<functionname>ireplace_all()</functionname>
<sbr/>
<functionname>ireplace_all_copy()</functionname>
<sbr/>
<functionname>erase_all()</functionname>
<sbr/>
<functionname>erase_all_copy()</functionname>
<sbr/>
<functionname>ierase_all()</functionname>
<sbr/>
<functionname>ierase_all_copy()</functionname>
</entry>
</row>
<row>
<entry>replace/erase_head</entry>
<entry>Replace/Erase the head of the input</entry>
<entry>
<functionname>replace_head()</functionname>
<sbr/>
<functionname>replace_head_copy()</functionname>
<sbr/>
<functionname>erase_head()</functionname>
<sbr/>
<functionname>erase_head_copy()</functionname>
<sbr/>
</entry>
</row>
<row>
<entry>replace/erase_tail</entry>
<entry>Replace/Erase the tail of the input</entry>
<entry>
<functionname>replace_tail()</functionname>
<sbr/>
<functionname>replace_tail_copy()</functionname>
<sbr/>
<functionname>erase_tail()</functionname>
<sbr/>
<functionname>erase_tail_copy()</functionname>
<sbr/>
</entry>
</row>
<row>
<entry>replace/erase_regex</entry>
<entry>Replace/Erase a substring matching the given regular expression</entry>
<entry>
<functionname>replace_regex()</functionname>
<sbr/>
<functionname>replace_regex_copy()</functionname>
<sbr/>
<functionname>erase_regex()</functionname>
<sbr/>
<functionname>erase_regex_copy()</functionname>
<sbr/>
</entry>
</row>
<row>
<entry>replace/erase_regex_all</entry>
<entry>Replace/Erase all substrings matching the given regular expression</entry>
<entry>
<functionname>replace_all_regex()</functionname>
<sbr/>
<functionname>replace_all_regex_copy()</functionname>
<sbr/>
<functionname>erase_all_regex()</functionname>
<sbr/>
<functionname>erase_all_regex_copy()</functionname>
<sbr/>
</entry>
</row>
<row>
<entry>find_format</entry>
<entry>Generic replace algorithm</entry>
<entry>
<functionname>find_format()</functionname>
<sbr/>
<functionname>find_format_copy()</functionname>
<sbr/>
<functionname>find_format_all()</functionname>
<sbr/>
<functionname>find_format_all_copy()()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Split</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry>find_all</entry>
<entry>Find/Extract all matching substrings in the input</entry>
<entry>
<functionname>find_all()</functionname>
<sbr/>
<functionname>ifind_all()</functionname>
<sbr/>
<functionname>find_all_regex()</functionname>
</entry>
</row>
<row>
<entry>split</entry>
<entry>Split input into parts</entry>
<entry>
<functionname>split()</functionname>
<sbr/>
<functionname>split_regex()</functionname>
</entry>
</row>
<row>
<entry>iter_find</entry>
<entry>Iteratively apply the finder to the input to find all matching substrings</entry>
<entry>
<functionname>iter_find()</functionname>
</entry>
</row>
<row>
<entry>iter_split</entry>
<entry>Use the finder to find matching substrings in the input and use them as separators to split the input into parts</entry>
<entry>
<functionname>iter_split()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Join</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Algorithm name</entry>
<entry>Description</entry>
<entry>Functions</entry>
</row>
</thead>
<tbody>
<row>
<entry>join</entry>
<entry>Join all elements in a container into a single string</entry>
<entry>
<functionname>join</functionname>
</entry>
</row>
<row>
<entry>join_if</entry>
<entry>Join all elements in a container that satisfies the condition into a single string</entry>
<entry>
<functionname>join_if()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section>
<title>Finders and Formatters</title>
<table>
<title>Finders</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Finder</entry>
<entry>Description</entry>
<entry>Generators</entry>
</row>
</thead>
<tbody>
<row>
<entry>first_finder</entry>
<entry>Search for the first match of the string in an input</entry>
<entry>
<functionname>first_finder()</functionname>
</entry>
</row>
<row>
<entry>last_finder</entry>
<entry>Search for the last match of the string in an input</entry>
<entry>
<functionname>last_finder()</functionname>
</entry>
</row>
<row>
<entry>nth_finder</entry>
<entry>Search for the nth (zero-indexed) match of the string in an input</entry>
<entry>
<functionname>nth_finder()</functionname>
</entry>
</row>
<row>
<entry>head_finder</entry>
<entry>Retrieve the head of an input</entry>
<entry>
<functionname>head_finder()</functionname>
</entry>
</row>
<row>
<entry>tail_finder</entry>
<entry>Retrieve the tail of an input</entry>
<entry>
<functionname>tail_finder()</functionname>
</entry>
</row>
<row>
<entry>token_finder</entry>
<entry>Search for a matching token in an input</entry>
<entry>
<functionname>token_finder()</functionname>
</entry>
</row>
<row>
<entry>range_finder</entry>
<entry>Do no search, always returns the given range</entry>
<entry>
<functionname>range_finder()</functionname>
</entry>
</row>
<row>
<entry>regex_finder</entry>
<entry>Search for a substring matching the given regex</entry>
<entry>
<functionname>regex_finder()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Formatters</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Formatter</entry>
<entry>Description</entry>
<entry>Generators</entry>
</row>
</thead>
<tbody>
<row>
<entry>const_formatter</entry>
<entry>Constant formatter. Always return the specified string</entry>
<entry>
<functionname>const_formatter()</functionname>
</entry>
</row>
<row>
<entry>identity_formatter</entry>
<entry>Identity formatter. Return unmodified input input</entry>
<entry>
<functionname>identity_formatter()</functionname>
</entry>
</row>
<row>
<entry>empty_formatter</entry>
<entry>Null formatter. Always return an empty string</entry>
<entry>
<functionname>empty_formatter()</functionname>
</entry>
</row>
<row>
<entry>regex_formatter</entry>
<entry>Regex formatter. Format regex match using the specification in the format string</entry>
<entry>
<functionname>regex_formatter()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section>
<title>Iterators</title>
<table>
<title>Find Iterators</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Iterator name</entry>
<entry>Description</entry>
<entry>Iterator class</entry>
</row>
</thead>
<tbody>
<row>
<entry>find_iterator</entry>
<entry>Iterates through matching substrings in the input</entry>
<entry>
<classname>find_iterator</classname>
</entry>
</row>
<row>
<entry>split_iterator</entry>
<entry>Iterates through gaps between matching substrings in the input</entry>
<entry>
<classname>split_iterator</classname>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section>
<title>Classification</title>
<table>
<title>Predicates</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Predicate name</entry>
<entry>Description</entry>
<entry>Generator</entry>
</row>
</thead>
<tbody>
<row>
<entry>is_classified</entry>
<entry>Generic <code>ctype</code> mask based classification</entry>
<entry>
<functionname>is_classified()</functionname>
</entry>
</row>
<row>
<entry>is_space</entry>
<entry>Recognize spaces</entry>
<entry>
<functionname>is_space()</functionname>
</entry>
</row>
<row>
<entry>is_alnum</entry>
<entry>Recognize alphanumeric characters</entry>
<entry>
<functionname>is_alnum()</functionname>
</entry>
</row>
<row>
<entry>is_alpha</entry>
<entry>Recognize letters</entry>
<entry>
<functionname>is_alpha()</functionname>
</entry>
</row>
<row>
<entry>is_cntrl</entry>
<entry>Recognize control characters</entry>
<entry>
<functionname>is_cntrl()</functionname>
</entry>
</row>
<row>
<entry>is_digit</entry>
<entry>Recognize decimal digits</entry>
<entry>
<functionname>is_digit()</functionname>
</entry>
</row>
<row>
<entry>is_graph</entry>
<entry>Recognize graphical characters</entry>
<entry>
<functionname>is_graph()</functionname>
</entry>
</row>
<row>
<entry>is_lower</entry>
<entry>Recognize lower case characters</entry>
<entry>
<functionname>is_lower()</functionname>
</entry>
</row>
<row>
<entry>is_print</entry>
<entry>Recognize printable characters</entry>
<entry>
<functionname>is_print()</functionname>
</entry>
</row>
<row>
<entry>is_punct</entry>
<entry>Recognize punctuation characters</entry>
<entry>
<functionname>is_punct()</functionname>
</entry>
</row>
<row>
<entry>is_upper</entry>
<entry>Recognize uppercase characters</entry>
<entry>
<functionname>is_upper()</functionname>
</entry>
</row>
<row>
<entry>is_xdigit</entry>
<entry>Recognize hexadecimal digits</entry>
<entry>
<functionname>is_xdigit()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>

View File

@ -1,43 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.rationale" last-revision="$Date$">
<title>Rationale</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<using-namespace name="boost::algorithm"/>
<section id="string_algo.structure">
<title>Library structure</title>
<para>
When designing a library it is always a problem to find a balance between generalization
and usability. A generic utility can have a wider range of usage with more options for extensibility,
but it can also bring unwanted complexity for everyday usage.
</para>
<para>
Imagine a library for drawing geometric objects. It can contain one generic function <code>draw()</code>
with many parameters specifying what to draw, like size, number of edges, shape etc.
This would allow you to draw almost anything, but usually a user only needs to draw
only a triangle or a square and she will have to specify this simple request in a
very complicated way.For this purpose two functions, <code>draw_triangle()</code> and
<code>draw_square()</code>, would suit much better then a generic <code>draw()</code> function.
</para>
<para>
The String Algorithm Library solves this problem by dividing the interface into two layers.
The first layer (defined in the namespace boost) contains ready to use algorithms specialized
for common tasks. They are provided in multiple variants to better suit specific needs.
The second layer (defined in the namespace <code>boost::string_algo</code>), provides generic interfaces with
more options for extending and tunning.
<para>
</para>
For instance, a <functionname>boost::trim()</functionname> algorithm trims spaces from
an input string. When there is a need to trim something else, there is
<functionname>boost::string_algo::trim()</functionname> which interface allows one to specify a
predicate which selects the characters to be removed.
</para>
</section>
<section it="string_algo.locale">
<section it="string_algo.locale">
<title>Locales</title>
<para>
@ -49,15 +25,15 @@
C++ allows to work with multiple different instances of locales at once. If an algorithm
manipulates some data in a way that requires the usage of locales, there must be a way
to specify them. However, one instance of locales is sufficient for most of the applications,
and for a user it could be very tedious to specify which locales to use on every place
and for a user it could be very tedious to specify which locales to use at every place
where it is needed.
</para>
<para>
Fortunately, the C++ standard allows to specify the <emphasis>global</emphasis> locales (using static member
function <code>std:locale::global()</code>). When instantiating an
<code>std::locale</code> class without explicit information, the instance will
be initialized with the <emphasis>global</emphasis> locale. It means, that if an algorithm needs a locale,
it should have an <code>std::locale</code> parameter with default value <code>std::locale()</code>.
be initialized with the <emphasis>global</emphasis> locale. This implies, that if an algorithm needs a locale,
it should have an <code>std::locale</code> parameter defaulting to <code>std::locale()</code>.
If a user needs to specify locales explicitly, she can do so. Otherwise the <emphasis>global</emphasis>
locales are used.
</para>
@ -67,9 +43,9 @@
<para>
Regular expressions are an essential part of text processing. For this reason, the library
provides also regex variants of some algorithms. The library does not try to replace
<libraryname>Boost.Regex</libraryname>, but it merely wraps its functionality in a new interface.
As a part of this library regex algorithms integrate smoothly with other components which
also provides regex variants of some algorithms. The library does not attempt to replace
<libraryname>Boost.Regex</libraryname>; it merely wraps its functionality in a new interface.
As a part of this library, regex algorithms integrate smoothly with other components, which
brings additional value.
</para>
</section>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.release_notes" last-revision="$Date$">
<using-namespace name="boost"/>
<using-namespace name="boost::algorithm"/>
<title>Release Notes</title>
<itemizedlist>
<listitem>
<para><emphasis role="bold">1.32</emphasis></para>
<para>Initial release in Boost</para>
</listitem>
<listitem>
<para><emphasis role="bold">1.33</emphasis></para>
<para>Internal version of collection traits removed, library adapted to Boost.Range</para>
</listitem>
<listitem>
<para><emphasis role="bold">1.34</emphasis></para>
<itemizedlist>
<listitem>
<functionname>lexicographical_compare()</functionname>
</listitem>
<listitem>
<functionname>join()</functionname> and <functionname>join_if()</functionname>
</listitem>
<listitem>
New comparison predicates <code>is_less</code>, <code>is_not_greater</code>
</listitem>
<listitem>
Negative indexes support (like Perl) in various algorihtms
(<code>*_head/tail</code>, <code>*_nth</code>).
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>

View File

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library name="string_algo" dirname="string_algo" xmlns:xi="http://www.w3.org/2001/XInclude"
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<library name="String Algorithms" dirname="algorithm/string" xmlns:xi="http://www.w3.org/2001/XInclude"
id="string_algo" last-revision="$Date$">
<libraryinfo>
<author>
@ -12,6 +18,7 @@
<copyright>
<year>2002</year>
<year>2003</year>
<year>2004</year>
<holder>Pavol Droba</holder>
</copyright>
@ -24,17 +31,20 @@
</legalnotice>
<librarypurpose>
A set of generic string-related algorithms and utilities.
A set of generic string-related algorithms and utilities
</librarypurpose>
<librarycategory name="category:algoritms"/>
<librarycategory name="category:algorithms"/>
<librarycategory name="category:string-text"/>
</libraryinfo>
<title>Boost String Algorithms Library</title>
<xi:include href="intro.xml"/>
<xi:include href="release_notes.xml"/>
<xi:include href="usage.xml"/>
<xi:include href="quickref.xml"/>
<xi:include href="design.xml"/>
<xi:include href="concept.xml"/>
<xi:include href="reference.boostbook"/>
<xi:include href="autodoc.xml"/>
<xi:include href="rationale.xml"/>
<xi:include href="environment.xml"/>
<xi:include href="credits.xml"/>

View File

@ -1,11 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!-- Copyright (c) 2002-2006 Pavol Droba.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="string_algo.usage" last-revision="$Date$">
<title>Usage</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<using-namespace name="boost::algorithm"/>
<section>
@ -15,17 +23,20 @@
Using the algorithms is straightforward. Let us have a look at the first example:
</para>
<programlisting>
#include &lt;boost/string_algo.hpp&gt;
#include &lt;boost/algorithm/string.hpp&gt;
using namespace std;
using namespace boost;
namespace sa=boost::string_algo
// ...
string str1(" hello world! ");
trim( to_upper(str1) ); // str1 == "HELLO WORLD!"
to_upper(str1); // str1 == " HELLO WORLD! "
trim(str1); // str1 == "HELLO WORLD!"
string str2=ireplace_first_copy(str1,"hello","goodbye"); // str2 == "goodbye WORLD!"
string str2=
to_lower_copy(
ireplace_first_copy(
str1,"hello","goodbye")); // str2 == "goodbye world!"
</programlisting>
<para>
This example converts str1 to upper case and trims spaces from the start and the end
@ -35,19 +46,19 @@
<itemizedlist>
<listitem>
<para><emphasis role="bold">Container parameters:</emphasis>
Unlike the STL algorithms, parameters are not specified only in form
Unlike in the STL algorithms, parameters are not specified only in the form
of iterators. The STL convention allows for great flexibility,
but it has several limitation. It is not possible to <emphasis>stack</emphasis> algorithms together,
because a container is passed in two parameters, so it is not possible to use
but it has several limitations. It is not possible to <emphasis>stack</emphasis> algorithms together,
because a container is passed in two parameters. Therefore it is not possible to use
a return value from another algorithm. It is considerably easier to write
<code>to_lower(str1)</code>, then <code>to_lower(str1.begin(), str1.end())</code>.
<code>to_lower(str1)</code>, than <code>to_lower(str1.begin(), str1.end())</code>.
</para>
<para>
The magic of <link linkend="string_algo.container_traits">container_traits</link>
provides a uniform way of handling different containers.
The magic of <ulink url="../../libs/range/index.html">Boost.Range</ulink>
provides a uniform way of handling different string types.
If there is a need to pass a pair of iterators,
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link>
can be used to package iterators into a structure with the container interface.
<ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>
can be used to package iterators into a structure with a compatible interface.
</para>
</listitem>
<listitem>
@ -61,27 +72,26 @@
</listitem>
<listitem>
<para><emphasis role="bold">Algorithm stacking:</emphasis>
Copy versions return a transformed input as a result. Mutable variants return
a reference to the input. Thus both versions allow a simple chaining of
transformations within one expression (i.e. one can write
<code>trim_copy(to_upper_copy(s))</code> as well as <code>trim(to_upper(s))</code>).
Copy versions return a transformed input as a result, thus allow a simple chaining of
transformations within one expression (i.e. one can write <code>trim_copy(to_upper_copy(s))</code>).
Mutable versions have <code>void</code> return, to avoid misuse.
</para>
</listitem>
<listitem>
<para><emphasis role="bold">Naming:</emphasis>
Naming follows the conventions from the Standard C++ Library. If there is a
copy and mutable version of the same algorithm, the mutable version has no suffix
and the copy version has suffix <emphasis>_copy</emphasis>.
Some algorithms have prefix <emphasis>i</emphasis>
copy and a mutable version of the same algorithm, the mutable version has no suffix
and the copy version has the suffix <emphasis>_copy</emphasis>.
Some algorithms have the prefix <emphasis>i</emphasis>
(e.g. <functionname>ifind_first()</functionname>).
This prefix identifies that the algorithm works in a case-insensitive manner.
</para>
</listitem>
</itemizedlist>
<para>
To use the library, include the <headername>boost/string_algo.hpp</headername> header.
To use the library, include the <headername>boost/algorithm/string.hpp</headername> header.
If the regex related functions are needed, include the
<headername>boost/string_algo_regex.hpp</headername> header.
<headername>boost/algorithm/string_regex.hpp</headername> header.
</para>
</section>
<section>
@ -97,7 +107,10 @@
</programlisting>
<para>
<functionname>to_upper()</functionname> and <functionname>to_lower()</functionname> convert the case of
characters in a container using a specified locale.
characters in a string using a specified locale.
</para>
<para>
For more information see the reference for <headername>boost/algorithm/string/case_conv.hpp</headername>.
</para>
</section>
<section>
@ -117,7 +130,7 @@
string str1("command.com");
cout
&lt;&lt; str1
&lt;&lt; is_executable("command.com")? "is": "is not"
&lt;&lt; (is_executable("command.com")? "is": "is not")
&lt;&lt; "an executable"
&lt;&lt; endl; // prints "command.com is an executable"
@ -125,47 +138,51 @@
char text1[]="hello world!";
cout
&lt;&lt; text1
&lt;&lt; all( text1, is_lower&lt;char&gt;() )? "is": "is not"
&lt;&lt; "written in the lower case"
&lt;&lt; (all( text1, is_lower() )? "is": "is not")
&lt;&lt; " written in the lower case"
&lt;&lt; endl; // prints "hello world! is written in the lower case"
</programlisting>
<para>
The predicates are resolving if a substring is contained in the input string
under various conditions. The conditions are if a string starts with the substring,
The predicates determine whether if a substring is contained in the input string
under various conditions. The conditions are: a string starts with the substring,
ends with the substring,
simply contains the substring or if both strings are equal. See the reference for
<headername>boost/string_algo/predicate.hpp</headername> for more details.
<headername>boost/algorithm/string/predicate.hpp</headername> for more details.
</para>
<para>
In addition the algorithm <functionname>all()</functionname> checks
all elements of a container to satisfy a condition specified by a predicate.
This predicate can be any unary predicate, but the library provides a bunch of
useful string-related predicates ready for use.
These are located in the <headername>boost/string_algo/classification.hpp</headername> header.
useful string-related predicates and combinators ready for use.
These are located in the <headername>boost/algorithm/string/classification.hpp</headername> header.
Classification predicates can be combined using logical combinators to form
a more complex expressions. For example: <code>is_from_range('a','z') || is_digit()</code>
</para>
</section>
<section>
<title>Trimming</title>
<para>
When parsing the input of a user, strings usually have unwanted leading or trailing
When parsing the input from a user, strings usually have unwanted leading or trailing
characters. To get rid of them, we need trim functions:
</para>
<programlisting>
string str1=" hello world! ";
string str2=trim_left_copy(str1); // str2 == "hello world! "
string str3=trim_right_copy(str2); // str3 == " hello world!"
string str3=trim_right_copy(str1); // str3 == " hello world!"
trim(str1); // str1 == "hello world!"
string phone="00423333444";
// remove leading 0 from the phone number
sa::trim_left(phone,is_any_of&lt;char&gt;("0")); // phone == "423333444"
trim_left_if(phone,is_any_of("0")); // phone == "423333444"
</programlisting>
<para>
It is possible to trim the spaces on the right, on the left or on the both sides of a string.
And for those cases when there is a need to remove something else than blank space, the
<code>string_algo</code> namespace contains generic versions of the trim algorithms. Using these,
a user can specify a functor which will select the <emphasis>space</emphasis> to be removed. It is possible to use
classification predicates like <functionname>is_digit()</functionname> mentioned in the previous paragraph.
See the reference for the <headername>boost/string_algo/trim.hpp</headername>.
It is possible to trim the spaces on the right, on the left or on both sides of a string.
And for those cases when there is a need to remove something else than blank space, there
are <emphasis>_if</emphasis> variants. Using these, a user can specify a functor which will
select the <emphasis>space</emphasis> to be removed. It is possible to use classification
predicates like <functionname>is_digit()</functionname> mentioned in the previous paragraph.
See the reference for the <headername>boost/algorithm/string/trim.hpp</headername>.
</para>
</section>
<section>
@ -182,28 +199,38 @@
// text = "hello dommy!"
to_upper(result); // text == "hello doMMy!"
// iterator_range is convertible to bool
if(find_first(text, "dolly"))
{
cout &lt;&lt; "Dolly is there" &lt;&lt; endl;
}
</programlisting>
<para>
We have used <functionname>find_last()</functionname> to search the <code>text</code> for "ll".
The result is given in the <link linkend="string_algo.iterator_range"><code>iterator_range</code></link>.
The result is given in the <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>.
This range delimits the
part of the input which satisfies the find criteria. In our example it is the last occurrence of "ll".
As we can see, input of the <functionname>find_last()</functionname> algorithm can be also
char[] because this type is supported by
<link linkend="string_algo.container_traits">container_traits</link>.
<ulink url="../../libs/range/index.html">Boost.Range</ulink>.
Following lines transform the result. Notice, that
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link> have familiar
The following lines transform the result. Notice that
<ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink> has familiar
<code>begin()</code> and <code>end()</code> methods, so it can be used like any other STL container.
Also it is convertible to bool therefore it is easy to use find algorithms for a simple containment checking.
</para>
<para>
Find algorithms are located in <headername>boost/algorithm/string/find.hpp</headername>.
</para>
</section>
<section>
<title>Replace Algorithms</title>
<para>
Find algorithms can be used for searching for a specific part of the sequence. Replace goes one step
Find algorithms can be used for searching for a specific part of string. Replace goes one step
further. After a matching part is found, it is substituted with something else. The substitution is computed
from an original, using some transformation.
from the original, using some transformation.
</para>
<programlisting>
string str1="Hello Dolly, Hello World!"
@ -216,7 +243,7 @@
For the complete list of replace and erase functions see the
<link linkend="string_algo.reference">reference</link>.
There is a lot of predefined function for common usage, however, the library allows you to
define a custom <code>replace()</code> that suits a specific need. There is a generic <functionname>replace()</functionname>
define a custom <code>replace()</code> that suits a specific need. There is a generic <functionname>find_format()</functionname>
function which takes two parameters.
The first one is a <link linkend="string_algo.finder_concept">Finder</link> object, the second one is
a <link linkend="string_algo.formatter_concept">Formatter</link> object.
@ -224,14 +251,81 @@
takes the result of the Finder (usually a reference to the found substring) and creates a
substitute for it. Replace algorithm puts these two together and makes the desired substitution.
</para>
<para>
Check <headername>boost/algorithm/string/replace.hpp</headername>, <headername>boost/algorithm/string/erase.hpp</headername> and
<headername>boost/algorithm/string/find_format.hpp</headername> for reference.
</para>
</section>
<section>
<title>Find Iterator</title>
<para>
An extension to find algorithms it the Find Iterator. Instead of searching for just a one part of a string,
the find iterator allows us to iterate over the substrings matching the specified criteria.
This facility is using the <link linkend="string_algo.finder_concept">Finder</link> to incrementally
search the string.
Dereferencing a find iterator yields an <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>
object, that delimits the current match.
</para>
<para>
There are two iterators provided <classname>find_iterator</classname> and
<classname>split_iterator</classname>. The former iterates over substrings that are found using the specified
Finder. The latter iterates over the gaps between these substrings.
</para>
<programlisting>
string str1("abc-*-ABC-*-aBc");
// Find all 'abc' substrings (ignoring the case)
// Create a find_iterator
typedef find_iterator&lt;string::iterator&gt; string_find_iterator;
for(string_find_iterator It=
make_find_iterator(str1, first_finder("abc", is_iequal()));
It!=string_find_iterator();
++It)
{
cout &lt;&lt; copy_range&lt;std::string&gt;(*It) &lt;&lt; endl;
}
// Output will be:
// abc
// ABC
// aBC
typedef split_iterator&lt;string::iterator&gt; string_split_iterator;
for(string_split_iterator It=
make_split_iterator(str1, first_finder("-*-", is_iequal()));
It!=string_split_iterator();
++It)
{
cout &lt;&lt; copy_range&lt;std::string&gt;(*It) &lt;&lt; endl;
}
// Output will be:
// abc
// ABC
// aBC
</programlisting>
<para>
Note that the find iterators have only one template parameter. It is the base iterator type.
The Finder is specified at runtime. This allows us to typedef a find iterator for
common string types and reuse it. Additionally make_*_iterator functions help
to construct a find iterator for a particular range.
</para>
<para>
See the reference in <headername>boost/algorithm/string/find_iterator.hpp</headername>.
</para>
</section>
<section>
<title>Split</title>
<para>
Split algorithms allow one to divide a sequence into parts. Each part represents a
<emphasis>token</emphasis> and tokens are separated by <emphasis>separators</emphasis>.
One can either search for tokens or search for separators:
Split algorithms are an extension to the find iterator for one common usage scenario.
These algorithms use a find iterator and store all matches into the provided
container. This container must be able to hold copies (e.g. <code>std::string</code>) or
references (e.g. <code>iterator_range</code>) of the extracted substrings.
</para>
<para>
Two algorithms are provided. <functionname>find_all()</functionname> finds all copies
of a string in the input. <functionname>split()</functionname> splits the input into parts.
</para>
<programlisting>
@ -242,34 +336,26 @@
find_vector_type FindVec; // #1: Search for separators
ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] }
typdef vector&lt; string &gt; split_vector_type;
typedef vector&lt; string &gt; split_vector_type;
split_vector_type SplitVec; // #2: Search for tokens
split( SplitVec, str1, is_any_of&lt;char&gt;("-*") ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
split( SplitVec, str1, is_any_of("-*"), token_compress_on ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
</programlisting>
<para>
<code>[hello]</code> designates an <code>iterator_range</code> delimiting this substring.
</para>
<para>
The result of a split algorithm is a <emphasis>container of containers</emphasis>. There is only one restriction:
The inner container type must be able to hold extracted parts of the input sequence. This example
shows the special case where the inner container is an
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link>
instead of e.g. <code>std::string</code>. This way, a user gets a reference
(in the form of iterators) delimiting the parts of the input sequence. Otherwise, a copy of
each extracted part is created and added to the outer container.
First example show how to construct a container to hold references to all extracted
substrings. Algorithm <functionname>ifind_all()</functionname> puts into FindVec references
to all substrings that are in case-insensitive manner equal to "abc".
</para>
<para>
So to recap, there are two basic algorithms: <functionname>find_all()</functionname>
returns extracts the parts
matching the specification whereas <functionname>split()</functionname> uses the matching
parts as delimiters, and extracts the parts in between them.
Second example uses <functionname>split()</functionname> to split string str1 into parts
separated by characters '-' or '*'. These parts are then put into the SplitVec.
It is possible to specify if adjacent separators are concatenated or not.
</para>
<para>
Generalizations of these two algorithms are called <functionname>iter_find()</functionname> and
<functionname>iter_split()</functionname>. They take a
<link linkend="string_algo.finder_concept">Finder</link> object, as an argument to search for
the substring.
</para>
</section>
More information can be found in the reference: <headername>boost/algorithm/string/split.hpp</headername>.
</para>
</section>
</section>

View File

@ -7,69 +7,12 @@
#
# See http://www.boost.org for updates, documentation, and revision history.
subproject libs/algorithm/string/example ;
exe conv_example
:
conv_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe predicate_example
:
predicate_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe find_example
:
find_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe replace_example
:
replace_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe rle_example
:
rle_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe trim_example
:
trim_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe regex_example
:
regex_example.cpp
<lib>../../../regex/build/boost_regex
:
<include>$(BOOST_ROOT)
:
;
exe split_example
:
split_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe conv_example : conv_example.cpp ;
exe predicate_example : predicate_example.cpp ;
exe find_example : find_example.cpp ;
exe replace_example : replace_example.cpp ;
exe rle_example : rle_example.cpp ;
exe trim_example : trim_example.cpp ;
exe regex_example : regex_example.cpp /boost/regex//boost_regex ;
exe split_example : split_example.cpp ;

View File

@ -49,7 +49,7 @@ int main()
cout << "\";.,\" are all punctuation characters" << endl;
}
// Classification predicated can be combined
// Classification predicates can be combined
if ( all("abcxxx", is_any_of("xabc") && !is_space() ) )
{
cout << "true" << endl;

View File

@ -10,9 +10,10 @@
#include <string>
#include <iostream>
#include <iterator>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/case_conv.hpp>
//#include <boost/algorithm/string/replace.hpp>
//#include <boost/algorithm/string/erase.hpp>
//#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string.hpp>
//Following two includes contain second-layer function.
//They are already included by first-layer header

View File

@ -24,7 +24,7 @@ using namespace std;
using namespace boost;
// replace mark specification, specialize for a specific element type
template< typename T > T repeat_mark() { return std::numeric_limits<T>::max(); };
template< typename T > T repeat_mark() { return (std::numeric_limits<T>::max)(); };
// Compression -----------------------------------------------------------------------
@ -59,7 +59,7 @@ struct find_compressF
{
input_iterator_type It2=It++;
if ( It==End || Cnt>=std::numeric_limits<value_type>::max() )
if ( It==End || Cnt>=(std::numeric_limits<value_type>::max)() )
{
return result_type( MStart, It );
}
@ -114,10 +114,13 @@ public:
result_type operator()( const ReplaceT& Replace ) const
{
SeqT r;
r.push_back( repeat_mark<value_type>() );
r.push_back( *(Replace.begin()) );
r.push_back( value_type( Replace.size() ) );
if(!Replace.empty())
{
r.push_back( repeat_mark<value_type>() );
r.push_back( *(Replace.begin()) );
r.push_back( value_type( Replace.size() ) );
}
return r;
}
};
@ -183,14 +186,18 @@ public:
template< typename ReplaceT >
result_type operator()( const ReplaceT& Replace ) const
{
// extract info
typename ReplaceT::const_iterator It=Replace.begin();
value_type Value=*(++It);
value_type Repeat=*(++It);
SeqT r;
for( value_type Index=0; Index<Repeat; Index++ ) r.push_back( Value );
if(!Replace.empty())
{
// extract info
typename ReplaceT::const_iterator It=Replace.begin();
value_type Value=*(++It);
value_type Repeat=*(++It);
for( value_type Index=0; Index<Repeat; Index++ ) r.push_back( Value );
}
return r;
}

View File

@ -12,7 +12,6 @@
#include <iostream>
#include <iterator>
#include <functional>
#include <boost/algorithm/string/iterator_range.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
@ -36,7 +35,7 @@ int main()
It!=string_find_iterator();
++It)
{
cout << copy_iterator_range<std::string>(*It) << endl;
cout << copy_range<std::string>(*It) << endl;
// shift all chars in the match by one
transform(
It->begin(), It->end(),

14
string/index.html Normal file
View File

@ -0,0 +1,14 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/string_algo.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../../doc/html/string_algo.html">../../doc/html/string_algo.html</a>
&nbsp;<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</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

@ -1,71 +0,0 @@
# Boost string_algo library test suite Jamfile ----------------------------
#
# Copyright Pavol Droba 2002-2003. Use, modification and
# distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org for updates, documentation, and revision history.
subproject libs/algorithm/string/test ;
# bring in rules for testing
import testing ;
# Make tests run by default.
DEPENDS all : test ;
{
test-suite string_algo
: [ run
container_test.cpp
: :
:
: container
]
[ run
trim_test.cpp
: :
:
: trim
]
[ run
conv_test.cpp
: :
:
: conv
]
[ run
predicate_test.cpp
: :
:
: predicate
]
[ run
find_test.cpp
: :
:
: find
]
[ run
split_test.cpp
: :
:
: split
]
[ run
replace_test.cpp
: :
:
: replace
]
[ run
regex_test.cpp
<lib>../../../regex/build/boost_regex
: :
:
: regex
]
;
}

69
string/test/Jamfile.v2 Normal file
View File

@ -0,0 +1,69 @@
# Boost string_algo library test suite Jamfile ----------------------------
#
# Copyright Pavol Droba 2002-2003. Use, modification and
# distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org for updates, documentation, and revision history.
import testing ;
test-suite algorithm/string
: [ run
trim_test.cpp
: :
:
: trim
]
[ run
conv_test.cpp
: :
:
: conv
]
[ run
predicate_test.cpp
: :
:
: predicate
]
[ run
find_test.cpp
: :
:
: find
]
[ run
split_test.cpp
: :
:
: split
]
[ run
join_test.cpp
: :
:
: join
]
[ run
replace_test.cpp
: :
:
: replace
]
[ run
regex_test.cpp
../../../regex/build//boost_regex
: :
:
: regex
]
[ run
find_format_test.cpp
: :
:
: find_format
]
;

View File

@ -1,127 +0,0 @@
// Boost string_algo library substr_test.cpp file ------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <utility>
#include <vector>
#include <boost/algorithm/string/collection_traits.hpp>
#include <boost/type_traits.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
// test tools
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
namespace algo = ::boost::algorithm;
template< typename T >
void argument_cv_test( const T& C, const string& strResult )
{
BOOST_CHECK( equals( make_iterator_range(algo::begin(C),algo::end(C)), strResult ) );
BOOST_CHECK( algo::size(C)==strResult.size() );
BOOST_CHECK( algo::empty(C)==strResult.empty() );
}
template< typename T >
void argument_test( T& C, const string& strResult )
{
BOOST_CHECK( equals( make_iterator_range(algo::begin(C),algo::end(C)), strResult ) );
BOOST_CHECK( algo::size(C)==strResult.size() );
BOOST_CHECK( algo::empty(C)==strResult.empty() );
}
void container_test()
{
BOOST_CHECKPOINT( "type test" );
// types test
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<string>::type,
string::iterator>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<const string>::type,
string::const_iterator>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<char[4]>::type, char*>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<const char[4]>::type,
const char*>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<char*>::type, char*>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<const char*>::type,
const char*>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<
pair<string::iterator, string::iterator> >::type, string::iterator>::value) );
BOOST_REQUIRE( (is_same<
algo::result_iterator_of<
const pair<string::iterator, string::iterator> >::type,
string::iterator>::value) );
BOOST_CHECKPOINT( "non-empty sequence test" );
string str1("abc");
vector<char> vec1( str1.begin(), str1.end() );
pair<string::iterator, string::iterator> pair1=
make_pair( str1.begin(), str1.end() );
char ach1[]="abc";
char *pch1="abc";
// begin/end tests
argument_cv_test( str1, "abc" );
argument_test( str1, "abc" );
argument_cv_test( vec1, "abc" );
argument_test( vec1, "abc" );
argument_cv_test( pair1, "abc" );
argument_test( pair1, "abc" );
argument_cv_test( ach1, "abc" );
argument_test( ach1, "abc" );
argument_cv_test( pch1, "abc" );
argument_test( pch1, "abc" );
BOOST_CHECKPOINT( "empty sequence test" );
string str2;
vector<char> vec2( str2.begin(), str2.end() );
pair<string::iterator, string::iterator> pair2=
make_pair( str2.begin(), str2.end() );
char ach2[]="";
char *pch2=0;
// begin/end tests
argument_cv_test( str2, "" );
argument_test( str2, "" );
argument_cv_test( vec2, "" );
argument_test( vec2, "" );
argument_cv_test( pair2, "" );
argument_test( pair2, "" );
argument_cv_test( ach2, "" );
argument_test( ach2, "" );
argument_cv_test( pch2, "" );
argument_test( pch2, "" );
};
// test main
int test_main( int, char*[] )
{
container_test();
return 0;
}

View File

@ -7,13 +7,14 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/case_conv.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <iostream>
#include <algorithm>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
@ -81,8 +82,8 @@ void conv_test()
to_upper( str3 );
BOOST_CHECK( str3=="" );
free(pch1);
free(pch2);
delete[] pch1;
delete[] pch2;
}
// test main

View File

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

View File

@ -7,6 +7,9 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/classification.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -15,8 +18,6 @@
#include <iostream>
#include <iterator>
#include <sstream>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
@ -27,7 +28,7 @@ void find_test()
string str1("123abcxXxabcXxXabc321");
string str2("abc");
string str3("");
char* pch1="123abcxxxabcXXXabc321";
const char* pch1="123abcxxxabcXXXabc321";
vector<int> vec1( str1.begin(), str1.end() );
// find results ------------------------------------------------------------//
@ -47,18 +48,18 @@ void find_test()
nc_result=find_first( str1, string("abc") );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_result=find_first( const_cast<const string&>(str1), str2 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
cv_result=ifind_first( const_cast<const string&>(str1), "xXX" );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 6) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 9) );
( (cv_result.begin()-str1.begin()) == 6) &&
( (cv_result.end()-str1.begin()) == 9) );
ch_result=find_first( pch1, "abc" );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) );
@ -68,18 +69,18 @@ void find_test()
nc_result=find_last( str1, string("abc") );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 18) );
( (nc_result.begin()-str1.begin()) == 15) &&
( (nc_result.end()-str1.begin()) == 18) );
cv_result=find_last( const_cast<const string&>(str1), str2 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 18) );
( (cv_result.begin()-str1.begin()) == 15) &&
( (cv_result.end()-str1.begin()) == 18) );
cv_result=ifind_last( const_cast<const string&>(str1), "XXx" );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 12) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 15) );
( (cv_result.begin()-str1.begin()) == 12) &&
( (cv_result.end()-str1.begin()) == 15) );
ch_result=find_last( pch1, "abc" );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 15) && ( (ch_result.end() - pch1 ) == 18 ) );
@ -89,18 +90,35 @@ void find_test()
nc_result=find_nth( str1, string("abc"), 1 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 9) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 12) );
( (nc_result.begin()-str1.begin()) == 9) &&
( (nc_result.end()-str1.begin()) == 12) );
nc_result=find_nth( str1, string("abc"), -1 );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 15) &&
( (nc_result.end()-str1.begin()) == 18) );
cv_result=find_nth( const_cast<const string&>(str1), str2, 1 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 9) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 12) );
( (cv_result.begin()-str1.begin()) == 9) &&
( (cv_result.end()-str1.begin()) == 12) );
cv_result=find_nth( const_cast<const string&>(str1), str2, -1 );
BOOST_CHECK(
( (cv_result.begin()-str1.begin()) == 15) &&
( (cv_result.end()-str1.begin()) == 18) );
cv_result=ifind_nth( const_cast<const string&>(str1), "xxx", 1 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 12) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 15) );
( (cv_result.begin()-str1.begin()) == 12) &&
( (cv_result.end()-str1.begin()) == 15) );
cv_result=ifind_nth( const_cast<const string&>(str1), "xxx", 1 );
BOOST_CHECK(
( (cv_result.begin()-str1.begin()) == 12) &&
( (cv_result.end()-str1.begin()) == 15) );
ch_result=find_nth( pch1, "abc", 1 );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 9) && ( (ch_result.end() - pch1 ) == 12 ) );
@ -110,13 +128,18 @@ void find_test()
nc_result=find_head( str1, 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 0) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 0) &&
( (nc_result.end()-str1.begin()) == 6) );
nc_result=find_head( str1, -6 );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 0) &&
( (str1.end()-nc_result.end()) == 6 ) );
cv_result=find_head( const_cast<const string&>(str1), 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 0) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 0) &&
( (cv_result.end()-str1.begin()) == 6) );
ch_result=find_head( pch1, 6 );
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 0 ) && ( (ch_result.end() - pch1 ) == 6 ) );
@ -126,13 +149,19 @@ void find_test()
nc_result=find_tail( str1, 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 21) );
( (nc_result.begin()-str1.begin()) == 15) &&
( (nc_result.end()-str1.begin()) == 21) );
nc_result=find_tail( str1, -6 );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 6) &&
( (nc_result.end()-str1.begin()) == 21) );
cv_result=find_tail( const_cast<const string&>(str1), 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 21) );
( (cv_result.begin()-str1.begin()) == 15) &&
( (cv_result.end()-str1.begin()) == 21) );
ch_result=find_tail( pch1, 6 );
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 15 ) && ( (ch_result.end() - pch1 ) == 21 ) );
@ -142,23 +171,23 @@ void find_test()
nc_result=find_token( str1, is_any_of("abc"), token_compress_on );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_on );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
nc_result=find_token( str1, is_any_of("abc"), token_compress_off );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 4) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 4) );
cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_off );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 4) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 4) );
ch_result=find_token( pch1, is_any_of("abc"), token_compress_off );
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 3 ) && ( (ch_result.end() - pch1 ) == 4 ) );
@ -168,26 +197,26 @@ void find_test()
nc_result=find(str1, first_finder(string("abc")));
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_result=find(const_cast<const string&>(str1), first_finder(str2) );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
// multi-type comparison test
BOOST_CHECKPOINT( "multi-type" );
nc_vresult=find_first( vec1, string("abc") );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_vresult=find_first( const_cast<const vector<int>&>(vec1), str2 );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
// overflow test
BOOST_CHECKPOINT( "overflow" );

79
string/test/join_test.cpp Normal file
View File

@ -0,0 +1,79 @@
// Boost string_algo library iterator_test.cpp file ---------------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/classification.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
bool is_not_empty(const std::string& str)
{
return !str.empty();
}
void join_test()
{
// Prepare inputs
vector<string> tokens1;
tokens1.push_back("xx");
tokens1.push_back("abc");
tokens1.push_back("xx");
vector<string> tokens2;
tokens2.push_back("");
tokens2.push_back("xx");
tokens2.push_back("abc");
tokens2.push_back("");
tokens2.push_back("abc");
tokens2.push_back("xx");
tokens2.push_back("");
vector<string> tokens3;
tokens3.push_back("");
tokens3.push_back("");
tokens3.push_back("");
vector<string> empty_tokens;
vector<vector<int> > vtokens;
for(unsigned int n=0; n<tokens2.size(); ++n)
{
vtokens.push_back(vector<int>(tokens2[n].begin(), tokens2[n].end()));
}
BOOST_CHECK( equals(join(tokens1, "-"), "xx-abc-xx") );
BOOST_CHECK( equals(join(tokens2, "-"), "-xx-abc--abc-xx-") );
BOOST_CHECK( equals(join(vtokens, "-"), "-xx-abc--abc-xx-") );
BOOST_CHECK( equals(join(empty_tokens, "-"), "") );
BOOST_CHECK( equals(join_if(tokens2, "-", is_not_empty), "xx-abc-abc-xx") );
BOOST_CHECK( equals(join_if(empty_tokens, "-", is_not_empty), "") );
BOOST_CHECK( equals(join_if(tokens3, "-", is_not_empty), "") );
}
// test main
int test_main( int, char*[] )
{
join_test();
return 0;
}

View File

@ -7,6 +7,9 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/classification.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -14,8 +17,6 @@
#include <vector>
#include <iostream>
#include <functional>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
@ -55,6 +56,14 @@ void predicate_test()
BOOST_CHECK( iequals( "AbC", "abc" ) );
BOOST_CHECK( !iequals( "aBc", "yyy" ) );
BOOST_CHECK( lexicographical_compare("abc", "abd") );
BOOST_CHECK( !lexicographical_compare("abc", "abc") );
BOOST_CHECK( lexicographical_compare("abc", "abd", is_less()) );
BOOST_CHECK( !ilexicographical_compare("aBD", "AbC") );
BOOST_CHECK( ilexicographical_compare("aBc", "AbD") );
BOOST_CHECK( lexicographical_compare("abC", "aBd", is_iless()) );
// multi-type comparison test
BOOST_CHECK( starts_with( vec1, string("123") ) );
BOOST_CHECK( ends_with( vec1, string("321") ) );
@ -84,12 +93,32 @@ void predicate_test()
BOOST_CHECK( ends_with( "123xxx321", "321" ) );
BOOST_CHECK( contains( "123xxx321", "xxx" ) );
BOOST_CHECK( equals( "123xxx321", "123xxx321" ) );
}
template<typename Pred, typename Input>
void test_pred(const Pred& pred, const Input& input, bool bYes)
{
// test assignment operator
Pred pred1=pred;
pred1=pred;
pred1=pred1;
if(bYes)
{
BOOST_CHECK( all( input, pred ) );
BOOST_CHECK( all( input, pred1 ) );
}
else
{
BOOST_CHECK( !all( input, pred ) );
BOOST_CHECK( !all( input, pred1 ) );
}
}
#define TEST_CLASS( Pred, YesInput, NoInput )\
{\
BOOST_CHECK( all( string(YesInput), Pred ) );\
BOOST_CHECK( !all( string(NoInput), Pred ) );\
test_pred(Pred, YesInput, true); \
test_pred(Pred, NoInput, false); \
}
void classification_test()
@ -111,6 +140,14 @@ void classification_test()
TEST_CLASS( !is_classified(std::ctype_base::space), "...", "..\n\r\t " );
TEST_CLASS( ( !is_any_of("abc") && is_from_range('a','e') ) || is_space(), "d e", "abcde" );
// is_any_of test
// TEST_CLASS( !is_any_of(""), "", "aaa" )
TEST_CLASS( is_any_of("a"), "a", "ab" )
TEST_CLASS( is_any_of("ba"), "ab", "abc" )
TEST_CLASS( is_any_of("cba"), "abc", "abcd" )
TEST_CLASS( is_any_of("hgfedcba"), "abcdefgh", "abcdefghi" )
TEST_CLASS( is_any_of("qponmlkjihgfedcba"), "abcdefghijklmnopq", "zzz" )
}
#undef TEST_CLASS

View File

@ -7,6 +7,13 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/regex.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/sequence_traits.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -14,8 +21,6 @@
#include <vector>
#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string/sequence_traits.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
@ -24,7 +29,7 @@ using namespace boost;
static void find_test()
{
string str1("123a1cxxxa23cXXXa456c321");
char* pch1="123a1cxxxa23cXXXa456c321";
const char* pch1="123a1cxxxa23cXXXa456c321";
regex rx("a[0-9]+c");
vector<int> vec1( str1.begin(), str1.end() );
vector<string> tokens;
@ -41,13 +46,13 @@ static void find_test()
// basic tests
nc_result=find_regex( str1, rx );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_result=find_regex( str1, rx );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
ch_result=find_regex( pch1, rx );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) );
@ -55,13 +60,13 @@ static void find_test()
// multi-type comparison test
nc_vresult=find_regex( vec1, rx );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.end()) == 6) );
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_vresult=find_regex( vec1, rx );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.end()) == 6) );
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
// find_all_regex test
find_all_regex( tokens, str1, rx );
@ -82,6 +87,23 @@ static void find_test()
}
static void join_test()
{
// Prepare inputs
vector<string> tokens1;
tokens1.push_back("xx");
tokens1.push_back("abc");
tokens1.push_back("xx");
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
BOOST_CHECK( equals(join_if(tokens1, "-", regex("x+")), "xx-xx") );
BOOST_CHECK( equals(join_if(tokens1, "-", regex("[abc]+")), "abc") );
#else
BOOST_CHECK( equals(join_if_regex(tokens1, "-", regex("x+")), "xx-xx") );
BOOST_CHECK( equals(join_if_regex(tokens1, "-", regex("[abc]+")), "abc") );
#endif
}
static void replace_test()
{
string str1("123a1cxxxa23cXXXa456c321");
@ -130,6 +152,7 @@ static void replace_test()
int test_main( int, char*[] )
{
find_test();
join_test();
replace_test();
return 0;

View File

@ -7,6 +7,14 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/std/list_traits.hpp>
#include <boost/algorithm/string/std/string_traits.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/formatter.hpp>
#include <boost/algorithm/string/classification.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -15,16 +23,10 @@
#include <list>
#include <iostream>
#include <boost/algorithm/string/std/list_traits.hpp>
#include <boost/algorithm/string/std/string_traits.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/preprocessor/seq/enum.hpp>
using namespace std;
using namespace boost;
@ -51,6 +53,7 @@ void sequence_traits_test()
}
// Combine tests for all variants of the algorithm
#define C_ ,
#define TEST_ALGO( Algo, Input, Params, Output ) \
{\
BOOST_CHECKPOINT( #Algo " - Copy" );\
@ -58,12 +61,12 @@ void sequence_traits_test()
string str1(Input);\
\
/* Copy test */ \
BOOST_CHECK( Algo##_copy( str1, BOOST_PP_SEQ_ENUM( Params ) )==Output );\
BOOST_CHECK( Algo##_copy( str1, Params )==Output );\
\
BOOST_CHECKPOINT( #Algo " - Iterator" );\
/* Iterator test */\
string strout;\
Algo##_copy( back_inserter(strout), str1, BOOST_PP_SEQ_ENUM( Params ) );\
Algo##_copy( back_inserter(strout), str1, Params );\
BOOST_CHECK( strout==Output ); \
\
/* In-place test */\
@ -71,98 +74,136 @@ void sequence_traits_test()
list<char> list1( str1.begin(), str1.end() );\
\
BOOST_CHECKPOINT( #Algo " - Inplace(string)" );\
Algo( str1, BOOST_PP_SEQ_ENUM( Params ) ); \
Algo( str1, Params ); \
BOOST_CHECK( equals( str1, Output ) ); \
\
BOOST_CHECKPOINT( #Algo " - Inplace(vector)" );\
Algo( vec1, BOOST_PP_SEQ_ENUM( Params ) ); \
Algo( vec1, Params ); \
BOOST_CHECK( equals( vec1, Output ) );\
\
BOOST_CHECKPOINT( #Algo " - Inplace(list)" );\
Algo( list1, BOOST_PP_SEQ_ENUM( Params ) ); \
Algo( list1, Params ); \
BOOST_CHECK( equals( list1, Output ) );\
}
void replace_test()
void replace_first_test()
{
// replace first
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("YYY")), string("1YYY3abc2") );
TEST_ALGO( ireplace_first, "1AbC3abc2", ("aBc")("YYY"), string("1YYY3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("Z")), string("1Z3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("XXXX")), string("1XXXX3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", (string(""))(string("XXXX")), string("1abc3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", ("")("XXXX"), string("1abc3abc2") );
TEST_ALGO( replace_first, "", (string(""))(string("XXXX")), string("") );
TEST_ALGO( erase_first, "1abc3abc2", (string("abc")), string("13abc2") );
TEST_ALGO( ierase_first, "1aBc3abc2", ("abC"), "13abc2" );
TEST_ALGO( erase_first, "1abc3abc2", ("abc"), "13abc2" );
TEST_ALGO( erase_first, "1abc3abc2", (string("")), string("1abc3abc2") );
TEST_ALGO( erase_first, "", (string("abc")), string("") );
TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("YYY"), string("1YYY3abc2") );
TEST_ALGO( ireplace_first, "1AbC3abc2", "aBc" C_ "YYY", string("1YYY3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("Z"), string("1Z3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("XXXX"), string("1XXXX3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", string("") C_ string("XXXX"), string("1abc3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", "" C_ "XXXX", string("1abc3abc2") );
TEST_ALGO( replace_first, "", string("") C_ string("XXXX"), string("") );
TEST_ALGO( erase_first, "1abc3abc2", string("abc"), string("13abc2") );
TEST_ALGO( ierase_first, "1aBc3abc2", "abC", "13abc2" );
TEST_ALGO( erase_first, "1abc3abc2", "abc", "13abc2" );
TEST_ALGO( erase_first, "1abc3abc2", string(""), string("1abc3abc2") );
TEST_ALGO( erase_first, "", string("abc"), string("") );
}
void replace_last_test()
{
// replace last
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("YYY")), string("1abc3YYY2") );
TEST_ALGO( ireplace_last, "1abc3AbC2", ("aBc")("YYY"), string("1abc3YYY2") );
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("Z")), string("1abc3Z2") );
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("XXXX")), string("1abc3XXXX2") );
TEST_ALGO( replace_last, "1abc3abc2", ("abc")("XXXX"), string("1abc3XXXX2") );
TEST_ALGO( replace_last, "", (string(""))(string("XXXX")), string("") );
TEST_ALGO( erase_last, "1abc3abc2", (string("abc")), string("1abc32") );
TEST_ALGO( ierase_last, "1aBc3aBc2", ("ABC"), string("1aBc32") );
TEST_ALGO( erase_last, "1abc3abc2", ("abc"), string("1abc32") );
TEST_ALGO( erase_last, "1abc3abc2", (string("")), string("1abc3abc2") );
TEST_ALGO( erase_last, "", (string("abc")), string("") );
TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("YYY"), string("1abc3YYY2") );
TEST_ALGO( ireplace_last, "1abc3AbC2", "aBc" C_ "YYY", string("1abc3YYY2") );
TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("Z"), string("1abc3Z2") );
TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("XXXX"), string("1abc3XXXX2") );
TEST_ALGO( replace_last, "1abc3abc2", "abc" C_ "XXXX", string("1abc3XXXX2") );
TEST_ALGO( replace_last, "", string("") C_ string("XXXX"), string("") );
TEST_ALGO( erase_last, "1abc3abc2", string("abc"), string("1abc32") );
TEST_ALGO( ierase_last, "1aBc3aBc2", "ABC", string("1aBc32") );
TEST_ALGO( erase_last, "1abc3abc2", "abc", string("1abc32") );
TEST_ALGO( erase_last, "1abc3abc2", string(""), string("1abc3abc2") );
TEST_ALGO( erase_last, "", string("abc"), string("") );
}
void replace_all_test()
{
// replace all
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("YYY")), string("1YYY3YYY2") );
TEST_ALGO( ireplace_all, "1aBc3AbC2", ("abC")("YYY"), string("1YYY3YYY2") );
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("Z")), string("1Z3Z2") );
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("XXXX")), string("1XXXX3XXXX2") );
TEST_ALGO( replace_all, "1abc3abc2", ("abc")("XXXX"), string("1XXXX3XXXX2") );
TEST_ALGO( replace_all, "", (string(""))(string("XXXX")), string("") );
TEST_ALGO( erase_all, "1abc3abc2", (string("abc")), string("132") );
TEST_ALGO( ierase_all, "1aBc3aBc2", ("aBC"), string("132") );
TEST_ALGO( erase_all, "1abc3abc2", ("abc"), string("132") );
TEST_ALGO( erase_all, "1abc3abc2", (string("")), string("1abc3abc2") );
TEST_ALGO( erase_all, "", (string("abc")), string("") );
TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("YYY"), string("1YYY3YYY2") );
TEST_ALGO( replace_all, string("1abc3abc2"), "/" C_ "\\", string("1abc3abc2") );
TEST_ALGO( ireplace_all, "1aBc3AbC2", "abC" C_ "YYY", string("1YYY3YYY2") );
TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("Z"), string("1Z3Z2") );
TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("XXXX"), string("1XXXX3XXXX2") );
TEST_ALGO( replace_all, "1abc3abc2", "abc" C_ "XXXX", string("1XXXX3XXXX2") );
TEST_ALGO( replace_all, "", string("") C_ string("XXXX"), string("") );
TEST_ALGO( erase_all, "1abc3abc2", string("abc"), string("132") );
TEST_ALGO( ierase_all, "1aBc3aBc2", "aBC", string("132") );
TEST_ALGO( erase_all, "1abc3abc2", "abc", string("132") );
TEST_ALGO( erase_all, "1abc3abc2", string(""), string("1abc3abc2") );
TEST_ALGO( erase_all, "", string("abc"), string("") );
}
void replace_nth_test()
{
// replace nth
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("YYY")), string("1YYY3abc2") );
TEST_ALGO( ireplace_nth, "1AbC3abc2", ("aBc")(0)("YYY"), string("1YYY3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("Z")), string("1Z3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("XXXX")), string("1XXXX3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", ("abc")(0)("XXXX"), string("1XXXX3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string(""))(0)(string("XXXX")), string("1abc3abc2") );
TEST_ALGO( replace_nth, "", (string(""))(0)(string("XXXX")), string("") );
TEST_ALGO( erase_nth, "1abc3abc2", (string("abc"))(0), string("13abc2") );
TEST_ALGO( ierase_nth, "1aBc3aBc2", ("ABC")(0), string("13aBc2") );
TEST_ALGO( erase_nth, "1abc3abc2", ("abc")(0), string("13abc2") );
TEST_ALGO( erase_nth, "1abc3abc2", (string(""))(0), string("1abc3abc2") );
TEST_ALGO( erase_nth, "", (string("abc"))(0), string("") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(1)(string("YYY")), string("1abc3YYY2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(2)(string("YYY")), string("1abc3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("YYY"), string("1YYY3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ -1 C_ string("YYY"), string("1abc3YYY2") );
TEST_ALGO( ireplace_nth, "1AbC3abc2", "aBc" C_ 0 C_ "YYY", string("1YYY3abc2") );
TEST_ALGO( ireplace_nth, "1AbC3abc2", "aBc" C_ -1 C_ "YYY", string("1AbC3YYY2") );
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("Z"), string("1Z3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("XXXX"), string("1XXXX3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ 0 C_ "XXXX", string("1XXXX3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ 3 C_ "XXXX", string("1abc3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ -3 C_ "XXXX", string("1abc3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", string("") C_ 0 C_ string("XXXX"), string("1abc3abc2") );
TEST_ALGO( replace_nth, "", string("") C_ 0 C_ string("XXXX"), string("") );
TEST_ALGO( replace_nth, "", string("") C_ -1 C_ string("XXXX"), string("") );
TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ 0, string("13abc2") );
TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ -1, string("1abc32") );
TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ -3, string("1abc3abc2") );
TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ 0, string("13aBc2") );
TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ -1, string("1aBc32") );
TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ -3, string("1aBc3aBc2") );
TEST_ALGO( erase_nth, "1abc3abc2", "abc" C_ 0, string("13abc2") );
TEST_ALGO( erase_nth, "1abc3abc2", string("") C_ 0, string("1abc3abc2") );
TEST_ALGO( erase_nth, "", string("abc") C_ 0, string("") );
TEST_ALGO( erase_nth, "", string("abc") C_ -1, string("") );
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 1 C_ string("YYY"), string("1abc3YYY2") );
TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 2 C_ string("YYY"), string("1abc3abc2") );
}
void replace_head_test()
{
// replace head
TEST_ALGO( replace_head, "abc3abc2", (3)(string("YYY")), string("YYY3abc2") );
TEST_ALGO( replace_head, "abc3abc2", (3)("YYY"), string("YYY3abc2") );
TEST_ALGO( replace_head, "abc", (3)(string("Z")), string("Z") );
TEST_ALGO( replace_head, "abc", (6)(string("XXXX")), string("XXXX") );
TEST_ALGO( replace_head, "abc3abc2", (0)(string("XXXX")), string("abc3abc2") );
TEST_ALGO( replace_head, "", (4)(string("XXXX")), string("") );
TEST_ALGO( erase_head, "abc3abc2", (3), string("3abc2") );
TEST_ALGO( erase_head, "abc3abc2", (0), string("abc3abc2") );
TEST_ALGO( erase_head, "", (4), string("") );
TEST_ALGO( replace_head, "abc3abc2", 3 C_ string("YYY"), string("YYY3abc2") );
TEST_ALGO( replace_head, "abc3abc2", -3 C_ string("YYY"), string("YYYbc2") );
TEST_ALGO( replace_head, "abc3abc2", 3 C_ "YYY", string("YYY3abc2") );
TEST_ALGO( replace_head, "abc", 3 C_ string("Z"), string("Z") );
TEST_ALGO( replace_head, "abc", 6 C_ string("XXXX"), string("XXXX") );
TEST_ALGO( replace_head, "abc", -6 C_ string("XXXX"), string("abc") );
TEST_ALGO( replace_head, "abc3abc2", 0 C_ string("XXXX"), string("abc3abc2") );
TEST_ALGO( replace_head, "", 4 C_ string("XXXX"), string("") );
TEST_ALGO( replace_head, "", -4 C_ string("XXXX"), string("") );
TEST_ALGO( erase_head, "abc3abc2", 3, string("3abc2") );
TEST_ALGO( erase_head, "abc3abc2", -3, string("bc2") );
TEST_ALGO( erase_head, "abc3abc2", 0, string("abc3abc2") );
TEST_ALGO( erase_head, "", 4, string("") );
TEST_ALGO( erase_head, "", -4, string("") );
}
void replace_tail_test()
{
// replace tail
TEST_ALGO( replace_tail, "abc3abc", (3)(string("YYY")), string("abc3YYY") );
TEST_ALGO( replace_tail, "abc3abc", (3)("YYY"), string("abc3YYY") );
TEST_ALGO( replace_tail, "abc", (3)(string("Z")), string("Z") );
TEST_ALGO( replace_tail, "abc", (6)(string("XXXX")), string("XXXX") );
TEST_ALGO( replace_tail, "abc3abc", (0)(string("XXXX")), string("abc3abc") );
TEST_ALGO( replace_tail, "", (4)(string("XXXX")), string("") );
TEST_ALGO( erase_tail, "abc3abc", (3), string("abc3") );
TEST_ALGO( erase_tail, "abc3abc", (0), string("abc3abc") );
TEST_ALGO( erase_tail, "", (4), string("") );
TEST_ALGO( replace_tail, "abc3abc", 3 C_ string("YYY"), string("abc3YYY") );
TEST_ALGO( replace_tail, "abc3abc", -3 C_ "YYY", string("abcYYY") );
TEST_ALGO( replace_tail, "abc", 3 C_ string("Z"), string("Z") );
TEST_ALGO( replace_tail, "abc", 6 C_ string("XXXX"), string("XXXX") );
TEST_ALGO( replace_tail, "abc", -6 C_ string("XXXX"), string("abc") );
TEST_ALGO( replace_tail, "abc3abc", 0 C_ string("XXXX"), string("abc3abc") );
TEST_ALGO( replace_tail, "", 4 C_ string("XXXX"), string("") );
TEST_ALGO( replace_tail, "", -4 C_ string("XXXX"), string("") );
TEST_ALGO( erase_tail, "abc3abc", 3, string("abc3") );
TEST_ALGO( erase_tail, "abc3abc", -3, string("abc") );
TEST_ALGO( erase_tail, "abc3abc", 0, string("abc3abc") );
TEST_ALGO( erase_tail, "", 4, string("") );
TEST_ALGO( erase_tail, "", -4, string("") );
}
void replace_range_test()
{
// replace_range
{
BOOST_CHECKPOINT( "replace_range" );
@ -210,8 +251,11 @@ void replace_test()
make_iterator_range(str1.begin()+1, str1.begin()+4));
BOOST_CHECK( str1==string("13abc2") );
}
}
// container traits complatibility tests
void collection_comp_test()
{
// container traits compatibility tests
{
string strout;
replace_first_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" );
@ -244,11 +288,36 @@ void replace_test()
}
}
void dissect_format_test()
{
BOOST_CHECK(
find_format_all_copy(
string("aBc123Abc"),
first_finder("abc", is_iequal()),
dissect_formatter(token_finder(is_upper())))=="B123A");
BOOST_CHECK(
find_format_all_copy(
string("abc 123 abc"),
token_finder(is_space(), token_compress_on),
dissect_formatter(head_finder(1)))=="abc 123 abc");
}
// test main
int test_main( int, char*[] )
{
sequence_traits_test();
replace_test();
replace_first_test();
replace_last_test();
replace_all_test();
replace_nth_test();
replace_head_test();
replace_tail_test();
replace_range_test();
collection_comp_test();
dissect_format_test();
return 0;
}

View File

@ -7,6 +7,11 @@
// See http://www.boost.org for updates, documentation, and revision history.
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
@ -15,11 +20,6 @@
#include <iostream>
#include <boost/test/test_tools.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
using namespace std;
@ -38,22 +38,33 @@ void deep_compare( const T1& X, const T2& Y )
void iterator_test()
{
string str1("xx-abc--xx-abb");
string str2("Xx-abc--xX-abb");
string str2("Xx-abc--xX-abb-xx");
string str3("xx");
char* pch1="xx-abc--xx-abb";
string strempty("");
const char* pch1="xx-abc--xx-abb";
vector<string> tokens;
vector< vector<int> > vtokens;
// find_all tests
find_all(
tokens,
pch1,
"xx" );
BOOST_REQUIRE( tokens.size()==2 );
BOOST_CHECK( tokens[0]==string("xx") );
BOOST_CHECK( tokens[1]==string("xx") );
ifind_all(
tokens,
str2,
"xx" );
BOOST_REQUIRE( tokens.size()==2 );
BOOST_REQUIRE( tokens.size()==3 );
BOOST_CHECK( tokens[0]==string("Xx") );
BOOST_CHECK( tokens[1]==string("xX") );
BOOST_CHECK( tokens[2]==string("xx") );
// find_all tests
find_all(
tokens,
str1,
@ -63,7 +74,6 @@ void iterator_test()
BOOST_CHECK( tokens[0]==string("xx") );
BOOST_CHECK( tokens[1]==string("xx") );
find_all(
vtokens,
str1,
@ -73,14 +83,15 @@ void iterator_test()
// split tests
split(
tokens,
str1,
is_any_of("x"),
str2,
is_any_of("xX"),
token_compress_on );
BOOST_REQUIRE( tokens.size()==3 );
BOOST_REQUIRE( tokens.size()==4 );
BOOST_CHECK( tokens[0]==string("") );
BOOST_CHECK( tokens[1]==string("-abc--") );
BOOST_CHECK( tokens[2]==string("-abb") );
BOOST_CHECK( tokens[2]==string("-abb-") );
BOOST_CHECK( tokens[3]==string("") );
split(
tokens,
@ -112,6 +123,45 @@ void iterator_test()
BOOST_CHECK( tokens[2]==string("") );
BOOST_CHECK( tokens[3]==string("xx") );
BOOST_CHECK( tokens[4]==string("abb") );
split(
tokens,
str3,
is_any_of(","),
token_compress_off);
BOOST_REQUIRE( tokens.size()==1 );
BOOST_CHECK( tokens[0]==string("xx") );
split(
tokens,
strempty,
is_punct(),
token_compress_off);
BOOST_REQUIRE( tokens.size()==1 );
BOOST_CHECK( tokens[0]==string("") );
find_iterator<string::iterator> fiter=make_find_iterator(str1, first_finder("xx"));
BOOST_CHECK(equals(*fiter, "xx"));
++fiter;
BOOST_CHECK(equals(*fiter, "xx"));
++fiter;
BOOST_CHECK(fiter==find_iterator<string::iterator>());
split_iterator<string::iterator> siter=make_split_iterator(str1, token_finder(is_any_of("-"), token_compress_on));
BOOST_CHECK(equals(*siter, "xx"));
++siter;
BOOST_CHECK(equals(*siter, "abc"));
++siter;
BOOST_CHECK(equals(*siter, "xx"));
++siter;
BOOST_CHECK(equals(*siter, "abb"));
++siter;
BOOST_CHECK(siter==split_iterator<string::iterator>(siter));
BOOST_CHECK(siter==split_iterator<string::iterator>());
}
// test main

View File

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