mirror of
https://github.com/boostorg/algorithm.git
synced 2025-06-27 21:11:03 +02:00
String Algorithm Library: initial commit
[SVN r22431]
This commit is contained in:
61
string/doc/Jamfile.v2
Normal file
61
string/doc/Jamfile.v2
Normal 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
199
string/doc/concept.xml
Normal 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<Iter></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<typename ForwardIteratorT>
|
||||
boost::iterator_range<ForwardIterator> 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<std::string> 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<typename FindResultT>
|
||||
std::string operator()( const FindResultT& 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<std::string::const_iterator>& Match )
|
||||
{
|
||||
std::string Temp( Match.begin(), Match.end() );
|
||||
return Temp;
|
||||
}
|
||||
</programlisting>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
13
string/doc/credits.xml
Normal file
13
string/doc/credits.xml
Normal 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
281
string/doc/design.xml
Normal 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<></code>, but
|
||||
the <code>std::pair<></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<></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<iterator,iterator>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Container traits support a subset of container concept (Std §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<C></classname>::type</entry>
|
||||
<entry><code>C::value_type</code></entry>
|
||||
<entry>Type of contained values</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_difference_type<C></classname>::type</entry>
|
||||
<entry><code>C::difference_type</code></entry>
|
||||
<entry>difference type of the container</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_iterator<C></classname>::type</entry>
|
||||
<entry><code>C::iterator</code></entry>
|
||||
<entry>iterator type of the container</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>container_const_iterator<C></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<C></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.§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<C></classname>::value</entry>
|
||||
<entry>Specifies that the sequence has std::string like replace method</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><classname>sequence_has_stable_iterators<C></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<C></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<C></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<T> and
|
||||
std::basic_string<T> from the standard library and SGI's std::rope<T> and std::slist<T>.
|
||||
</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 << 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>
|
55
string/doc/environment.xml
Normal file
55
string/doc/environment.xml
Normal 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
45
string/doc/intro.xml
Normal 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
76
string/doc/rationale.xml
Normal 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>
|
42
string/doc/string_algo.xml
Normal file
42
string/doc/string_algo.xml
Normal 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
275
string/doc/usage.xml
Normal 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 <boost/string_algo.hpp>
|
||||
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& filename )
|
||||
{
|
||||
return
|
||||
iends_with(filename, ".exe") ||
|
||||
iends_with(filename, ".com");
|
||||
}
|
||||
|
||||
// ...
|
||||
string str1("command.com");
|
||||
cout
|
||||
<< str1
|
||||
<< is_executable("command.com")? "is": "is not"
|
||||
<< "an executable"
|
||||
<< endl; // prints "command.com is an executable"
|
||||
|
||||
//..
|
||||
char text1[]="hello world!";
|
||||
cout
|
||||
<< text1
|
||||
<< all( text1, is_lower<char>() )? "is": "is not"
|
||||
<< "written in the lower case"
|
||||
<< 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<char>("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<char*> result=find_last(text,"ll");
|
||||
|
||||
transform( result.begin(), result.end(), result.begin(), bind2nd(plus<char>(), 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< iterator_range<string::iterator> > find_vector_type;
|
||||
|
||||
find_vector_type FindVec; // #1: Search for separators
|
||||
ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] }
|
||||
|
||||
typdef vector< string > split_vector_type;
|
||||
|
||||
split_vector_type SplitVec; // #2: Search for tokens
|
||||
split( SplitVec, str1, is_any_of<char>("-*") ); // 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
75
string/example/Jamfile
Normal 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)
|
||||
:
|
||||
;
|
41
string/example/conv_example.cpp
Normal file
41
string/example/conv_example.cpp
Normal 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;
|
||||
}
|
58
string/example/find_example.cpp
Normal file
58
string/example/find_example.cpp
Normal 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;
|
||||
}
|
61
string/example/predicate_example.cpp
Normal file
61
string/example/predicate_example.cpp
Normal 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;
|
||||
}
|
42
string/example/regex_example.cpp
Normal file
42
string/example/regex_example.cpp
Normal 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;
|
||||
}
|
88
string/example/replace_example.cpp
Normal file
88
string/example/replace_example.cpp
Normal 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;
|
||||
}
|
241
string/example/rle_example.cpp
Normal file
241
string/example/rle_example.cpp
Normal 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;
|
||||
}
|
63
string/example/split_example.cpp
Normal file
63
string/example/split_example.cpp
Normal 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;
|
||||
}
|
47
string/example/trim_example.cpp
Normal file
47
string/example/trim_example.cpp
Normal 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
68
string/test/Jamfile
Normal 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
|
||||
]
|
||||
|
||||
;
|
||||
|
127
string/test/container_test.cpp
Normal file
127
string/test/container_test.cpp
Normal 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
88
string/test/conv_test.cpp
Normal 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
230
string/test/find_test.cpp
Normal 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;
|
||||
}
|
125
string/test/predicate_test.cpp
Normal file
125
string/test/predicate_test.cpp
Normal 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
135
string/test/regex_test.cpp
Normal 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;
|
||||
}
|
247
string/test/replace_test.cpp
Normal file
247
string/test/replace_test.cpp
Normal 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
123
string/test/split_test.cpp
Normal 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
117
string/test/trim_test.cpp
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user