Compare commits

..

14 Commits

Author SHA1 Message Date
Daniel James 9e726bfd25 Create a maintenance branch for Boost 1.54.0
[SVN r84945]
2013-07-03 21:01:45 +00:00
Andrey Semashev e02523e286 Merged changes from trunk. Fixes operator<< handling of width specification.
[SVN r84674]
2013-06-07 17:33:25 +00:00
Marshall Clow 0d605befd4 Merge bug fix in test to release
[SVN r84449]
2013-05-23 18:38:20 +00:00
Vicente J. Botet Escriba 4080fe22e3 utility/noncopyable : fix #6578.
[SVN r83869]
2013-04-13 13:49:52 +00:00
Vicente J. Botet Escriba 2eda3f5299 Utility/address_off: fix #7079.
[SVN r83524]
2013-03-23 01:44:06 +00:00
Vicente J. Botet Escriba 1ab9131bca Utility: merge [68982] to fix #5213.
[SVN r83427]
2013-03-14 17:35:42 +00:00
Eric Niebler d51799518b merge [82901], [82902], and [83147] from trunk
[SVN r83403]
2013-03-10 21:18:49 +00:00
Eric Niebler f9540f360c merge [82960] to release, fixes #7663
[SVN r83381]
2013-03-09 22:55:05 +00:00
Marshall Clow c1fdb477c1 Merged boost::algorithm::gather and updated tests for Utility, Algorithm and Utility libraries
[SVN r83154]
2013-02-25 18:43:26 +00:00
Marshall Clow 1b2cd6378b Merge doc typo; Fixes #8002
[SVN r82821]
2013-02-11 16:22:32 +00:00
Marshall Clow 9383bbc283 Merge typo in docs; Fixes 7974
[SVN r82819]
2013-02-11 16:10:24 +00:00
Marshall Clow 1730c1319b Merge string_ref doc changes to release
[SVN r82490]
2013-01-14 16:34:16 +00:00
Marshall Clow 856b01240a Merge string_ref to release
[SVN r82047]
2012-12-17 14:36:31 +00:00
Marshall Clow 611395441e Merge deprecated macro change for Boost.Utility to release; no functionality change
[SVN r81855]
2012-12-11 16:41:54 +00:00
17 changed files with 1702 additions and 19 deletions
+19 -4
View File
@@ -43,7 +43,7 @@ using quickbook ;
path-constant boost-images : ../../../doc/src/images ;
xml declval : declval.qbk ;
boostbook standalone
boostbook standalone_declval
:
declval
:
@@ -62,7 +62,22 @@ boostbook standalone
;
xml string_ref : string_ref.qbk ;
boostbook standalone_string_ref
:
string_ref
:
# File name of HTML output:
<xsl:param>root.filename=string_ref
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=0
# How far down sections get TOC's
<xsl:param>toc.section.depth=1
# Max depth in each TOC:
<xsl:param>toc.max.depth=1
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=1
;
+280
View File
@@ -0,0 +1,280 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>String_Ref</title>
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="string_ref.html" title="String_Ref">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
<td align="center"><a href="../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
<div class="article">
<div class="titlepage">
<div>
<div><h2 class="title">
<a name="string_ref"></a>String_Ref</h2></div>
<div><div class="authorgroup"><div class="author"><h3 class="author">
<span class="firstname">Marshall</span> <span class="surname">Clow</span>
</h3></div></div></div>
<div><p class="copyright">Copyright &#169; 2012 Marshall Clow</p></div>
<div><div class="legalnotice">
<a name="string_ref.legal"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></div>
</div>
<hr>
</div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl>
<dt><span class="section"><a href="string_ref.html#string_ref.overview">Overview</a></span></dt>
<dt><span class="section"><a href="string_ref.html#string_ref.examples">Examples</a></span></dt>
<dt><span class="section"><a href="string_ref.html#string_ref.reference">Reference </a></span></dt>
<dt><span class="section"><a href="string_ref.html#string_ref.history">History</a></span></dt>
</dl>
</div>
<div class="section string_ref_overview">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.overview"></a><a class="link" href="string_ref.html#string_ref.overview" title="Overview">Overview</a>
</h2></div></div></div>
<p>
Boost.StringRef is an implementation of Jeffrey Yaskin's <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html" target="_top">N3442:
string_ref: a non-owning reference to a string</a>.
</p>
<p>
When you are parsing/processing strings from some external source, frequently
you want to pass a piece of text to a procedure for specialized processing.
The canonical way to do this is as a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
but that has certain drawbacks:
</p>
<p>
1) If you are processing a buffer of text (say a HTTP response or the contents
of a file), then you have to create the string from the text you want to pass,
which involves memory allocation and copying of data.
</p>
<p>
2) if a routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
and wants to pass a portion of that string to another routine, then it must
create a new string of that substring.
</p>
<p>
3) A routine receives a constant <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
and wants to return a portion of the string, then it must create a new string
to return.
</p>
<p>
<code class="computeroutput"><span class="identifier">string_ref</span></code> is designed to solve
these efficiency problems. A <code class="computeroutput"><span class="identifier">string_ref</span></code>
is a read-only reference to a contiguous sequence of characters, and provides
much of the functionality of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is cheap to create,
copy and pass by value, because it does not actually own the storage that it
points to.
</p>
<p>
A <code class="computeroutput"><span class="identifier">string_ref</span></code> is implemented
as a small struct that contains a pointer to the start of the character data
and a count. A <code class="computeroutput"><span class="identifier">string_ref</span></code> is
cheap to create and cheap to copy.
</p>
<p>
<code class="computeroutput"><span class="identifier">string_ref</span></code> acts as a container;
it includes all the methods that you would expect in a container, including
iteration support, <code class="computeroutput"><span class="keyword">operator</span> <span class="special">[]</span></code>,
<code class="computeroutput"><span class="identifier">at</span></code> and <code class="computeroutput"><span class="identifier">size</span></code>.
It can be used with any of the iterator-based algorithms in the STL - as long
as you don't need to change the underlying data (<code class="computeroutput"><span class="identifier">sort</span></code>
and <code class="computeroutput"><span class="identifier">remove</span></code>, for example, will
not work)
</p>
<p>
Besides generic container functionality, <code class="computeroutput"><span class="identifier">string_ref</span></code>
provides a subset of the interface of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>.
This makes it easy to replace parameters of type <code class="computeroutput"><span class="keyword">const</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span></code>
with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>. Like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>,
<code class="computeroutput"><span class="identifier">string_ref</span></code> has a static member
variable named <code class="computeroutput"><span class="identifier">npos</span></code> to denote
the result of failed searches, and to mean "the end".
</p>
<p>
Because a <code class="computeroutput"><span class="identifier">string_ref</span></code> does not
own the data that it "points to", it introduces lifetime issues into
code that uses it. The programmer must ensure that the data that a <code class="computeroutput"><span class="identifier">string_ref</span></code> refers to exists as long as the
<code class="computeroutput"><span class="identifier">string_ref</span></code> does.
</p>
</div>
<div class="section string_ref_examples">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.examples"></a><a class="link" href="string_ref.html#string_ref.examples" title="Examples">Examples</a>
</h2></div></div></div>
<p>
Integrating <code class="computeroutput"><span class="identifier">string_ref</span></code> into
your code is fairly simple. Wherever you pass a <code class="computeroutput"><span class="keyword">const</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span></code>
or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> as a parameter, that's a candidate
for passing a <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span></code>.
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
<span class="special">}</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
</pre>
<p>
Let's figure out what happens in this (contrived) example.
</p>
<p>
First, a temporary string is created from the string literal <code class="computeroutput"><span class="string">"ABCDEFG"</span></code>, and it is passed (by reference)
to the routine <code class="computeroutput"><span class="identifier">extract_part</span></code>.
Then a second string is created in the call <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">::</span><span class="identifier">substr</span></code>
and returned to <code class="computeroutput"><span class="identifier">extract_part</span></code>
(this copy may be elided by RVO). Then <code class="computeroutput"><span class="identifier">extract_part</span></code>
returns that string back to the caller (again this copy may be elided). The
first temporary string is deallocated, and <code class="computeroutput"><span class="identifier">front</span></code>
is called on the second string, and then it is deallocated as well.
</p>
<p>
Two <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>s are created, and two copy operations.
That's (potentially) four memory allocations and deallocations, and the associated
copying of data.
</p>
<p>
Now let's look at the same code with <code class="computeroutput"><span class="identifier">string_ref</span></code>:
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_ref</span> <span class="identifier">bar</span> <span class="special">)</span> <span class="special">{</span>
<span class="keyword">return</span> <span class="identifier">bar</span><span class="special">.</span><span class="identifier">substr</span> <span class="special">(</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span> <span class="special">);</span>
<span class="special">}</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="string">"ABCDEFG"</span> <span class="special">).</span><span class="identifier">front</span><span class="special">()</span> <span class="special">==</span> <span class="string">"C"</span> <span class="special">)</span> <span class="special">{</span> <span class="comment">/* do something */</span> <span class="special">}</span>
</pre>
<p>
No memory allocations. No copying of character data. No changes to the code
other than the types. There are two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
created, and two <code class="computeroutput"><span class="identifier">string_ref</span></code>s
copied, but those are cheap operations.
</p>
</div>
<div class="section string_ref_reference">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.reference"></a><a class="link" href="string_ref.html#string_ref.reference" title="Reference">Reference </a>
</h2></div></div></div>
<p>
The header file "string_ref.hpp" defines a template <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">basic_string_ref</span></code>,
and four specializations - for <code class="computeroutput"><span class="keyword">char</span></code>
/ <code class="computeroutput"><span class="keyword">wchar_t</span></code> / <code class="computeroutput"><span class="identifier">char16_t</span></code>
/ <code class="computeroutput"><span class="identifier">char32_t</span></code> .
</p>
<p>
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">string_ref</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>
</p>
<p>
Construction and copying:
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="special">();</span> <span class="comment">// Constructs an empty string_ref</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a NULL-terminated string</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">str</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">len</span><span class="special">);</span> <span class="comment">// Constructs from a pointer, length pair</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">&gt;</span>
<span class="identifier">basic_string_ref</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span><span class="special">&lt;</span><span class="identifier">charT</span><span class="special">,</span> <span class="identifier">traits</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">&gt;&amp;</span> <span class="identifier">str</span><span class="special">);</span> <span class="comment">// Constructs from a std::string</span>
<span class="identifier">basic_string_ref</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span>
<span class="identifier">basic_string_ref</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">basic_string_ref</span> <span class="special">&amp;</span><span class="identifier">rhs</span><span class="special">);</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">string_ref</span></code> does not define
a move constructor nor a move-assignment operator because copying a <code class="computeroutput"><span class="identifier">string_ref</span></code> is just a cheap as moving one.
</p>
<p>
Basic container-like functions:
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">length</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">max_size</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">bool</span> <span class="identifier">empty</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="comment">// All iterators are const_iterators</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">begin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">end</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">const_iterator</span> <span class="identifier">cend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crbegin</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">rend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">const_reverse_iterator</span> <span class="identifier">crend</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
<p>
Access to the individual elements (all of which are const):
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="identifier">at</span><span class="special">(</span><span class="identifier">size_t</span> <span class="identifier">pos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="identifier">front</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&amp;</span> <span class="identifier">back</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">data</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
<p>
Modifying the <code class="computeroutput"><span class="identifier">string_ref</span></code> (but
not the underlying data):
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">clear</span><span class="special">();</span>
<span class="keyword">void</span> <span class="identifier">remove_prefix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
<span class="keyword">void</span> <span class="identifier">remove_suffix</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">);</span>
</pre>
<p>
Searching:
</p>
<pre class="programlisting"><span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span> <span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">s</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
<p>
String-like operations:
</p>
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_ref</span> <span class="identifier">substr</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">pos</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">=</span><span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <span class="comment">// Creates a new string_ref</span>
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">charT</span> <span class="identifier">c</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
<span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">basic_string_ref</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span>
</pre>
</div>
<div class="section string_ref_history">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="string_ref.history"></a><a class="link" href="string_ref.html#string_ref.history" title="History">History</a>
</h2></div></div></div>
<h4>
<a name="string_ref.history.h0"></a>
<span><a name="string_ref.history.boost_1_53"></a></span><a class="link" href="string_ref.html#string_ref.history.boost_1_53">boost
1.53</a>
</h4>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
Introduced
</li></ul></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: January 14, 2013 at 16:24:14 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"></div>
</body>
</html>
+167
View File
@@ -0,0 +1,167 @@
[/
/ Copyright (c) 2012 Marshall Clow
/
/ 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)
/]
[article String_Ref
[quickbook 1.5]
[authors [Clow, Marshall]]
[copyright 2012 Marshall Clow]
[license
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])
]
]
[/===============]
[section Overview]
[/===============]
Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
string_ref: a non-owning reference to a string].
When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks:
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return.
`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy.
`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work)
Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does.
[endsect]
[/===============]
[section Examples]
[/===============]
Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`.
std::string extract_part ( const std::string &bar ) {
return bar.substr ( 2, 3 );
}
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
Let's figure out what happens in this (contrived) example.
First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.
Now let's look at the same code with `string_ref`:
boost::string_ref extract_part ( boost::string_ref bar ) {
return bar.substr ( 2, 3 );
}
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations.
[endsect]
[/=================]
[section:reference Reference ]
[/=================]
The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
`#include <boost/utility/string_ref.hpp>`
Construction and copying:
BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref
BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair
template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
basic_string_ref (const basic_string_ref &rhs);
basic_string_ref& operator=(const basic_string_ref &rhs);
`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one.
Basic container-like functions:
BOOST_CONSTEXPR size_type size() const ;
BOOST_CONSTEXPR size_type length() const ;
BOOST_CONSTEXPR size_type max_size() const ;
BOOST_CONSTEXPR bool empty() const ;
// All iterators are const_iterators
BOOST_CONSTEXPR const_iterator begin() const ;
BOOST_CONSTEXPR const_iterator cbegin() const ;
BOOST_CONSTEXPR const_iterator end() const ;
BOOST_CONSTEXPR const_iterator cend() const ;
const_reverse_iterator rbegin() const ;
const_reverse_iterator crbegin() const ;
const_reverse_iterator rend() const ;
const_reverse_iterator crend() const ;
Access to the individual elements (all of which are const):
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
const charT& at(size_t pos) const ;
BOOST_CONSTEXPR const charT& front() const ;
BOOST_CONSTEXPR const charT& back() const ;
BOOST_CONSTEXPR const charT* data() const ;
Modifying the `string_ref` (but not the underlying data):
void clear();
void remove_prefix(size_type n);
void remove_suffix(size_type n);
Searching:
size_type find(basic_string_ref s) const ;
size_type find(charT c) const ;
size_type rfind(basic_string_ref s) const ;
size_type rfind(charT c) const ;
size_type find_first_of(charT c) const ;
size_type find_last_of (charT c) const ;
size_type find_first_of(basic_string_ref s) const ;
size_type find_last_of(basic_string_ref s) const ;
size_type find_first_not_of(basic_string_ref s) const ;
size_type find_first_not_of(charT c) const ;
size_type find_last_not_of(basic_string_ref s) const ;
size_type find_last_not_of(charT c) const ;
String-like operations:
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref
bool starts_with(charT c) const ;
bool starts_with(basic_string_ref x) const ;
bool ends_with(charT c) const ;
bool ends_with(basic_string_ref x) const ;
[endsect]
[/===============]
[section History]
[/===============]
[heading boost 1.53]
* Introduced
[endsect]
+1 -1
View File
@@ -46,7 +46,7 @@ HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_pla
<p>Suppose we have a class</p>
<pre>struct X
{
X ( int, std:::string ) ;
X ( int, std::string ) ;
} ;</pre>
<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p>
<pre>struct C
+6 -1
View File
@@ -101,7 +101,12 @@ namespace boost
<< "***** Internal Program Error - assertion (" << expr << ") failed in "
<< function << ":\n"
<< file << '(' << line << "): " << msg << std::endl;
std::abort();
#ifdef UNDER_CE
// The Windows CE CRT library does not have abort() so use exit(-1) instead.
std::exit(-1);
#else
std::abort();
#endif
}
} // detail
} // assertion
+15 -3
View File
@@ -9,6 +9,8 @@
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
#define BOOST_NONCOPYABLE_HPP_INCLUDED
#include <boost/config.hpp>
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
@@ -21,11 +23,21 @@ namespace noncopyable_ // protection from unintended ADL
class noncopyable
{
protected:
noncopyable() {}
#ifndef BOOST_NO_DEFAULTED_FUNCTIONS
BOOST_CONSTEXPR noncopyable() = default;
~noncopyable() = default;
#else
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
#endif
#ifndef BOOST_NO_DELETED_FUNCTIONS
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
#else
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
noncopyable& operator=( const noncopyable& );
#endif
};
}
+2 -2
View File
@@ -1,4 +1,4 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Douglas Gregor (gregod@cs.rpi.edu)
//
// Copyright (C) 2002, 2008 Peter Dimov
@@ -50,7 +50,7 @@ template<class T> struct addressof_impl
template<class T> T * addressof( T & v )
{
#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) )
#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC )
return boost::detail::addressof_impl<T>::f( v, 0 );
+8 -1
View File
@@ -46,7 +46,7 @@
#ifndef BOOST_RESULT_OF_USE_TR1
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_DECLTYPE)
# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE)
# define BOOST_RESULT_OF_USE_DECLTYPE
# else
# define BOOST_RESULT_OF_USE_TR1
@@ -68,6 +68,13 @@ template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_im
#ifdef BOOST_NO_SFINAE_EXPR
// There doesn't seem to be any other way to turn this off such that the presence of
// the user-defined operator,() below doesn't cause spurious warning all over the place,
// so unconditionally turn it off.
#if BOOST_MSVC
# pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
#endif
struct result_of_private_type {};
struct result_of_weird_type {
+536
View File
@@ -0,0 +1,536 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
Based on the StringRef implementation in LLVM (http://llvm.org) and
N3422 by Jeffrey Yasskin
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
*/
#ifndef BOOST_STRING_REF_HPP
#define BOOST_STRING_REF_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/string_ref_fwd.hpp>
#include <boost/throw_exception.hpp>
#include <cstddef>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#include <string>
#include <iosfwd>
namespace boost {
namespace detail {
// A helper functor because sometimes we don't have lambdas
template <typename charT, typename traits>
class string_ref_traits_eq {
public:
string_ref_traits_eq ( charT ch ) : ch_(ch) {}
bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
charT ch_;
};
}
template<typename charT, typename traits>
class basic_string_ref {
public:
// types
typedef charT value_type;
typedef const charT* pointer;
typedef const charT& reference;
typedef const charT& const_reference;
typedef pointer const_iterator; // impl-defined
typedef const_iterator iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
// construct/copy
BOOST_CONSTEXPR basic_string_ref ()
: ptr_(NULL), len_(0) {}
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs)
: ptr_(rhs.ptr_), len_(rhs.len_) {}
basic_string_ref& operator=(const basic_string_ref &rhs) {
ptr_ = rhs.ptr_;
len_ = rhs.len_;
return *this;
}
basic_string_ref(const charT* str)
: ptr_(str), len_(traits::length(str)) {}
template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
: ptr_(str.data()), len_(str.length()) {}
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len)
: ptr_(str), len_(len) {}
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
template<typename Allocator>
explicit operator std::basic_string<charT, traits, Allocator>() const {
return std::basic_string<charT, traits, Allocator> ( ptr_, len_ );
}
#endif
std::basic_string<charT, traits> to_string () const {
return std::basic_string<charT, traits> ( ptr_, len_ );
}
// iterators
BOOST_CONSTEXPR const_iterator begin() const { return ptr_; }
BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; }
BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; }
BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; }
const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); }
const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); }
const_reverse_iterator rend() const { return const_reverse_iterator (begin()); }
const_reverse_iterator crend() const { return const_reverse_iterator (begin()); }
// capacity
BOOST_CONSTEXPR size_type size() const { return len_; }
BOOST_CONSTEXPR size_type length() const { return len_; }
BOOST_CONSTEXPR size_type max_size() const { return len_; }
BOOST_CONSTEXPR bool empty() const { return len_ == 0; }
// element access
BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; }
const charT& at(size_t pos) const {
if ( pos >= len_ )
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) );
return ptr_[pos];
}
BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; }
BOOST_CONSTEXPR const charT& back() const { return ptr_[len_-1]; }
BOOST_CONSTEXPR const charT* data() const { return ptr_; }
// modifiers
void clear() { len_ = 0; }
void remove_prefix(size_type n) {
if ( n > len_ )
n = len_;
ptr_ += n;
len_ -= n;
}
void remove_suffix(size_type n) {
if ( n > len_ )
n = len_;
len_ -= n;
}
// basic_string_ref string operations
basic_string_ref substr(size_type pos, size_type n=npos) const {
if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
if ( n == npos || pos + n > size())
n = size () - pos;
return basic_string_ref ( data() + pos, n );
}
int compare(basic_string_ref x) const {
const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
}
bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
bool starts_with(basic_string_ref x) const {
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
}
bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
bool ends_with(basic_string_ref x) const {
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
}
size_type find(basic_string_ref s) const {
const_iterator iter = std::search ( this->cbegin (), this->cend (),
s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find(charT c) const {
const_iterator iter = std::find_if ( this->cbegin (), this->cend (),
detail::string_ref_traits_eq<charT, traits> ( c ));
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type rfind(basic_string_ref s) const {
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
s.crbegin (), s.crend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
size_type rfind(charT c) const {
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
detail::string_ref_traits_eq<charT, traits> ( c ));
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
size_type find_first_of(charT c) const { return find (c); }
size_type find_last_of (charT c) const { return rfind (c); }
size_type find_first_of(basic_string_ref s) const {
const_iterator iter = std::find_first_of
( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find_last_of(basic_string_ref s) const {
const_reverse_iterator iter = std::find_first_of
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
}
size_type find_first_not_of(basic_string_ref s) const {
const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
size_type find_first_not_of(charT c) const {
for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter )
if ( !traits::eq ( c, *iter ))
return std::distance ( this->cbegin (), iter );
return npos;
}
size_type find_last_not_of(basic_string_ref s) const {
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
size_type find_last_not_of(charT c) const {
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
if ( !traits::eq ( c, *iter ))
return reverse_distance ( this->crbegin (), iter );
return npos;
}
private:
template <typename r_iter>
size_type reverse_distance ( r_iter first, r_iter last ) const {
return len_ - 1 - std::distance ( first, last );
}
template <typename Iterator>
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
for ( ; first != last ; ++first )
if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
return first;
return last;
}
const charT *ptr_;
std::size_t len_;
};
// Comparison operators
// Equality
template<typename charT, typename traits>
inline bool operator==(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
if ( x.size () != y.size ()) return false;
return x.compare(y) == 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator==(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x == basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) == y;
}
template<typename charT, typename traits>
inline bool operator==(basic_string_ref<charT, traits> x, const charT * y) {
return x == basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator==(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) == y;
}
// Inequality
template<typename charT, typename traits>
inline bool operator!=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
if ( x.size () != y.size ()) return true;
return x.compare(y) != 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator!=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x != basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) != y;
}
template<typename charT, typename traits>
inline bool operator!=(basic_string_ref<charT, traits> x, const charT * y) {
return x != basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator!=(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) != y;
}
// Less than
template<typename charT, typename traits>
inline bool operator<(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) < 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x < basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) < y;
}
template<typename charT, typename traits>
inline bool operator<(basic_string_ref<charT, traits> x, const charT * y) {
return x < basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator<(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) < y;
}
// Greater than
template<typename charT, typename traits>
inline bool operator>(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) > 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x > basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) > y;
}
template<typename charT, typename traits>
inline bool operator>(basic_string_ref<charT, traits> x, const charT * y) {
return x > basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator>(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) > y;
}
// Less than or equal to
template<typename charT, typename traits>
inline bool operator<=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) <= 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x <= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) <= y;
}
template<typename charT, typename traits>
inline bool operator<=(basic_string_ref<charT, traits> x, const charT * y) {
return x <= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator<=(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) <= y;
}
// Greater than or equal to
template<typename charT, typename traits>
inline bool operator>=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) {
return x.compare(y) >= 0;
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x >= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) >= y;
}
template<typename charT, typename traits>
inline bool operator>=(basic_string_ref<charT, traits> x, const charT * y) {
return x >= basic_string_ref<charT, traits>(y);
}
template<typename charT, typename traits>
inline bool operator>=(const charT * x, basic_string_ref<charT, traits> y) {
return basic_string_ref<charT, traits>(x) >= y;
}
namespace detail {
template<class charT, class traits>
inline void insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
enum { chunk_size = 8 };
charT fill_chars[chunk_size];
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
for (; n >= chunk_size && os.good(); n -= chunk_size)
os.write(fill_chars, static_cast< std::size_t >(chunk_size));
if (n > 0 && os.good())
os.write(fill_chars, n);
}
template<class charT, class traits>
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
const std::size_t size = str.size();
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
if (!align_left) {
detail::insert_fill_chars(os, alignment_size);
if (os.good())
os.write(str.data(), size);
}
else {
os.write(str.data(), size);
if (os.good())
detail::insert_fill_chars(os, alignment_size);
}
}
} // namespace detail
// Inserter
template<class charT, class traits>
inline std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
if (os.good()) {
const std::size_t size = str.size();
const std::size_t w = static_cast< std::size_t >(os.width());
if (w <= size)
os.write(str.data(), size);
else
detail::insert_aligned(os, str);
os.width(0);
}
return os;
}
#if 0
// numeric conversions
//
// These are short-term implementations.
// In a production environment, I would rather avoid the copying.
//
inline int stoi (string_ref str, size_t* idx=0, int base=10) {
return std::stoi ( std::string(str), idx, base );
}
inline long stol (string_ref str, size_t* idx=0, int base=10) {
return std::stol ( std::string(str), idx, base );
}
inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) {
return std::stoul ( std::string(str), idx, base );
}
inline long long stoll (string_ref str, size_t* idx=0, int base=10) {
return std::stoll ( std::string(str), idx, base );
}
inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) {
return std::stoull ( std::string(str), idx, base );
}
inline float stof (string_ref str, size_t* idx=0) {
return std::stof ( std::string(str), idx );
}
inline double stod (string_ref str, size_t* idx=0) {
return std::stod ( std::string(str), idx );
}
inline long double stold (string_ref str, size_t* idx=0) {
return std::stold ( std::string(str), idx );
}
inline int stoi (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoi ( std::wstring(str), idx, base );
}
inline long stol (wstring_ref str, size_t* idx=0, int base=10) {
return std::stol ( std::wstring(str), idx, base );
}
inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoul ( std::wstring(str), idx, base );
}
inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoll ( std::wstring(str), idx, base );
}
inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) {
return std::stoull ( std::wstring(str), idx, base );
}
inline float stof (wstring_ref str, size_t* idx=0) {
return std::stof ( std::wstring(str), idx );
}
inline double stod (wstring_ref str, size_t* idx=0) {
return std::stod ( std::wstring(str), idx );
}
inline long double stold (wstring_ref str, size_t* idx=0) {
return std::stold ( std::wstring(str), idx );
}
#endif
}
#if 0
namespace std {
// Hashing
template<> struct hash<boost::string_ref>;
template<> struct hash<boost::u16string_ref>;
template<> struct hash<boost::u32string_ref>;
template<> struct hash<boost::wstring_ref>;
}
#endif
#endif
+37
View File
@@ -0,0 +1,37 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
Based on the StringRef implementation in LLVM (http://llvm.org) and
N3422 by Jeffrey Yasskin
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
*/
#ifndef BOOST_STRING_REF_FWD_HPP
#define BOOST_STRING_REF_FWD_HPP
#include <boost/config.hpp>
#include <string>
namespace boost {
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_ref;
typedef basic_string_ref<char, std::char_traits<char> > string_ref;
typedef basic_string_ref<wchar_t, std::char_traits<wchar_t> > wstring_ref;
#ifndef BOOST_NO_CXX11_CHAR16_T
typedef basic_string_ref<char16_t, std::char_traits<char16_t> > u16string_ref;
#endif
#ifndef BOOST_NO_CXX11_CHAR32_T
typedef basic_string_ref<char32_t, std::char_traits<char32_t> > u32string_ref;
#endif
}
#endif
+3 -1
View File
@@ -28,7 +28,9 @@
<a href="swap.html">swap</a><br>
<a href="throw_exception.html">throw_exception</a><br>
<a href="utility.htm">utility</a><br>
<a href="value_init.htm">value_init</a></p>
<a href="doc/html/string_ref.html">string_ref</a><br>
<a href="value_init.htm">value_init</a>
</p>
</blockquote>
<hr>
<p>&copy; Copyright Beman Dawes, 2001</p>
+8
View File
@@ -8,6 +8,11 @@
# bring in rules for testing
import testing ;
alias unit_test_framework
: # sources
/boost//unit_test_framework
;
# Please keep the tests ordered by filename
test-suite utility
:
@@ -31,6 +36,9 @@ test-suite utility
[ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ compile result_of_test.cpp ]
[ run ../shared_iterator_test.cpp ]
[ run string_ref_test1.cpp unit_test_framework ]
[ run string_ref_test2.cpp unit_test_framework ]
[ run string_ref_test_io.cpp unit_test_framework ]
[ run ../value_init_test.cpp ]
[ run ../value_init_workaround_test.cpp ]
[ run ../initialized_test.cpp ]
+3 -3
View File
@@ -104,7 +104,7 @@ struct no_result_type_or_result
cv_overload_check<const int> operator()() const;
cv_overload_check<volatile int> operator()() volatile;
cv_overload_check<const volatile int> operator()() const volatile;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
long operator()(int const&);
@@ -122,7 +122,7 @@ struct no_result_type_or_result_template
cv_overload_check<const int> operator()() const;
cv_overload_check<volatile int> operator()() volatile;
cv_overload_check<const volatile int> operator()() const volatile;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
long operator()(int const&);
@@ -291,7 +291,7 @@ int main()
BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value));
#if !defined(BOOST_NO_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
+109
View File
@@ -0,0 +1,109 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <algorithm>
#include <string>
#include <boost/utility/string_ref.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
typedef boost::string_ref string_ref;
// Should be equal
void interop ( const std::string &str, string_ref ref ) {
// BOOST_CHECK ( str == ref );
BOOST_CHECK ( str.size () == ref.size ());
BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ()));
BOOST_CHECK ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
}
void null_tests ( const char *p ) {
// All zero-length string-refs should be equal
string_ref sr1; // NULL, 0
string_ref sr2 ( NULL, 0 );
string_ref sr3 ( p, 0 );
string_ref sr4 ( p );
sr4.clear ();
BOOST_CHECK ( sr1 == sr2 );
BOOST_CHECK ( sr1 == sr3 );
BOOST_CHECK ( sr2 == sr3 );
BOOST_CHECK ( sr1 == sr4 );
}
// make sure that substrings work just like strings
void test_substr ( const std::string &str ) {
const size_t sz = str.size ();
string_ref ref ( str );
// Substrings at the end
for ( size_t i = 0; i <= sz; ++ i )
interop ( str.substr ( i ), ref.substr ( i ));
// Substrings at the beginning
for ( size_t i = 0; i <= sz; ++ i )
interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
// All possible substrings
for ( size_t i = 0; i < sz; ++i )
for ( size_t j = i; j < sz; ++j )
interop ( str.substr ( i, j ), ref.substr ( i, j ));
}
// make sure that removing prefixes and suffixes work just like strings
void test_remove ( const std::string &str ) {
const size_t sz = str.size ();
std::string work;
string_ref ref;
for ( size_t i = 1; i <= sz; ++i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( 0, i );
ref.remove_prefix (i);
}
}
for ( size_t i = 1; i < sz; ++ i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( work.size () - i, i );
ref.remove_suffix (i);
}
}
}
const char *test_strings [] = {
"",
"1",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789",
NULL
};
BOOST_AUTO_TEST_CASE( test_main )
{
const char **p = &test_strings[0];
while ( *p != NULL ) {
interop ( *p, *p );
test_substr ( *p );
test_remove ( *p );
null_tests ( *p );
p++;
}
}
+318
View File
@@ -0,0 +1,318 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <cstring> // for std::strchr
#include <boost/utility/string_ref.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
typedef boost::string_ref string_ref;
void ends_with ( const char *arg ) {
const size_t sz = strlen ( arg );
string_ref sr ( arg );
string_ref sr2 ( arg );
const char *p = arg;
while ( *p ) {
BOOST_CHECK ( sr.ends_with ( p ));
++p;
}
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.ends_with ( sr2 ));
sr2.remove_prefix (1);
}
sr2 = arg;
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.ends_with ( sr2 ));
sr2.remove_prefix (1);
}
char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.ends_with ( ch ));
BOOST_CHECK ( !sr2.ends_with ( ++ch ));
BOOST_CHECK ( sr2.ends_with ( string_ref ()));
}
void starts_with ( const char *arg ) {
const size_t sz = strlen ( arg );
string_ref sr ( arg );
string_ref sr2 ( arg );
const char *p = arg + std::strlen ( arg ) - 1;
while ( p >= arg ) {
std::string foo ( arg, p + 1 );
BOOST_CHECK ( sr.starts_with ( foo ));
--p;
}
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.starts_with ( sr2 ));
sr2.remove_suffix (1);
}
char ch = *arg;
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.starts_with ( ch ));
BOOST_CHECK ( !sr2.starts_with ( ++ch ));
BOOST_CHECK ( sr2.starts_with ( string_ref ()));
}
void reverse ( const char *arg ) {
// Round trip
string_ref sr1 ( arg );
std::string string1 ( sr1.rbegin (), sr1.rend ());
string_ref sr2 ( string1 );
std::string string2 ( sr2.rbegin (), sr2.rend ());
BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
BOOST_CHECK ( string2 == arg );
BOOST_CHECK ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
}
// This helper function eliminates signed vs. unsigned warnings
string_ref::size_type ptr_diff ( const char *res, const char *base ) {
BOOST_CHECK ( res >= base );
return static_cast<string_ref::size_type> ( res - base );
}
void find ( const char *arg ) {
string_ref sr1;
string_ref sr2;
const char *p;
// Look for each character in the string(searching from the start)
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
++p;
}
// Look for each character in the string (searching from the end)
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
++p;
}
// Look for pairs on characters (searching from the start)
sr1 = arg;
p = arg;
while ( *p && *(p+1)) {
string_ref sr3 ( p, 2 );
string_ref::size_type pos = sr1.find ( sr3 );
BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast<string_ref::size_type>( p - arg ));
p++;
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.find(ch);
const char *strp = std::strchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.rfind(ch);
const char *strp = std::strrchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos ));
if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
}
// Find everything at the start
p = arg;
sr1 = arg;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1);
++p;
}
// Find everything at the end
sr1 = arg;
p = arg + strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1);
--p;
}
// Find everything at the start
sr1 = arg;
p = arg;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_first_of(*p);
BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1);
++p;
}
// Find everything at the end
sr1 = arg;
p = arg + strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_last_of(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1);
--p;
}
// Basic sanity checking for "find_first_of / find_first_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 );
BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_ref::npos );
sr1.remove_prefix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos1 = sr1.find_first_of(*p);
string_ref::size_type pos2 = sr1.find_first_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
if ( pos2 != string_ref::npos ) {
for ( size_t i = 0 ; i < pos2; ++i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
// Basic sanity checking for "find_last_of / find_last_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 ));
BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_ref::npos );
sr1.remove_suffix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_ref::size_type pos1 = sr1.find_last_of(*p);
string_ref::size_type pos2 = sr1.find_last_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
BOOST_CHECK ( pos2 == string_ref::npos || pos1 < sr1.size ());
if ( pos2 != string_ref::npos ) {
for ( size_t i = sr1.size () -1 ; i > pos2; --i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
}
void to_string ( const char *arg ) {
string_ref sr1;
std::string str1;
std::string str2;
str1.assign ( arg );
sr1 = arg;
// str2 = sr1.to_string<std::allocator<char> > ();
str2 = sr1.to_string ();
BOOST_CHECK ( str1 == str2 );
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
std::string str3 = static_cast<std::string> ( sr1 );
BOOST_CHECK ( str1 == str3 );
#endif
}
void compare ( const char *arg ) {
string_ref sr1;
std::string str1;
std::string str2 = str1;
str1.assign ( arg );
sr1 = arg;
BOOST_CHECK ( sr1 == sr1); // compare string_ref and string_ref
BOOST_CHECK ( sr1 == str1); // compare string and string_ref
BOOST_CHECK ( str1 == sr1 ); // compare string_ref and string
BOOST_CHECK ( sr1 == arg ); // compare string_ref and pointer
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_ref
if ( sr1.size () > 0 ) {
(*str1.rbegin())++;
BOOST_CHECK ( sr1 != str1 );
BOOST_CHECK ( str1 != sr1 );
BOOST_CHECK ( sr1 < str1 );
BOOST_CHECK ( sr1 <= str1 );
BOOST_CHECK ( str1 > sr1 );
BOOST_CHECK ( str1 >= sr1 );
(*str1.rbegin()) -= 2;
BOOST_CHECK ( sr1 != str1 );
BOOST_CHECK ( str1 != sr1 );
BOOST_CHECK ( sr1 > str1 );
BOOST_CHECK ( sr1 >= str1 );
BOOST_CHECK ( str1 < sr1 );
BOOST_CHECK ( str1 <= sr1 );
}
}
const char *test_strings [] = {
"",
"0",
"abc",
"AAA", // all the same
"adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
"abc\0asdfadsfasf",
NULL
};
BOOST_AUTO_TEST_CASE( test_main )
{
const char **p = &test_strings[0];
while ( *p != NULL ) {
starts_with ( *p );
ends_with ( *p );
reverse ( *p );
find ( *p );
to_string ( *p );
compare ( *p );
p++;
}
}
+183
View File
@@ -0,0 +1,183 @@
/*
* Copyright Andrey Semashev 2013.
* 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)
*/
/*!
* \file string_ref_test_io.cpp
* \author Andrey Semashev
* \date 26.05.2013
*
* \brief This header contains tests for stream operations of \c basic_string_ref.
*/
#define BOOST_TEST_MODULE string_ref_test_io
#include <boost/utility/string_ref.hpp>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/config.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/test/unit_test.hpp>
typedef boost::mpl::vector<
char
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
, wchar_t
#endif
/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available.
#if !defined(BOOST_NO_CXX11_CHAR16_T)
, char16_t
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
, char32_t
#endif
*/
>::type char_types;
static const char* test_strings[] =
{
"begin",
"abcd",
"end"
};
//! The context with test data for particular character type
template< typename CharT >
struct context
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
string_type begin, abcd, end;
context()
{
boost::string_ref str = test_strings[0];
std::copy(str.begin(), str.end(), std::back_inserter(begin));
str = test_strings[1];
std::copy(str.begin(), str.end(), std::back_inserter(abcd));
str = test_strings[2];
std::copy(str.begin(), str.end(), std::back_inserter(end));
}
};
// Test regular output
BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
ostream_type strm;
strm << string_ref_type(ctx.abcd);
BOOST_CHECK(strm.str() == ctx.abcd);
}
// Test support for padding
BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
// Test for padding
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test for long padding
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test that short width does not truncate the string
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
}
// Test support for padding fill
BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
ostream_type strm_ref;
strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test support for alignment
BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
context< char_type > ctx;
// Left alignment
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Right alignment
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
}
+7 -3
View File
@@ -84,8 +84,10 @@ const std::list&lt;T&gt;::iterator next = boost::next(prev, 2);</pre>
will prevent the otherwise implicitly-generated functions (which don't have the
proper semantics) from becoming a trap for other programmers.</p>
<p>The traditional way to deal with these is to declare a private copy constructor
and copy assignment, and then document why this is done.&nbsp; But deriving
from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
and copy assignment, and then document why this is done.&nbsp; A new alternative
was introduced in C++2011, declaring a copy constructor and a copy assignment
operator, but marking both as <code>delete</code>d.&nbsp; Deriving
from <b>noncopyable</b> is simpler and clearer, and doesn't require additional
documentation.</p>
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be used
to verify class <b>noncopyable</b> works as expected. It has have been run
@@ -106,7 +108,9 @@ class ResourceLadenFileSystem : boost::noncopyable {
about the effect on compiler optimization of adding (even trivial inline)
destructor declarations. He says &quot;Probably this concern is misplaced,
because noncopyable will be used mostly for classes which own resources and
thus have non-trivial destruction semantics.&quot;</p>
thus have non-trivial destruction semantics.&quot;&nbsp; With C++2011, using an
optimized and trivial constructor and similar destructor can be enforced by
declaring both and marking them <code>default</code>.</p>
<h2><a name="addressof">Function template addressof()</a></h2>
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
<blockquote>