String Algorithm Library: initial commit

[SVN r22431]
This commit is contained in:
Pavol Droba
2004-03-04 22:12:19 +00:00
parent 3d9b6badea
commit 1deef19d55
73 changed files with 12359 additions and 0 deletions

61
string/doc/Jamfile.v2 Normal file
View File

@ -0,0 +1,61 @@
# 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
# htt../..//www.boost.org/LICENSE_1_0.txt)
#
# See htt../..//www.boost.org for updates, documentation, and revision history.
project boost/libs/algorithm/string/doc ;
doxygen reference
:
../../../../boost/algorithm/string.hpp
../../../../boost/algorithm/string_regex.hpp
../../../../boost/algorithm/string/classification.hpp
../../../../boost/algorithm/string/iterator_range.hpp
../../../../boost/algorithm/string/sequence_traits.hpp
../../../../boost/algorithm/string/std_containers_traits.hpp
../../../../boost/algorithm/string/container_traits.hpp
../../../../boost/algorithm/string/concept.hpp
../../../../boost/algorithm/string/compare.hpp
../../../../boost/algorithm/string/constants.hpp
../../../../boost/algorithm/string/case_conv.hpp
../../../../boost/algorithm/string/find.hpp
../../../../boost/algorithm/string/finder.hpp
../../../../boost/algorithm/string/find_iterator.hpp
../../../../boost/algorithm/string/trim.hpp
../../../../boost/algorithm/string/predicate.hpp
../../../../boost/algorithm/string/split.hpp
../../../../boost/algorithm/string/iter_find.hpp
../../../../boost/algorithm/string/erase.hpp
../../../../boost/algorithm/string/replace.hpp
../../../../boost/algorithm/string/find_format.hpp
../../../../boost/algorithm/string/formatter.hpp
../../../../boost/algorithm/string/regex.hpp
../../../../boost/algorithm/string/regex_find_format.hpp
:
<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;\""
;
boostbook string_algo
:
string_algo.xml
;

199
string/doc/concept.xml Normal file
View File

@ -0,0 +1,199 @@
<?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">
<section id="string_algo.concept" last-revision="$Date$">
<title>Concepts</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<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 searching 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;ForwardIterator&gt; operator()(
ForwardIteratorT Begin,
ForwardIteratorT End )
{
return boost::make_range( Begin, End );
}
};
</programlisting>
</listitem>
<listitem>
Function Finder. Finder can be any function object. That means, an 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 formating
on it. Algorithms can abstract from formating 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 formating and
returns repackaged match. <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>

13
string/doc/credits.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<section id="string_algo.credits" last-revision="$Date$">
<title>Credits</title>
<section id="string_algo.ack">
<title>Acknowledgments</title>
<para>
Thanks for everybody who gave suggestions and comments. Especially to Thorsten Ottosen, Jeff Garland
and the other boost members who participated.
</para>
</section>
</section>

281
string/doc/design.xml Normal file
View File

@ -0,0 +1,281 @@
<?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">
<section id="string_algo.design" last-revision="$Date$">
<title>Design Topics</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<section id="string_algo.iterator_range">
<title><code>iterator_range</code> class</title>
<para>
An <classname>iterator_range</classname> is an encapsulation of a pair of iterators that
delimit a sequence (or, a range). This concept is widely used by
sequence manipulating algorithms. Although being so useful, there no direct support
for it in the standard library (The closest thing is that some algorithms return a pair of iterators).
Instead all STL algorithms have two distinct parameters for beginning and end of a range. This design
is natural for implementation of generic algorithms, but it forbids to work with a range as a single value.
</para>
<para>
It is possible to encapsulate a range in <code>std::pair&lt;&gt;</code>, but
the <code>std::pair&lt;&gt;</code> is a too generic encapsulation, so it is not best match for a range.
For instance, it does not enforce that begin and end iterators are of the same type.
</para>
<para>
Naturally the range concept is heavily used also in this library. During the development of
the library, it was discovered, that there is a need for a reasonable encapsulation for it.
A core part of the library deals with substring searching algorithms. Any such an algorithm,
returns a range delimiting the result of the search. <code>std::pair&lt;&gt;</code> was considered as
unsuitable. Therefore the <code>iterator_range</code> was defined.
</para>
<para>
The intention of the <code>iterator_range</code> class is to manage a range as a single value and provide
a basic interface for common operations. Its interface is similar to that of container.
In addition of <code>begin()</code>
and <code>end()</code> accessors, it has member functions for checking if the range is empty,
or to determine the size of the range. It has also a set of member typedefs that extract
type information from the encapsulated iterators. As such, the interface is compatible with
the <link linkend="string_algo.container_traits">container traits</link> requirements so
it is possible to use this class as a parameter to many algorithms in this library.
</para>
</section>
<section id="string_algo.container_traits">
<title>Container Traits</title>
<para>
Container traits provide uniform access to different types of containers.
This functionality allows to write generic algorithms which work with several
different kinds of containers. For this library it means, that, for instance,
many algorithms work with <code>std::string</code> as well as with <code>char[]</code>.
</para>
<para>
The following container types are supported:
<itemizedlist>
<listitem>
Standard containers
</listitem>
<listitem>
Built-in arrays (like int[])
</listitem>
<listitem>
Null terminated strings (this includes char[],wchar_t[],char*, and wchar_t*)
</listitem>
<listitem>
std::pair&lt;iterator,iterator&gt;
</listitem>
</itemizedlist>
</para>
<para>
Container traits support a subset of container concept (Std &sect;23.1). This subset
can be described as an input container concept, e.g. a container with an immutable content.
Its definition can be found in the header <headername>boost/string_algo/container_traits.hpp</headername>.
</para>
<para>
In the table C denotes a container and c is an object of C.
</para>
<table>
<title>Container Traits</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>Name</entry>
<entry>Standard container equivalent</entry>
<entry>Description</entry>
</row>Maeterlinck
</thead>
<tbody>
<row>
<entry><classname>container_value_type&lt;C&gt;</classname>::type</entry>
<entry><code>C::value_type</code></entry>
<entry>Type of contained values</entry>
</row>
<row>
<entry><classname>container_difference_type&lt;C&gt;</classname>::type</entry>
<entry><code>C::difference_type</code></entry>
<entry>difference type of the container</entry>
</row>
<row>
<entry><classname>container_iterator&lt;C&gt;</classname>::type</entry>
<entry><code>C::iterator</code></entry>
<entry>iterator type of the container</entry>
</row>
<row>
<entry><classname>container_const_iterator&lt;C&gt;</classname>::type</entry>
<entry><code>C::const_iterator</code></entry>
<entry>const_iterator type of the container</entry>
</row>
<row>
<entry><classname>container_result_iterator&lt;C&gt;</classname>::type</entry>
<entry></entry>
<entry>
result_iterator type of the container. This type maps to <code>C::iterator</code>
for mutable container and <code>C::const_iterator</code> for const containers.
</entry>
</row>
<row>
<entry><functionname>begin(c)</functionname></entry>
<entry><code>c.begin()</code></entry>
<entry>
Gets the iterator pointing to the start of the container.
</entry>
</row>
<row>
<entry><functionname>end(c)</functionname></entry>
<entry><code>c.end()</code></entry>
<entry>
Gets the iterator pointing to the end of the container.
</entry>
</row>
<row>
<entry><functionname>size(c)</functionname></entry>
<entry><code>c.size()</code></entry>
<entry>
Gets the size of the container.
</entry>
</row>
<row>
<entry><functionname>empty(c)</functionname></entry>
<entry><code>c.empty()</code></entry>
<entry>
Checks if the container is empty.
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
The container traits are only a temporary part of this library. There is a plan for a separate submission
of a container_traits library to Boost. Once it gets accepted, String Algorithm Library will be adopted to
use it and the internal implementation will be deprecated.
</para>
</section>
<section id="string_algo.sequence_traits">
<title>Sequence Traits</title>
<para>
Major difference between <code>std::list</code> and <code>std::vector</code> is not in the interfaces
they provide, rather in the inner details of the class and the way how it performs
various operation. The problem is that it is not possible to infer this difference from the
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 allows one to specify additional properties of a sequence container (see Std.&sect;32.2).
These properties are then used by algorithms to select optimized handling for some operations.
The sequence traits are declared in the header
<headername>boost/string_algo/sequence_traits.hpp</headername>.
</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>sequence_has_native_replace&lt;C&gt;</classname>::value</entry>
<entry>Specifies that the sequence has std::string like replace method</entry>
</row>
<row>
<entry><classname>sequence_has_stable_iterators&lt;C&gt;</classname>::value</entry>
<entry>
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>sequence_has_const_time_insert&lt;C&gt;</classname>::value</entry>
<entry>
Specifies that the insert method of the sequence has
constant time complexity.
</entry>
</row>
<row>
<entry><classname>sequence_has_const_time_erase&lt;C&gt;</classname>::value</entry>
<entry>
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 magnitued 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 an advantage of specific features if possible
(by using <link linkend="string_algo.sequence_traits">Sequence traits</link>)
</para>
</section>
<section id="string_algo.split">
<title>Split Algorithms</title>
<para>
Split algorithms are a logical extension of <link linkend="string_algo.find">find facility</link>.
Instead of searching for one match, the whole input is searched. The result of the search is then used
to partition the input. It depends on the algorithms which parts are returned as the result of
split operations. It can be the matching parts (<functionname>find_all()</functionname>) of the parts in
between (<functionname>split()</functionname>).
</para>
</section>
</section>

View File

@ -0,0 +1,55 @@
<?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">
<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/string_algo/regex.hpp</headername>.
If this header is used, an 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/string_algo/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/string_algo/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>
</para>
<para>
There are known limitation on platforms not supporting partial template specialization.
Library depends on correctly implemented std::iterator_traits class. If a standard library provided
with compiler is broken, the String Algorithm Library cannot function properly. Usually it implies
that primitive pointer iterators are not working with the library functions.
</para>
</section>
</section>

45
string/doc/intro.xml Normal file
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">
<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 a <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>
The library has layered structure to simplify the usage without sacrificing the
generalization.
The easy-to-use interface, defined in the namespace <code>boost</code>, represents the first layer.
Algorithms and classes defined here do not offer a lot of customization opportunities
rather they are provided in more different variants, so a user can chose the
one that suits her needs.
The second layer, defined in the namespace <code>boost::string_algo</code>, on the
other hand, is generic. Basically it contains the same set of algorithms as the first layer,
but the interface is more flexible and allows more customization, but it is harder to use.
The first layer is implemented as set of wrappers around the second layer.
</para>
<para>
The documentation is divided into several sections. For a quick start read the
<link linkend="string_algo.usage">Usage</link> section.
<link linkend="string_algo.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>

76
string/doc/rationale.xml Normal file
View File

@ -0,0 +1,76 @@
<?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">
<section id="string_algo.rationale" last-revision="$Date$">
<title>Rationale</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<section id="string_algo.structure">
<title>Library structure</title>
<para>
When designing a library it is always a problem to find a balance between generalization
and usability. A generic utility can have a wider range of usage with more options for extensibility,
but it can also bring unwanted complexity for everyday usage.
</para>
<para>
Imagine a library for drawing geometric objects. It can contain one generic function <code>draw()</code>
with many parameters specifying what to draw, like size, number of edges, shape etc.
This would allow you to draw almost anything, but usually a user only needs to draw
only a triangle or a square and she will have to specify this simple request in a
very complicated way.For this purpose two functions, <code>draw_triangle()</code> and
<code>draw_square()</code>, would suit much better then a generic <code>draw()</code> function.
</para>
<para>
The String Algorithm Library solves this problem by dividing the interface into two layers.
The first layer (defined in the namespace boost) contains ready to use algorithms specialized
for common tasks. They are provided in multiple variants to better suit specific needs.
The second layer (defined in the namespace <code>boost::string_algo</code>), provides generic interfaces with
more options for extending and tunning.
<para>
</para>
For instance, a <functionname>boost::trim()</functionname> algorithm trims spaces from
an input string. When there is a need to trim something else, there is
<functionname>boost::string_algo::trim()</functionname> which interface allows one to specify a
predicate which selects the characters to be removed.
</para>
</section>
<section it="string_algo.locale">
<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 on every place
where it is needed.
</para>
<para>
Fortunately, the C++ standard allows to specify the <emphasis>global</emphasis> locales (using static member
function <code>std:locale::global()</code>). When instantiating an
<code>std::locale</code> class without explicit information, the instance will
be initialized with the <emphasis>global</emphasis> locale. It means, that if an algorithm needs a locale,
it should have an <code>std::locale</code> parameter with default value <code>std::locale()</code>.
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
provides also regex variants of some algorithms. The library does not try to replace
<libraryname>Boost.Regex</libraryname>, but it merely wraps its functionality in a new interface.
As a part of this library regex algorithms integrate smoothly with other components which
brings additional value.
</para>
</section>
</section>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library name="string_algo" dirname="string_algo" xmlns:xi="http://www.w3.org/2001/XInclude"
id="string_algo" last-revision="$Date$">
<libraryinfo>
<author>
<firstname>Pavol</firstname>
<surname>Droba</surname>
</author>
<copyright>
<year>2002</year>
<year>2003</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:algoritms"/>
</libraryinfo>
<title>Boost String Algorithms Library</title>
<xi:include href="intro.xml"/>
<xi:include href="usage.xml"/>
<xi:include href="design.xml"/>
<xi:include href="concept.xml"/>
<xi:include href="reference.boostbook"/>
<xi:include href="rationale.xml"/>
<xi:include href="environment.xml"/>
<xi:include href="credits.xml"/>
</library>

275
string/doc/usage.xml Normal file
View File

@ -0,0 +1,275 @@
<?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">
<section id="string_algo.usage" last-revision="$Date$">
<title>Usage</title>
<using-namespace name="boost"/>
<using-namespace name="boost::string_algo"/>
<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/string_algo.hpp&gt;
using namespace std;
using namespace boost;
namespace sa=boost::string_algo
// ...
string str1(" hello world! ");
trim( to_upper(str1) ); // str1 == "HELLO WORLD!"
string str2=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 the STL algorithms, parameters are not specified only in form
of iterators. The STL convention allows for great flexibility,
but it has several limitation. It is not possible to <emphasis>stack</emphasis> algorithms together,
because a container is passed in two parameters, so it is not possible to use
a return value from another algorithm. It is considerably easier to write
<code>to_lower(str1)</code>, then <code>to_lower(str1.begin(), str1.end())</code>.
</para>
<para>
The magic of <link linkend="string_algo.container_traits">container_traits</link>
provides a uniform way of handling different containers.
If there is a need to pass a pair of iterators,
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link>
can be used to package iterators into a structure with the container interface.
</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. Mutable variants return
a reference to the input. Thus both versions allow a simple chaining of
transformations within one expression (i.e. one can write
<code>trim_copy(to_upper_copy(s))</code> as well as <code>trim(to_upper(s))</code>).
</para>
</listitem>
<listitem>
<para><emphasis role="bold">Naming:</emphasis>
Naming follows the conventions from the Standard C++ Library. If there is a
copy and mutable version of the same algorithm, the mutable version has no suffix
and the copy version has suffix <emphasis>_copy</emphasis>.
Some algorithms have prefix <emphasis>i</emphasis>
(e.g. <functionname>ifind_first()</functionname>).
This prefix identifies that the algorithm works in a case-insensitive manner.
</para>
</listitem>
</itemizedlist>
<para>
To use the library, include the <headername>boost/string_algo.hpp</headername> header.
If the regex related functions are needed, include the
<headername>boost/string_algo_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 container using a specified locale.
</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("command.com")? "is": "is not"
&lt;&lt; "an executable"
&lt;&lt; endl; // prints "command.com is an executable"
//..
char text1[]="hello world!";
cout
&lt;&lt; text1
&lt;&lt; all( text1, is_lower&lt;char&gt;() )? "is": "is not"
&lt;&lt; "written in the lower case"
&lt;&lt; endl; // prints "hello world! is written in the lower case"
</programlisting>
<para>
The predicates are resolving if a substring is contained in the input string
under various conditions. The conditions are if a string starts with the substring,
ends with the substring,
simply contains the substring or if both strings are equal. See the reference for
<headername>boost/string_algo/predicate.hpp</headername> for more details.
In addition the algorithm <functionname>all()</functionname> checks
all elements of a container to satisfy a condition specified by a predicate.
This predicate can be any unary predicate, but the library provides a bunch of
useful string-related predicates ready for use.
These are located in the <headername>boost/string_algo/classification.hpp</headername> header.
</para>
</section>
<section>
<title>Trimming</title>
<para>
When parsing the input of a user, strings usually have unwanted leading or trailing
characters. To get rid of them, we need trim functions:
</para>
<programlisting>
string str1=" hello world! ";
string str2=trim_left_copy(str1); // str2 == "hello world! "
string str3=trim_right_copy(str2); // str3 == " hello world!"
trim(str1); // str1 == "hello world!"
string phone="00423333444";
// remove leading 0 from the phone number
sa::trim_left(phone,is_any_of&lt;char&gt;("0")); // phone == "423333444"
</programlisting>
<para>
It is possible to trim the spaces on the right, on the left or on the both sides of a string.
And for those cases when there is a need to remove something else than blank space, the
<code>string_algo</code> namespace contains generic versions of the trim algorithms. Using these,
a user can specify a functor which will select the <emphasis>space</emphasis> to be removed. It is possible to use
classification predicates like <functionname>is_digit()</functionname> mentioned in the previous paragraph.
See the reference for the <headername>boost/string_algo/trim.hpp</headername>.
</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!"
</programlisting>
<para>
We have used <functionname>find_last()</functionname> to search the <code>text</code> for "ll".
The result is given in the <link linkend="string_algo.iterator_range"><code>iterator_range</code></link>.
This range delimits the
part of the input which satisfies the find criteria. In our example it is the last occurrence of "ll".
As we can see, input of the <functionname>find_last()</functionname> algorithm can be also
char[] because this type is supported by
<link linkend="string_algo.container_traits">container_traits</link>.
Following lines transform the result. Notice, that
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link> have familiar
<code>begin()</code> and <code>end()</code> methods, so it can be used like any other STL container.
</para>
</section>
<section>
<title>Replace Algorithms</title>
<para>
Find algorithms can be used for searching for a specific part of the sequence. Replace goes one step
further. After a matching part is found, it is substituted with something else. The substitution is computed
from an 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>replace()</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>
</section>
<section>
<title>Split</title>
<para>
Split algorithms allow one to divide a sequence into parts. Each part represents a
<emphasis>token</emphasis> and tokens are separated by <emphasis>separators</emphasis>.
One can either search for tokens or search for separators:
</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] }
typdef vector&lt; string &gt; split_vector_type;
split_vector_type SplitVec; // #2: Search for tokens
split( SplitVec, str1, is_any_of&lt;char&gt;("-*") ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
</programlisting>
<para>
<code>[hello]</code> designates an <code>iterator_range</code> delimiting this substring.
</para>
<para>
The result of a split algorithm is a <emphasis>container of containers</emphasis>. There is only one restriction:
The inner container type must be able to hold extracted parts of the input sequence. This example
shows the special case where the inner container is an
<link linkend="string_algo.iterator_range"><code>iterator_range</code></link>
instead of e.g. <code>std::string</code>. This way, a user gets a reference
(in the form of iterators) delimiting the parts of the input sequence. Otherwise, a copy of
each extracted part is created and added to the outer container.
</para>
<para>
So to recap, there are two basic algorithms: <functionname>find_all()</functionname>
returns extracts the parts
matching the specification whereas <functionname>split()</functionname> uses the matching
parts as delimiters, and extracts the parts in between them.
</para>
<para>
Generalizations of these two algorithms are called <functionname>iter_find()</functionname> and
<functionname>iter_split()</functionname>. They take a
<link linkend="string_algo.finder_concept">Finder</link> object, as an argument to search for
the substring.
</para>
</section>
</section>

75
string/example/Jamfile Normal file
View File

@ -0,0 +1,75 @@
# 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.
subproject libs/algorithm/string/example ;
exe conv_example
:
conv_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe predicate_example
:
predicate_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe find_example
:
find_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe replace_example
:
replace_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe rle_example
:
rle_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe trim_example
:
trim_example.cpp
:
<include>$(BOOST_ROOT)
:
;
exe regex_example
:
regex_example.cpp
<lib>../../../regex/build/boost_regex
:
<include>$(BOOST_ROOT)
:
;
exe split_example
:
split_example.cpp
:
<include>$(BOOST_ROOT)
:
;

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 containes '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 predicated 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,88 @@
// 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>
//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,241 @@
// 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;
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
{
// extract info
typename ReplaceT::const_iterator It=Replace.begin();
value_type Value=*(++It);
value_type Repeat=*(++It);
SeqT r;
for( value_type Index=0; Index<Repeat; Index++ ) r.push_back( Value );
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,63 @@
// 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/iterator_range.hpp>
#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_iterator_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;
}

68
string/test/Jamfile Normal file
View File

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

View File

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

88
string/test/conv_test.cpp Normal file
View File

@ -0,0 +1,88 @@
// 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 unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <iostream>
#include <boost/algorithm/string/case_conv.hpp>
#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("");
char* pch1=strdup("AbCdEfG 123 xxxYYYzZzZ");
char* pch2=strdup("AbCdEfG 123 xxxYYYzZzZ");
// *** 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=="" );
free(pch1);
free(pch2);
}
// test main
int test_main( int, char*[] )
{
conv_test();
return 0;
}

230
string/test/find_test.cpp Normal file
View File

@ -0,0 +1,230 @@
// Boost string_algo library substr_test.cpp file ------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <iterator>
#include <sstream>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
void find_test()
{
string str1("123abcxXxabcXxXabc321");
string str2("abc");
string str3("");
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_CHECKPOINT( "find_first" );
nc_result=find_first( str1, string("abc") );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
cv_result=find_first( const_cast<const string&>(str1), str2 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
cv_result=ifind_first( const_cast<const string&>(str1), "xXX" );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 6) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 9) );
ch_result=find_first( pch1, "abc" );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) );
// find_last
BOOST_CHECKPOINT( "find_last" );
nc_result=find_last( str1, string("abc") );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 18) );
cv_result=find_last( const_cast<const string&>(str1), str2 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 18) );
cv_result=ifind_last( const_cast<const string&>(str1), "XXx" );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 12) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 15) );
ch_result=find_last( pch1, "abc" );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 15) && ( (ch_result.end() - pch1 ) == 18 ) );
// find_nth
BOOST_CHECKPOINT( "find_nth" );
nc_result=find_nth( str1, string("abc"), 1 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 9) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 12) );
cv_result=find_nth( const_cast<const string&>(str1), str2, 1 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 9) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 12) );
cv_result=ifind_nth( const_cast<const string&>(str1), "xxx", 1 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 12) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 15) );
ch_result=find_nth( pch1, "abc", 1 );
BOOST_CHECK(( (ch_result.begin() - pch1 ) == 9) && ( (ch_result.end() - pch1 ) == 12 ) );
// find_head
BOOST_CHECKPOINT( "find_head" );
nc_result=find_head( str1, 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 0) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
cv_result=find_head( const_cast<const string&>(str1), 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 0) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
ch_result=find_head( pch1, 6 );
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 0 ) && ( (ch_result.end() - pch1 ) == 6 ) );
// find_tail
BOOST_CHECKPOINT( "find_tail" );
nc_result=find_tail( str1, 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 21) );
cv_result=find_tail( const_cast<const string&>(str1), 6 );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 15) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 21) );
ch_result=find_tail( pch1, 6 );
BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 15 ) && ( (ch_result.end() - pch1 ) == 21 ) );
// find_token
BOOST_CHECKPOINT( "find_token" );
nc_result=find_token( str1, is_any_of("abc"), token_compress_on );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_on );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
nc_result=find_token( str1, is_any_of("abc"), token_compress_off );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 4) );
cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_off );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 4) );
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_CHECKPOINT( "generic find" );
nc_result=find(str1, first_finder(string("abc")));
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
cv_result=find(const_cast<const string&>(str1), first_finder(str2) );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
// multi-type comparison test
BOOST_CHECKPOINT( "multi-type" );
nc_vresult=find_first( vec1, string("abc") );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.end()) == 6) );
cv_vresult=find_first( const_cast<const vector<int>&>(vec1), str2 );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.end()) == 6) );
// overflow test
BOOST_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_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
int test_main( int, char*[] )
{
find_test();
return 0;
}

View File

@ -0,0 +1,125 @@
// 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 unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <functional>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
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" ) );
// 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" ) );
}
#define TEST_CLASS( Pred, YesInput, NoInput )\
{\
BOOST_CHECK( all( string(YesInput), Pred ) );\
BOOST_CHECK( !all( string(NoInput), Pred ) );\
}
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", "\nasdf" );
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" );
}
#undef TEST_CLASS
// test main
int test_main( int, char*[] )
{
predicate_test();
classification_test();
return 0;
}

135
string/test/regex_test.cpp Normal file
View File

@ -0,0 +1,135 @@
// Boost string_algo library substr_test.cpp file ------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
using namespace boost;
static void find_test()
{
string str1("123a1cxxxa23cXXXa456c321");
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(
(distance<string::const_iterator>( str1.begin(),nc_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),nc_result.end()) == 6) );
cv_result=find_regex( str1, rx );
BOOST_CHECK(
(distance<string::const_iterator>( str1.begin(),cv_result.begin()) == 3) &&
(distance<string::const_iterator>( str1.begin(),cv_result.end()) == 6) );
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(
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),nc_vresult.end()) == 6) );
cv_vresult=find_regex( vec1, rx );
BOOST_CHECK(
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.begin()) == 3) &&
(distance<vector<int>::const_iterator>( vec1.begin(),cv_vresult.end()) == 6) );
*/
// 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 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() );
// inmutable 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") );
}
int test_main( int, char*[] )
{
find_test();
replace_test();
return 0;
}

View File

@ -0,0 +1,247 @@
// Boost string_algo library substr_test.cpp file ------------------//
// Copyright Pavol Droba 2002-2003. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for updates, documentation, and revision history.
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <list>
#include <iostream>
#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>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/preprocessor/seq/enum.hpp>
using namespace std;
using namespace boost;
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 TEST_ALGO( Algo, Input, Params, Output ) \
{\
BOOST_CHECKPOINT( #Input );\
\
string str1(Input);\
\
/* Copy test */ \
BOOST_CHECK( Algo##_copy( str1, BOOST_PP_SEQ_ENUM( Params ) )==Output );\
\
/* Iterator test */\
string strout;\
Algo##_copy( back_inserter(strout), str1, BOOST_PP_SEQ_ENUM( Params ) );\
BOOST_CHECK( strout==Output ); \
\
/* In-place test */\
vector<char> vec1( str1.begin(), str1.end() );\
list<char> list1( str1.begin(), str1.end() );\
Algo( str1, BOOST_PP_SEQ_ENUM( Params ) ); \
BOOST_CHECK( equals( str1, Output ) );\
Algo( vec1, BOOST_PP_SEQ_ENUM( Params ) ); \
BOOST_CHECK( equals( vec1, Output ) );\
Algo( list1, BOOST_PP_SEQ_ENUM( Params ) ); \
BOOST_CHECK( equals( list1, Output ) );\
}
void replace_test()
{
// replace first
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("YYY")), string("1YYY3abc2") );
TEST_ALGO( ireplace_first, "1AbC3abc2", ("aBc")("YYY"), string("1YYY3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("Z")), string("1Z3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", (string("abc"))(string("XXXX")), string("1XXXX3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", (string(""))(string("XXXX")), string("1abc3abc2") );
TEST_ALGO( replace_first, "1abc3abc2", ("")("XXXX"), string("1abc3abc2") );
TEST_ALGO( replace_first, "", (string(""))(string("XXXX")), string("") );
TEST_ALGO( erase_first, "1abc3abc2", (string("abc")), string("13abc2") );
TEST_ALGO( ierase_first, "1aBc3abc2", ("abC"), "13abc2" );
TEST_ALGO( erase_first, "1abc3abc2", ("abc"), "13abc2" );
TEST_ALGO( erase_first, "1abc3abc2", (string("")), string("1abc3abc2") );
TEST_ALGO( erase_first, "", (string("abc")), string("") );
// replace last
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("YYY")), string("1abc3YYY2") );
TEST_ALGO( ireplace_last, "1abc3AbC2", ("aBc")("YYY"), string("1abc3YYY2") );
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("Z")), string("1abc3Z2") );
TEST_ALGO( replace_last, "1abc3abc2", (string("abc"))(string("XXXX")), string("1abc3XXXX2") );
TEST_ALGO( replace_last, "1abc3abc2", ("abc")("XXXX"), string("1abc3XXXX2") );
TEST_ALGO( replace_last, "", (string(""))(string("XXXX")), string("") );
TEST_ALGO( erase_last, "1abc3abc2", (string("abc")), string("1abc32") );
TEST_ALGO( ierase_last, "1aBc3aBc2", ("ABC"), string("1aBc32") );
TEST_ALGO( erase_last, "1abc3abc2", ("abc"), string("1abc32") );
TEST_ALGO( erase_last, "1abc3abc2", (string("")), string("1abc3abc2") );
TEST_ALGO( erase_last, "", (string("abc")), string("") );
// replace all
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("YYY")), string("1YYY3YYY2") );
TEST_ALGO( ireplace_all, "1aBc3AbC2", ("abC")("YYY"), string("1YYY3YYY2") );
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("Z")), string("1Z3Z2") );
TEST_ALGO( replace_all, "1abc3abc2", (string("abc"))(string("XXXX")), string("1XXXX3XXXX2") );
TEST_ALGO( replace_all, "1abc3abc2", ("abc")("XXXX"), string("1XXXX3XXXX2") );
TEST_ALGO( replace_all, "", (string(""))(string("XXXX")), string("") );
TEST_ALGO( erase_all, "1abc3abc2", (string("abc")), string("132") );
TEST_ALGO( ierase_all, "1aBc3aBc2", ("aBC"), string("132") );
TEST_ALGO( erase_all, "1abc3abc2", ("abc"), string("132") );
TEST_ALGO( erase_all, "1abc3abc2", (string("")), string("1abc3abc2") );
TEST_ALGO( erase_all, "", (string("abc")), string("") );
// replace nth
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("YYY")), string("1YYY3abc2") );
TEST_ALGO( ireplace_nth, "1AbC3abc2", ("aBc")(0)("YYY"), string("1YYY3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("Z")), string("1Z3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(0)(string("XXXX")), string("1XXXX3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", ("abc")(0)("XXXX"), string("1XXXX3abc2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string(""))(0)(string("XXXX")), string("1abc3abc2") );
TEST_ALGO( replace_nth, "", (string(""))(0)(string("XXXX")), string("") );
TEST_ALGO( erase_nth, "1abc3abc2", (string("abc"))(0), string("13abc2") );
TEST_ALGO( ierase_nth, "1aBc3aBc2", ("ABC")(0), string("13aBc2") );
TEST_ALGO( erase_nth, "1abc3abc2", ("abc")(0), string("13abc2") );
TEST_ALGO( erase_nth, "1abc3abc2", (string(""))(0), string("1abc3abc2") );
TEST_ALGO( erase_nth, "", (string("abc"))(0), string("") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(1)(string("YYY")), string("1abc3YYY2") );
TEST_ALGO( replace_nth, "1abc3abc2", (string("abc"))(2)(string("YYY")), string("1abc3abc2") );
// replace head
TEST_ALGO( replace_head, "abc3abc2", (3)(string("YYY")), string("YYY3abc2") );
TEST_ALGO( replace_head, "abc3abc2", (3)("YYY"), string("YYY3abc2") );
TEST_ALGO( replace_head, "abc", (3)(string("Z")), string("Z") );
TEST_ALGO( replace_head, "abc", (6)(string("XXXX")), string("XXXX") );
TEST_ALGO( replace_head, "abc3abc2", (0)(string("XXXX")), string("abc3abc2") );
TEST_ALGO( replace_head, "", (4)(string("XXXX")), string("") );
TEST_ALGO( erase_head, "abc3abc2", (3), string("3abc2") );
TEST_ALGO( erase_head, "abc3abc2", (0), string("abc3abc2") );
TEST_ALGO( erase_head, "", (4), string("") );
// replace tail
TEST_ALGO( replace_tail, "abc3abc", (3)(string("YYY")), string("abc3YYY") );
TEST_ALGO( replace_tail, "abc3abc", (3)("YYY"), string("abc3YYY") );
TEST_ALGO( replace_tail, "abc", (3)(string("Z")), string("Z") );
TEST_ALGO( replace_tail, "abc", (6)(string("XXXX")), string("XXXX") );
TEST_ALGO( replace_tail, "abc3abc", (0)(string("XXXX")), string("abc3abc") );
TEST_ALGO( replace_tail, "", (4)(string("XXXX")), string("") );
TEST_ALGO( erase_tail, "abc3abc", (3), string("abc3") );
TEST_ALGO( erase_tail, "abc3abc", (0), string("abc3abc") );
TEST_ALGO( erase_tail, "", (4), string("") );
// replace_range
{
BOOST_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_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") );
}
// container traits complatibility 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") );
}
}
// test main
int test_main( int, char*[] )
{
sequence_traits_test();
replace_test();
return 0;
}

123
string/test/split_test.cpp Normal file
View File

@ -0,0 +1,123 @@
// 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 unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <vector>
#include <iostream>
#include <boost/test/test_tools.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
// equals predicate is used for result comparison
#include <boost/algorithm/string/predicate.hpp>
using namespace std;
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");
string str3("xx");
char* pch1="xx-abc--xx-abb";
vector<string> tokens;
vector< vector<int> > vtokens;
ifind_all(
tokens,
str2,
"xx" );
BOOST_REQUIRE( tokens.size()==2 );
BOOST_CHECK( tokens[0]==string("Xx") );
BOOST_CHECK( tokens[1]==string("xX") );
// find_all tests
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,
str1,
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(
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") );
}
// test main
int test_main( int, char*[] )
{
iterator_test();
return 0;
}

117
string/test/trim_test.cpp Normal file
View File

@ -0,0 +1,117 @@
// 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 unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <string>
#include <iostream>
#include <boost/algorithm/string/trim.hpp>
#include <boost/test/test_tools.hpp>
using namespace std;
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" );
}
// test main
int test_main( int, char*[] )
{
trim_test();
return 0;
}