[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
# Boost string_algo library documentation 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 toolset ;
toolset.using doxygen ;
boostbook string_algo : string_algo.xml autodoc
:
<xsl:param>boost.root=../../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
doxygen autodoc
:
[ glob ../../../../boost/algorithm/string.hpp ]
[ glob ../../../../boost/algorithm/string_regex.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 ]
[ glob ../../../../boost/algorithm/string/trim_all.hpp ]
:
<doxygen:param>HIDE_UNDOC_MEMBERS=YES
<doxygen:param>EXTRACT_PRIVATE=NO
<doxygen:param>ENABLE_PREPROCESSING=YES
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>EXPAND_ONLY_PREDEF=YES
<doxygen:param>SEARCH_INCLUDES=YES
<doxygen:param>PREDEFINED="BOOST_STRING_TYPENAME=typename \"BOOST_STATIC_CONSTANT(type,var)=static const type var;\""
;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,205 @@
<?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::algorithm"/>
<section>
<title>Definitions</title>
<table>
<title>Notation</title>
<tgroup cols="2" align="left">
<tbody>
<row>
<entry><code>F</code></entry>
<entry>A type that is a model of Finder</entry>
</row>
<row>
<entry><code>Fmt</code></entry>
<entry>A type that is a model of Formatter</entry>
</row>
<row>
<entry><code>Iter</code></entry>
<entry>
Iterator Type
</entry>
</row>
<row>
<entry><code>f</code></entry>
<entry>Object of type <code>F</code></entry>
</row>
<row>
<entry><code>fmt</code></entry>
<entry>Object of type <code>Fmt</code></entry>
</row>
<row>
<entry><code>i,j</code></entry>
<entry>Objects of type <code>Iter</code></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section id="string_algo.finder_concept">
<title>Finder Concept</title>
<para>
Finder is a functor which searches for an arbitrary part of a container.
The result of the search is given as an <classname>iterator_range</classname>
delimiting the selected part.
</para>
<table>
<title>Valid Expressions</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Expression</entry>
<entry>Return Type</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>f(i,j)</code></entry>
<entry>Convertible to <code>iterator_range&lt;Iter&gt;</code></entry>
<entry>Perform the search on the interval [i,j) and returns the result of the search</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
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.
</para>
<para>
Note, that it is only required that the finder works with a particular iterator type. However,
a Finder operation can be defined as a template, allowing the Finder to work with any iterator.
</para>
<para>
<emphasis role="bold">Examples</emphasis>
</para>
<para>
<itemizedlist>
<listitem>
Finder implemented as a class. This Finder always returns the whole input as a match. <code>operator()</code>
is templated, so that the finder can be used on any iterator type.
<programlisting>
struct simple_finder
{
template&lt;typename ForwardIteratorT&gt;
boost::iterator_range&lt;ForwardIteratorT&gt; operator()(
ForwardIteratorT Begin,
ForwardIteratorT End )
{
return boost::make_range( Begin, End );
}
};
</programlisting>
</listitem>
<listitem>
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.
<programlisting>
boost::iterator_range&lt;std::string&gt; simple_finder(
std::string::const_iterator Begin,
std::string::const_iterator End )
{
return boost::make_range( Begin, End );
}
</programlisting>
</listitem>
</itemizedlist>
</para>
</section>
<section id="string_algo.formatter_concept">
<title>Formatter concept</title>
<para>
Formatters are used by <link linkend="string_algo.replace">replace algorithms</link>.
They are used in close combination with finders.
A formatter is a functor, which takes a result from a Finder operation and transforms it in a specific way.
The operation of the formatter can use additional information provided by a specific finder,
for example <functionname>regex_formatter()</functionname> uses the match information from
<functionname>regex_finder()</functionname> to format the result of formatter operation.
</para>
<table>
<title>Valid Expressions</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Expression</entry>
<entry>Return Type</entry>
<entry>Effects</entry>
</row>
</thead>
<tbody>
<row>
<entry><code>fmt(f(i,j))</code></entry>
<entry>A container type, accessible using container traits</entry>
<entry>Formats the result of the finder operation</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Similarly to finders, formatters generalize format operations. When a finder is used to
select a part of the input, formatter takes this selection and performs some formatting
on it. Algorithms can abstract from formatting using a formatter.
</para>
<para>
<emphasis role="bold">Examples</emphasis>
</para>
<para>
<itemizedlist>
<listitem>
Formatter implemented as a class. This Formatter does not perform any formatting and
returns the match, repackaged. <code>operator()</code>
is templated, so that the Formatter can be used on any Finder type.
<programlisting>
struct simple_formatter
{
template&lt;typename FindResultT&gt;
std::string operator()( const FindResultT&amp; Match )
{
std::string Temp( Match.begin(), Match.end() );
return Temp;
}
};
</programlisting>
</listitem>
<listitem>
Function Formatter. Similarly to Finder, Formatter can be any function object.
However, as a function, it can be used only with a specific Finder type.
<programlisting>
std::string simple_formatter( boost::iterator_range&lt;std::string::const_iterator&gt;&amp; Match )
{
std::string Temp( Match.begin(), Match.end() );
return Temp;
}
</programlisting>
</listitem>
</itemizedlist>
</para>
</section>
</section>

View File

@@ -0,0 +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>
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

@@ -0,0 +1,223 @@
<?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::algorithm"/>
<section id="string_algo.string">
<title>String Representation</title>
<para>
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>
<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>
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.sequence_traits">
<title>Sequence Traits</title>
<para>
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
of a particular container.
</para>
<para>
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/algorithm/string/sequence_traits.hpp</headername>.
</para>
<para>
In the table C denotes a container and c is an object of C.
</para>
<table>
<title>Sequence Traits</title>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Trait</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<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>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>
do not invalidate iterators.
</entry>
</row>
<row>
<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>has_const_time_erase&lt;C&gt;</classname>::value</entry>
<entry>
Specifies that the erase method of the sequence has constant time complexity
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Current implementation contains specializations for std::list&lt;T&gt; and
std::basic_string&lt;T&gt; from the standard library and SGI's std::rope&lt;T&gt; and std::slist&lt;T&gt;.
</para>
</section>
<section id="string_algo.find">
<title>Find Algorithms</title>
<para>
Find algorithms have similar functionality to <code>std::search()</code> algorithm. They provide a different
interface which is more suitable for common string operations.
Instead of returning just the start of matching subsequence they return a range which is necessary
when the length of the matching subsequence is not known beforehand.
This feature also allows a partitioning of the input sequence into three
parts: a prefix, a substring and a suffix.
</para>
<para>
Another difference is an addition of various searching methods besides find_first, including find_regex.
</para>
<para>
It the library, find algorithms are implemented in terms of
<link linkend="string_algo.finder_concept">Finders</link>. Finders are used also by other facilities
(replace,split).
For convenience, there are also function wrappers for these finders to simplify find operations.
</para>
<para>
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 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
complexity as an option
</para>
</section>
<section id="string_algo.replace">
<title>Replace Algorithms</title>
<para>
The implementation of replace algorithms follows the layered structure of the library. The
lower layer implements generic substitution of a range in the input sequence.
This layer takes a <link linkend="string_algo.finder_concept">Finder</link> object and a
<link linkend="string_algo.formatter_concept">Formatter</link> object as an input. These two
functors define what to replace and what to replace it with. The upper layer functions
are just wrapping calls to the lower layer. Finders are shared with the find and split facility.
</para>
<para>
As usual, the implementation of the lower layer is designed to work with a generic sequence while
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>Find Iterators &amp; Split Algorithms</title>
<para>
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

@@ -0,0 +1,65 @@
<?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>
<title>Build</title>
<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/algorithm/string_regex.hpp</headername>.
If this header is used, the application must be linked with the <libraryname>Boost.Regex</libraryname>
library.
</para>
</section>
<section>
<title>Examples</title>
<para>
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.
</para>
</section>
<section>
<title>Tests</title>
<para>
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>
</section>
<section>
<title>Portability</title>
<para>
The library has been successfully compiled and tested with the following compilers:
<itemizedlist>
<listitem>Microsoft Visual C++ 7.0</listitem>
<listitem>Microsoft Visual C++ 7.1</listitem>
<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 <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

@@ -0,0 +1,54 @@
<?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>
<para>
The String Algorithm Library provides a generic implementation of
string-related algorithms which are missing in STL. It is an extension
to the algorithms library of STL and it includes trimming, case conversion,
predicates and find/replace functions. All of them come in different variants
so it is easier to choose the best fit for a particular need.
</para>
<para>
The implementation is not restricted to work with a particular container
(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 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 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.
See the <link linkend="string_algo.reference">Reference</link> for the complete list of provided utilities
and algorithms. Functions and classes in the reference are organized by the headers in which they are defined.
The reference contains links to the detailed description for every entity in the library.
</para>
</section>

View File

@@ -0,0 +1,758 @@
<?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>
<row>
<entry>is_any_of</entry>
<entry>Recognize any of a sequence of characters</entry>
<entry>
<functionname>is_any_of()</functionname>
</entry>
</row>
<row>
<entry>is_from_range</entry>
<entry>Recognize characters inside a min..max range</entry>
<entry>
<functionname>is_from_range()</functionname>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>

View File

@@ -0,0 +1,52 @@
<?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::algorithm"/>
<section it="string_algo.locale">
<title>Locales</title>
<para>
Locales have a very close relation to string processing. They contain information about
the character sets and are used, for example, to change the case of characters and
to classify the characters.
</para>
<para>
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 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. 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>
</section>
<section id="string_algo.regex">
<title>Regular Expressions</title>
<para>
Regular expressions are an essential part of text processing. For this reason, the library
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>
</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 algorithms
(<code>*_head/tail</code>, <code>*_nth</code>).
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</section>

View File

@@ -0,0 +1,52 @@
<?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)
-->
<library name="String Algorithms" dirname="algorithm/string" xmlns:xi="http://www.w3.org/2001/XInclude"
id="string_algo" last-revision="$Date$">
<libraryinfo>
<author>
<firstname>Pavol</firstname>
<surname>Droba</surname>
</author>
<copyright>
<year>2002</year>
<year>2003</year>
<year>2004</year>
<holder>Pavol Droba</holder>
</copyright>
<legalnotice>
<para>Use, modification and distribution is subject to the Boost
Software License, Version 1.0. (See accompanying file
<filename>LICENSE_1_0.txt</filename> or copy at <ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>
</legalnotice>
<librarypurpose>
A set of generic string-related algorithms and utilities
</librarypurpose>
<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="autodoc.xml"/>
<xi:include href="rationale.xml"/>
<xi:include href="environment.xml"/>
<xi:include href="credits.xml"/>
</library>

View File

@@ -0,0 +1,366 @@
<?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::algorithm"/>
<section>
<title>First Example</title>
<para>
Using the algorithms is straightforward. Let us have a look at the first example:
</para>
<programlisting>
#include &lt;boost/algorithm/string.hpp&gt;
using namespace std;
using namespace boost;
// ...
string str1(" hello world! ");
to_upper(str1); // str1 == " HELLO WORLD! "
trim(str1); // str1 == "HELLO 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
of the string. str2 is then created as a copy of str1 with "hello" replaced with "goodbye".
This example demonstrates several important concepts used in the library:
</para>
<itemizedlist>
<listitem>
<para><emphasis role="bold">Container parameters:</emphasis>
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 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>, than <code>to_lower(str1.begin(), str1.end())</code>.
</para>
<para>
The magic of <ulink url="../../libs/range/index.html">Boost.Range</ulink>
provides a uniform way of handling different string types.
If there is a need to pass a pair of iterators,
<ulink url="../../libs/range/doc/html/range/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>
<para><emphasis role="bold">Copy vs. Mutable:</emphasis>
Many algorithms in the library are performing a transformation of the input.
The transformation can be done in-place, mutating the input sequence, or a copy
of the transformed input can be created, leaving the input intact. None of
these possibilities is superior to the other one and both have different
advantages and disadvantages. For this reason, both are provided with the library.
</para>
</listitem>
<listitem>
<para><emphasis role="bold">Algorithm stacking:</emphasis>
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 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/algorithm/string.hpp</headername> header.
If the regex related functions are needed, include the
<headername>boost/algorithm/string_regex.hpp</headername> header.
</para>
</section>
<section>
<title>Case conversion</title>
<para>
STL has a nice way of converting character case. Unfortunately, it works only
for a single character and we want to convert a string,
</para>
<programlisting>
string str1("HeLlO WoRld!");
to_upper(str1); // str1=="HELLO WORLD!"
</programlisting>
<para>
<functionname>to_upper()</functionname> and <functionname>to_lower()</functionname> convert the case of
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>
<title>Predicates and Classification</title>
<para>
A part of the library deals with string related predicates. Consider this example:
</para>
<programlisting>
bool is_executable( string&amp; filename )
{
return
iends_with(filename, ".exe") ||
iends_with(filename, ".com");
}
// ...
string str1("command.com");
cout
&lt;&lt; str1
&lt;&lt; (is_executable(str1)? "is": "is not")
&lt;&lt; "an executable"
&lt;&lt; endl; // prints "command.com is an executable"
//..
char text1[]="hello";
cout
&lt;&lt; text1
&lt;&lt; (all( text1, is_lower() )? " is": " is not")
&lt;&lt; " written in the lower case"
&lt;&lt; endl; // prints "hello is written in the lower case"
</programlisting>
<para>
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/algorithm/string/predicate.hpp</headername> for more details.
</para>
<para>
Note that if we had used "hello world" as the input to the test, it would have
output "hello world is not written in the lower case" because the space in the
input string is not a lower case letter.
</para>
<para>
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 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 from a user, strings often 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(str1); // str3 == " hello world!"
trim(str1); // str1 == "hello world!"
string phone="00423333444";
// remove leading 0 from the phone number
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 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>
<title>Find algorithms</title>
<para>
The library contains a set of find algorithms. Here is an example:
</para>
<programlisting>
char text[]="hello dolly!";
iterator_range&lt;char*&gt; result=find_last(text,"ll");
transform( result.begin(), result.end(), result.begin(), bind2nd(plus&lt;char&gt;(), 1) );
// 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 <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
<ulink url="../../libs/range/index.html">Boost.Range</ulink>.
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 string. Replace goes one step
further. After a matching part is found, it is substituted with something else. The substitution is computed
from the original, using some transformation.
</para>
<programlisting>
string str1="Hello Dolly, Hello World!"
replace_first(str1, "Dolly", "Jane"); // str1 == "Hello Jane, Hello World!"
replace_last(str1, "Hello", "Goodbye"); // str1 == "Hello Jane, Goodbye World!"
erase_all(str1, " "); // str1 == "HelloJane,GoodbyeWorld!"
erase_head(str1, 6); // str1 == "Jane,GoodbyeWorld!"
</programlisting>
<para>
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>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.
The Finder object is a functor which performs the searching for the replacement part. The Formatter object
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 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>
string str1("hello abc-*-ABC-*-aBc goodbye");
typedef vector&lt; iterator_range&lt;string::iterator&gt; &gt; find_vector_type;
find_vector_type FindVec; // #1: Search for separators
ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] }
typedef vector&lt; string &gt; split_vector_type;
split_vector_type SplitVec; // #2: Search for tokens
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>
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>
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>
More information can be found in the reference: <headername>boost/algorithm/string/split.hpp</headername>.
</para>
</section>
</section>

View File

@@ -0,0 +1,18 @@
# Boost string_algo library examples 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.
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

@@ -0,0 +1,41 @@
// Boost string_algo library example 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 <string>
#include <vector>
#include <iostream>
#include <iterator>
#include <boost/algorithm/string/case_conv.hpp>
using namespace std;
using namespace boost;
int main()
{
cout << "* Case Conversion Example *" << endl << endl;
string str1("AbCdEfG");
vector<char> vec1( str1.begin(), str1.end() );
// Convert vector of chars to lower case
cout << "lower-cased copy of vec1: ";
to_lower_copy( ostream_iterator<char>(cout), vec1 );
cout << endl;
// Conver string str1 to upper case ( copy the input )
cout << "upper-cased copy of str1: " << to_upper_copy( str1 ) << endl;
// Inplace conversion
to_lower( str1 );
cout << "lower-cased str1: " << str1 << endl;
cout << endl;
return 0;
}

View File

@@ -0,0 +1,58 @@
// Boost string_algo library example 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 <string>
#include <iostream>
#include <algorithm>
#include <functional>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/find.hpp>
using namespace std;
using namespace boost;
int main()
{
cout << "* Find Example *" << endl << endl;
string str1("abc___cde___efg");
string str2("abc");
// find "cde" substring
iterator_range<string::iterator> range=find_first( str1, string("cde") );
// convert a substring to upper case
// note that iterator range can be directly passed to the algorithm
to_upper( range );
cout << "str1 with upper-cased part matching cde: " << str1 << endl;
// get a head of the string
iterator_range<string::iterator> head=find_head( str1, 3 );
cout << "head(3) of the str1: " << string( head.begin(), head.end() ) << endl;
// get the tail
head=find_tail( str2, 5 );
cout << "tail(5) of the str2: " << string( head.begin(), head.end() ) << endl;
// char processing
char text[]="hello dolly!";
iterator_range<char*> crange=find_last(text,"ll");
// transform the range ( add 1 )
transform( crange.begin(), crange.end(), crange.begin(), bind2nd( plus<char>(), 1 ) );
// uppercase the range
to_upper( crange );
cout << text << endl;
cout << endl;
return 0;
}

View File

@@ -0,0 +1,61 @@
// Boost string_algo library example 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 <string>
#include <iostream>
#include <functional>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/bind.hpp>
using namespace std;
using namespace boost;
int main()
{
cout << "* Predicate Example *" << endl << endl;
string str1("123xxx321");
string str2("abc");
// Check if str1 starts with '123'
cout << "str1 starts with \"123\": " <<
(starts_with( str1, string("123") )?"true":"false") << endl;
// Check if str1 ends with '123'
cout << "str1 ends with \"123\": " <<
(ends_with( str1, string("123") )?"true":"false") << endl;
// Check if str1 contains 'xxx'
cout << "str1 contains \"xxx\": " <<
(contains( str1, string("xxx") )?"true":"false") << endl;
// Check if str2 equals to 'abc'
cout << "str2 equals \"abc\": " <<
(equals( str2, string("abc") )?"true":"false") << endl;
// Classification functors and all predicate
if ( all(";.,", is_punct() ) )
{
cout << "\";.,\" are all punctuation characters" << endl;
}
// Classification predicates can be combined
if ( all("abcxxx", is_any_of("xabc") && !is_space() ) )
{
cout << "true" << endl;
}
cout << endl;
return 0;
}

View File

@@ -0,0 +1,42 @@
// Boost string_algo library example 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 <string>
#include <iostream>
#include <iterator>
#include <boost/regex.hpp>
#include <boost/algorithm/string/regex.hpp>
using namespace std;
using namespace boost;
int main()
{
cout << "* Regex Example *" << endl << endl;
string str1("abc__(456)__123__(123)__cde");
// Replace all substrings matching (digit+)
cout <<
"replace all (digit+) in str1 with #digit+# :" <<
replace_all_regex_copy( str1, regex("\\(([0-9]+)\\)"), string("#$1#") ) << endl;
// Erase all substrings matching (digit+)
cout <<
"remove all sequences of letters from str1 :" <<
erase_all_regex_copy( str1, regex("[[:alpha:]]+") ) << endl;
// in-place regex transformation
replace_all_regex( str1, regex("_(\\([^\\)]*\\))_"), string("-$1-") );
cout << "transformad str1: " << str1 << endl;
cout << endl;
return 0;
}

View File

@@ -0,0 +1,89 @@
// Boost string_algo library example 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 <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.hpp>
//Following two includes contain second-layer function.
//They are already included by first-layer header
//#include <boost/algorithm/string/replace2.hpp>
//#include <boost/algorithm/string/find2.hpp>
using namespace std;
using namespace boost;
// uppercase formatter
/*
Convert an input to upper case.
Note, that this formatter can be used only on std::string inputs.
*/
inline string upcase_formatter(
const iterator_range<string::const_iterator>& Replace )
{
string Temp(Replace.begin(), Replace.end());
to_upper(Temp);
return Temp;
}
int main()
{
cout << "* Replace Example *" << endl << endl;
string str1("abc___cde___efg");
// Erase 6-9th characters from the string
cout << "str1 without 6th to 9th character:" <<
erase_range_copy( str1, make_iterator_range(str1.begin()+6, str1.begin()+9) ) << endl;
// Replace 6-9th character with '+++'
cout << "str1 with 6th to 9th character replaced with '+++': " <<
replace_range_copy(
str1, make_iterator_range(str1.begin()+6, str1.begin()+9), "+++" ) << endl;
cout << "str1 with 'cde' replaced with 'XYZ': ";
// Replace first 'cde' with 'XYZ'. Modify the input
replace_first_copy( ostream_iterator<char>(cout), str1, "cde", "XYZ" );
cout << endl;
// Replace all '___'
cout << "str1 with all '___' replaced with '---': " <<
replace_all_copy( str1, "___", "---" ) << endl;
// Erase all '___'
cout << "str1 without all '___': " <<
erase_all_copy( str1, "___" ) << endl;
// replace third and 5th occurrence of _ in str1
// note that nth argument is 0-based
replace_nth( str1, "_", 4, "+" );
replace_nth( str1, "_", 2, "+" );
cout << "str1 with third and 5th occurrence of _ replace: " << str1 << endl;
// Custom formatter examples
string str2("abC-xxxx-AbC-xxxx-abc");
// Find string 'abc' ignoring the case and convert it to upper case
cout << "Upcase all 'abc'(s) in the str2: " <<
find_format_all_copy(
str2,
first_finder("abc", is_iequal()),
upcase_formatter );
cout << endl;
return 0;
}

View File

@@ -0,0 +1,248 @@
// Boost string_algo library example 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.
/*
RLE compression using replace framework. Goal is to compress a sequence of
repeating characters into 3 bytes ( repeat mark, character and repetition count ).
For simplification, it works only on numeric-value sequences.
*/
#include <string>
#include <iostream>
#include <limits>
#include <boost/detail/iterator.hpp>
#include <boost/algorithm/string/find_format.hpp>
#include <boost/algorithm/string/finder.hpp>
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)(); };
// Compression -----------------------------------------------------------------------
// compress finder -rle
/*
Find a sequence which can be compressed. It has to be at least 3-character long
sequence of repetitive characters
*/
struct find_compressF
{
// Construction
find_compressF() {}
// Operation
template<typename ForwardIteratorT>
iterator_range<ForwardIteratorT> operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef typename boost::detail::iterator_traits<input_iterator_type>::value_type value_type;
typedef iterator_range<input_iterator_type> result_type;
// begin of the matching segment
input_iterator_type MStart=End;
// Repetition counter
value_type Cnt=0;
// Search for a sequence of repetitive characters
for(input_iterator_type It=Begin; It!=End;)
{
input_iterator_type It2=It++;
if ( It==End || Cnt>=(std::numeric_limits<value_type>::max)() )
{
return result_type( MStart, It );
}
if ( *It==*It2 )
{
if ( MStart==End )
{
// Mark the start
MStart=It2;
}
// Increate repetition counter
Cnt++;
}
else
{
if ( MStart!=End )
{
if ( Cnt>2 )
return result_type( MStart, It );
else
{
MStart=End;
Cnt=0;
}
}
}
}
return result_type( End, End );
}
};
// rle compress format
/*
Transform a sequence into repeat mark, character and count
*/
template<typename SeqT>
struct format_compressF
{
private:
typedef SeqT result_type;
typedef typename SeqT::value_type value_type;
public:
// Construction
format_compressF() {};
// Operation
template< typename ReplaceT >
result_type operator()( const ReplaceT& Replace ) const
{
SeqT r;
if(!Replace.empty())
{
r.push_back( repeat_mark<value_type>() );
r.push_back( *(Replace.begin()) );
r.push_back( value_type( Replace.size() ) );
}
return r;
}
};
// Decompression -----------------------------------------------------------------------
// find decompress-rle functor
/*
find a repetition block
*/
struct find_decompressF
{
// Construction
find_decompressF() {}
// Operation
template<typename ForwardIteratorT>
iterator_range<ForwardIteratorT> operator()(
ForwardIteratorT Begin,
ForwardIteratorT End ) const
{
typedef ForwardIteratorT input_iterator_type;
typedef typename boost::detail::iterator_traits<input_iterator_type>::value_type value_type;
typedef iterator_range<input_iterator_type> result_type;
for(input_iterator_type It=Begin; It!=End; It++)
{
if( *It==repeat_mark<value_type>() )
{
// Repeat mark found, extract body
input_iterator_type It2=It++;
if ( It==End ) break;
It++;
if ( It==End ) break;
It++;
return result_type( It2, It );
}
}
return result_type( End, End );
}
};
// rle decompress format
/*
transform a repetition block into a sequence of characters
*/
template< typename SeqT >
struct format_decompressF
{
private:
typedef SeqT result_type;
typedef typename SeqT::value_type value_type;
public:
// Construction
format_decompressF() {};
// Operation
template< typename ReplaceT >
result_type operator()( const ReplaceT& Replace ) const
{
SeqT r;
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;
}
};
int main()
{
cout << "* RLE Compression Example *" << endl << endl;
string original("123_AA_*ZZZZZZZZZZZZZZ*34");
// copy compression
string compress=find_format_all_copy(
original,
find_compressF(),
format_compressF<string>() );
cout << "Compressed string: " << compress << endl;
// Copy decompression
string decompress=find_format_all_copy(
compress,
find_decompressF(),
format_decompressF<string>() );
cout << "Decompressed string: " << decompress << endl;
// in-place compression
find_format_all(
original,
find_compressF(),
format_compressF<string>() );
cout << "Compressed string: " << original << endl;
// in-place decompression
find_format_all(
original,
find_decompressF(),
format_decompressF<string>() );
cout << "Decompressed string: " << original << endl;
cout << endl;
return 0;
}

View File

@@ -0,0 +1,62 @@
// Boost string_algo library example 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 <string>
#include <vector>
#include <iostream>
#include <iterator>
#include <functional>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/find_iterator.hpp>
using namespace std;
using namespace boost;
int main()
{
cout << "* Split Example *" << endl << endl;
string str1("abc-*-ABC-*-aBc");
cout << "Before: " << str1 << endl;
// Find all 'abc' substrings (ignoring the case)
// Create a find_iterator
typedef find_iterator<string::iterator> string_find_iterator;
for(string_find_iterator It=
make_find_iterator(str1, first_finder("abc", is_iequal()));
It!=string_find_iterator();
++It)
{
cout << copy_range<std::string>(*It) << endl;
// shift all chars in the match by one
transform(
It->begin(), It->end(),
It->begin(),
bind2nd( plus<char>(), 1 ) );
}
// Print the string now
cout << "After: " << str1 << endl;
// Split the string into tokens ( use '-' and '*' as delimiters )
// We need copies of the input only, and adjacent tokens are compressed
vector<std::string> ResultCopy;
split(ResultCopy, str1, is_any_of("-*"), token_compress_on);
for(unsigned int nIndex=0; nIndex<ResultCopy.size(); nIndex++)
{
cout << nIndex << ":" << ResultCopy[nIndex] << endl;
};
cout << endl;
return 0;
}

View File

@@ -0,0 +1,47 @@
// Boost string_algo library example 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 <string>
#include <iostream>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace std;
using namespace boost;
int main()
{
cout << "* Trim Example *" << endl << endl;
string str1(" 1x x x x1 ");
string str2("<>trim<>");
string str3("123abs343");
// Simple left trim
cout << "trim_left copy of str1: " << "\"" << trim_left_copy( str1 ) << "\"" << endl;
// Inplace right trim
trim_right( str1 );
cout << "trim_right on str1: " << "\"" << str1 << "\"" << endl;
// Parametric trim. 'Space' is defined using is_any_of predicate
cout
<< "trimmed copy of str4 ( space='<>' ): "
<< "\""<< trim_copy_if( str2, is_any_of("<>") ) << "\"" << endl;
// Parametric trim. 'Space' is defined using is_digit predicate
cout
<< "trimmed copy of str5 ( space=digit ): "
<< "\"" << trim_copy_if( str3, is_digit() ) << "\"" << endl;
cout << endl;
return 0;
}

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

@@ -0,0 +1,74 @@
# 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 ;
alias unit_test_framework
: # sources
/boost//unit_test_framework
;
test-suite algorithm/string
: [ run
trim_test.cpp unit_test_framework
: :
:
: trim
]
[ run
conv_test.cpp unit_test_framework
: :
:
: conv
]
[ run
predicate_test.cpp unit_test_framework
: :
:
: predicate
]
[ run
find_test.cpp unit_test_framework
: :
:
: find
]
[ run
split_test.cpp unit_test_framework
: :
:
: split
]
[ run
join_test.cpp unit_test_framework
: :
:
: join
]
[ run
replace_test.cpp unit_test_framework
: :
:
: replace
]
[ run
regex_test.cpp unit_test_framework
../../../regex/build//boost_regex
: :
:
: regex
]
[ run
find_format_test.cpp unit_test_framework
: :
:
: find_format
]
;

View File

@@ -0,0 +1,94 @@
// Boost string_algo library conv_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/case_conv.hpp>
// Include unit test framework
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <iostream>
#include <algorithm>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
void conv_test()
{
string str1("AbCdEfG 123 xxxYYYzZzZ");
string str2("AbCdEfG 123 xxxYYYzZzZ");
string str3("");
const char pch[]="AbCdEfG 123 xxxYYYzZzZ";
unsigned int pchlen=sizeof(pch);
char* pch1=new char[pchlen];
std::copy(pch, pch+pchlen, pch1);
char* pch2=new char[pchlen];
std::copy(pch, pch+pchlen, pch2);
// *** iterator tests *** //
string strout;
to_lower_copy( back_inserter(strout), str1 );
BOOST_CHECK( strout=="abcdefg 123 xxxyyyzzzz" );
strout.clear();
to_upper_copy( back_inserter(strout), str1 );
BOOST_CHECK( strout=="ABCDEFG 123 XXXYYYZZZZ" );
strout.clear();
to_lower_copy( back_inserter(strout), "AbCdEfG 123 xxxYYYzZzZ" );
BOOST_CHECK( strout=="abcdefg 123 xxxyyyzzzz" );
strout.clear();
to_upper_copy( back_inserter(strout), "AbCdEfG 123 xxxYYYzZzZ" );
BOOST_CHECK( strout=="ABCDEFG 123 XXXYYYZZZZ" );
strout.clear();
to_lower_copy( back_inserter(strout), pch1 );
BOOST_CHECK( strout=="abcdefg 123 xxxyyyzzzz" );
strout.clear();
to_upper_copy( back_inserter(strout), pch1 );
BOOST_CHECK( strout=="ABCDEFG 123 XXXYYYZZZZ" );
// *** value passing tests *** //
BOOST_CHECK( to_lower_copy( str1 )=="abcdefg 123 xxxyyyzzzz" );
BOOST_CHECK( to_upper_copy( str1 )=="ABCDEFG 123 XXXYYYZZZZ" );
BOOST_CHECK( to_lower_copy( str3 )=="" );
BOOST_CHECK( to_upper_copy( str3 )=="" );
// *** inplace tests *** //
to_lower( str1 );
BOOST_CHECK( str1=="abcdefg 123 xxxyyyzzzz" );
to_upper( str2 );
BOOST_CHECK( str2=="ABCDEFG 123 XXXYYYZZZZ" );
// c-string modification
to_lower( pch1 );
BOOST_CHECK( string(pch1)=="abcdefg 123 xxxyyyzzzz" );
to_upper( pch2 );
BOOST_CHECK( string(pch2)=="ABCDEFG 123 XXXYYYZZZZ" );
to_lower( str3 );
BOOST_CHECK( str3=="" );
to_upper( str3 );
BOOST_CHECK( str3=="" );
delete[] pch1;
delete[] pch2;
}
// test main
BOOST_AUTO_TEST_CASE( test_main )
{
conv_test();
}

View File

@@ -0,0 +1,162 @@
// 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
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.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);
}
BOOST_AUTO_TEST_CASE( test_main )
{
find_format_test();
find_format_all_test();
}

View File

@@ -0,0 +1,275 @@
// 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 <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
// Include unit test framework
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <iterator>
#include <sstream>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
void find_test()
{
string str1("123abcxXxabcXxXabc321");
string str2("abc");
string str3("");
const char* pch1="123abcxxxabcXXXabc321";
vector<int> vec1( str1.begin(), str1.end() );
// find results ------------------------------------------------------------//
iterator_range<string::iterator> nc_result;
iterator_range<string::const_iterator> cv_result;
iterator_range<vector<int>::iterator> nc_vresult;
iterator_range<vector<int>::const_iterator> cv_vresult;
iterator_range<const char*> ch_result;
// basic tests ------------------------------------------------------------//
// find_first
BOOST_TEST_CHECKPOINT( "find_first" );
nc_result=find_first( str1, string("abc") );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_result=find_first( const_cast<const string&>(str1), str2 );
BOOST_CHECK(
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
cv_result=ifind_first( const_cast<const string&>(str1), "xXX" );
BOOST_CHECK(
( (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 ) );
// find_last
BOOST_TEST_CHECKPOINT( "find_last" );
nc_result=find_last( str1, string("abc") );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 15) &&
( (nc_result.end()-str1.begin()) == 18) );
cv_result=find_last( const_cast<const string&>(str1), str2 );
BOOST_CHECK(
( (cv_result.begin()-str1.begin()) == 15) &&
( (cv_result.end()-str1.begin()) == 18) );
cv_result=ifind_last( const_cast<const string&>(str1), "XXx" );
BOOST_CHECK(
( (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 ) );
// find_nth
BOOST_TEST_CHECKPOINT( "find_nth" );
nc_result=find_nth( str1, string("abc"), 1 );
BOOST_CHECK(
( (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(
( (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(
( (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 ) );
// find_head
BOOST_TEST_CHECKPOINT( "find_head" );
nc_result=find_head( str1, 6 );
BOOST_CHECK(
( (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(
( (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 ) );
// find_tail
BOOST_TEST_CHECKPOINT( "find_tail" );
nc_result=find_tail( str1, 6 );
BOOST_CHECK(
( (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(
( (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 ) );
// find_token
BOOST_TEST_CHECKPOINT( "find_token" );
nc_result=find_token( str1, is_any_of("abc"), token_compress_on );
BOOST_CHECK(
( (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(
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
string s1("abc def ghi jkl");
find_iterator<string::iterator> fEnd;
find_iterator<string::iterator> fxIt = make_find_iterator(s1,
token_finder(is_alnum(), token_compress_on));
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("abc")));
++fxIt;
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("def")));
++fxIt;
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("ghi")));
++fxIt;
BOOST_CHECK((fxIt != fEnd) && (*fxIt == string("jkl")));
++fxIt;
BOOST_CHECK(fxIt == fEnd);
nc_result=find_token( str1, is_any_of("abc"), token_compress_off );
BOOST_CHECK(
( (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(
( (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 ) );
// generic find
BOOST_TEST_CHECKPOINT( "generic find" );
nc_result=find(str1, first_finder(string("abc")));
BOOST_CHECK(
( (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(
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
// multi-type comparison test
BOOST_TEST_CHECKPOINT( "multi-type" );
nc_vresult=find_first( vec1, string("abc") );
BOOST_CHECK(
( (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(
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
// overflow test
BOOST_TEST_CHECKPOINT( "overflow" );
nc_result=find_first( str2, string("abcd") );
BOOST_CHECK( nc_result.begin()==nc_result.end() );
cv_result=find_first( const_cast<const string&>(str2), string("abcd") );
BOOST_CHECK( cv_result.begin()==cv_result.end() );
cv_result=find_head( const_cast<const string&>(str2), 4 );
BOOST_CHECK( string( cv_result.begin(), cv_result.end() )== string("abc") );
cv_result=find_tail( const_cast<const string&>(str2), 4 );
BOOST_CHECK( string( cv_result.begin(), cv_result.end() )== string("abc") );
// Empty string test
BOOST_TEST_CHECKPOINT( "empty" );
nc_result=find_first( str3, string("abcd") );
BOOST_CHECK( nc_result.begin()==nc_result.end() );
nc_result=find_first( str1, string("") );
BOOST_CHECK( nc_result.begin()==nc_result.end() );
cv_result=find_first( const_cast<const string&>(str3), string("abcd") );
BOOST_CHECK( cv_result.begin()==cv_result.end() );
cv_result=find_first( const_cast<const string&>(str1), string("") );
BOOST_CHECK( cv_result.begin()==cv_result.end() );
// iterator_range specific tests
ostringstream osstr;
osstr << find_first( str1, "abc" );
BOOST_CHECK( osstr.str()=="abc" );
}
// test main
BOOST_AUTO_TEST_CASE( test_main )
{
find_test();
}

View File

@@ -0,0 +1,78 @@
// 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
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.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), "") );
}
BOOST_AUTO_TEST_CASE( test_main )
{
join_test();
}

View File

@@ -0,0 +1,160 @@
// Boost string_algo library predicate_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/predicate.hpp>
#include <boost/algorithm/string/classification.hpp>
// Include unit test framework
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <functional>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
void predicate_test()
{
string str1("123xxx321");
string str1_prefix("123");
string str2("abc");
string str3("");
string str4("abc");
vector<int> vec1( str1.begin(), str1.end() );
// Basic tests
BOOST_CHECK( starts_with( str1, string("123") ) );
BOOST_CHECK( !starts_with( str1, string("1234") ) );
BOOST_CHECK( istarts_with( "aBCxxx", "abc" ) );
BOOST_CHECK( !istarts_with( "aBCxxx", "abcd" ) );
BOOST_CHECK( ends_with( str1, string("321") ) );
BOOST_CHECK( !ends_with( str1, string("123") ) );
BOOST_CHECK( iends_with( "aBCxXx", "XXX" ) );
BOOST_CHECK( !iends_with( "aBCxxX", "xXXX" ) );
BOOST_CHECK( contains( str1, string("xxx") ) );
BOOST_CHECK( !contains( str1, string("yyy") ) );
BOOST_CHECK( icontains( "123XxX321", "xxx" ) );
BOOST_CHECK( !icontains( "123xXx321", "yyy" ) );
BOOST_CHECK( equals( str2, string("abc") ) );
BOOST_CHECK( !equals( str1, string("yyy") ) );
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") ) );
BOOST_CHECK( contains( vec1, string("xxx") ) );
BOOST_CHECK( equals( vec1, str1 ) );
// overflow test
BOOST_CHECK( !starts_with( str2, string("abcd") ) );
BOOST_CHECK( !ends_with( str2, string("abcd") ) );
BOOST_CHECK( !contains( str2, string("abcd") ) );
BOOST_CHECK( !equals( str2, string("abcd") ) );
// equal test
BOOST_CHECK( starts_with( str2, string("abc") ) );
BOOST_CHECK( ends_with( str2, string("abc") ) );
BOOST_CHECK( contains( str2, string("abc") ) );
BOOST_CHECK( equals( str2, string("abc") ) );
//! Empty string test
BOOST_CHECK( starts_with( str2, string("") ) );
BOOST_CHECK( ends_with( str2, string("") ) );
BOOST_CHECK( contains( str2, string("") ) );
BOOST_CHECK( equals( str3, string("") ) );
//! Container compatibility test
BOOST_CHECK( starts_with( "123xxx321", "123" ) );
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 )\
{\
test_pred(Pred, YesInput, true); \
test_pred(Pred, NoInput, false); \
}
void classification_test()
{
TEST_CLASS( is_space(), "\n\r\t ", "..." );
TEST_CLASS( is_alnum(), "ab129ABc", "_ab129ABc" );
TEST_CLASS( is_alpha(), "abc", "abc1" );
TEST_CLASS( is_cntrl(), "\n\t\r", "..." );
TEST_CLASS( is_digit(), "1234567890", "abc" );
TEST_CLASS( is_graph(), "123abc.,", " \t" );
TEST_CLASS( is_lower(), "abc", "Aasdf" );
TEST_CLASS( is_print(), "abs", "\003\004asdf" );
TEST_CLASS( is_punct(), ".,;\"", "abc" );
TEST_CLASS( is_upper(), "ABC", "aBc" );
TEST_CLASS( is_xdigit(), "ABC123", "XFD" );
TEST_CLASS( is_any_of( string("abc") ), "aaabbcc", "aaxb" );
TEST_CLASS( is_any_of( "abc" ), "aaabbcc", "aaxb" );
TEST_CLASS( is_from_range( 'a', 'c' ), "aaabbcc", "aaxb" );
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
BOOST_AUTO_TEST_CASE( test_main )
{
predicate_test();
classification_test();
}

View File

@@ -0,0 +1,158 @@
// 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 <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
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <boost/regex.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
static void find_test()
{
string str1("123a1cxxxa23cXXXa456c321");
const char* pch1="123a1cxxxa23cXXXa456c321";
regex rx("a[0-9]+c");
vector<int> vec1( str1.begin(), str1.end() );
vector<string> tokens;
// find results
iterator_range<string::iterator> nc_result;
iterator_range<string::const_iterator> cv_result;
iterator_range<vector<int>::iterator> nc_vresult;
iterator_range<vector<int>::const_iterator> cv_vresult;
iterator_range<const char*> ch_result;
// basic tests
nc_result=find_regex( str1, rx );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_result=find_regex( str1, rx );
BOOST_CHECK(
( (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 ) );
// multi-type comparison test
nc_vresult=find_regex( vec1, rx );
BOOST_CHECK(
( (nc_result.begin()-str1.begin()) == 3) &&
( (nc_result.end()-str1.begin()) == 6) );
cv_vresult=find_regex( vec1, rx );
BOOST_CHECK(
( (cv_result.begin()-str1.begin()) == 3) &&
( (cv_result.end()-str1.begin()) == 6) );
// find_all_regex test
find_all_regex( tokens, str1, rx );
BOOST_REQUIRE( tokens.size()==3 );
BOOST_CHECK( tokens[0]==string("a1c") );
BOOST_CHECK( tokens[1]==string("a23c") );
BOOST_CHECK( tokens[2]==string("a456c") );
// split_regex test
split_regex( tokens, str1, rx );
BOOST_REQUIRE( tokens.size()==4 );
BOOST_CHECK( tokens[0]==string("123") );
BOOST_CHECK( tokens[1]==string("xxx") );
BOOST_CHECK( tokens[2]==string("XXX") );
BOOST_CHECK( tokens[3]==string("321") );
}
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");
regex rx1("a([0-9]+)c");
regex rx2("([xX]+)");
regex rx3("_[^_]*_");
string fmt1("_A$1C_");
string fmt2("_xXx_");
vector<int> vec1( str1.begin(), str1.end() );
// immutable tests
// basic tests
BOOST_CHECK( replace_regex_copy( str1, rx1, fmt1 )==string("123_A1C_xxxa23cXXXa456c321") );
BOOST_CHECK( replace_all_regex_copy( str1, rx1, fmt1 )==string("123_A1C_xxx_A23C_XXX_A456C_321") );
BOOST_CHECK( erase_regex_copy( str1, rx1 )==string("123xxxa23cXXXa456c321") );
BOOST_CHECK( erase_all_regex_copy( str1, rx1 )==string(string("123xxxXXX321")) );
// output iterator variants test
string strout;
replace_regex_copy( back_inserter(strout), str1, rx1, fmt1 );
BOOST_CHECK( strout==string("123_A1C_xxxa23cXXXa456c321") );
strout.clear();
replace_all_regex_copy( back_inserter(strout), str1, rx1, fmt1 );
BOOST_CHECK( strout==string("123_A1C_xxx_A23C_XXX_A456C_321") );
strout.clear();
erase_regex_copy( back_inserter(strout), str1, rx1 );
BOOST_CHECK( strout==string("123xxxa23cXXXa456c321") );
strout.clear();
erase_all_regex_copy( back_inserter(strout), str1, rx1 );
BOOST_CHECK( strout==string("123xxxXXX321") );
strout.clear();
// in-place test
replace_regex( str1, rx1, fmt2 );
BOOST_CHECK( str1==string("123_xXx_xxxa23cXXXa456c321") );
replace_all_regex( str1, rx2, fmt1 );
BOOST_CHECK( str1==string("123__AxXxC___AxxxC_a23c_AXXXC_a456c321") );
erase_regex( str1, rx3 );
BOOST_CHECK( str1==string("123AxXxC___AxxxC_a23c_AXXXC_a456c321") );
erase_all_regex( str1, rx3 );
BOOST_CHECK( str1==string("123AxXxCa23ca456c321") );
}
BOOST_AUTO_TEST_CASE( test_main )
{
find_test();
join_test();
replace_test();
}

View File

@@ -0,0 +1,321 @@
// 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 <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
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <list>
#include <iostream>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
void sequence_traits_test()
{
// basic_string traits
BOOST_CHECK( boost::algorithm::has_native_replace<string>::value );
BOOST_CHECK( !boost::algorithm::has_stable_iterators<string>::value );
BOOST_CHECK( !boost::algorithm::has_const_time_insert<string>::value );
BOOST_CHECK( !boost::algorithm::has_const_time_erase<string>::value );
// vector traits
BOOST_CHECK( !boost::algorithm::has_native_replace< vector<char> >::value );
BOOST_CHECK( !boost::algorithm::has_stable_iterators< vector<char> >::value );
BOOST_CHECK( !boost::algorithm::has_const_time_insert< vector<char> >::value );
BOOST_CHECK( !boost::algorithm::has_const_time_erase< vector<char> >::value );
// list traits
BOOST_CHECK( !boost::algorithm::has_native_replace< list<char> >::value );
BOOST_CHECK( boost::algorithm::has_stable_iterators< list<char> >::value );
BOOST_CHECK( boost::algorithm::has_const_time_insert< list<char> >::value );
BOOST_CHECK( boost::algorithm::has_const_time_erase< list<char> >::value );
}
// Combine tests for all variants of the algorithm
#define C_ ,
#define TEST_ALGO( Algo, Input, Params, Output ) \
{\
BOOST_TEST_CHECKPOINT( #Algo " - Copy" );\
\
string str1(Input);\
\
/* Copy test */ \
BOOST_CHECK( Algo##_copy( str1, Params )==Output );\
\
BOOST_TEST_CHECKPOINT( #Algo " - Iterator" );\
/* Iterator test */\
string strout;\
Algo##_copy( back_inserter(strout), str1, Params );\
BOOST_CHECK( strout==Output ); \
\
/* In-place test */\
vector<char> vec1( str1.begin(), str1.end() );\
list<char> list1( str1.begin(), str1.end() );\
\
BOOST_TEST_CHECKPOINT( #Algo " - Inplace(string)" );\
Algo( str1, Params ); \
BOOST_CHECK( equals( str1, Output ) ); \
\
BOOST_TEST_CHECKPOINT( #Algo " - Inplace(vector)" );\
Algo( vec1, Params ); \
BOOST_CHECK( equals( vec1, Output ) );\
\
BOOST_TEST_CHECKPOINT( #Algo " - Inplace(list)" );\
Algo( list1, Params ); \
BOOST_CHECK( equals( list1, Output ) );\
}
void replace_first_test()
{
// replace first
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") 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") 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") 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 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 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_TEST_CHECKPOINT( "replace_range" );
string str1("1abc3abc2");
BOOST_CHECK(
replace_range_copy(
str1,
make_iterator_range(str1.begin()+1, str1.begin()+4),
string("XXX") )==string("1XXX3abc2") );
string strout;
replace_range_copy(
back_inserter( strout ),
str1,
make_iterator_range(str1.begin()+1, str1.begin()+4),
string("XXX") );
BOOST_CHECK( strout==string("1XXX3abc2") );
replace_range(
str1,
make_iterator_range(str1.begin()+1, str1.begin()+4),
string("XXX") );
BOOST_CHECK( str1==string("1XXX3abc2") );
}
// erase_range
{
BOOST_TEST_CHECKPOINT( "erase_range" );
string str1("1abc3abc2");
BOOST_CHECK(
erase_range_copy(
str1,
make_iterator_range(str1.begin()+1, str1.begin()+4))==string("13abc2") );
string strout;
erase_range_copy(
back_inserter( strout ),
str1,
make_iterator_range(str1.begin()+1, str1.begin()+4));
BOOST_CHECK( strout==string("13abc2") );
erase_range(
str1,
make_iterator_range(str1.begin()+1, str1.begin()+4));
BOOST_CHECK( str1==string("13abc2") );
}
}
void collection_comp_test()
{
// container traits compatibility tests
{
string strout;
replace_first_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" );
BOOST_CHECK( strout==string("1YYY3abc2") );
}
{
string strout;
replace_last_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" );
BOOST_CHECK( strout==string("1abc3YYY2") );
}
{
string strout;
replace_all_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" );
BOOST_CHECK( strout==string("1YYY3YYY2") );
}
{
string strout;
replace_nth_copy( back_inserter(strout), "1abc3abc2", "abc", 1, "YYY" );
BOOST_CHECK( strout==string("1abc3YYY2") );
}
{
string strout;
replace_head_copy( back_inserter(strout), "abc3abc2", 3 , "YYY" );
BOOST_CHECK( strout==string("YYY3abc2") );
}
{
string strout;
replace_tail_copy( back_inserter(strout), "abc3abc", 3 , "YYY" );
BOOST_CHECK( strout==string("abc3YYY") );
}
}
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");
}
BOOST_AUTO_TEST_CASE( test_main )
{
sequence_traits_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();
}

View File

@@ -0,0 +1,193 @@
// 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/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
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
template< typename T1, typename T2 >
void deep_compare( const T1& X, const T2& Y )
{
BOOST_REQUIRE( X.size() == Y.size() );
for( unsigned int nIndex=0; nIndex<X.size(); ++nIndex )
{
BOOST_CHECK( equals( X[nIndex], Y[nIndex] ) );
}
}
void iterator_test()
{
string str1("xx-abc--xx-abb");
string str2("Xx-abc--xX-abb-xx");
string str3("xx");
string strempty("");
const char* pch1="xx-abc--xx-abb";
vector<string> tokens;
vector< vector<int> > vtokens;
// 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()==3 );
BOOST_CHECK( tokens[0]==string("Xx") );
BOOST_CHECK( tokens[1]==string("xX") );
BOOST_CHECK( tokens[2]==string("xx") );
find_all(
tokens,
str1,
"xx" );
BOOST_REQUIRE( tokens.size()==2 );
BOOST_CHECK( tokens[0]==string("xx") );
BOOST_CHECK( tokens[1]==string("xx") );
find_all(
vtokens,
str1,
string("xx") );
deep_compare( tokens, vtokens );
// split tests
split(
tokens,
str2,
is_any_of("xX"),
token_compress_on );
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[3]==string("") );
split(
tokens,
pch1,
is_any_of("x"),
token_compress_on );
BOOST_REQUIRE( tokens.size()==3 );
BOOST_CHECK( tokens[0]==string("") );
BOOST_CHECK( tokens[1]==string("-abc--") );
BOOST_CHECK( tokens[2]==string("-abb") );
split(
vtokens,
str1,
is_any_of("x"),
token_compress_on );
deep_compare( tokens, vtokens );
split(
tokens,
str1,
is_punct(),
token_compress_off );
BOOST_REQUIRE( tokens.size()==5 );
BOOST_CHECK( tokens[0]==string("xx") );
BOOST_CHECK( tokens[1]==string("abc") );
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"));
find_iterator<string::iterator> fiter2;
BOOST_CHECK(equals(*fiter, "xx"));
++fiter;
fiter2 = fiter;
BOOST_CHECK(equals(*fiter, "xx"));
BOOST_CHECK(equals(*fiter2, "xx"));
++fiter;
BOOST_CHECK(fiter==find_iterator<string::iterator>());
BOOST_CHECK(equals(*fiter2, "xx"));
++fiter2;
BOOST_CHECK(fiter2==find_iterator<string::iterator>());
split_iterator<string::iterator> siter=make_split_iterator(str1, token_finder(is_any_of("-"), token_compress_on));
split_iterator<string::iterator> siter2;
BOOST_CHECK(equals(*siter, "xx"));
++siter;
siter2 = siter;
BOOST_CHECK(equals(*siter, "abc"));
BOOST_CHECK(equals(*siter2, "abc"));
++siter;
BOOST_CHECK(equals(*siter, "xx"));
BOOST_CHECK(equals(*siter2, "abc"));
++siter;
BOOST_CHECK(equals(*siter, "abb"));
++siter;
BOOST_CHECK(siter==split_iterator<string::iterator>(siter));
BOOST_CHECK(siter==split_iterator<string::iterator>());
// Make sure we work with forward iterators
// See bug #7989
list<char> l1;
find_iterator<list<char>::iterator> liter=make_find_iterator(l1, first_finder("xx"));
}
BOOST_AUTO_TEST_CASE( test_main )
{
iterator_test();
}

View File

@@ -0,0 +1,202 @@
// Boost string_algo library trim_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/trim.hpp>
#include <boost/algorithm/string/trim_all.hpp>
// Include unit test framework
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <string>
#include <iostream>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
void trim_test()
{
string str1(" 1x x x x1 ");
string str2(" 2x x x x2 ");
string str3(" ");
// *** value passing tests *** //
// general string test
BOOST_CHECK( trim_left_copy( str1 )=="1x x x x1 " ) ;
BOOST_CHECK( trim_right_copy( str1 )==" 1x x x x1" ) ;
BOOST_CHECK( trim_copy( str1 )=="1x x x x1" ) ;
// spaces-only string test
BOOST_CHECK( trim_left_copy( str3 )=="" );
BOOST_CHECK( trim_right_copy( str3 )=="" );
BOOST_CHECK( trim_copy( str3 )=="" );
// empty string check
BOOST_CHECK( trim_left_copy( string("") )=="" );
BOOST_CHECK( trim_right_copy( string("") )=="" );
BOOST_CHECK( trim_copy( string("") )=="" );
// iterator tests
string str;
trim_left_copy_if( std::back_inserter(str), str1, is_space() );
BOOST_CHECK( str=="1x x x x1 " );
str.clear();
trim_right_copy_if( std::back_inserter(str), str1, is_space() );
BOOST_CHECK( str==" 1x x x x1" );
str.clear();
trim_copy_if( std::back_inserter(str), str1, is_space() );
BOOST_CHECK( str=="1x x x x1" );
str.clear();
trim_left_copy_if(
std::back_inserter(str),
" 1x x x x1 ",
is_space() );
BOOST_CHECK( str=="1x x x x1 " );
str.clear();
trim_right_copy_if(
std::back_inserter(str),
" 1x x x x1 ",
is_space() );
BOOST_CHECK( str==" 1x x x x1" );
str.clear();
trim_copy_if(
std::back_inserter(str),
" 1x x x x1 ",
is_space() );
BOOST_CHECK( str=="1x x x x1" );
// *** inplace tests *** //
// general string test
trim_left( str1 );
BOOST_CHECK( str1=="1x x x x1 " );
trim_right( str1 );
BOOST_CHECK( str1=="1x x x x1" );
trim( str2 );
BOOST_CHECK( str2=="2x x x x2" );
// spaces-only string test
str3 = " "; trim_left( str3 );
BOOST_CHECK( str3=="" );
str3 = " "; trim_right( str3 );
BOOST_CHECK( str3=="" );
str3 = " "; trim( str3 );
BOOST_CHECK( str3=="" );
// empty string check
str3 = ""; trim_left( str3 );
BOOST_CHECK( str3=="" );
str3 = ""; trim_right( str3 );
BOOST_CHECK( str3=="" );
str3 = ""; trim( str3 );
BOOST_CHECK( str3=="" );
// *** non-standard predicate tests *** //
BOOST_CHECK(
trim_copy_if(
string("123abc456"),
is_classified(std::ctype_base::digit) )=="abc" );
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" );
}
BOOST_AUTO_TEST_CASE( test_main )
{
trim_test();
trim_all_test();
trim_fill_test();
}