diff options
Diffstat (limited to 'libs/algorithm/string')
32 files changed, 4339 insertions, 0 deletions
diff --git a/libs/algorithm/string/doc/Jamfile.v2 b/libs/algorithm/string/doc/Jamfile.v2 new file mode 100644 index 000000000..9ddebb8b6 --- /dev/null +++ b/libs/algorithm/string/doc/Jamfile.v2 @@ -0,0 +1,59 @@ +# Boost string_algo library documentation Jamfile --------------------------------- +# +# Copyright Pavol Droba 2002-2003. Use, modification and +# distribution is subject to the Boost Software License, Version +# 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# See http://www.boost.org for updates, documentation, and revision history. + +import toolset ; +toolset.using doxygen ; + +boostbook string_algo : string_algo.xml autodoc + : + <xsl:param>boost.root=../../../../.. + <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + ; + +doxygen autodoc + : + [ glob ../../../../boost/algorithm/string.hpp ] + [ glob ../../../../boost/algorithm/string_regex.hpp ] + + [ glob ../../../../boost/algorithm/string/classification.hpp ] + [ glob ../../../../boost/algorithm/string/iterator_range.hpp ] + [ glob ../../../../boost/algorithm/string/sequence_traits.hpp ] + [ glob ../../../../boost/algorithm/string/std_containers_traits.hpp ] + [ glob ../../../../boost/algorithm/string/concept.hpp ] + [ glob ../../../../boost/algorithm/string/compare.hpp ] + [ glob ../../../../boost/algorithm/string/constants.hpp ] + [ glob ../../../../boost/algorithm/string/case_conv.hpp ] + [ glob ../../../../boost/algorithm/string/find.hpp ] + [ glob ../../../../boost/algorithm/string/finder.hpp ] + [ glob ../../../../boost/algorithm/string/find_iterator.hpp ] + [ glob ../../../../boost/algorithm/string/trim.hpp ] + [ glob ../../../../boost/algorithm/string/predicate.hpp ] + [ glob ../../../../boost/algorithm/string/split.hpp ] + [ glob ../../../../boost/algorithm/string/iter_find.hpp ] + [ glob ../../../../boost/algorithm/string/erase.hpp ] + [ glob ../../../../boost/algorithm/string/join.hpp ] + [ glob ../../../../boost/algorithm/string/replace.hpp ] + [ glob ../../../../boost/algorithm/string/find_format.hpp ] + [ glob ../../../../boost/algorithm/string/formatter.hpp ] + [ glob ../../../../boost/algorithm/string/regex.hpp ] + [ glob ../../../../boost/algorithm/string/regex_find_format.hpp ] + [ glob ../../../../boost/algorithm/string/trim_all.hpp ] + : + <doxygen:param>HIDE_UNDOC_MEMBERS=YES + <doxygen:param>EXTRACT_PRIVATE=NO + <doxygen:param>ENABLE_PREPROCESSING=YES + <doxygen:param>MACRO_EXPANSION=YES + <doxygen:param>EXPAND_ONLY_PREDEF=YES + <doxygen:param>SEARCH_INCLUDES=YES + <doxygen:param>PREDEFINED="BOOST_STRING_TYPENAME=typename \"BOOST_STATIC_CONSTANT(type,var)=static const type var;\"" + ; + + + + diff --git a/libs/algorithm/string/doc/concept.xml b/libs/algorithm/string/doc/concept.xml new file mode 100644 index 000000000..4f17b43a0 --- /dev/null +++ b/libs/algorithm/string/doc/concept.xml @@ -0,0 +1,205 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.concept" last-revision="$Date: 2012-12-28 10:19:25 -0800 (Fri, 28 Dec 2012) $"> + <title>Concepts</title> + + <using-namespace name="boost"/> + <using-namespace name="boost::algorithm"/> + + <section> + <title>Definitions</title> + + <table> + <title>Notation</title> + <tgroup cols="2" align="left"> + <tbody> + <row> + <entry><code>F</code></entry> + <entry>A type that is a model of Finder</entry> + </row> + <row> + <entry><code>Fmt</code></entry> + <entry>A type that is a model of Formatter</entry> + </row> + <row> + <entry><code>Iter</code></entry> + <entry> + Iterator Type + </entry> + </row> + <row> + <entry><code>f</code></entry> + <entry>Object of type <code>F</code></entry> + </row> + <row> + <entry><code>fmt</code></entry> + <entry>Object of type <code>Fmt</code></entry> + </row> + <row> + <entry><code>i,j</code></entry> + <entry>Objects of type <code>Iter</code></entry> + </row> + </tbody> + </tgroup> + </table> + </section> + + <section id="string_algo.finder_concept"> + <title>Finder Concept</title> + + <para> + Finder is a functor which searches for an arbitrary part of a container. + The result of the search is given as an <classname>iterator_range</classname> + delimiting the selected part. + </para> + + <table> + <title>Valid Expressions</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Expression</entry> + <entry>Return Type</entry> + <entry>Effects</entry> + </row> + </thead> + <tbody> + <row> + <entry><code>f(i,j)</code></entry> + <entry>Convertible to <code>iterator_range<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 search in a container and a Finder is a generalization of such + search operations that allows algorithms to abstract from searching. For instance, generic replace + algorithms can replace any part of the input, and the Finder is used to select the desired one. + </para> + <para> + Note, that it is only required that the finder works with a particular iterator type. However, + a Finder operation can be defined as a template, allowing the Finder to work with any iterator. + </para> + <para> + <emphasis role="bold">Examples</emphasis> + </para> + <para> + <itemizedlist> + <listitem> + Finder implemented as a class. This Finder always returns the whole input as a match. <code>operator()</code> + is templated, so that the finder can be used on any iterator type. + + <programlisting> +struct simple_finder +{ + template<typename ForwardIteratorT> + boost::iterator_range<ForwardIteratorT> operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + return boost::make_range( Begin, End ); + } +}; + </programlisting> + </listitem> + <listitem> + Function Finder. Finder can be any function object. That is, any ordinary function with the + required signature can be used as well. However, such a function can be used only for + a specific iterator type. + + <programlisting> +boost::iterator_range<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 formatting + on it. Algorithms can abstract from formatting using a formatter. + </para> + <para> + <emphasis role="bold">Examples</emphasis> + </para> + <para> + <itemizedlist> + <listitem> + Formatter implemented as a class. This Formatter does not perform any formatting and + returns the match, repackaged. <code>operator()</code> + is templated, so that the Formatter can be used on any Finder type. + + <programlisting> +struct simple_formatter +{ + template<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> diff --git a/libs/algorithm/string/doc/credits.xml b/libs/algorithm/string/doc/credits.xml new file mode 100644 index 000000000..c8959e9ab --- /dev/null +++ b/libs/algorithm/string/doc/credits.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.credits" last-revision="$Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $"> + <title>Credits</title> + <section id="string_algo.ack"> + <title>Acknowledgments</title> + <para> + The author would like to thank everybody who gave suggestions and comments. Especially valuable + were the contributions of Thorsten Ottosen, Jeff Garland and the other boost members who participated + in the review process, namely David Abrahams, Daniel Frey, Beman Dawes, John Maddock, David B.Held, Pavel Vozenilek + and many other. + </para> + <para> + Additional thanks go to Stefan Slapeta and Toon Knapen, who have been very resourceful in solving various + portability issues. + </para> + </section> +</section> diff --git a/libs/algorithm/string/doc/design.xml b/libs/algorithm/string/doc/design.xml new file mode 100644 index 000000000..2d614a563 --- /dev/null +++ b/libs/algorithm/string/doc/design.xml @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.design" last-revision="$Date: 2010-04-21 16:00:35 -0700 (Wed, 21 Apr 2010) $"> + <title>Design Topics</title> + + <using-namespace name="boost"/> + <using-namespace name="boost::algorithm"/> + + <section id="string_algo.string"> + <title>String Representation</title> + + <para> + As the name suggest, this library works mainly with strings. However, in the context of this library, + a string is not restricted to any particular implementation (like <code>std::basic_string</code>), + rather it is a concept. This allows the algorithms in this library to be reused for any string type, + that satisfies the given requirements. + </para> + <para> + <emphasis role="bold">Definition:</emphasis> A string is a + <ulink url="../../libs/range/index.html">range</ulink> of characters accessible in sequential + ordered fashion. Character is any value type with "cheap" copying and assignment. + </para> + <para> + First requirement of string-type is that it must accessible using + <ulink url="../../libs/range/index.html">Boost.Range</ulink>. This facility allows to access + the elements inside the string in a uniform iterator-based fashion. + This is sufficient for our library + </para> + <para> + Second requirement defines the way in which the characters are stored in the string. Algorithms in + this library work with an assumption that copying a character is cheaper then allocating extra + storage to cache results. This is a natural assumption for common character types. Algorithms will + work even if this requirement is not satisfied, however at the cost of performance degradation. + <para> + </para> + In addition some algorithms have additional requirements on the string-type. Particularly, it is required + that an algorithm can create a new string of the given type. In this case, it is required that + the type satisfies the sequence (Std §23.1.1) requirements. + </para> + <para> + In the reference and also in the code, requirement on the string type is designated by the name of + template argument. <code>RangeT</code> means that the basic range requirements must hold. + <code>SequenceT</code> designates extended sequence requirements. + </para> + </section> + + <section id="string_algo.sequence_traits"> + <title>Sequence Traits</title> + + <para> + The major difference between <code>std::list</code> and <code>std::vector</code> is not in the interfaces + they provide, but rather in the inner details of the class and the way how it performs + various operations. The problem is that it is not possible to infer this difference from the + definitions of classes without some special mechanism. + However, some algorithms can run significantly faster with the knowledge of the properties + of a particular container. + </para> + <para> + Sequence traits allow one to specify additional properties of a sequence container (see Std.§32.2). + These properties are then used by algorithms to select optimized handling for some operations. + The sequence traits are declared in the header + <headername>boost/algorithm/string/sequence_traits.hpp</headername>. + </para> + + <para> + In the table C denotes a container and c is an object of C. + </para> + <table> + <title>Sequence Traits</title> + <tgroup cols="2" align="left"> + <thead> + <row> + <entry>Trait</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><classname>has_native_replace<C></classname>::value</entry> + <entry>Specifies that the sequence has std::string like replace method</entry> + </row> + <row> + <entry><classname>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>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>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 by magnitude smaller than n) the current implementation + provides acceptable efficiency. + Even the C++ standard defines the required complexity for search algorithm as O(n * m). + It is possible that a future version of library will also contain algorithms with linear + complexity as an option + </para> + </section> + <section id="string_algo.replace"> + <title>Replace Algorithms</title> + + <para> + The implementation of replace algorithms follows the layered structure of the library. The + lower layer implements generic substitution of a range in the input sequence. + This layer takes a <link linkend="string_algo.finder_concept">Finder</link> object and a + <link linkend="string_algo.formatter_concept">Formatter</link> object as an input. These two + functors define what to replace and what to replace it with. The upper layer functions + are just wrapping calls to the lower layer. Finders are shared with the find and split facility. + </para> + <para> + As usual, the implementation of the lower layer is designed to work with a generic sequence while + taking advantage of specific features if possible + (by using <link linkend="string_algo.sequence_traits">Sequence traits</link>) + </para> + </section> + <section id="string_algo.split"> + <title>Find Iterators & Split Algorithms</title> + + <para> + Find iterators are a logical extension of the <link linkend="string_algo.find">find facility</link>. + Instead of searching for one match, the whole input can be iteratively searched for multiple matches. + The result of the search is then used to partition the input. It depends on the algorithms which parts + are returned as the result. They can be the matching parts (<classname>find_iterator</classname>) of the parts in + between (<classname>split_iterator</classname>). + </para> + <para> + In addition the split algorithms like <functionname>find_all()</functionname> and <functionname>split()</functionname> + can simplify the common operations. They use a find iterator to search the whole input and copy the + matches they found into the supplied container. + </para> + </section> + <section id="string_algo.exception"> + <title>Exception Safety</title> + + <para> + The library requires that all operations on types used as template + or function arguments provide the <emphasis>basic exception-safety guarantee</emphasis>. + In turn, all functions and algorithms in this library, except where stated + otherwise, will provide the <emphasis>basic exception-safety guarantee</emphasis>. + In other words: + The library maintains its invariants and does not leak resources in + the face of exceptions. Some library operations give stronger + guarantees, which are documented on an individual basis. + </para> + + <para> + Some functions can provide the <emphasis>strong exception-safety guarantee</emphasis>. + That means that following statements are true: + <itemizedlist> + <listitem> + If an exception is thrown, there are no effects other than those + of the function + </listitem> + <listitem> + If an exception is thrown other than by the function, there are no effects + </listitem> + </itemizedlist> + This guarantee can be provided under the condition that the operations + on the types used for arguments for these functions either + provide the strong exception guarantee or do not alter the global state . + </para> + <para> + In the reference, under the term <emphasis>strong exception-safety guarantee</emphasis>, we mean the + guarantee as defined above. + </para> + <para> + For more information about the exception safety topics, follow this + <ulink url="http://www.boost.org/more/generic_exception_safety.html">link</ulink> + </para> + </section> +</section> diff --git a/libs/algorithm/string/doc/environment.xml b/libs/algorithm/string/doc/environment.xml new file mode 100644 index 000000000..3b65ce99d --- /dev/null +++ b/libs/algorithm/string/doc/environment.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.env" last-revision="$Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $"> + <title>Environment</title> + <section> + <title>Build</title> + <para> + The whole library is provided in headers. Regex variants of some algorithms, + however, are dependent on the <libraryname>Boost.Regex</libraryname> library. All such algorithms are + separated in <headername>boost/algorithm/string_regex.hpp</headername>. + If this header is used, the application must be linked with the <libraryname>Boost.Regex</libraryname> + library. + </para> + </section> + + <section> + <title>Examples</title> + <para> + Examples showing the basic usage of the library can be found in the libs/algorithm/string/example + directory. There is a separate file for the each part of the library. Please follow the boost + build guidelines to build examples using the bjam. To successfully build regex examples + the <libraryname>Boost.Regex</libraryname> library is required. + </para> + </section> + + <section> + <title>Tests</title> + <para> + A full set of test cases for the library is located in the libs/algorithm/string/test directory. + The test cases can be executed using the boost build system. For the tests of regular + expression variants of algorithms, the <libraryname>Boost.Regex</libraryname> library is required. + </para> + </section> + + <section> + <title>Portability</title> + <para> + The library has been successfully compiled and tested with the following compilers: + + <itemizedlist> + <listitem>Microsoft Visual C++ 7.0</listitem> + <listitem>Microsoft Visual C++ 7.1</listitem> + <listitem>GCC 3.2</listitem> + <listitem>GCC 3.3.1</listitem> + </itemizedlist> + + See <ulink url="http://boost.sourceforge.net/regression-logs/">Boost regression tables</ulink> + for additional info for a particular compiler. + </para> + <para> + There are known limitation on platforms not supporting partial template specialization. + Library depends on correctly implemented <code>std::iterator_traits</code> class. + If a standard library provided with compiler is broken, the String Algorithm Library + cannot function properly. Usually it implies that primitive pointer iterators are not + working with the library functions. + </para> + </section> +</section> diff --git a/libs/algorithm/string/doc/external_concepts.html b/libs/algorithm/string/doc/external_concepts.html new file mode 100644 index 000000000..af403bebb --- /dev/null +++ b/libs/algorithm/string/doc/external_concepts.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title> Concepts and External Concepts </title><meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1"></head> <body><table ><tr ><td ><img src="../../../../boost.png" width="100%" border="0"></td><td ><h1 >Concepts and External Concepts</h1></td></tr></table><p >Generic programming in C++ is characterized by the use of function and class templates where + the template parameter(s) must satisfy certain requirements.Often these + requirements are so important that we give them a name: we call + such a set of type requirements a <b>concept</b>. We say that a type <i> + conforms to a concept</i> or that it <i>is a model of a concept</i> if it + satisfies all of those requirements. The concept can be specified as a set + of member functions with well-defined semantics + and a set of nested typedefs with well-defined properties.</p><p >Often it much more flexible to provide free-standing functions and typedefs + which provides the exact same semantics (but a different syntax) as + specified + by the concept. This allows generic code to treat different types <i> as if + </i> they fulfilled the concept. In this case we say that the concept has + been <b> externalized </b> or that the new requirements constitutes an <b>external + concept </b>. We say that a type <i> conforms to an external concept </i> + or that it <i> is a model of an external concept </i>. A concept may exist + without a corresponding external concept and conversely.</p><p >Whenever a concept specifies a member function, the corresponding external + concept + must specify a free-standing function of the same name, same return type and + the same argument list except there is an extra first argument which must + be of the type (or a reference to that type) that is to fulfill the external + concept. If the corresonding member function has any cv-qulifiers, the + first argument must have the same cv-qualifiers. Whenever a concept + specifies a nested typedef, the corresponding external concept + specifies a <b>type-generator</b>, that is, a type with a nested typedef + named <code>type</code>. The type-generator has the name as the nested typedef with + <code>_of</code> appended. + The converse relationship of an external concept and its corresponding concept + also holds.</p><p ><b ><i >Example:</i></b></p><p >A type <code>T</code> fulfills the FooConcept if it + has the follwing public members:</p><code> void T::foo( int ) const; <br> + int T::bar(); <br> + typedef <i>implementation defined </i> foo_type;</code><p >The corresponding external concept is the ExternalFooConcept.</p><p >A type <code>T</code> fullfills the ExternalFooConcept if these + free-standing functions and type-generators exists:</p><code>void foo( const T&, int ); <br> + int bar( T& ); <br> + foo_type_of< T >::type;</code> <br> <br><hr size="1" ><h3 >Literature</h3><ul ><li > <a href="http://www.boost.org/more/generic_programming.html#type_generator" target="_self" >Type Generators</a> </li><li > <a href="http://www.boost.org/more/generic_programming.html#concept" target="_self" >Concepts</a> </li><li > <a href="http://www.sgi.com/tech/stl/stl_introduction.html" target="_self" >Concepts and SGI STL</a> </li></ul><hr size="1" ><p >© Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk). +<br>Use, modification and distribution is subject to the Boost + Software License, Version 1.0. (See accompanying file + <code class="filename">LICENSE_1_0.txt</code> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) +</br> +</p> + <!-- Copyright Dezide Aps 2003-2004 --> diff --git a/libs/algorithm/string/doc/intro.xml b/libs/algorithm/string/doc/intro.xml new file mode 100644 index 000000000..b2afe661c --- /dev/null +++ b/libs/algorithm/string/doc/intro.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.intro" last-revision="$Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $"> + <title>Introduction</title> + + <para> + The String Algorithm Library provides a generic implementation of + string-related algorithms which are missing in STL. It is an extension + to the algorithms library of STL and it includes trimming, case conversion, + predicates and find/replace functions. All of them come in different variants + so it is easier to choose the best fit for a particular need. + </para> + <para> + The implementation is not restricted to work with a particular container + (like <code>std::basic_string</code>), rather it is as generic as + possible. This generalization is not compromising the performance since + algorithms are using container specific features when it means a performance + gain. + </para> + <para> + <emphasis role="bold"> + Important note: In this documentation we use term <emphasis>string</emphasis> to + designate a sequence of <emphasis>characters</emphasis> stored in an arbitrary container. + A <emphasis>string</emphasis> is not restricted to <code>std::basic_string</code> and + <emphasis>character</emphasis> does not have to be <code>char</code> or <code>wchar_t</code>, + although these are most common candidates. + </emphasis> + Consult the <link linkend="string_algo.design">design chapter</link> to see precise specification of + supported string types. + </para> + <para> + The library interface functions and classes are defined in namespace <code>boost::algorithm</code>, and + they are lifted into namespace <code>boost</code> via using declaration. + </para> + <para> + The documentation is divided into several sections. For a quick start read the + <link linkend="string_algo.usage">Usage</link> section followed by + <link linkend="string_algo.quickref">Quick Reference</link>. + <link linkend="string_algo.design">The Design Topics</link>, + <link linkend="string_algo.concept">Concepts</link> and <link linkend="string_algo.rationale">Rationale</link> + provide some explanation about the library design and structure an explain how it should be used. + See the <link linkend="string_algo.reference">Reference</link> for the complete list of provided utilities + and algorithms. Functions and classes in the reference are organized by the headers in which they are defined. + The reference contains links to the detailed description for every entity in the library. + </para> +</section> diff --git a/libs/algorithm/string/doc/quickref.xml b/libs/algorithm/string/doc/quickref.xml new file mode 100644 index 000000000..8f495bc01 --- /dev/null +++ b/libs/algorithm/string/doc/quickref.xml @@ -0,0 +1,758 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.quickref" last-revision="$Date: 2012-01-15 08:49:25 -0800 (Sun, 15 Jan 2012) $"> + <title>Quick Reference</title> + + <using-namespace name="boost"/> + <using-namespace name="boost::algorithm"/> + + <section> + <title>Algorithms</title> + + <table> + <title>Case Conversion</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry><code>to_upper</code></entry> + <entry>Convert a string to upper case</entry> + <entry> + <functionname>to_upper_copy()</functionname> + <sbr/> + <functionname>to_upper()</functionname> + </entry> + </row> + <row> + <entry><code>to_lower</code></entry> + <entry>Convert a string to lower case</entry> + <entry> + <functionname>to_lower_copy()</functionname> + <sbr/> + <functionname>to_lower()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + <table> + <title>Trimming</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry><code>trim_left</code></entry> + <entry>Remove leading spaces from a string</entry> + <entry> + <functionname>trim_left_copy_if()</functionname> + <sbr/> + <functionname>trim_left_if()</functionname> + <sbr/> + <functionname>trim_left_copy()</functionname> + <sbr/> + <functionname>trim_left()</functionname> + </entry> + </row> + <row> + <entry><code>trim_right</code></entry> + <entry>Remove trailing spaces from a string</entry> + <entry> + <functionname>trim_right_copy_if()</functionname> + <sbr/> + <functionname>trim_right_if()</functionname> + <sbr/> + <functionname>trim_right_copy()</functionname> + <sbr/> + <functionname>trim_right()</functionname> + </entry> + </row> + <row> + <entry><code>trim</code></entry> + <entry>Remove leading and trailing spaces from a string</entry> + <entry> + <functionname>trim_copy_if()</functionname> + <sbr/> + <functionname>trim_if()</functionname> + <sbr/> + <functionname>trim_copy()</functionname> + <sbr/> + <functionname>trim()</functionname> + </entry> + </row> + + </tbody> + </tgroup> + </table> + <table> + <title>Predicates</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry><code>starts_with</code></entry> + <entry>Check if a string is a prefix of the other one</entry> + <entry> + <functionname>starts_with()</functionname> + <sbr/> + <functionname>istarts_with()</functionname> + </entry> + </row> + <row> + <entry><code>ends_with</code></entry> + <entry>Check if a string is a suffix of the other one</entry> + <entry> + <functionname>ends_with()</functionname> + <sbr/> + <functionname>iends_with()</functionname> + </entry> + </row> + <row> + <entry><code>contains</code></entry> + <entry>Check if a string is contained of the other one</entry> + <entry> + <functionname>contains()</functionname> + <sbr/> + <functionname>icontains()</functionname> + </entry> + </row> + <row> + <entry><code>equals</code></entry> + <entry>Check if two strings are equal</entry> + <entry> + <functionname>equals()</functionname> + <sbr/> + <functionname>iequals()</functionname> + </entry> + </row> + <row> + <entry><code>lexicographical_compare</code></entry> + <entry>Check if a string is lexicographically less then another one</entry> + <entry> + <functionname>lexicographical_compare()</functionname> + <sbr/> + <functionname>ilexicographical_compare()</functionname> + </entry> + </row> + + <row> + <entry><code>all</code></entry> + <entry>Check if all elements of a string satisfy the given predicate</entry> + <entry> + <functionname>all()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + <table> + <title>Find algorithms</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry>find_first</entry> + <entry>Find the first occurrence of a string in the input</entry> + <entry> + <functionname>find_first()</functionname> + <sbr/> + <functionname>ifind_first()</functionname> + </entry> + </row> + <row> + <entry>find_last</entry> + <entry>Find the last occurrence of a string in the input</entry> + <entry> + <functionname>find_last()</functionname> + <sbr/> + <functionname>ifind_last()</functionname> + </entry> + </row> + <row> + <entry>find_nth</entry> + <entry>Find the nth (zero-indexed) occurrence of a string in the input</entry> + <entry> + <functionname>find_nth()</functionname> + <sbr/> + <functionname>ifind_nth()</functionname> + </entry> + </row> + <row> + <entry>find_head</entry> + <entry>Retrieve the head of a string</entry> + <entry> + <functionname>find_head()</functionname> + </entry> + </row> + <row> + <entry>find_tail</entry> + <entry>Retrieve the tail of a string</entry> + <entry> + <functionname>find_tail()</functionname> + </entry> + </row> + <row> + <entry>find_token</entry> + <entry>Find first matching token in the string</entry> + <entry> + <functionname>find_token()</functionname> + </entry> + </row> + <row> + <entry>find_regex</entry> + <entry>Use the regular expression to search the string</entry> + <entry> + <functionname>find_regex()</functionname> + </entry> + </row> + <row> + <entry>find</entry> + <entry>Generic find algorithm</entry> + <entry> + <functionname>find()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + <table> + <title>Erase/Replace</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry>replace/erase_first</entry> + <entry>Replace/Erase the first occurrence of a string in the input</entry> + <entry> + <functionname>replace_first()</functionname> + <sbr/> + <functionname>replace_first_copy()</functionname> + <sbr/> + <functionname>ireplace_first()</functionname> + <sbr/> + <functionname>ireplace_first_copy()</functionname> + <sbr/> + <functionname>erase_first()</functionname> + <sbr/> + <functionname>erase_first_copy()</functionname> + <sbr/> + <functionname>ierase_first()</functionname> + <sbr/> + <functionname>ierase_first_copy()</functionname> + </entry> + </row> + <row> + <entry>replace/erase_last</entry> + <entry>Replace/Erase the last occurrence of a string in the input</entry> + <entry> + <functionname>replace_last()</functionname> + <sbr/> + <functionname>replace_last_copy()</functionname> + <sbr/> + <functionname>ireplace_last()</functionname> + <sbr/> + <functionname>ireplace_last_copy()</functionname> + <sbr/> + <functionname>erase_last()</functionname> + <sbr/> + <functionname>erase_last_copy()</functionname> + <sbr/> + <functionname>ierase_last()</functionname> + <sbr/> + <functionname>ierase_last_copy()</functionname> + </entry> + </row> + <row> + <entry>replace/erase_nth</entry> + <entry>Replace/Erase the nth (zero-indexed) occurrence of a string in the input</entry> + <entry> + <functionname>replace_nth()</functionname> + <sbr/> + <functionname>replace_nth_copy()</functionname> + <sbr/> + <functionname>ireplace_nth()</functionname> + <sbr/> + <functionname>ireplace_nth_copy()</functionname> + <sbr/> + <functionname>erase_nth()</functionname> + <sbr/> + <functionname>erase_nth_copy()</functionname> + <sbr/> + <functionname>ierase_nth()</functionname> + <sbr/> + <functionname>ierase_nth_copy()</functionname> + </entry> + </row> + <row> + <entry>replace/erase_all</entry> + <entry>Replace/Erase the all occurrences of a string in the input</entry> + <entry> + <functionname>replace_all()</functionname> + <sbr/> + <functionname>replace_all_copy()</functionname> + <sbr/> + <functionname>ireplace_all()</functionname> + <sbr/> + <functionname>ireplace_all_copy()</functionname> + <sbr/> + <functionname>erase_all()</functionname> + <sbr/> + <functionname>erase_all_copy()</functionname> + <sbr/> + <functionname>ierase_all()</functionname> + <sbr/> + <functionname>ierase_all_copy()</functionname> + </entry> + </row> + <row> + <entry>replace/erase_head</entry> + <entry>Replace/Erase the head of the input</entry> + <entry> + <functionname>replace_head()</functionname> + <sbr/> + <functionname>replace_head_copy()</functionname> + <sbr/> + <functionname>erase_head()</functionname> + <sbr/> + <functionname>erase_head_copy()</functionname> + <sbr/> + </entry> + </row> + <row> + <entry>replace/erase_tail</entry> + <entry>Replace/Erase the tail of the input</entry> + <entry> + <functionname>replace_tail()</functionname> + <sbr/> + <functionname>replace_tail_copy()</functionname> + <sbr/> + <functionname>erase_tail()</functionname> + <sbr/> + <functionname>erase_tail_copy()</functionname> + <sbr/> + </entry> + </row> + <row> + <entry>replace/erase_regex</entry> + <entry>Replace/Erase a substring matching the given regular expression</entry> + <entry> + <functionname>replace_regex()</functionname> + <sbr/> + <functionname>replace_regex_copy()</functionname> + <sbr/> + <functionname>erase_regex()</functionname> + <sbr/> + <functionname>erase_regex_copy()</functionname> + <sbr/> + </entry> + </row> + <row> + <entry>replace/erase_regex_all</entry> + <entry>Replace/Erase all substrings matching the given regular expression</entry> + <entry> + <functionname>replace_all_regex()</functionname> + <sbr/> + <functionname>replace_all_regex_copy()</functionname> + <sbr/> + <functionname>erase_all_regex()</functionname> + <sbr/> + <functionname>erase_all_regex_copy()</functionname> + <sbr/> + </entry> + </row> + <row> + <entry>find_format</entry> + <entry>Generic replace algorithm</entry> + <entry> + <functionname>find_format()</functionname> + <sbr/> + <functionname>find_format_copy()</functionname> + <sbr/> + <functionname>find_format_all()</functionname> + <sbr/> + <functionname>find_format_all_copy()()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + <table> + <title>Split</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry>find_all</entry> + <entry>Find/Extract all matching substrings in the input</entry> + <entry> + <functionname>find_all()</functionname> + <sbr/> + <functionname>ifind_all()</functionname> + <sbr/> + <functionname>find_all_regex()</functionname> + </entry> + </row> + <row> + <entry>split</entry> + <entry>Split input into parts</entry> + <entry> + <functionname>split()</functionname> + <sbr/> + <functionname>split_regex()</functionname> + </entry> + </row> + <row> + <entry>iter_find</entry> + <entry>Iteratively apply the finder to the input to find all matching substrings</entry> + <entry> + <functionname>iter_find()</functionname> + </entry> + </row> + <row> + <entry>iter_split</entry> + <entry>Use the finder to find matching substrings in the input and use them as separators to split the input into parts</entry> + <entry> + <functionname>iter_split()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + <table> + <title>Join</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Algorithm name</entry> + <entry>Description</entry> + <entry>Functions</entry> + </row> + </thead> + <tbody> + <row> + <entry>join</entry> + <entry>Join all elements in a container into a single string</entry> + <entry> + <functionname>join</functionname> + </entry> + </row> + <row> + <entry>join_if</entry> + <entry>Join all elements in a container that satisfies the condition into a single string</entry> + <entry> + <functionname>join_if()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + </section> + <section> + <title>Finders and Formatters</title> + + <table> + <title>Finders</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Finder</entry> + <entry>Description</entry> + <entry>Generators</entry> + </row> + </thead> + <tbody> + <row> + <entry>first_finder</entry> + <entry>Search for the first match of the string in an input</entry> + <entry> + <functionname>first_finder()</functionname> + </entry> + </row> + <row> + <entry>last_finder</entry> + <entry>Search for the last match of the string in an input</entry> + <entry> + <functionname>last_finder()</functionname> + </entry> + </row> + <row> + <entry>nth_finder</entry> + <entry>Search for the nth (zero-indexed) match of the string in an input</entry> + <entry> + <functionname>nth_finder()</functionname> + </entry> + </row> + <row> + <entry>head_finder</entry> + <entry>Retrieve the head of an input</entry> + <entry> + <functionname>head_finder()</functionname> + </entry> + </row> + <row> + <entry>tail_finder</entry> + <entry>Retrieve the tail of an input</entry> + <entry> + <functionname>tail_finder()</functionname> + </entry> + </row> + <row> + <entry>token_finder</entry> + <entry>Search for a matching token in an input</entry> + <entry> + <functionname>token_finder()</functionname> + </entry> + </row> + <row> + <entry>range_finder</entry> + <entry>Do no search, always returns the given range</entry> + <entry> + <functionname>range_finder()</functionname> + </entry> + </row> + <row> + <entry>regex_finder</entry> + <entry>Search for a substring matching the given regex</entry> + <entry> + <functionname>regex_finder()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + + <table> + <title>Formatters</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Formatter</entry> + <entry>Description</entry> + <entry>Generators</entry> + </row> + </thead> + <tbody> + <row> + <entry>const_formatter</entry> + <entry>Constant formatter. Always return the specified string</entry> + <entry> + <functionname>const_formatter()</functionname> + </entry> + </row> + <row> + <entry>identity_formatter</entry> + <entry>Identity formatter. Return unmodified input input</entry> + <entry> + <functionname>identity_formatter()</functionname> + </entry> + </row> + <row> + <entry>empty_formatter</entry> + <entry>Null formatter. Always return an empty string</entry> + <entry> + <functionname>empty_formatter()</functionname> + </entry> + </row> + <row> + <entry>regex_formatter</entry> + <entry>Regex formatter. Format regex match using the specification in the format string</entry> + <entry> + <functionname>regex_formatter()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + </section> + <section> + <title>Iterators</title> + + <table> + <title>Find Iterators</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Iterator name</entry> + <entry>Description</entry> + <entry>Iterator class</entry> + </row> + </thead> + <tbody> + <row> + <entry>find_iterator</entry> + <entry>Iterates through matching substrings in the input</entry> + <entry> + <classname>find_iterator</classname> + </entry> + </row> + <row> + <entry>split_iterator</entry> + <entry>Iterates through gaps between matching substrings in the input</entry> + <entry> + <classname>split_iterator</classname> + </entry> + </row> + </tbody> + </tgroup> + </table> + </section> + + <section> + <title>Classification</title> + + <table> + <title>Predicates</title> + <tgroup cols="3" align="left"> + <thead> + <row> + <entry>Predicate name</entry> + <entry>Description</entry> + <entry>Generator</entry> + </row> + </thead> + <tbody> + <row> + <entry>is_classified</entry> + <entry>Generic <code>ctype</code> mask based classification</entry> + <entry> + <functionname>is_classified()</functionname> + </entry> + </row> + <row> + <entry>is_space</entry> + <entry>Recognize spaces</entry> + <entry> + <functionname>is_space()</functionname> + </entry> + </row> + <row> + <entry>is_alnum</entry> + <entry>Recognize alphanumeric characters</entry> + <entry> + <functionname>is_alnum()</functionname> + </entry> + </row> + <row> + <entry>is_alpha</entry> + <entry>Recognize letters</entry> + <entry> + <functionname>is_alpha()</functionname> + </entry> + </row> + <row> + <entry>is_cntrl</entry> + <entry>Recognize control characters</entry> + <entry> + <functionname>is_cntrl()</functionname> + </entry> + </row> + <row> + <entry>is_digit</entry> + <entry>Recognize decimal digits</entry> + <entry> + <functionname>is_digit()</functionname> + </entry> + </row> + <row> + <entry>is_graph</entry> + <entry>Recognize graphical characters</entry> + <entry> + <functionname>is_graph()</functionname> + </entry> + </row> + <row> + <entry>is_lower</entry> + <entry>Recognize lower case characters</entry> + <entry> + <functionname>is_lower()</functionname> + </entry> + </row> + <row> + <entry>is_print</entry> + <entry>Recognize printable characters</entry> + <entry> + <functionname>is_print()</functionname> + </entry> + </row> + <row> + <entry>is_punct</entry> + <entry>Recognize punctuation characters</entry> + <entry> + <functionname>is_punct()</functionname> + </entry> + </row> + <row> + <entry>is_upper</entry> + <entry>Recognize uppercase characters</entry> + <entry> + <functionname>is_upper()</functionname> + </entry> + </row> + <row> + <entry>is_xdigit</entry> + <entry>Recognize hexadecimal digits</entry> + <entry> + <functionname>is_xdigit()</functionname> + </entry> + </row> + <row> + <entry>is_any_of</entry> + <entry>Recognize any of a sequence of characters</entry> + <entry> + <functionname>is_any_of()</functionname> + </entry> + </row> + <row> + <entry>is_from_range</entry> + <entry>Recognize characters inside a min..max range</entry> + <entry> + <functionname>is_from_range()</functionname> + </entry> + </row> + </tbody> + </tgroup> + </table> + </section> +</section> diff --git a/libs/algorithm/string/doc/rationale.xml b/libs/algorithm/string/doc/rationale.xml new file mode 100644 index 000000000..fe4e8f1c3 --- /dev/null +++ b/libs/algorithm/string/doc/rationale.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.rationale" last-revision="$Date: 2008-02-27 12:00:24 -0800 (Wed, 27 Feb 2008) $"> + <title>Rationale</title> + + <using-namespace name="boost"/> + <using-namespace name="boost::algorithm"/> + + <section it="string_algo.locale"> + <title>Locales</title> + + <para> + Locales have a very close relation to string processing. They contain information about + the character sets and are used, for example, to change the case of characters and + to classify the characters. + </para> + <para> + C++ allows to work with multiple different instances of locales at once. If an algorithm + manipulates some data in a way that requires the usage of locales, there must be a way + to specify them. However, one instance of locales is sufficient for most of the applications, + and for a user it could be very tedious to specify which locales to use at every place + where it is needed. + </para> + <para> + Fortunately, the C++ standard allows to specify the <emphasis>global</emphasis> locales (using static member + function <code>std:locale::global()</code>). When instantiating an + <code>std::locale</code> class without explicit information, the instance will + be initialized with the <emphasis>global</emphasis> locale. This implies, that if an algorithm needs a locale, + it should have an <code>std::locale</code> parameter defaulting to <code>std::locale()</code>. + If a user needs to specify locales explicitly, she can do so. Otherwise the <emphasis>global</emphasis> + locales are used. + </para> + </section> + <section id="string_algo.regex"> + <title>Regular Expressions</title> + + <para> + Regular expressions are an essential part of text processing. For this reason, the library + also provides regex variants of some algorithms. The library does not attempt to replace + <libraryname>Boost.Regex</libraryname>; it merely wraps its functionality in a new interface. + As a part of this library, regex algorithms integrate smoothly with other components, which + brings additional value. + </para> + </section> +</section> diff --git a/libs/algorithm/string/doc/release_notes.xml b/libs/algorithm/string/doc/release_notes.xml new file mode 100644 index 000000000..ba2a39c5d --- /dev/null +++ b/libs/algorithm/string/doc/release_notes.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<section id="string_algo.release_notes" last-revision="$Date: 2012-12-28 10:19:25 -0800 (Fri, 28 Dec 2012) $"> + + <using-namespace name="boost"/> + <using-namespace name="boost::algorithm"/> + + <title>Release Notes</title> + + <itemizedlist> + <listitem> + <para><emphasis role="bold">1.32</emphasis></para> + <para>Initial release in Boost</para> + </listitem> + <listitem> + <para><emphasis role="bold">1.33</emphasis></para> + <para>Internal version of collection traits removed, library adapted to Boost.Range</para> + </listitem> + <listitem> + <para><emphasis role="bold">1.34</emphasis></para> + <itemizedlist> + <listitem> + <functionname>lexicographical_compare()</functionname> + </listitem> + <listitem> + <functionname>join()</functionname> and <functionname>join_if()</functionname> + </listitem> + <listitem> + New comparison predicates <code>is_less</code>, <code>is_not_greater</code> + </listitem> + <listitem> + Negative indexes support (like Perl) in various algorithms + (<code>*_head/tail</code>, <code>*_nth</code>). + </listitem> + </itemizedlist> + </listitem> + </itemizedlist> +</section> diff --git a/libs/algorithm/string/doc/string_algo.xml b/libs/algorithm/string/doc/string_algo.xml new file mode 100644 index 000000000..1eb4a2c8d --- /dev/null +++ b/libs/algorithm/string/doc/string_algo.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + +<library name="String Algorithms" dirname="algorithm/string" xmlns:xi="http://www.w3.org/2001/XInclude" + id="string_algo" last-revision="$Date: 2010-07-10 13:29:03 -0700 (Sat, 10 Jul 2010) $"> + <libraryinfo> + <author> + <firstname>Pavol</firstname> + <surname>Droba</surname> + </author> + + <copyright> + <year>2002</year> + <year>2003</year> + <year>2004</year> + <holder>Pavol Droba</holder> + </copyright> + + <legalnotice> + <para>Use, modification and distribution is subject to the Boost + Software License, Version 1.0. (See accompanying file + <filename>LICENSE_1_0.txt</filename> or copy at <ulink + url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>) + </para> + </legalnotice> + + <librarypurpose> + A set of generic string-related algorithms and utilities + </librarypurpose> + <librarycategory name="category:algorithms"/> + <librarycategory name="category:string-text"/> + </libraryinfo> + + <title>Boost String Algorithms Library</title> + <xi:include href="intro.xml"/> + <xi:include href="release_notes.xml"/> + <xi:include href="usage.xml"/> + <xi:include href="quickref.xml"/> + <xi:include href="design.xml"/> + <xi:include href="concept.xml"/> + <xi:include href="autodoc.xml"/> + <xi:include href="rationale.xml"/> + <xi:include href="environment.xml"/> + <xi:include href="credits.xml"/> +</library> + diff --git a/libs/algorithm/string/doc/usage.xml b/libs/algorithm/string/doc/usage.xml new file mode 100644 index 000000000..4d14ee16c --- /dev/null +++ b/libs/algorithm/string/doc/usage.xml @@ -0,0 +1,366 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" +"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> + + +<!-- Copyright (c) 2002-2006 Pavol Droba. + Subject to the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) +--> + + +<section id="string_algo.usage" last-revision="$Date: 2013-05-22 08:10:49 -0700 (Wed, 22 May 2013) $"> + <title>Usage</title> + + <using-namespace name="boost"/> + <using-namespace name="boost::algorithm"/> + + + <section> + <title>First Example</title> + + <para> + Using the algorithms is straightforward. Let us have a look at the first example: + </para> + <programlisting> + #include <boost/algorithm/string.hpp> + using namespace std; + using namespace boost; + + // ... + + string str1(" hello world! "); + to_upper(str1); // str1 == " HELLO WORLD! " + trim(str1); // str1 == "HELLO WORLD!" + + string str2= + to_lower_copy( + ireplace_first_copy( + str1,"hello","goodbye")); // str2 == "goodbye world!" + </programlisting> + <para> + This example converts str1 to upper case and trims spaces from the start and the end + of the string. str2 is then created as a copy of str1 with "hello" replaced with "goodbye". + This example demonstrates several important concepts used in the library: + </para> + <itemizedlist> + <listitem> + <para><emphasis role="bold">Container parameters:</emphasis> + Unlike in the STL algorithms, parameters are not specified only in the form + of iterators. The STL convention allows for great flexibility, + but it has several limitations. It is not possible to <emphasis>stack</emphasis> algorithms together, + because a container is passed in two parameters. Therefore it is not possible to use + a return value from another algorithm. It is considerably easier to write + <code>to_lower(str1)</code>, than <code>to_lower(str1.begin(), str1.end())</code>. + </para> + <para> + The magic of <ulink url="../../libs/range/index.html">Boost.Range</ulink> + provides a uniform way of handling different string types. + If there is a need to pass a pair of iterators, + <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink> + can be used to package iterators into a structure with a compatible interface. + </para> + </listitem> + <listitem> + <para><emphasis role="bold">Copy vs. Mutable:</emphasis> + Many algorithms in the library are performing a transformation of the input. + The transformation can be done in-place, mutating the input sequence, or a copy + of the transformed input can be created, leaving the input intact. None of + these possibilities is superior to the other one and both have different + advantages and disadvantages. For this reason, both are provided with the library. + </para> + </listitem> + <listitem> + <para><emphasis role="bold">Algorithm stacking:</emphasis> + Copy versions return a transformed input as a result, thus allow a simple chaining of + transformations within one expression (i.e. one can write <code>trim_copy(to_upper_copy(s))</code>). + Mutable versions have <code>void</code> return, to avoid misuse. + </para> + </listitem> + <listitem> + <para><emphasis role="bold">Naming:</emphasis> + Naming follows the conventions from the Standard C++ Library. If there is a + copy and a mutable version of the same algorithm, the mutable version has no suffix + and the copy version has the suffix <emphasis>_copy</emphasis>. + Some algorithms have the prefix <emphasis>i</emphasis> + (e.g. <functionname>ifind_first()</functionname>). + This prefix identifies that the algorithm works in a case-insensitive manner. + </para> + </listitem> + </itemizedlist> + <para> + To use the library, include the <headername>boost/algorithm/string.hpp</headername> header. + If the regex related functions are needed, include the + <headername>boost/algorithm/string_regex.hpp</headername> header. + </para> + </section> + <section> + <title>Case conversion</title> + + <para> + STL has a nice way of converting character case. Unfortunately, it works only + for a single character and we want to convert a string, + </para> + <programlisting> + string str1("HeLlO WoRld!"); + to_upper(str1); // str1=="HELLO WORLD!" + </programlisting> + <para> + <functionname>to_upper()</functionname> and <functionname>to_lower()</functionname> convert the case of + characters in a string using a specified locale. + </para> + <para> + For more information see the reference for <headername>boost/algorithm/string/case_conv.hpp</headername>. + </para> + </section> + <section> + <title>Predicates and Classification</title> + <para> + A part of the library deals with string related predicates. Consider this example: + </para> + <programlisting> + bool is_executable( string& filename ) + { + return + iends_with(filename, ".exe") || + iends_with(filename, ".com"); + } + + // ... + string str1("command.com"); + cout + << str1 + << (is_executable(str1)? "is": "is not") + << "an executable" + << endl; // prints "command.com is an executable" + + //.. + char text1[]="hello"; + cout + << text1 + << (all( text1, is_lower() )? " is": " is not") + << " written in the lower case" + << endl; // prints "hello is written in the lower case" + </programlisting> + <para> + The predicates determine whether if a substring is contained in the input string + under various conditions. The conditions are: a string starts with the substring, + ends with the substring, + simply contains the substring or if both strings are equal. See the reference for + <headername>boost/algorithm/string/predicate.hpp</headername> for more details. + </para> + <para> + Note that if we had used "hello world" as the input to the test, it would have + output "hello world is not written in the lower case" because the space in the + input string is not a lower case letter. + </para> + <para> + In addition the algorithm <functionname>all()</functionname> checks + all elements of a container to satisfy a condition specified by a predicate. + This predicate can be any unary predicate, but the library provides a bunch of + useful string-related predicates and combinators ready for use. + These are located in the <headername>boost/algorithm/string/classification.hpp</headername> header. + Classification predicates can be combined using logical combinators to form + a more complex expressions. For example: <code>is_from_range('a','z') || is_digit()</code> + </para> + </section> + <section> + <title>Trimming</title> + + <para> + When parsing the input from a user, strings often have unwanted leading or trailing + characters. To get rid of them, we need trim functions: + </para> + <programlisting> + string str1=" hello world! "; + string str2=trim_left_copy(str1); // str2 == "hello world! " + string str3=trim_right_copy(str1); // str3 == " hello world!" + trim(str1); // str1 == "hello world!" + + string phone="00423333444"; + // remove leading 0 from the phone number + trim_left_if(phone,is_any_of("0")); // phone == "423333444" + </programlisting> + <para> + It is possible to trim the spaces on the right, on the left or on both sides of a string. + And for those cases when there is a need to remove something else than blank space, there + are <emphasis>_if</emphasis> variants. Using these, a user can specify a functor which will + select the <emphasis>space</emphasis> to be removed. It is possible to use classification + predicates like <functionname>is_digit()</functionname> mentioned in the previous paragraph. + See the reference for the <headername>boost/algorithm/string/trim.hpp</headername>. + </para> + </section> + <section> + <title>Find algorithms</title> + + <para> + The library contains a set of find algorithms. Here is an example: + </para> + <programlisting> + char text[]="hello dolly!"; + iterator_range<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!" + + // iterator_range is convertible to bool + if(find_first(text, "dolly")) + { + cout << "Dolly is there" << endl; + } + </programlisting> + <para> + We have used <functionname>find_last()</functionname> to search the <code>text</code> for "ll". + The result is given in the <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink>. + This range delimits the + part of the input which satisfies the find criteria. In our example it is the last occurrence of "ll". + + As we can see, input of the <functionname>find_last()</functionname> algorithm can be also + char[] because this type is supported by + <ulink url="../../libs/range/index.html">Boost.Range</ulink>. + + The following lines transform the result. Notice that + <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink> has familiar + <code>begin()</code> and <code>end()</code> methods, so it can be used like any other STL container. + Also it is convertible to bool therefore it is easy to use find algorithms for a simple containment checking. + </para> + <para> + Find algorithms are located in <headername>boost/algorithm/string/find.hpp</headername>. + </para> + </section> + <section> + <title>Replace Algorithms</title> + <para> + Find algorithms can be used for searching for a specific part of string. Replace goes one step + further. After a matching part is found, it is substituted with something else. The substitution is computed + from the original, using some transformation. + </para> + <programlisting> + string str1="Hello Dolly, Hello World!" + replace_first(str1, "Dolly", "Jane"); // str1 == "Hello Jane, Hello World!" + replace_last(str1, "Hello", "Goodbye"); // str1 == "Hello Jane, Goodbye World!" + erase_all(str1, " "); // str1 == "HelloJane,GoodbyeWorld!" + erase_head(str1, 6); // str1 == "Jane,GoodbyeWorld!" + </programlisting> + <para> + For the complete list of replace and erase functions see the + <link linkend="string_algo.reference">reference</link>. + There is a lot of predefined function for common usage, however, the library allows you to + define a custom <code>replace()</code> that suits a specific need. There is a generic <functionname>find_format()</functionname> + function which takes two parameters. + The first one is a <link linkend="string_algo.finder_concept">Finder</link> object, the second one is + a <link linkend="string_algo.formatter_concept">Formatter</link> object. + The Finder object is a functor which performs the searching for the replacement part. The Formatter object + takes the result of the Finder (usually a reference to the found substring) and creates a + substitute for it. Replace algorithm puts these two together and makes the desired substitution. + </para> + <para> + Check <headername>boost/algorithm/string/replace.hpp</headername>, <headername>boost/algorithm/string/erase.hpp</headername> and + <headername>boost/algorithm/string/find_format.hpp</headername> for reference. + </para> + </section> + <section> + <title>Find Iterator</title> + + <para> + An extension to find algorithms it the Find Iterator. Instead of searching for just a one part of a string, + the find iterator allows us to iterate over the substrings matching the specified criteria. + This facility is using the <link linkend="string_algo.finder_concept">Finder</link> to incrementally + search the string. + Dereferencing a find iterator yields an <ulink url="../../libs/range/doc/html/range/reference/utilities/iterator_range.html"><code>boost::iterator_range</code></ulink> + object, that delimits the current match. + </para> + <para> + There are two iterators provided <classname>find_iterator</classname> and + <classname>split_iterator</classname>. The former iterates over substrings that are found using the specified + Finder. The latter iterates over the gaps between these substrings. + </para> + <programlisting> + string str1("abc-*-ABC-*-aBc"); + // Find all 'abc' substrings (ignoring the case) + // Create a find_iterator + typedef find_iterator<string::iterator> string_find_iterator; + for(string_find_iterator It= + make_find_iterator(str1, first_finder("abc", is_iequal())); + It!=string_find_iterator(); + ++It) + { + cout << copy_range<std::string>(*It) << endl; + } + + // Output will be: + // abc + // ABC + // aBC + + typedef split_iterator<string::iterator> string_split_iterator; + for(string_split_iterator It= + make_split_iterator(str1, first_finder("-*-", is_iequal())); + It!=string_split_iterator(); + ++It) + { + cout << copy_range<std::string>(*It) << endl; + } + + // Output will be: + // abc + // ABC + // aBC + </programlisting> + <para> + Note that the find iterators have only one template parameter. It is the base iterator type. + The Finder is specified at runtime. This allows us to typedef a find iterator for + common string types and reuse it. Additionally make_*_iterator functions help + to construct a find iterator for a particular range. + </para> + <para> + See the reference in <headername>boost/algorithm/string/find_iterator.hpp</headername>. + </para> + </section> + <section> + <title>Split</title> + + <para> + Split algorithms are an extension to the find iterator for one common usage scenario. + These algorithms use a find iterator and store all matches into the provided + container. This container must be able to hold copies (e.g. <code>std::string</code>) or + references (e.g. <code>iterator_range</code>) of the extracted substrings. + </para> + <para> + Two algorithms are provided. <functionname>find_all()</functionname> finds all copies + of a string in the input. <functionname>split()</functionname> splits the input into parts. + </para> + + <programlisting> + string str1("hello abc-*-ABC-*-aBc goodbye"); + + typedef vector< iterator_range<string::iterator> > find_vector_type; + + find_vector_type FindVec; // #1: Search for separators + ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] } + + typedef vector< string > split_vector_type; + + split_vector_type SplitVec; // #2: Search for tokens + split( SplitVec, str1, is_any_of("-*"), token_compress_on ); // SplitVec == { "hello abc","ABC","aBc goodbye" } + </programlisting> + <para> + <code>[hello]</code> designates an <code>iterator_range</code> delimiting this substring. + </para> + <para> + First example show how to construct a container to hold references to all extracted + substrings. Algorithm <functionname>ifind_all()</functionname> puts into FindVec references + to all substrings that are in case-insensitive manner equal to "abc". + </para> + <para> + Second example uses <functionname>split()</functionname> to split string str1 into parts + separated by characters '-' or '*'. These parts are then put into the SplitVec. + It is possible to specify if adjacent separators are concatenated or not. + </para> + <para> + More information can be found in the reference: <headername>boost/algorithm/string/split.hpp</headername>. + </para> + </section> +</section> diff --git a/libs/algorithm/string/example/Jamfile b/libs/algorithm/string/example/Jamfile new file mode 100644 index 000000000..74c923f8b --- /dev/null +++ b/libs/algorithm/string/example/Jamfile @@ -0,0 +1,18 @@ +# Boost string_algo library examples Jamfile --------------------------------- +# +# Copyright Pavol Droba 2002-2003. Use, modification and +# distribution is subject to the Boost Software License, Version +# 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# See http://www.boost.org for updates, documentation, and revision history. + + +exe conv_example : conv_example.cpp ; +exe predicate_example : predicate_example.cpp ; +exe find_example : find_example.cpp ; +exe replace_example : replace_example.cpp ; +exe rle_example : rle_example.cpp ; +exe trim_example : trim_example.cpp ; +exe regex_example : regex_example.cpp /boost/regex//boost_regex ; +exe split_example : split_example.cpp ;
\ No newline at end of file diff --git a/libs/algorithm/string/example/conv_example.cpp b/libs/algorithm/string/example/conv_example.cpp new file mode 100644 index 000000000..b6a08f9ca --- /dev/null +++ b/libs/algorithm/string/example/conv_example.cpp @@ -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; +} diff --git a/libs/algorithm/string/example/find_example.cpp b/libs/algorithm/string/example/find_example.cpp new file mode 100644 index 000000000..7fd7e60a1 --- /dev/null +++ b/libs/algorithm/string/example/find_example.cpp @@ -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; +} diff --git a/libs/algorithm/string/example/predicate_example.cpp b/libs/algorithm/string/example/predicate_example.cpp new file mode 100644 index 000000000..473ab8b57 --- /dev/null +++ b/libs/algorithm/string/example/predicate_example.cpp @@ -0,0 +1,61 @@ +// Boost string_algo library example file ---------------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <string> +#include <iostream> +#include <functional> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/algorithm/string/classification.hpp> +#include <boost/bind.hpp> + + +using namespace std; +using namespace boost; + +int main() +{ + cout << "* Predicate Example *" << endl << endl; + + string str1("123xxx321"); + string str2("abc"); + + // Check if str1 starts with '123' + cout << "str1 starts with \"123\": " << + (starts_with( str1, string("123") )?"true":"false") << endl; + + // Check if str1 ends with '123' + cout << "str1 ends with \"123\": " << + (ends_with( str1, string("123") )?"true":"false") << endl; + + // Check if str1 contains 'xxx' + cout << "str1 contains \"xxx\": " << + (contains( str1, string("xxx") )?"true":"false") << endl; + + + // Check if str2 equals to 'abc' + cout << "str2 equals \"abc\": " << + (equals( str2, string("abc") )?"true":"false") << endl; + + + // Classification functors and all predicate + if ( all(";.,", is_punct() ) ) + { + cout << "\";.,\" are all punctuation characters" << endl; + } + + // Classification predicates can be combined + if ( all("abcxxx", is_any_of("xabc") && !is_space() ) ) + { + cout << "true" << endl; + } + + cout << endl; + + return 0; +} diff --git a/libs/algorithm/string/example/regex_example.cpp b/libs/algorithm/string/example/regex_example.cpp new file mode 100644 index 000000000..9eba1c73a --- /dev/null +++ b/libs/algorithm/string/example/regex_example.cpp @@ -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; +} diff --git a/libs/algorithm/string/example/replace_example.cpp b/libs/algorithm/string/example/replace_example.cpp new file mode 100644 index 000000000..12089fa2d --- /dev/null +++ b/libs/algorithm/string/example/replace_example.cpp @@ -0,0 +1,89 @@ +// Boost string_algo library example file ---------------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <string> +#include <iostream> +#include <iterator> +//#include <boost/algorithm/string/replace.hpp> +//#include <boost/algorithm/string/erase.hpp> +//#include <boost/algorithm/string/case_conv.hpp> +#include <boost/algorithm/string.hpp> + +//Following two includes contain second-layer function. +//They are already included by first-layer header + +//#include <boost/algorithm/string/replace2.hpp> +//#include <boost/algorithm/string/find2.hpp> + +using namespace std; +using namespace boost; + +// uppercase formatter +/* + Convert an input to upper case. + Note, that this formatter can be used only on std::string inputs. +*/ +inline string upcase_formatter( + const iterator_range<string::const_iterator>& Replace ) +{ + string Temp(Replace.begin(), Replace.end()); + to_upper(Temp); + return Temp; +} + +int main() +{ + cout << "* Replace Example *" << endl << endl; + + string str1("abc___cde___efg"); + + // Erase 6-9th characters from the string + cout << "str1 without 6th to 9th character:" << + erase_range_copy( str1, make_iterator_range(str1.begin()+6, str1.begin()+9) ) << endl; + + // Replace 6-9th character with '+++' + cout << "str1 with 6th to 9th character replaced with '+++': " << + replace_range_copy( + str1, make_iterator_range(str1.begin()+6, str1.begin()+9), "+++" ) << endl; + + cout << "str1 with 'cde' replaced with 'XYZ': "; + + // Replace first 'cde' with 'XYZ'. Modify the input + replace_first_copy( ostream_iterator<char>(cout), str1, "cde", "XYZ" ); + cout << endl; + + // Replace all '___' + cout << "str1 with all '___' replaced with '---': " << + replace_all_copy( str1, "___", "---" ) << endl; + + // Erase all '___' + cout << "str1 without all '___': " << + erase_all_copy( str1, "___" ) << endl; + + // replace third and 5th occurrence of _ in str1 + // note that nth argument is 0-based + replace_nth( str1, "_", 4, "+" ); + replace_nth( str1, "_", 2, "+" ); + + cout << "str1 with third and 5th occurrence of _ replace: " << str1 << endl; + + // Custom formatter examples + string str2("abC-xxxx-AbC-xxxx-abc"); + + // Find string 'abc' ignoring the case and convert it to upper case + cout << "Upcase all 'abc'(s) in the str2: " << + find_format_all_copy( + str2, + first_finder("abc", is_iequal()), + upcase_formatter ); + + cout << endl; + + return 0; +} diff --git a/libs/algorithm/string/example/rle_example.cpp b/libs/algorithm/string/example/rle_example.cpp new file mode 100644 index 000000000..9e52b96b3 --- /dev/null +++ b/libs/algorithm/string/example/rle_example.cpp @@ -0,0 +1,248 @@ +// Boost string_algo library example file ---------------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +/* + RLE compression using replace framework. Goal is to compress a sequence of + repeating characters into 3 bytes ( repeat mark, character and repetition count ). + For simplification, it works only on numeric-value sequences. +*/ + +#include <string> +#include <iostream> +#include <limits> +#include <boost/detail/iterator.hpp> +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/finder.hpp> + +using namespace std; +using namespace boost; + +// replace mark specification, specialize for a specific element type +template< typename T > T repeat_mark() { return (std::numeric_limits<T>::max)(); }; + +// Compression ----------------------------------------------------------------------- + + +// compress finder -rle +/* + Find a sequence which can be compressed. It has to be at least 3-character long + sequence of repetitive characters +*/ +struct find_compressF +{ + // Construction + find_compressF() {} + + // Operation + template<typename ForwardIteratorT> + iterator_range<ForwardIteratorT> operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef ForwardIteratorT input_iterator_type; + typedef typename boost::detail::iterator_traits<input_iterator_type>::value_type value_type; + typedef iterator_range<input_iterator_type> result_type; + + // begin of the matching segment + input_iterator_type MStart=End; + // Repetition counter + value_type Cnt=0; + + // Search for a sequence of repetitive characters + for(input_iterator_type It=Begin; It!=End;) + { + input_iterator_type It2=It++; + + if ( It==End || Cnt>=(std::numeric_limits<value_type>::max)() ) + { + return result_type( MStart, It ); + } + + if ( *It==*It2 ) + { + if ( MStart==End ) + { + // Mark the start + MStart=It2; + } + + // Increate repetition counter + Cnt++; + } + else + { + if ( MStart!=End ) + { + if ( Cnt>2 ) + return result_type( MStart, It ); + else + { + MStart=End; + Cnt=0; + } + } + } + } + + return result_type( End, End ); + } +}; + +// rle compress format +/* + Transform a sequence into repeat mark, character and count +*/ +template<typename SeqT> +struct format_compressF +{ +private: + typedef SeqT result_type; + typedef typename SeqT::value_type value_type; + +public: + // Construction + format_compressF() {}; + + // Operation + template< typename ReplaceT > + result_type operator()( const ReplaceT& Replace ) const + { + SeqT r; + if(!Replace.empty()) + { + r.push_back( repeat_mark<value_type>() ); + r.push_back( *(Replace.begin()) ); + r.push_back( value_type( Replace.size() ) ); + } + + return r; + } +}; + +// Decompression ----------------------------------------------------------------------- + + +// find decompress-rle functor +/* + find a repetition block +*/ +struct find_decompressF +{ + // Construction + find_decompressF() {} + + // Operation + template<typename ForwardIteratorT> + iterator_range<ForwardIteratorT> operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef ForwardIteratorT input_iterator_type; + typedef typename boost::detail::iterator_traits<input_iterator_type>::value_type value_type; + typedef iterator_range<input_iterator_type> result_type; + + for(input_iterator_type It=Begin; It!=End; It++) + { + if( *It==repeat_mark<value_type>() ) + { + // Repeat mark found, extract body + input_iterator_type It2=It++; + + if ( It==End ) break; + It++; + if ( It==End ) break; + It++; + + return result_type( It2, It ); + } + } + + return result_type( End, End ); + } +}; + +// rle decompress format +/* + transform a repetition block into a sequence of characters +*/ +template< typename SeqT > +struct format_decompressF +{ +private: + typedef SeqT result_type; + typedef typename SeqT::value_type value_type; + +public: + // Construction + format_decompressF() {}; + + // Operation + template< typename ReplaceT > + result_type operator()( const ReplaceT& Replace ) const + { + SeqT r; + + if(!Replace.empty()) + { + // extract info + typename ReplaceT::const_iterator It=Replace.begin(); + + value_type Value=*(++It); + value_type Repeat=*(++It); + + for( value_type Index=0; Index<Repeat; Index++ ) r.push_back( Value ); + } + + return r; + } +}; + + +int main() +{ + cout << "* RLE Compression Example *" << endl << endl; + + string original("123_AA_*ZZZZZZZZZZZZZZ*34"); + + // copy compression + string compress=find_format_all_copy( + original, + find_compressF(), + format_compressF<string>() ); + + cout << "Compressed string: " << compress << endl; + + // Copy decompression + string decompress=find_format_all_copy( + compress, + find_decompressF(), + format_decompressF<string>() ); + + cout << "Decompressed string: " << decompress << endl; + + // in-place compression + find_format_all( + original, + find_compressF(), + format_compressF<string>() ); + + cout << "Compressed string: " << original << endl; + + // in-place decompression + find_format_all( + original, + find_decompressF(), + format_decompressF<string>() ); + + cout << "Decompressed string: " << original << endl; + + cout << endl; + + return 0; +} diff --git a/libs/algorithm/string/example/split_example.cpp b/libs/algorithm/string/example/split_example.cpp new file mode 100644 index 000000000..27e261c93 --- /dev/null +++ b/libs/algorithm/string/example/split_example.cpp @@ -0,0 +1,62 @@ +// Boost string_algo library example file ---------------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <string> +#include <vector> +#include <iostream> +#include <iterator> +#include <functional> +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/find_iterator.hpp> + +using namespace std; +using namespace boost; + +int main() +{ + cout << "* Split Example *" << endl << endl; + + string str1("abc-*-ABC-*-aBc"); + + cout << "Before: " << str1 << endl; + + // Find all 'abc' substrings (ignoring the case) + // Create a find_iterator + typedef find_iterator<string::iterator> string_find_iterator; + for(string_find_iterator It= + make_find_iterator(str1, first_finder("abc", is_iequal())); + It!=string_find_iterator(); + ++It) + { + cout << copy_range<std::string>(*It) << endl; + // shift all chars in the match by one + transform( + It->begin(), It->end(), + It->begin(), + bind2nd( plus<char>(), 1 ) ); + } + + // Print the string now + cout << "After: " << str1 << endl; + + // Split the string into tokens ( use '-' and '*' as delimiters ) + // We need copies of the input only, and adjacent tokens are compressed + vector<std::string> ResultCopy; + split(ResultCopy, str1, is_any_of("-*"), token_compress_on); + + for(unsigned int nIndex=0; nIndex<ResultCopy.size(); nIndex++) + { + cout << nIndex << ":" << ResultCopy[nIndex] << endl; + }; + + cout << endl; + + return 0; +} diff --git a/libs/algorithm/string/example/trim_example.cpp b/libs/algorithm/string/example/trim_example.cpp new file mode 100644 index 000000000..7b1a0bd1e --- /dev/null +++ b/libs/algorithm/string/example/trim_example.cpp @@ -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; +} diff --git a/libs/algorithm/string/index.html b/libs/algorithm/string/index.html new file mode 100644 index 000000000..dc0e1b9c4 --- /dev/null +++ b/libs/algorithm/string/index.html @@ -0,0 +1,14 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=../../../doc/html/string_algo.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="../../../doc/html/string_algo.html">../../doc/html/string_algo.html</a> + <hr> +<p>© Copyright Beman Dawes, 2001</p> +<p>Distributed under the Boost Software License, Version 1.0. (See accompanying +file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy +at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p> +</body> +</html>
\ No newline at end of file diff --git a/libs/algorithm/string/test/Jamfile.v2 b/libs/algorithm/string/test/Jamfile.v2 new file mode 100644 index 000000000..7f60df703 --- /dev/null +++ b/libs/algorithm/string/test/Jamfile.v2 @@ -0,0 +1,74 @@ +# Boost string_algo library test suite Jamfile ---------------------------- +# +# Copyright Pavol Droba 2002-2003. Use, modification and +# distribution is subject to the Boost Software License, Version +# 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# See http://www.boost.org for updates, documentation, and revision history. + +import testing ; + +alias unit_test_framework + : # sources + /boost//unit_test_framework + ; + +test-suite algorithm/string + : [ run + trim_test.cpp unit_test_framework + : : + : + : trim + ] + [ run + conv_test.cpp unit_test_framework + : : + : + : conv + ] + [ run + predicate_test.cpp unit_test_framework + : : + : + : predicate + ] + [ run + find_test.cpp unit_test_framework + : : + : + : find + ] + [ run + split_test.cpp unit_test_framework + : : + : + : split + ] + [ run + join_test.cpp unit_test_framework + : : + : + : join + ] + [ run + replace_test.cpp unit_test_framework + : : + : + : replace + ] + [ run + regex_test.cpp unit_test_framework + ../../../regex/build//boost_regex + : : + : + : regex + ] + [ run + find_format_test.cpp unit_test_framework + : : + : + : find_format + ] + ; + diff --git a/libs/algorithm/string/test/conv_test.cpp b/libs/algorithm/string/test/conv_test.cpp new file mode 100644 index 000000000..c583d3efe --- /dev/null +++ b/libs/algorithm/string/test/conv_test.cpp @@ -0,0 +1,94 @@ +// Boost string_algo library conv_test.cpp file ---------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/case_conv.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <iostream> +#include <algorithm> +#include <boost/test/test_tools.hpp> + +using namespace std; +using namespace boost; + +void conv_test() +{ + string str1("AbCdEfG 123 xxxYYYzZzZ"); + string str2("AbCdEfG 123 xxxYYYzZzZ"); + string str3(""); + const char pch[]="AbCdEfG 123 xxxYYYzZzZ"; + unsigned int pchlen=sizeof(pch); + + char* pch1=new char[pchlen]; + std::copy(pch, pch+pchlen, pch1); + char* pch2=new char[pchlen]; + std::copy(pch, pch+pchlen, pch2); + + // *** iterator tests *** // + + string strout; + to_lower_copy( back_inserter(strout), str1 ); + BOOST_CHECK( strout=="abcdefg 123 xxxyyyzzzz" ); + strout.clear(); + to_upper_copy( back_inserter(strout), str1 ); + BOOST_CHECK( strout=="ABCDEFG 123 XXXYYYZZZZ" ); + + strout.clear(); + to_lower_copy( back_inserter(strout), "AbCdEfG 123 xxxYYYzZzZ" ); + BOOST_CHECK( strout=="abcdefg 123 xxxyyyzzzz" ); + strout.clear(); + to_upper_copy( back_inserter(strout), "AbCdEfG 123 xxxYYYzZzZ" ); + BOOST_CHECK( strout=="ABCDEFG 123 XXXYYYZZZZ" ); + + strout.clear(); + to_lower_copy( back_inserter(strout), pch1 ); + BOOST_CHECK( strout=="abcdefg 123 xxxyyyzzzz" ); + strout.clear(); + to_upper_copy( back_inserter(strout), pch1 ); + BOOST_CHECK( strout=="ABCDEFG 123 XXXYYYZZZZ" ); + + // *** value passing tests *** // + + BOOST_CHECK( to_lower_copy( str1 )=="abcdefg 123 xxxyyyzzzz" ); + BOOST_CHECK( to_upper_copy( str1 )=="ABCDEFG 123 XXXYYYZZZZ" ); + + BOOST_CHECK( to_lower_copy( str3 )=="" ); + BOOST_CHECK( to_upper_copy( str3 )=="" ); + + // *** inplace tests *** // + + to_lower( str1 ); + BOOST_CHECK( str1=="abcdefg 123 xxxyyyzzzz" ); + to_upper( str2 ); + BOOST_CHECK( str2=="ABCDEFG 123 XXXYYYZZZZ" ); + + // c-string modification + to_lower( pch1 ); + BOOST_CHECK( string(pch1)=="abcdefg 123 xxxyyyzzzz" ); + to_upper( pch2 ); + BOOST_CHECK( string(pch2)=="ABCDEFG 123 XXXYYYZZZZ" ); + + to_lower( str3 ); + BOOST_CHECK( str3=="" ); + to_upper( str3 ); + BOOST_CHECK( str3=="" ); + + delete[] pch1; + delete[] pch2; +} + +// test main +BOOST_AUTO_TEST_CASE( test_main ) +{ + conv_test(); +} diff --git a/libs/algorithm/string/test/find_format_test.cpp b/libs/algorithm/string/test/find_format_test.cpp new file mode 100644 index 000000000..645cdba3a --- /dev/null +++ b/libs/algorithm/string/test/find_format_test.cpp @@ -0,0 +1,162 @@ +// Boost string_algo library find_format_test.cpp file ------------------// + +// Copyright (c) 2009 Steven Watanabe +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/formatter.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <boost/test/test_tools.hpp> + +// We're only using const_formatter. +template<class Formatter> +struct formatter_result { + typedef boost::iterator_range<const char*> type; +}; + +template<class Formatter> +struct checked_formatter { +public: + checked_formatter(const Formatter& formatter) : formatter_(formatter) {} + template< typename T > + typename formatter_result<Formatter>::type operator()( const T & s ) const { + BOOST_CHECK( !s.empty() ); + return formatter_(s); + } +private: + Formatter formatter_; +}; + +template<class Formatter> +checked_formatter<Formatter> +make_checked_formatter(const Formatter& formatter) { + return checked_formatter<Formatter>(formatter); +} + +void find_format_test() +{ + const std::string source = "$replace $replace"; + std::string expected = "ok $replace"; + std::string output(80, '\0'); + + std::string::iterator pos = + boost::find_format_copy( + output.begin(), + source, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); + BOOST_CHECK(pos == output.begin() + expected.size()); + output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); + BOOST_CHECK_EQUAL(output, expected); + + output = + boost::find_format_copy( + source, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); + BOOST_CHECK_EQUAL(output, expected); + + // now try finding a string that doesn't exist + output.resize(80); + pos = + boost::find_format_copy( + output.begin(), + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); + BOOST_CHECK(pos == output.begin() + source.size()); + output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); + BOOST_CHECK_EQUAL(output, source); + + output = + boost::find_format_copy( + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); + BOOST_CHECK_EQUAL(output, source); + + // in place version + output = source; + boost::find_format( + output, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); + BOOST_CHECK_EQUAL(output, expected); + output = source; + boost::find_format( + output, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); + BOOST_CHECK_EQUAL(output, source); +} + +void find_format_all_test() +{ + const std::string source = "$replace $replace"; + std::string expected = "ok ok"; + std::string output(80, '\0'); + + std::string::iterator pos = + boost::find_format_all_copy(output.begin(), + source, + boost::first_finder("$replace"), + boost::const_formatter("ok")); + BOOST_CHECK(pos == output.begin() + expected.size()); + output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); + BOOST_CHECK_EQUAL(output, expected); + + output = + boost::find_format_all_copy( + source, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); + BOOST_CHECK_EQUAL(output, expected); + + // now try finding a string that doesn't exist + output.resize(80); + pos = + boost::find_format_all_copy( + output.begin(), + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); + BOOST_CHECK(pos == output.begin() + source.size()); + output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); + BOOST_CHECK_EQUAL(output, source); + + output = + boost::find_format_all_copy( + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); + BOOST_CHECK_EQUAL(output, source); + + // in place version + output = source; + boost::find_format_all( + output, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); + BOOST_CHECK_EQUAL(output, expected); + output = source; + boost::find_format_all( + output, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); + BOOST_CHECK_EQUAL(output, source); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + find_format_test(); + find_format_all_test(); +} diff --git a/libs/algorithm/string/test/find_test.cpp b/libs/algorithm/string/test/find_test.cpp new file mode 100644 index 000000000..85facb0a7 --- /dev/null +++ b/libs/algorithm/string/test/find_test.cpp @@ -0,0 +1,273 @@ +// Boost string_algo library substr_test.cpp file ------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/find.hpp> +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/split.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> +#include <iostream> +#include <iterator> +#include <sstream> +#include <boost/test/test_tools.hpp> + +using namespace std; +using namespace boost; + +void find_test() +{ + string str1("123abcxXxabcXxXabc321"); + string str2("abc"); + string str3(""); + const char* pch1="123abcxxxabcXXXabc321"; + vector<int> vec1( str1.begin(), str1.end() ); + + // find results ------------------------------------------------------------// + iterator_range<string::iterator> nc_result; + iterator_range<string::const_iterator> cv_result; + + iterator_range<vector<int>::iterator> nc_vresult; + iterator_range<vector<int>::const_iterator> cv_vresult; + + iterator_range<const char*> ch_result; + + // basic tests ------------------------------------------------------------// + + + // find_first + BOOST_TEST_CHECKPOINT( "find_first" ); + + nc_result=find_first( str1, string("abc") ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 6) ); + + cv_result=find_first( const_cast<const string&>(str1), str2 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 6) ); + + cv_result=ifind_first( const_cast<const string&>(str1), "xXX" ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 6) && + ( (cv_result.end()-str1.begin()) == 9) ); + + ch_result=find_first( pch1, "abc" ); + BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) ); + + // find_last + BOOST_TEST_CHECKPOINT( "find_last" ); + + nc_result=find_last( str1, string("abc") ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 15) && + ( (nc_result.end()-str1.begin()) == 18) ); + + cv_result=find_last( const_cast<const string&>(str1), str2 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 15) && + ( (cv_result.end()-str1.begin()) == 18) ); + + cv_result=ifind_last( const_cast<const string&>(str1), "XXx" ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 12) && + ( (cv_result.end()-str1.begin()) == 15) ); + + ch_result=find_last( pch1, "abc" ); + BOOST_CHECK(( (ch_result.begin() - pch1 ) == 15) && ( (ch_result.end() - pch1 ) == 18 ) ); + + // find_nth + BOOST_TEST_CHECKPOINT( "find_nth" ); + + nc_result=find_nth( str1, string("abc"), 1 ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 9) && + ( (nc_result.end()-str1.begin()) == 12) ); + + nc_result=find_nth( str1, string("abc"), -1 ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 15) && + ( (nc_result.end()-str1.begin()) == 18) ); + + + cv_result=find_nth( const_cast<const string&>(str1), str2, 1 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 9) && + ( (cv_result.end()-str1.begin()) == 12) ); + + cv_result=find_nth( const_cast<const string&>(str1), str2, -1 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 15) && + ( (cv_result.end()-str1.begin()) == 18) ); + + cv_result=ifind_nth( const_cast<const string&>(str1), "xxx", 1 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 12) && + ( (cv_result.end()-str1.begin()) == 15) ); + + cv_result=ifind_nth( const_cast<const string&>(str1), "xxx", 1 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 12) && + ( (cv_result.end()-str1.begin()) == 15) ); + + + ch_result=find_nth( pch1, "abc", 1 ); + BOOST_CHECK(( (ch_result.begin() - pch1 ) == 9) && ( (ch_result.end() - pch1 ) == 12 ) ); + + // find_head + BOOST_TEST_CHECKPOINT( "find_head" ); + + nc_result=find_head( str1, 6 ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 0) && + ( (nc_result.end()-str1.begin()) == 6) ); + + nc_result=find_head( str1, -6 ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 0) && + ( (str1.end()-nc_result.end()) == 6 ) ); + + cv_result=find_head( const_cast<const string&>(str1), 6 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 0) && + ( (cv_result.end()-str1.begin()) == 6) ); + + ch_result=find_head( pch1, 6 ); + BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 0 ) && ( (ch_result.end() - pch1 ) == 6 ) ); + + // find_tail + BOOST_TEST_CHECKPOINT( "find_tail" ); + + nc_result=find_tail( str1, 6 ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 15) && + ( (nc_result.end()-str1.begin()) == 21) ); + + nc_result=find_tail( str1, -6 ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 6) && + ( (nc_result.end()-str1.begin()) == 21) ); + + + cv_result=find_tail( const_cast<const string&>(str1), 6 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 15) && + ( (cv_result.end()-str1.begin()) == 21) ); + + ch_result=find_tail( pch1, 6 ); + BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 15 ) && ( (ch_result.end() - pch1 ) == 21 ) ); + + // find_token + BOOST_TEST_CHECKPOINT( "find_token" ); + + nc_result=find_token( str1, is_any_of("abc"), token_compress_on ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 6) ); + + cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_on ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 6) ); + + nc_result=find_token( str1, is_any_of("abc"), token_compress_off ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 4) ); + + cv_result=find_token( const_cast<const string&>(str1), is_any_of("abc"), token_compress_off ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 4) ); + + ch_result=find_token( pch1, is_any_of("abc"), token_compress_off ); + BOOST_CHECK( ( (ch_result.begin() - pch1 ) == 3 ) && ( (ch_result.end() - pch1 ) == 4 ) ); + + // generic find + BOOST_TEST_CHECKPOINT( "generic find" ); + + nc_result=find(str1, first_finder(string("abc"))); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 6) ); + + cv_result=find(const_cast<const string&>(str1), first_finder(str2) ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 6) ); + + // multi-type comparison test + BOOST_TEST_CHECKPOINT( "multi-type" ); + + nc_vresult=find_first( vec1, string("abc") ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 6) ); + + cv_vresult=find_first( const_cast<const vector<int>&>(vec1), str2 ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 6) ); + + // overflow test + BOOST_TEST_CHECKPOINT( "overflow" ); + + nc_result=find_first( str2, string("abcd") ); + BOOST_CHECK( nc_result.begin()==nc_result.end() ); + cv_result=find_first( const_cast<const string&>(str2), string("abcd") ); + BOOST_CHECK( cv_result.begin()==cv_result.end() ); + + cv_result=find_head( const_cast<const string&>(str2), 4 ); + BOOST_CHECK( string( cv_result.begin(), cv_result.end() )== string("abc") ); + cv_result=find_tail( const_cast<const string&>(str2), 4 ); + BOOST_CHECK( string( cv_result.begin(), cv_result.end() )== string("abc") ); + + // Empty string test + BOOST_TEST_CHECKPOINT( "empty" ); + + nc_result=find_first( str3, string("abcd") ); + BOOST_CHECK( nc_result.begin()==nc_result.end() ); + nc_result=find_first( str1, string("") ); + BOOST_CHECK( nc_result.begin()==nc_result.end() ); + + cv_result=find_first( const_cast<const string&>(str3), string("abcd") ); + BOOST_CHECK( cv_result.begin()==cv_result.end() ); + cv_result=find_first( const_cast<const string&>(str1), string("") ); + BOOST_CHECK( cv_result.begin()==cv_result.end() ); + + // iterator_range specific tests + ostringstream osstr; + osstr << find_first( str1, "abc" ); + BOOST_CHECK( osstr.str()=="abc" ); + + // Empty string test + BOOST_TEST_CHECKPOINT( "overlapping" ); + + std::string overlap_target("aaaa"); + std::vector<boost::iterator_range<std::string::iterator> > overlap_results; + boost::algorithm::find_all(overlap_results, overlap_target, string("aaa")); + BOOST_CHECK( overlap_results.size() == 2 ); + + std::string overlap_target2("aaaabbbbaaaa"); + boost::algorithm::find_all(overlap_results, overlap_target2, string("bb")); + BOOST_CHECK( overlap_results.size() == 3 ); + boost::algorithm::find_all(overlap_results, overlap_target2, string("aa")); + BOOST_CHECK( overlap_results.size() == 6 ); +} + +// test main +BOOST_AUTO_TEST_CASE( test_main ) +{ + find_test(); +} diff --git a/libs/algorithm/string/test/join_test.cpp b/libs/algorithm/string/test/join_test.cpp new file mode 100644 index 000000000..9c5150baf --- /dev/null +++ b/libs/algorithm/string/test/join_test.cpp @@ -0,0 +1,78 @@ +// Boost string_algo library iterator_test.cpp file ---------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/classification.hpp> +// equals predicate is used for result comparison +#include <boost/algorithm/string/predicate.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> +#include <iostream> + +#include <boost/test/test_tools.hpp> + + +using namespace std; +using namespace boost; + +bool is_not_empty(const std::string& str) +{ + return !str.empty(); +} + +void join_test() +{ + // Prepare inputs + vector<string> tokens1; + tokens1.push_back("xx"); + tokens1.push_back("abc"); + tokens1.push_back("xx"); + + vector<string> tokens2; + tokens2.push_back(""); + tokens2.push_back("xx"); + tokens2.push_back("abc"); + tokens2.push_back(""); + tokens2.push_back("abc"); + tokens2.push_back("xx"); + tokens2.push_back(""); + + vector<string> tokens3; + tokens3.push_back(""); + tokens3.push_back(""); + tokens3.push_back(""); + + vector<string> empty_tokens; + + vector<vector<int> > vtokens; + for(unsigned int n=0; n<tokens2.size(); ++n) + { + vtokens.push_back(vector<int>(tokens2[n].begin(), tokens2[n].end())); + } + + BOOST_CHECK( equals(join(tokens1, "-"), "xx-abc-xx") ); + BOOST_CHECK( equals(join(tokens2, "-"), "-xx-abc--abc-xx-") ); + BOOST_CHECK( equals(join(vtokens, "-"), "-xx-abc--abc-xx-") ); + BOOST_CHECK( equals(join(empty_tokens, "-"), "") ); + + BOOST_CHECK( equals(join_if(tokens2, "-", is_not_empty), "xx-abc-abc-xx") ); + BOOST_CHECK( equals(join_if(empty_tokens, "-", is_not_empty), "") ); + BOOST_CHECK( equals(join_if(tokens3, "-", is_not_empty), "") ); +} + + +BOOST_AUTO_TEST_CASE( test_main ) +{ + join_test(); +} diff --git a/libs/algorithm/string/test/predicate_test.cpp b/libs/algorithm/string/test/predicate_test.cpp new file mode 100644 index 000000000..ba1564e53 --- /dev/null +++ b/libs/algorithm/string/test/predicate_test.cpp @@ -0,0 +1,160 @@ +// Boost string_algo library predicate_test.cpp file ------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/predicate.hpp> +#include <boost/algorithm/string/classification.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> +#include <iostream> +#include <functional> +#include <boost/test/test_tools.hpp> + +using namespace std; +using namespace boost; + +void predicate_test() +{ + string str1("123xxx321"); + string str1_prefix("123"); + string str2("abc"); + string str3(""); + string str4("abc"); + vector<int> vec1( str1.begin(), str1.end() ); + + // Basic tests + BOOST_CHECK( starts_with( str1, string("123") ) ); + BOOST_CHECK( !starts_with( str1, string("1234") ) ); + + BOOST_CHECK( istarts_with( "aBCxxx", "abc" ) ); + BOOST_CHECK( !istarts_with( "aBCxxx", "abcd" ) ); + + BOOST_CHECK( ends_with( str1, string("321") ) ); + BOOST_CHECK( !ends_with( str1, string("123") ) ); + + BOOST_CHECK( iends_with( "aBCxXx", "XXX" ) ); + BOOST_CHECK( !iends_with( "aBCxxX", "xXXX" ) ); + + BOOST_CHECK( contains( str1, string("xxx") ) ); + BOOST_CHECK( !contains( str1, string("yyy") ) ); + + BOOST_CHECK( icontains( "123XxX321", "xxx" ) ); + BOOST_CHECK( !icontains( "123xXx321", "yyy" ) ); + + BOOST_CHECK( equals( str2, string("abc") ) ); + BOOST_CHECK( !equals( str1, string("yyy") ) ); + + BOOST_CHECK( iequals( "AbC", "abc" ) ); + BOOST_CHECK( !iequals( "aBc", "yyy" ) ); + + BOOST_CHECK( lexicographical_compare("abc", "abd") ); + BOOST_CHECK( !lexicographical_compare("abc", "abc") ); + BOOST_CHECK( lexicographical_compare("abc", "abd", is_less()) ); + + BOOST_CHECK( !ilexicographical_compare("aBD", "AbC") ); + BOOST_CHECK( ilexicographical_compare("aBc", "AbD") ); + BOOST_CHECK( lexicographical_compare("abC", "aBd", is_iless()) ); + + // multi-type comparison test + BOOST_CHECK( starts_with( vec1, string("123") ) ); + BOOST_CHECK( ends_with( vec1, string("321") ) ); + BOOST_CHECK( contains( vec1, string("xxx") ) ); + BOOST_CHECK( equals( vec1, str1 ) ); + + // overflow test + BOOST_CHECK( !starts_with( str2, string("abcd") ) ); + BOOST_CHECK( !ends_with( str2, string("abcd") ) ); + BOOST_CHECK( !contains( str2, string("abcd") ) ); + BOOST_CHECK( !equals( str2, string("abcd") ) ); + + // equal test + BOOST_CHECK( starts_with( str2, string("abc") ) ); + BOOST_CHECK( ends_with( str2, string("abc") ) ); + BOOST_CHECK( contains( str2, string("abc") ) ); + BOOST_CHECK( equals( str2, string("abc") ) ); + + //! Empty string test + BOOST_CHECK( starts_with( str2, string("") ) ); + BOOST_CHECK( ends_with( str2, string("") ) ); + BOOST_CHECK( contains( str2, string("") ) ); + BOOST_CHECK( equals( str3, string("") ) ); + + //! Container compatibility test + BOOST_CHECK( starts_with( "123xxx321", "123" ) ); + BOOST_CHECK( ends_with( "123xxx321", "321" ) ); + BOOST_CHECK( contains( "123xxx321", "xxx" ) ); + BOOST_CHECK( equals( "123xxx321", "123xxx321" ) ); + +} + +template<typename Pred, typename Input> +void test_pred(const Pred& pred, const Input& input, bool bYes) +{ + // test assignment operator + Pred pred1=pred; + pred1=pred; + pred1=pred1; + if(bYes) + { + BOOST_CHECK( all( input, pred ) ); + BOOST_CHECK( all( input, pred1 ) ); + } + else + { + BOOST_CHECK( !all( input, pred ) ); + BOOST_CHECK( !all( input, pred1 ) ); + } +} + +#define TEST_CLASS( Pred, YesInput, NoInput )\ +{\ + test_pred(Pred, YesInput, true); \ + test_pred(Pred, NoInput, false); \ +} + +void classification_test() +{ + TEST_CLASS( is_space(), "\n\r\t ", "..." ); + TEST_CLASS( is_alnum(), "ab129ABc", "_ab129ABc" ); + TEST_CLASS( is_alpha(), "abc", "abc1" ); + TEST_CLASS( is_cntrl(), "\n\t\r", "..." ); + TEST_CLASS( is_digit(), "1234567890", "abc" ); + TEST_CLASS( is_graph(), "123abc.,", " \t" ); + TEST_CLASS( is_lower(), "abc", "Aasdf" ); + TEST_CLASS( is_print(), "abs", "\003\004asdf" ); + TEST_CLASS( is_punct(), ".,;\"", "abc" ); + TEST_CLASS( is_upper(), "ABC", "aBc" ); + TEST_CLASS( is_xdigit(), "ABC123", "XFD" ); + TEST_CLASS( is_any_of( string("abc") ), "aaabbcc", "aaxb" ); + TEST_CLASS( is_any_of( "abc" ), "aaabbcc", "aaxb" ); + TEST_CLASS( is_from_range( 'a', 'c' ), "aaabbcc", "aaxb" ); + + TEST_CLASS( !is_classified(std::ctype_base::space), "...", "..\n\r\t " ); + TEST_CLASS( ( !is_any_of("abc") && is_from_range('a','e') ) || is_space(), "d e", "abcde" ); + + // is_any_of test +// TEST_CLASS( !is_any_of(""), "", "aaa" ) + TEST_CLASS( is_any_of("a"), "a", "ab" ) + TEST_CLASS( is_any_of("ba"), "ab", "abc" ) + TEST_CLASS( is_any_of("cba"), "abc", "abcd" ) + TEST_CLASS( is_any_of("hgfedcba"), "abcdefgh", "abcdefghi" ) + TEST_CLASS( is_any_of("qponmlkjihgfedcba"), "abcdefghijklmnopq", "zzz" ) +} + +#undef TEST_CLASS + +BOOST_AUTO_TEST_CASE( test_main ) +{ + predicate_test(); + classification_test(); +} diff --git a/libs/algorithm/string/test/regex_test.cpp b/libs/algorithm/string/test/regex_test.cpp new file mode 100644 index 000000000..f93c1d9d3 --- /dev/null +++ b/libs/algorithm/string/test/regex_test.cpp @@ -0,0 +1,158 @@ +// Boost string_algo library substr_test.cpp file ------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/regex.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/sequence_traits.hpp> +// equals predicate is used for result comparison +#include <boost/algorithm/string/predicate.hpp> + + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> +#include <iostream> +#include <boost/regex.hpp> +#include <boost/test/test_tools.hpp> + +using namespace std; +using namespace boost; + +static void find_test() +{ + string str1("123a1cxxxa23cXXXa456c321"); + const char* pch1="123a1cxxxa23cXXXa456c321"; + regex rx("a[0-9]+c"); + vector<int> vec1( str1.begin(), str1.end() ); + vector<string> tokens; + + // find results + iterator_range<string::iterator> nc_result; + iterator_range<string::const_iterator> cv_result; + + iterator_range<vector<int>::iterator> nc_vresult; + iterator_range<vector<int>::const_iterator> cv_vresult; + + iterator_range<const char*> ch_result; + + // basic tests + nc_result=find_regex( str1, rx ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 6) ); + + cv_result=find_regex( str1, rx ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 6) ); + + ch_result=find_regex( pch1, rx ); + BOOST_CHECK(( (ch_result.begin() - pch1 ) == 3) && ( (ch_result.end() - pch1 ) == 6 ) ); + + // multi-type comparison test + nc_vresult=find_regex( vec1, rx ); + BOOST_CHECK( + ( (nc_result.begin()-str1.begin()) == 3) && + ( (nc_result.end()-str1.begin()) == 6) ); + + cv_vresult=find_regex( vec1, rx ); + BOOST_CHECK( + ( (cv_result.begin()-str1.begin()) == 3) && + ( (cv_result.end()-str1.begin()) == 6) ); + + // find_all_regex test + find_all_regex( tokens, str1, rx ); + + BOOST_REQUIRE( tokens.size()==3 ); + BOOST_CHECK( tokens[0]==string("a1c") ); + BOOST_CHECK( tokens[1]==string("a23c") ); + BOOST_CHECK( tokens[2]==string("a456c") ); + + // split_regex test + split_regex( tokens, str1, rx ); + + BOOST_REQUIRE( tokens.size()==4 ); + BOOST_CHECK( tokens[0]==string("123") ); + BOOST_CHECK( tokens[1]==string("xxx") ); + BOOST_CHECK( tokens[2]==string("XXX") ); + BOOST_CHECK( tokens[3]==string("321") ); + +} + +static void join_test() +{ + // Prepare inputs + vector<string> tokens1; + tokens1.push_back("xx"); + tokens1.push_back("abc"); + tokens1.push_back("xx"); + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + BOOST_CHECK( equals(join_if(tokens1, "-", regex("x+")), "xx-xx") ); + BOOST_CHECK( equals(join_if(tokens1, "-", regex("[abc]+")), "abc") ); +#else + BOOST_CHECK( equals(join_if_regex(tokens1, "-", regex("x+")), "xx-xx") ); + BOOST_CHECK( equals(join_if_regex(tokens1, "-", regex("[abc]+")), "abc") ); +#endif +} + +static void replace_test() +{ + string str1("123a1cxxxa23cXXXa456c321"); + regex rx1("a([0-9]+)c"); + regex rx2("([xX]+)"); + regex rx3("_[^_]*_"); + string fmt1("_A$1C_"); + string fmt2("_xXx_"); + vector<int> vec1( str1.begin(), str1.end() ); + + // immutable tests + + // basic tests + BOOST_CHECK( replace_regex_copy( str1, rx1, fmt1 )==string("123_A1C_xxxa23cXXXa456c321") ); + BOOST_CHECK( replace_all_regex_copy( str1, rx1, fmt1 )==string("123_A1C_xxx_A23C_XXX_A456C_321") ); + BOOST_CHECK( erase_regex_copy( str1, rx1 )==string("123xxxa23cXXXa456c321") ); + BOOST_CHECK( erase_all_regex_copy( str1, rx1 )==string(string("123xxxXXX321")) ); + + // output iterator variants test + string strout; + replace_regex_copy( back_inserter(strout), str1, rx1, fmt1 ); + BOOST_CHECK( strout==string("123_A1C_xxxa23cXXXa456c321") ); + strout.clear(); + replace_all_regex_copy( back_inserter(strout), str1, rx1, fmt1 ); + BOOST_CHECK( strout==string("123_A1C_xxx_A23C_XXX_A456C_321") ); + strout.clear(); + erase_regex_copy( back_inserter(strout), str1, rx1 ); + BOOST_CHECK( strout==string("123xxxa23cXXXa456c321") ); + strout.clear(); + erase_all_regex_copy( back_inserter(strout), str1, rx1 ); + BOOST_CHECK( strout==string("123xxxXXX321") ); + strout.clear(); + + // in-place test + replace_regex( str1, rx1, fmt2 ); + BOOST_CHECK( str1==string("123_xXx_xxxa23cXXXa456c321") ); + + replace_all_regex( str1, rx2, fmt1 ); + BOOST_CHECK( str1==string("123__AxXxC___AxxxC_a23c_AXXXC_a456c321") ); + erase_regex( str1, rx3 ); + BOOST_CHECK( str1==string("123AxXxC___AxxxC_a23c_AXXXC_a456c321") ); + erase_all_regex( str1, rx3 ); + BOOST_CHECK( str1==string("123AxXxCa23ca456c321") ); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + find_test(); + join_test(); + replace_test(); +} diff --git a/libs/algorithm/string/test/replace_test.cpp b/libs/algorithm/string/test/replace_test.cpp new file mode 100644 index 000000000..789d8e482 --- /dev/null +++ b/libs/algorithm/string/test/replace_test.cpp @@ -0,0 +1,321 @@ +// Boost string_algo library substr_test.cpp file ------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/replace.hpp> +#include <boost/algorithm/string/erase.hpp> +#include <boost/algorithm/string/std/list_traits.hpp> +#include <boost/algorithm/string/std/string_traits.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/formatter.hpp> +#include <boost/algorithm/string/classification.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> +#include <list> +#include <iostream> + +// equals predicate is used for result comparison +#include <boost/algorithm/string/predicate.hpp> + +#include <boost/test/test_tools.hpp> + +using namespace std; +using namespace boost; + +void sequence_traits_test() +{ + // basic_string traits + BOOST_CHECK( boost::algorithm::has_native_replace<string>::value ); + BOOST_CHECK( !boost::algorithm::has_stable_iterators<string>::value ); + BOOST_CHECK( !boost::algorithm::has_const_time_insert<string>::value ); + BOOST_CHECK( !boost::algorithm::has_const_time_erase<string>::value ); + + // vector traits + BOOST_CHECK( !boost::algorithm::has_native_replace< vector<char> >::value ); + BOOST_CHECK( !boost::algorithm::has_stable_iterators< vector<char> >::value ); + BOOST_CHECK( !boost::algorithm::has_const_time_insert< vector<char> >::value ); + BOOST_CHECK( !boost::algorithm::has_const_time_erase< vector<char> >::value ); + + // list traits + BOOST_CHECK( !boost::algorithm::has_native_replace< list<char> >::value ); + BOOST_CHECK( boost::algorithm::has_stable_iterators< list<char> >::value ); + BOOST_CHECK( boost::algorithm::has_const_time_insert< list<char> >::value ); + BOOST_CHECK( boost::algorithm::has_const_time_erase< list<char> >::value ); +} + +// Combine tests for all variants of the algorithm +#define C_ , +#define TEST_ALGO( Algo, Input, Params, Output ) \ +{\ + BOOST_TEST_CHECKPOINT( #Algo " - Copy" );\ +\ + string str1(Input);\ +\ + /* Copy test */ \ + BOOST_CHECK( Algo##_copy( str1, Params )==Output );\ +\ + BOOST_TEST_CHECKPOINT( #Algo " - Iterator" );\ + /* Iterator test */\ + string strout;\ + Algo##_copy( back_inserter(strout), str1, Params );\ + BOOST_CHECK( strout==Output ); \ +\ + /* In-place test */\ + vector<char> vec1( str1.begin(), str1.end() );\ + list<char> list1( str1.begin(), str1.end() );\ +\ + BOOST_TEST_CHECKPOINT( #Algo " - Inplace(string)" );\ + Algo( str1, Params ); \ + BOOST_CHECK( equals( str1, Output ) ); \ +\ + BOOST_TEST_CHECKPOINT( #Algo " - Inplace(vector)" );\ + Algo( vec1, Params ); \ + BOOST_CHECK( equals( vec1, Output ) );\ +\ + BOOST_TEST_CHECKPOINT( #Algo " - Inplace(list)" );\ + Algo( list1, Params ); \ + BOOST_CHECK( equals( list1, Output ) );\ +} + +void replace_first_test() +{ + // replace first + TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("YYY"), string("1YYY3abc2") ); + TEST_ALGO( ireplace_first, "1AbC3abc2", "aBc" C_ "YYY", string("1YYY3abc2") ); + TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("Z"), string("1Z3abc2") ); + TEST_ALGO( replace_first, "1abc3abc2", string("abc") C_ string("XXXX"), string("1XXXX3abc2") ); + TEST_ALGO( replace_first, "1abc3abc2", string("") C_ string("XXXX"), string("1abc3abc2") ); + TEST_ALGO( replace_first, "1abc3abc2", "" C_ "XXXX", string("1abc3abc2") ); + TEST_ALGO( replace_first, "", string("") C_ string("XXXX"), string("") ); + TEST_ALGO( erase_first, "1abc3abc2", string("abc"), string("13abc2") ); + TEST_ALGO( ierase_first, "1aBc3abc2", "abC", "13abc2" ); + TEST_ALGO( erase_first, "1abc3abc2", "abc", "13abc2" ); + TEST_ALGO( erase_first, "1abc3abc2", string(""), string("1abc3abc2") ); + TEST_ALGO( erase_first, "", string("abc"), string("") ); +} + +void replace_last_test() +{ + // replace last + TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("YYY"), string("1abc3YYY2") ); + TEST_ALGO( ireplace_last, "1abc3AbC2", "aBc" C_ "YYY", string("1abc3YYY2") ); + TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("Z"), string("1abc3Z2") ); + TEST_ALGO( replace_last, "1abc3abc2", string("abc") C_ string("XXXX"), string("1abc3XXXX2") ); + TEST_ALGO( replace_last, "1abc3abc2", "abc" C_ "XXXX", string("1abc3XXXX2") ); + TEST_ALGO( replace_last, "", string("") C_ string("XXXX"), string("") ); + TEST_ALGO( erase_last, "1abc3abc2", string("abc"), string("1abc32") ); + TEST_ALGO( ierase_last, "1aBc3aBc2", "ABC", string("1aBc32") ); + TEST_ALGO( erase_last, "1abc3abc2", "abc", string("1abc32") ); + TEST_ALGO( erase_last, "1abc3abc2", string(""), string("1abc3abc2") ); + TEST_ALGO( erase_last, "", string("abc"), string("") ); +} + +void replace_all_test() +{ + // replace all + TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("YYY"), string("1YYY3YYY2") ); + TEST_ALGO( replace_all, string("1abc3abc2"), "/" C_ "\\", string("1abc3abc2") ); + TEST_ALGO( ireplace_all, "1aBc3AbC2", "abC" C_ "YYY", string("1YYY3YYY2") ); + TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("Z"), string("1Z3Z2") ); + TEST_ALGO( replace_all, "1abc3abc2", string("abc") C_ string("XXXX"), string("1XXXX3XXXX2") ); + TEST_ALGO( replace_all, "1abc3abc2", "abc" C_ "XXXX", string("1XXXX3XXXX2") ); + TEST_ALGO( replace_all, "", string("") C_ string("XXXX"), string("") ); + TEST_ALGO( erase_all, "1abc3abc2", string("abc"), string("132") ); + TEST_ALGO( ierase_all, "1aBc3aBc2", "aBC", string("132") ); + TEST_ALGO( erase_all, "1abc3abc2", "abc", string("132") ); + TEST_ALGO( erase_all, "1abc3abc2", string(""), string("1abc3abc2") ); + TEST_ALGO( erase_all, "", string("abc"), string("") ); +} + +void replace_nth_test() +{ + // replace nth + TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("YYY"), string("1YYY3abc2") ); + TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ -1 C_ string("YYY"), string("1abc3YYY2") ); + TEST_ALGO( ireplace_nth, "1AbC3abc2", "aBc" C_ 0 C_ "YYY", string("1YYY3abc2") ); + TEST_ALGO( ireplace_nth, "1AbC3abc2", "aBc" C_ -1 C_ "YYY", string("1AbC3YYY2") ); + TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("Z"), string("1Z3abc2") ); + TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 0 C_ string("XXXX"), string("1XXXX3abc2") ); + TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ 0 C_ "XXXX", string("1XXXX3abc2") ); + TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ 3 C_ "XXXX", string("1abc3abc2") ); + TEST_ALGO( replace_nth, "1abc3abc2", "abc" C_ -3 C_ "XXXX", string("1abc3abc2") ); + TEST_ALGO( replace_nth, "1abc3abc2", string("") C_ 0 C_ string("XXXX"), string("1abc3abc2") ); + TEST_ALGO( replace_nth, "", string("") C_ 0 C_ string("XXXX"), string("") ); + TEST_ALGO( replace_nth, "", string("") C_ -1 C_ string("XXXX"), string("") ); + TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ 0, string("13abc2") ); + TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ -1, string("1abc32") ); + TEST_ALGO( erase_nth, "1abc3abc2", string("abc") C_ -3, string("1abc3abc2") ); + TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ 0, string("13aBc2") ); + TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ -1, string("1aBc32") ); + TEST_ALGO( ierase_nth, "1aBc3aBc2", "ABC" C_ -3, string("1aBc3aBc2") ); + TEST_ALGO( erase_nth, "1abc3abc2", "abc" C_ 0, string("13abc2") ); + TEST_ALGO( erase_nth, "1abc3abc2", string("") C_ 0, string("1abc3abc2") ); + TEST_ALGO( erase_nth, "", string("abc") C_ 0, string("") ); + TEST_ALGO( erase_nth, "", string("abc") C_ -1, string("") ); + TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 1 C_ string("YYY"), string("1abc3YYY2") ); + TEST_ALGO( replace_nth, "1abc3abc2", string("abc") C_ 2 C_ string("YYY"), string("1abc3abc2") ); +} + +void replace_head_test() +{ + // replace head + TEST_ALGO( replace_head, "abc3abc2", 3 C_ string("YYY"), string("YYY3abc2") ); + TEST_ALGO( replace_head, "abc3abc2", -3 C_ string("YYY"), string("YYYbc2") ); + TEST_ALGO( replace_head, "abc3abc2", 3 C_ "YYY", string("YYY3abc2") ); + TEST_ALGO( replace_head, "abc", 3 C_ string("Z"), string("Z") ); + TEST_ALGO( replace_head, "abc", 6 C_ string("XXXX"), string("XXXX") ); + TEST_ALGO( replace_head, "abc", -6 C_ string("XXXX"), string("abc") ); + TEST_ALGO( replace_head, "abc3abc2", 0 C_ string("XXXX"), string("abc3abc2") ); + TEST_ALGO( replace_head, "", 4 C_ string("XXXX"), string("") ); + TEST_ALGO( replace_head, "", -4 C_ string("XXXX"), string("") ); + TEST_ALGO( erase_head, "abc3abc2", 3, string("3abc2") ); + TEST_ALGO( erase_head, "abc3abc2", -3, string("bc2") ); + TEST_ALGO( erase_head, "abc3abc2", 0, string("abc3abc2") ); + TEST_ALGO( erase_head, "", 4, string("") ); + TEST_ALGO( erase_head, "", -4, string("") ); +} + +void replace_tail_test() +{ + // replace tail + TEST_ALGO( replace_tail, "abc3abc", 3 C_ string("YYY"), string("abc3YYY") ); + TEST_ALGO( replace_tail, "abc3abc", -3 C_ "YYY", string("abcYYY") ); + TEST_ALGO( replace_tail, "abc", 3 C_ string("Z"), string("Z") ); + TEST_ALGO( replace_tail, "abc", 6 C_ string("XXXX"), string("XXXX") ); + TEST_ALGO( replace_tail, "abc", -6 C_ string("XXXX"), string("abc") ); + TEST_ALGO( replace_tail, "abc3abc", 0 C_ string("XXXX"), string("abc3abc") ); + TEST_ALGO( replace_tail, "", 4 C_ string("XXXX"), string("") ); + TEST_ALGO( replace_tail, "", -4 C_ string("XXXX"), string("") ); + TEST_ALGO( erase_tail, "abc3abc", 3, string("abc3") ); + TEST_ALGO( erase_tail, "abc3abc", -3, string("abc") ); + TEST_ALGO( erase_tail, "abc3abc", 0, string("abc3abc") ); + TEST_ALGO( erase_tail, "", 4, string("") ); + TEST_ALGO( erase_tail, "", -4, string("") ); +} + +void replace_range_test() +{ + // replace_range + { + BOOST_TEST_CHECKPOINT( "replace_range" ); + + string str1("1abc3abc2"); + BOOST_CHECK( + replace_range_copy( + str1, + make_iterator_range(str1.begin()+1, str1.begin()+4), + string("XXX") )==string("1XXX3abc2") ); + + string strout; + replace_range_copy( + back_inserter( strout ), + str1, + make_iterator_range(str1.begin()+1, str1.begin()+4), + string("XXX") ); + BOOST_CHECK( strout==string("1XXX3abc2") ); + + replace_range( + str1, + make_iterator_range(str1.begin()+1, str1.begin()+4), + string("XXX") ); + BOOST_CHECK( str1==string("1XXX3abc2") ); + } + // erase_range + { + BOOST_TEST_CHECKPOINT( "erase_range" ); + + string str1("1abc3abc2"); + BOOST_CHECK( + erase_range_copy( + str1, + make_iterator_range(str1.begin()+1, str1.begin()+4))==string("13abc2") ); + + string strout; + erase_range_copy( + back_inserter( strout ), + str1, + make_iterator_range(str1.begin()+1, str1.begin()+4)); + BOOST_CHECK( strout==string("13abc2") ); + + erase_range( + str1, + make_iterator_range(str1.begin()+1, str1.begin()+4)); + BOOST_CHECK( str1==string("13abc2") ); + } +} + +void collection_comp_test() +{ + // container traits compatibility tests + { + string strout; + replace_first_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" ); + BOOST_CHECK( strout==string("1YYY3abc2") ); + } + { + string strout; + replace_last_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" ); + BOOST_CHECK( strout==string("1abc3YYY2") ); + } + { + string strout; + replace_all_copy( back_inserter(strout), "1abc3abc2", "abc", "YYY" ); + BOOST_CHECK( strout==string("1YYY3YYY2") ); + } + { + string strout; + replace_nth_copy( back_inserter(strout), "1abc3abc2", "abc", 1, "YYY" ); + BOOST_CHECK( strout==string("1abc3YYY2") ); + } + { + string strout; + replace_head_copy( back_inserter(strout), "abc3abc2", 3 , "YYY" ); + BOOST_CHECK( strout==string("YYY3abc2") ); + } + { + string strout; + replace_tail_copy( back_inserter(strout), "abc3abc", 3 , "YYY" ); + BOOST_CHECK( strout==string("abc3YYY") ); + } +} + +void dissect_format_test() +{ + BOOST_CHECK( + find_format_all_copy( + string("aBc123Abc"), + first_finder("abc", is_iequal()), + dissect_formatter(token_finder(is_upper())))=="B123A"); + + + BOOST_CHECK( + find_format_all_copy( + string("abc 123 abc"), + token_finder(is_space(), token_compress_on), + dissect_formatter(head_finder(1)))=="abc 123 abc"); + +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + sequence_traits_test(); + replace_first_test(); + replace_last_test(); + replace_all_test(); + replace_nth_test(); + replace_head_test(); + replace_tail_test(); + replace_range_test(); + collection_comp_test(); + dissect_format_test(); +} diff --git a/libs/algorithm/string/test/split_test.cpp b/libs/algorithm/string/test/split_test.cpp new file mode 100644 index 000000000..429f3c4f6 --- /dev/null +++ b/libs/algorithm/string/test/split_test.cpp @@ -0,0 +1,193 @@ +// Boost string_algo library iterator_test.cpp file ---------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/classification.hpp> +// equals predicate is used for result comparison +#include <boost/algorithm/string/predicate.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> +#include <list> +#include <iostream> + +#include <boost/test/test_tools.hpp> + + +using namespace std; +using namespace boost; + +template< typename T1, typename T2 > +void deep_compare( const T1& X, const T2& Y ) +{ + BOOST_REQUIRE( X.size() == Y.size() ); + for( unsigned int nIndex=0; nIndex<X.size(); ++nIndex ) + { + BOOST_CHECK( equals( X[nIndex], Y[nIndex] ) ); + } +} + +void iterator_test() +{ + string str1("xx-abc--xx-abb"); + string str2("Xx-abc--xX-abb-xx"); + string str3("xx"); + string strempty(""); + const char* pch1="xx-abc--xx-abb"; + vector<string> tokens; + vector< vector<int> > vtokens; + + // find_all tests + find_all( + tokens, + pch1, + "xx" ); + + BOOST_REQUIRE( tokens.size()==2 ); + BOOST_CHECK( tokens[0]==string("xx") ); + BOOST_CHECK( tokens[1]==string("xx") ); + + ifind_all( + tokens, + str2, + "xx" ); + + BOOST_REQUIRE( tokens.size()==3 ); + BOOST_CHECK( tokens[0]==string("Xx") ); + BOOST_CHECK( tokens[1]==string("xX") ); + BOOST_CHECK( tokens[2]==string("xx") ); + + find_all( + tokens, + str1, + "xx" ); + + BOOST_REQUIRE( tokens.size()==2 ); + BOOST_CHECK( tokens[0]==string("xx") ); + BOOST_CHECK( tokens[1]==string("xx") ); + + find_all( + vtokens, + str1, + string("xx") ); + deep_compare( tokens, vtokens ); + + // split tests + split( + tokens, + str2, + is_any_of("xX"), + token_compress_on ); + + BOOST_REQUIRE( tokens.size()==4 ); + BOOST_CHECK( tokens[0]==string("") ); + BOOST_CHECK( tokens[1]==string("-abc--") ); + BOOST_CHECK( tokens[2]==string("-abb-") ); + BOOST_CHECK( tokens[3]==string("") ); + + split( + tokens, + pch1, + is_any_of("x"), + token_compress_on ); + + BOOST_REQUIRE( tokens.size()==3 ); + BOOST_CHECK( tokens[0]==string("") ); + BOOST_CHECK( tokens[1]==string("-abc--") ); + BOOST_CHECK( tokens[2]==string("-abb") ); + + split( + vtokens, + str1, + is_any_of("x"), + token_compress_on ); + deep_compare( tokens, vtokens ); + + split( + tokens, + str1, + is_punct(), + token_compress_off ); + + BOOST_REQUIRE( tokens.size()==5 ); + BOOST_CHECK( tokens[0]==string("xx") ); + BOOST_CHECK( tokens[1]==string("abc") ); + BOOST_CHECK( tokens[2]==string("") ); + BOOST_CHECK( tokens[3]==string("xx") ); + BOOST_CHECK( tokens[4]==string("abb") ); + + split( + tokens, + str3, + is_any_of(","), + token_compress_off); + + BOOST_REQUIRE( tokens.size()==1 ); + BOOST_CHECK( tokens[0]==string("xx") ); + + split( + tokens, + strempty, + is_punct(), + token_compress_off); + + BOOST_REQUIRE( tokens.size()==1 ); + BOOST_CHECK( tokens[0]==string("") ); + + + find_iterator<string::iterator> fiter=make_find_iterator(str1, first_finder("xx")); + find_iterator<string::iterator> fiter2; + + BOOST_CHECK(equals(*fiter, "xx")); + ++fiter; + + fiter2 = fiter; + BOOST_CHECK(equals(*fiter, "xx")); + BOOST_CHECK(equals(*fiter2, "xx")); + + ++fiter; + BOOST_CHECK(fiter==find_iterator<string::iterator>()); + BOOST_CHECK(equals(*fiter2, "xx")); + + ++fiter2; + BOOST_CHECK(fiter2==find_iterator<string::iterator>()); + + split_iterator<string::iterator> siter=make_split_iterator(str1, token_finder(is_any_of("-"), token_compress_on)); + split_iterator<string::iterator> siter2; + BOOST_CHECK(equals(*siter, "xx")); + ++siter; + + siter2 = siter; + BOOST_CHECK(equals(*siter, "abc")); + BOOST_CHECK(equals(*siter2, "abc")); + + ++siter; + BOOST_CHECK(equals(*siter, "xx")); + BOOST_CHECK(equals(*siter2, "abc")); + + ++siter; + BOOST_CHECK(equals(*siter, "abb")); + ++siter; + BOOST_CHECK(siter==split_iterator<string::iterator>(siter)); + BOOST_CHECK(siter==split_iterator<string::iterator>()); + +// Make sure we work with forward iterators +// See bug #7989 + list<char> l1; + find_iterator<list<char>::iterator> liter=make_find_iterator(l1, first_finder("xx")); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + iterator_test(); +} diff --git a/libs/algorithm/string/test/trim_test.cpp b/libs/algorithm/string/test/trim_test.cpp new file mode 100644 index 000000000..b254caaa4 --- /dev/null +++ b/libs/algorithm/string/test/trim_test.cpp @@ -0,0 +1,202 @@ +// Boost string_algo library trim_test.cpp file ---------------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/algorithm/string/trim.hpp> +#include <boost/algorithm/string/trim_all.hpp> + +// Include unit test framework +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +#include <string> +#include <iostream> +#include <boost/test/test_tools.hpp> + +using namespace std; +using namespace boost; + +void trim_test() +{ + string str1(" 1x x x x1 "); + string str2(" 2x x x x2 "); + string str3(" "); + + // *** value passing tests *** // + + // general string test + BOOST_CHECK( trim_left_copy( str1 )=="1x x x x1 " ) ; + BOOST_CHECK( trim_right_copy( str1 )==" 1x x x x1" ) ; + BOOST_CHECK( trim_copy( str1 )=="1x x x x1" ) ; + + // spaces-only string test + BOOST_CHECK( trim_left_copy( str3 )=="" ); + BOOST_CHECK( trim_right_copy( str3 )=="" ); + BOOST_CHECK( trim_copy( str3 )=="" ); + + // empty string check + BOOST_CHECK( trim_left_copy( string("") )=="" ); + BOOST_CHECK( trim_right_copy( string("") )=="" ); + BOOST_CHECK( trim_copy( string("") )=="" ); + + // iterator tests + string str; + trim_left_copy_if( std::back_inserter(str), str1, is_space() ); + BOOST_CHECK( str=="1x x x x1 " ); + + str.clear(); + trim_right_copy_if( std::back_inserter(str), str1, is_space() ); + BOOST_CHECK( str==" 1x x x x1" ); + + str.clear(); + trim_copy_if( std::back_inserter(str), str1, is_space() ); + BOOST_CHECK( str=="1x x x x1" ); + + str.clear(); + trim_left_copy_if( + std::back_inserter(str), + " 1x x x x1 ", + is_space() ); + BOOST_CHECK( str=="1x x x x1 " ); + + str.clear(); + trim_right_copy_if( + std::back_inserter(str), + " 1x x x x1 ", + is_space() ); + BOOST_CHECK( str==" 1x x x x1" ); + + str.clear(); + trim_copy_if( + std::back_inserter(str), + " 1x x x x1 ", + is_space() ); + BOOST_CHECK( str=="1x x x x1" ); + // *** inplace tests *** // + + // general string test + trim_left( str1 ); + BOOST_CHECK( str1=="1x x x x1 " ); + trim_right( str1 ); + BOOST_CHECK( str1=="1x x x x1" ); + trim( str2 ); + BOOST_CHECK( str2=="2x x x x2" ); + + // spaces-only string test + str3 = " "; trim_left( str3 ); + BOOST_CHECK( str3=="" ); + str3 = " "; trim_right( str3 ); + BOOST_CHECK( str3=="" ); + str3 = " "; trim( str3 ); + BOOST_CHECK( str3=="" ); + + // empty string check + str3 = ""; trim_left( str3 ); + BOOST_CHECK( str3=="" ); + str3 = ""; trim_right( str3 ); + BOOST_CHECK( str3=="" ); + str3 = ""; trim( str3 ); + BOOST_CHECK( str3=="" ); + + // *** non-standard predicate tests *** // + BOOST_CHECK( + trim_copy_if( + string("123abc456"), + is_classified(std::ctype_base::digit) )=="abc" ); + BOOST_CHECK( trim_copy_if( string("<>abc<>"), is_any_of( "<<>>" ) )=="abc" ); +} + +void trim_all_test() +{ + string str1(" 1x x x x1 "); + string str2("+---...2x+--x--+x-+-x2...---+"); + string str3(" "); + + // *** value passing tests *** // + + // general string test + BOOST_CHECK( trim_all_copy( str1 )=="1x x x x1" ) ; + BOOST_CHECK( trim_all_copy_if( str2, is_punct() )=="2x+x-x-x2" ) ; + + // spaces-only string test + BOOST_CHECK( trim_all_copy( str3 )=="" ); + + // empty string check + BOOST_CHECK( trim_all_copy( string("") )=="" ); + + // general string test + trim_all( str1 ); + BOOST_CHECK( str1=="1x x x x1" ) ; + trim_all_if( str2, is_punct() ); + BOOST_CHECK( str2=="2x+x-x-x2" ) ; + + // spaces-only string test + str3 = " "; trim_all( str3 ); + BOOST_CHECK( str3=="" ); + + // empty string check + str3 = ""; trim_all( str3 ); + BOOST_CHECK( str3=="" ); + BOOST_CHECK( str3=="" ); + + // *** non-standard predicate tests *** // + BOOST_CHECK( + trim_all_copy_if( + string("123abc127deb456"), + is_classified(std::ctype_base::digit) )=="abc1deb" ); + BOOST_CHECK( trim_all_copy_if( string("<>abc<>def<>"), is_any_of( "<<>>" ) )=="abc<def" ); +} + +void trim_fill_test() +{ + string str1(" 1x x x x1 "); + string str2("+---...2x+--x--+x-+-x2...---+"); + string str3(" "); + + // *** value passing tests *** // + + // general string test + BOOST_CHECK( trim_fill_copy( str1, "-" )=="1x-x-x-x1" ) ; + BOOST_CHECK( trim_fill_copy_if( str2, " ", is_punct() )=="2x x x x2" ) ; + + // spaces-only string test + BOOST_CHECK( trim_fill_copy( str3, " " )=="" ); + + // empty string check + BOOST_CHECK( trim_fill_copy( string(""), " " )=="" ); + + // general string test + trim_fill( str1, "-" ); + BOOST_CHECK( str1=="1x-x-x-x1" ) ; + trim_fill_if( str2, "", is_punct() ); + BOOST_CHECK( str2=="2xxxx2" ) ; + + // spaces-only string test + str3 = " "; trim_fill( str3, "" ); + BOOST_CHECK( str3=="" ); + + // empty string check + str3 = ""; trim_fill( str3, "" ); + BOOST_CHECK( str3=="" ); + BOOST_CHECK( str3=="" ); + + // *** non-standard predicate tests *** // + BOOST_CHECK( + trim_fill_copy_if( + string("123abc127deb456"), + "+", + is_classified(std::ctype_base::digit) )=="abc+deb" ); + BOOST_CHECK( trim_fill_copy_if( string("<>abc<>def<>"), "-", is_any_of( "<<>>" ) )=="abc-def" ); +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + trim_test(); + trim_all_test(); + trim_fill_test(); +} |